Developer Documentation
PluginCommunication.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 
52 
53 //=============================================================================
54 //
55 // CLASS Core - IMPLEMENTATION of Comunication with plugins
56 //
57 //=============================================================================
58 
59 
60 //== INCLUDES =================================================================
61 
62 #include "Core.hh"
63 
64 #include "OpenFlipper/BasePlugin/PluginFunctionsCore.hh"
65 #include <stdexcept>
66 
67 //== IMPLEMENTATION ==========================================================
68 
69 //========================================================================================
70 // === Object List Communication =======================
71 //========================================================================================
72 
81 void Core::slotObjectUpdated(int _identifier, const UpdateType& _type) {
82  if ( OpenFlipper::Options::doSlotDebugging() ) {
83  if ( sender() != 0 ) {
84  if ( sender()->metaObject() != 0 ) {
85  emit log(LOGINFO,"updatedObject( " + QString::number(_identifier) + ", " + updateTypeName(_type)
86  + tr(" ) called by ") + QString( sender()->metaObject()->className() ) );
87  }
88  } else {
89  emit log(LOGINFO,"updatedObject( " + QString::number(_identifier) + ", " + updateTypeName(_type) + tr(" ) called by Core") );
90  }
91  }
92 
93  // Disable redraws as everything here has to update the object only once
94  OpenFlipper::Options::redrawDisabled(true);
95 
96  // If we are called for a special object, we update it ourself so the Plugins dont need to do that.
97  BaseObject* object = 0;
98  if ( _identifier != -1 ) {
99  if ( !PluginFunctions::getObject(_identifier,object) ) {
100  emit log(LOGERR,tr("updated_objects called for non existing object with id : ") + QString::number(_identifier) );
101  return;
102  }
103  }
104 
105 
106  // If the identifier is -1 we force an update of all objects in the scene (Bad idea for scenes with many objects)
107  if ( _identifier == -1 ) {
108 
109  if ( sender() != 0 ) {
110  if ( sender()->metaObject() != 0 ) {
111  emit log(LOGWARN,"updatedObject( " + QString::number(_identifier) + ", " + updateTypeName(_type)
112  + tr(" ) called by ") + QString( sender()->metaObject()->className() + tr(" which is inefficient)") ) );
113  }
114  } else {
115  emit log(LOGWARN,"updatedObject( " + QString::number(_identifier) + ", " + updateTypeName(_type) + tr(" ) called by Core, which is inefficient!") );
116  }
117 
119 
120  // just inform the plugins as we don't do anything else (Do deprecated and new updatedObjects here)
121  emit signalObjectUpdated(o_it->id());
122  emit signalObjectUpdated(o_it->id(), _type);
123 
124  // Call the objects update function
125  o_it->update();
126 
127  }
128  } else {
129  // just inform the plugins as we don't do anything else (Do deprecated and new updatedObjects here)
130  emit signalObjectUpdated(_identifier);
131  emit signalObjectUpdated(_identifier, _type);
132  }
133 
134 
135  // If we have an single object, call it's update function
136  if ( object != 0 )
137  object->update(_type);
138 
139  // Reenable redraws
140  OpenFlipper::Options::redrawDisabled(false);
141 
142 
143  // Reset scenegraph but keep scene center!
144  resetScenegraph(false);
145 
146  updateView();
147 }
148 
150 
151  // tell plugins
152  emit visibilityChanged( _id );
153 
154  // Reset scenegraph but keep scene center!
155  resetScenegraph(false);
156 
157  updateView();
158 }
159 
163 {
164  // just inform the plugins as we don't do anything else
165  emit objectSelectionChanged(_id);
166 
167  // Send via second interface
169 
170  updateView();
171 }
172 
174 {
175  emit objectPropertiesChanged(_id);
176 }
177 
178 //========================================================================================
179 // === Texture Communication ===========================
180 //========================================================================================
181 
182 
186 void Core::slotAddTexture( QString _textureName , QString _filename, uint _dimension, int _id) {
187 
188  if (QThread::currentThread() != QApplication::instance()->thread())
189  {
190  //execute method in main thread
191  QMetaObject::invokeMethod(this,"slotAddTexture",Qt::BlockingQueuedConnection, Q_ARG(QString, _textureName), Q_ARG(QString, _filename), Q_ARG(uint, _dimension), Q_ARG(int, _id));
192  return;
193  }
194 
195  if ( OpenFlipper::Options::doSlotDebugging() ) {
196  if ( sender() != 0 ) {
197  if ( sender()->metaObject() != 0 ) {
198  emit log(LOGINFO,"addTexture( " + _textureName + "," + _filename + "," + QString::number(_dimension) + ", " + QString::number(_id) + tr(" ) called by ") +
199  QString( sender()->metaObject()->className() ) );
200  }
201  } else {
202  emit log(LOGINFO,"addTexture( " + _textureName + "," + _filename + "," + QString::number(_dimension) + ", " + QString::number(_id) + tr(" ) called by Core") );
203  }
204  }
205 
206  emit addTexture(_textureName , _filename,_dimension,_id);
207 }
208 
212 void Core::slotAddTexture( QString _textureName , QString _filename, uint _dimension) {
213 
214  if (QThread::currentThread() != QApplication::instance()->thread())
215  {
216  //execute method in main thread
217  QMetaObject::invokeMethod(this,"slotAddTexture",Qt::BlockingQueuedConnection, Q_ARG(QString, _textureName), Q_ARG(QString, _filename), Q_ARG(uint, _dimension));
218  return;
219  }
220 
221  if ( OpenFlipper::Options::doSlotDebugging() ) {
222  if ( sender() != 0 ) {
223  if ( sender()->metaObject() != 0 ) {
224  emit log(LOGINFO,"slotAddTexture( " + _textureName + "," + _filename + "," + QString::number(_dimension) + tr(" ) called by ") +
225  QString( sender()->metaObject()->className() ) );
226  }
227  } else {
228  emit log(LOGINFO,"slotAddTexture( " + _textureName + "," + _filename + "," +", " + QString::number(_dimension) + tr(" ) called by Core") );
229  }
230  }
231 
232  emit addTexture(_textureName , _filename,_dimension);
233 }
234 
238 void Core::slotUpdateTexture( QString _name , int _identifier){
239 
240  if ( OpenFlipper::Options::doSlotDebugging() ) {
241  if ( sender() != 0 ) {
242  if ( sender()->metaObject() != 0 ) {
243  emit log(LOGINFO,"slotUpdateTexture( " + _name + " , " + QString::number(_identifier) + tr(" ) called by ") +
244  QString( sender()->metaObject()->className() ) );
245  }
246  }
247  }
248 
249  emit updateTexture(_name, _identifier);
250 }
251 
252 void Core::slotMultiTextureAdded( QString _textureGroup , QString _name , QString _filename , int _id , int* _textureId ) {
253  slotMultiTextureAdded(_textureGroup, _name, _filename, _id, *_textureId);
254 }
255 
256 void Core::slotMultiTextureAdded( QString _textureGroup , QString _name , QString _filename , int _id , int& _textureId ) {
257 
258  if (QThread::currentThread() != QApplication::instance()->thread())
259  {
260  //execute method in main thread
261  QMetaObject::invokeMethod(this,"slotMultiTextureAdded",Qt::BlockingQueuedConnection, Q_ARG(QString, _textureGroup), Q_ARG(QString, _name), Q_ARG(QString, _filename), Q_ARG(int, _id), Q_ARG(int*, &_textureId));
262  return;
263  }
264 
265  if ( OpenFlipper::Options::doSlotDebugging() ) {
266  if ( sender() != 0 ) {
267  if ( sender()->metaObject() != 0 ) {
268  emit log(LOGINFO,"slotMultiTextureAdded( " + _textureGroup + ", " + _name + "," + _filename + "," + QString::number(_id) + tr(" ) called by ") +
269  QString( sender()->metaObject()->className() ) );
270  }
271  } else {
272  emit log(LOGINFO,"slotMultiTextureAdded( " + _textureGroup + ", " + _name + "," + _filename + "," + QString::number(_id) + tr(" ) called by Core") );
273  }
274  }
275 
276  emit addMultiTexture( _textureGroup , _name , _filename , _id , _textureId );
277 }
278 
283  emit updateAllTextures();
284 }
285 
289 void Core::slotSetTextureMode(QString _textureName, QString _mode, int _id) {
290 
291  if ( OpenFlipper::Options::doSlotDebugging() ) {
292  if ( sender() != 0 ) {
293  if ( sender()->metaObject() != 0 ) {
294  emit log(LOGINFO,"slotSetTextureMode( " + _textureName + " , " + _mode + " , " + QString::number(_id) + tr(" ) called by ") +
295  QString( sender()->metaObject()->className() ) );
296  }
297  }
298  }
299 
300  emit setTextureMode(_textureName,_mode,_id);
301 }
302 
306 void Core::slotSetTextureMode(QString _textureName ,QString _mode) {
307 
308  if ( OpenFlipper::Options::doSlotDebugging() ) {
309  if ( sender() != 0 ) {
310  if ( sender()->metaObject() != 0 ) {
311  emit log(LOGINFO,"slotSetTextureMode( " + _textureName + " , " + _mode + tr(" ) called by ") +
312  QString( sender()->metaObject()->className() ) );
313  }
314  }
315  }
316 
317  emit setTextureMode(_textureName,_mode);
318 }
319 
323 void Core::slotTextureUpdated( QString _textureName , int _identifier ) {
324  if ( OpenFlipper::Options::doSlotDebugging() ) {
325  if ( sender() != 0 ) {
326  if ( sender()->metaObject() != 0 ) {
327  emit log(LOGINFO,"slotTextureUpdated( " + _textureName + " , " + QString::number(_identifier) + tr(" ) called by ") +
328  QString( sender()->metaObject()->className() ) );
329  }
330  }
331  }
332  emit updatedTextures(_textureName,_identifier);
333 }
334 
337 void Core::slotSwitchTexture( QString _textureName, int _id ) {
338  emit switchTexture(_textureName, _id);
339 }
340 
343 void Core::slotSwitchTexture( QString _textureName ) {
344  emit switchTexture(_textureName);
345 }
346 
347 
350 void Core::slotTextureChangeImage( QString _textureName , QImage& _image ) {
351  emit textureChangeImage( _textureName ,_image );
352 }
353 
356 void Core::slotTextureChangeImage( QString _textureName , QImage& _image , int _id ) {
357  emit textureChangeImage( _textureName , _image , _id );
358 }
359 
362 void Core::slotTextureGetImage( QString _textureName , QImage& _image ) {
363  emit textureGetImage( _textureName ,_image );
364 }
365 
368 void Core::slotTextureGetImage( QString _textureName , QImage& _image , int _id ) {
369  emit textureGetImage( _textureName , _image , _id );
370 }
371 
374 void Core::slotTextureIndex( QString _textureName, int _id, int& _index){
375  emit textureIndex( _textureName, _id, _index);
376 }
377 
380 void Core::slotTextureIndexPropertyName( int _id, QString& _propertyName){
381  emit textureIndexPropertyName( _id, _propertyName);
382 }
383 
386 void Core::slotTextureName( int _id, int _textureIndex, QString& _textureName){
387  emit textureName( _id, _textureIndex, _textureName);
388 }
389 
392 void Core::slotTextureFilename( int _id, QString _textureName, QString& _textureFilename){
393  emit textureFilename( _id, _textureName, _textureFilename);
394 }
395 
398 void Core::slotGetCurrentTexture( int _id, QString& _textureName ){
399  emit getCurrentTexture( _id, _textureName );
400 }
401 
404 void Core::slotGetSubTextures( int _id, QString _multiTextureName, QStringList& _subTextures ){
405  emit getSubTextures( _id, _multiTextureName, _subTextures );
406 }
407 
408 //========================================================================================
409 // === Object Manager ============================
410 //========================================================================================
411 
413 void Core::newObject(int _objectId) {
414 
415  BaseObject* baseObject = 0;
416  PluginFunctions::getObject(_objectId,baseObject);
417 
418  if ( baseObject ) {
419  connect( baseObject, SIGNAL(visibilityChanged(int)), this, SLOT(slotVisibilityChanged(int)), Qt::DirectConnection) ;
420  connect( baseObject, SIGNAL(objectSelectionChanged(int)), this, SLOT(slotObjectSelectionChanged(int)), Qt::DirectConnection );
421  connect( baseObject, SIGNAL(objectPropertiesChanged(int)), this, SLOT(slotObjectPropertiesChanged(int)), Qt::DirectConnection );
422  } else {
423  emit log(LOGERR,tr("newObject received from objectManager with invalid id! This should not happen. The new Object will not work correctly!"));
424  }
425 
426 }
427 
429 void Core::deletedObject(int /*_objectId*/) {
430 }
431 
432 
433 //========================================================================================
434 // === Cross Plugin connections ============================
435 //========================================================================================
436 void Core::slotCrossPluginConnect( QString _pluginName1, const char* _signal, QString _pluginName2, const char* _slot) {
437  QObject* plugin1 = 0;
438  QObject* plugin2 = 0;
439 
440  for ( int i = 0 ; i < (int)plugins_.size(); ++i ) {
441  if ( plugins_[i].rpcName == _pluginName1 ) {
442  plugin1 = plugins_[i].plugin;
443  }
444  if ( plugins_[i].rpcName == _pluginName2 ) {
445  plugin2 = plugins_[i].plugin;
446  }
447  }
448 
449  if ( plugin1 == 0 ) {
450  emit log(LOGERR,tr("Cross Plugin Interconnection failed because plugin %1 was not found!").arg(_pluginName1));
451  return;
452  }
453 
454  if ( plugin2 == 0 ) {
455  emit log(LOGERR,tr("Cross Plugin Interconnection failed because plugin %1 was not found!").arg(_pluginName2));
456  return;
457  }
458 
459  // now connect them
460  connect(plugin1,_signal,plugin2,_slot);
461 }
462 
463 //========================================================================================
464 // === Renderer Settings ============================
465 //========================================================================================
466 void Core::slotSetRenderer(unsigned int _viewer, QString _rendererName) {
467  renderManager().setActive(_rendererName,_viewer);
468 }
469 
470 void Core::slotGetCurrentRenderer(unsigned int _viewer, QString& _rendererName) {
471  _rendererName = renderManager().active(_viewer)->name;
472 }
473 
474 void Core::slotMetadataDeserialized(
475  const QVector<QPair<QString, QString> > &data) {
476 
477  QString obj_metadata;
478  for (QVector<QPair<QString, QString> >::const_iterator
479  it = data.begin(); it != data.end(); ++it) {
480  if (it->first == "Mesh Comments")
481  obj_metadata = it->second;
482 
483  emit genericMetadataDeserialized(it->first, it->second);
484  }
485 
486  /*
487  * Now handle object metadata.
488  */
489  QRegExp re_begin("BEGIN Comments for object \"([^\\n]*)\"");
490  QRegExp re_end("\\nEND Comments for object \"([^\\n]*)\"");
491  enum STATE {
492  STATE_SEARCH_BEGIN,
493  STATE_CONSUME_INNER,
494  STATE_EOS,
495  };
496 
497  int cursor = 0;
498  QString current_object_name;
499  for (STATE state = STATE_SEARCH_BEGIN; state != STATE_EOS; ) {
500  switch (state) {
501  case STATE_SEARCH_BEGIN:
502  cursor = re_begin.indexIn(obj_metadata, cursor);
503  if (cursor == -1) {
504  state = STATE_EOS;
505  break;
506  }
507  current_object_name = re_begin.cap(1);
508  cursor += re_begin.matchedLength();
509  state = STATE_CONSUME_INNER;
510  break;
511  case STATE_CONSUME_INNER:
512  {
513  int next = re_end.indexIn(obj_metadata, cursor);
514  if (next == -1) {
515  state = STATE_EOS;
516  break;
517  }
518 
519  const QStringRef value = obj_metadata.midRef(cursor, next - cursor);
520 
521  emit objectMetadataDeserialized(current_object_name, value.toString());
522 #if QT_VERSION >= 0x050000
523  QJsonParseError json_error;
524  QJsonDocument json_doc =
525  QJsonDocument::fromJson(value.toUtf8(), &json_error);
526  if (json_error.error == QJsonParseError::NoError) {
527  emit objectMetadataDeserializedJson(
528  current_object_name, json_doc);
529  }
530 #endif
531  cursor = next + re_end.matchedLength();
532  state = STATE_SEARCH_BEGIN;
533  break;
534  }
535  default:
536  throw std::logic_error("metadataDeserialized(): Invalid state.");
537  }
538  }
539 }
540 
541 //=============================================================================
void getCurrentTexture(int _id, QString &_textureName)
get current texture
void objectSelectionChanged(int)
This signal is emitted if the object has been changed (source/target)
void resetScenegraph(bool _resetTrackBall)
void slotObjectSelectionChanged(int _id)
Called by Plugins if they changed the active object.
void updateAllTextures()
Update all textures in the plugins.
RendererInfo * active(int _id)
Get the current active renderer.
void signalObjectUpdated(int)
When this Signal is emitted all Plugins are informed that the object list changed.
void slotMultiTextureAdded(QString _textureGroup, QString _name, QString _filename, int _id, int &_textureId)
Called by a plugin if it creates a multitexture.
std::vector< PluginInfo > plugins_
List of all loaded plugins_.
Definition: Core.hh:1208
void slotGetSubTextures(int _id, QString _multiTextureName, QStringList &_subTextures)
Called by plugins if a multi-texture&#39;s sub textures should be fetched.
void slotGetCurrentTexture(int _id, QString &_textureName)
Called by plugins if current texture should be retrieved.
void textureChangeImage(QString _textureName, QImage &_image)
Change the image for a given texture.
void getSubTextures(int _id, QString _multiTextureName, QStringList &_subTextures)
get a multi-texture&#39;s sub textures
void slotTextureGetImage(QString _textureName, QImage &_image)
Called by plugins if texture image should be fetched.
void textureIndexPropertyName(int _id, QString &_propertyName)
get the texture index property name
void slotTextureIndexPropertyName(int _id, QString &_propertyName)
Called by plugins if texture index property name should be fetched.
bool getObject(int _identifier, BSplineCurveObject *&_object)
void slotUpdateTexture(QString _name, int _identifier)
Tell the plugins to update the given texture.
void slotVisibilityChanged(int _id)
Called when a plugin changes the visibility of an object.
void slotSetRenderer(unsigned int _viewer, QString _rendererName)
called to switch the renderer for a specific viewer
QString updateTypeName(UpdateType _id)
Get the name of a type with given id.
Definition: UpdateType.cc:274
void setTextureMode(QString _textureName, QString _mode, int _id)
A texture mode should be changed.
void slotUpdateAllTextures()
Update all textures in the plugins.
const QStringList ALL_OBJECTS
Iterable object range.
void slotCrossPluginConnect(QString _pluginName1, const char *_signal, QString _pluginName2, const char *_slot)
Called to create inter plugin connections.
void updateTexture(QString, int)
Tell the plugins to update the given texture.
Update type class.
Definition: UpdateType.hh:70
void slotObjectPropertiesChanged(int _id)
Called by plugins if object properties like names have changed.
void textureIndex(QString _textureName, int _id, int &_index)
get the texture index
void objectPropertiesChanged(int _id)
Tell plugins that object properties such as object names have been changed.
void textureGetImage(QString _textureName, QImage &_image)
fetch texture image
void slotSwitchTexture(QString _textureName, int _id)
Tells Plugins to switch to the given Texture.
void addMultiTexture(QString _textureGroup, QString _name, QString _filename, int _id, int &_textureId)
The texture with the given name and filename has been added.
const DataType DATA_ALL(UINT_MAX)
Identifier for all available objects.
void slotTextureName(int _id, int _textureIndex, QString &_textureName)
Called by plugins if texture name should be fetched.
void updateView()
Called when a plugin requests an update in the viewer.
Definition: Core.cc:887
void slotGetCurrentRenderer(unsigned int _viewer, QString &_rendererName)
called to get the currently active renderer renderer for a specific viewer
void addTexture(QString, QString, uint, int)
The texture with the given name and filename has been added.
void log(Logtype _type, QString _message)
Logg with OUT,WARN or ERR as type.
void newObject(int _objectId)
This slot is called by the object manager when a new object is created.
void slotTextureIndex(QString _textureName, int _id, int &_index)
Called by plugins if texture index should be fetched.
void slotTextureUpdated(QString _textureName, int _identifier)
A Texture has been updated.
void slotObjectUpdated(int _identifier, const UpdateType &_type=UPDATE_ALL)
Called by the plugins if they changed something in the object list (deleted, added, or other property changes)
void setActive(unsigned int _active, int _id)
set the active renderer
void switchTexture(QString, int)
Switch Texture Plugins to a given Mode.
void slotAddTexture(QString _textureName, QString _filename, uint _dimension, int _id)
Called by a plugin if it creates a texture.
void visibilityChanged(int _id)
Tell plugins that the visibility of an object has changed.
void deletedObject(int _objectId)
This slot is called by the object manager when an object is deleted.
void slotTextureFilename(int _id, QString _textureName, QString &_textureFilename)
Called by plugins if texture name should be fetched.
const UpdateType UPDATE_STATE(UpdateTypeSet(1)<< 12)
State has changed.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void slotSetTextureMode(QString _textureName, QString _mode, int _id)
A texture mode should be changed.
void textureFilename(int _id, QString _textureName, QString &_textureFilename)
get the texture&#39;s filename
QString name
Name of the plugin ( requested from the plugin on load)
Definition: RendererInfo.hh:77
void slotTextureChangeImage(QString _textureName, QImage &_image)
Called by plugins if texture image should be changed.
void updatedTextures(QString, int)
This Signal is send to the plugins if a texture has been updated.
void textureName(int _id, int _textureIndex, QString &_textureName)
get the texture name