/*! \page adding_empty_objects Adding empty Objects in a plugin
\section adding_empty_objects_overview Overview
OpenFlipper provides a set of datatypes (\ref datatypes_integrated ). While the load and save functions
automatically generate objects for the loaded data, it is also useful to generate objects of a specific datatype and
fill them with custom data. This page describes how a plugin can create a new object.

\section adding_empty_objects_creating Creating a new object

Your plugin has to implement a part of the \ref loadSaveInterfacePage.
So you have to derive from that interface and add the LoadSaveInterface::addEmptyObject  signal to your plugin:

\code

//includes
#include <OpenFlipper/BasePlugin/LoadSaveInterface.hh>
...


class ExamplePlugin::QObject, ... , LoadSaveInterface, ...
{
  Q_OBJECT
  Q_INTERFACES(BaseInterface)
  ...
  Q_INTERFACES(LoadSaveInterface)

signals:
  // LoadSaveInterface
  void addEmptyObject( DataType _type, int& _id);

...
\endcode

To generate the object you can implement the following in one of your functions:

\code
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>

void ExamplePlugin::exampleFunction() {
  // Variable which will store the id of the newly created object.
  int newObjectId = -1;

  // Emit the signal, that we want to create a new object of the specified type plane
  emit addEmptyObject(DATA_PLANE, newObjectId);

  // Get the newly created object
  PlaneObject* object = 0;
  PluginFunctions::getObject(newObjectId,object);

  if(object) {

      // Now you can use the object as usual, e.g. Get the node
      PlaneNode* planeNode = object->planeNode();

      // change it
      planeNode->setPosition(origin,normal);
      planeNode->setSize(kinectinfo_->getMaxDepth() / 2, kinectinfo_->getMaxDepth() / 2);

      // ...

  } else {
    // Something went wrong when creating the object.
  }

}
\endcode
Note, that the LoadSaveInterface::addEmptyObject signal is connected using a Qt::DirectConnection and immediately returns the ID of your new object. 
Of course you have to add the includes for the ObjectTypes you want to use to your list of includes. A list of available
ObjectTypes can be found here: \ref datatypes

\section qt_signals Qt Signals

As mentioned above, new objects are  created by emitting the LoadSaveInterface::addEmptyObject signal (more information on Qt signals http://doc.qt.io/qt-5/signalsandslots.html). In addition to that another signal is emitted, to inform other plugins about the new object. This signal is connected with a Qt::QueuedConnection which means, that it will be pushed to the Event-Queue of Qt. This allows other plugins to process the new object, e.g. create and add textures for it.
However, after the line "emit addEmptyObject(DATA_PLANE, newObjectId);" from the above example, there may be plugins that have not yet processed this information, which may cause problems if they change properties you want to set. To avoid such problems you can inject a new signal to the Event-Queue, because the Event-Queue is processed in order.

Example: YourPlugin.hh:
\code
signals:

[...]

// LoadSaveInterface
void addEmptyObject( DataType _type, int& _id);

//use this signal to make sure addEmptyObject was processed.
void doStuff(IdList);

[...]

slots:

[...]

void slotDoStuff(IdList _ist);

[...]
\endcode

YourPlugin.cc:
\code
void YourPlugin::pluginsInitialized()
{
  [...]
  connect(this, SIGNAL(doStuff(IdList)), this, SLOT(slotDoStuff(IdList)), Qt::QueuedConnection);
}

[...]

void YourPlugin::slotDoStuff(IdList _list)
{
  // You can use whatever plugin you want with your object now  
  // All others have finished processing addEmptyObject
  RPC::callFunctionValue<int>("datacontrol","groupObjects", _list, QString("test_group"));
}

void YourPlugin::createLotsOfObjects()
{
  //create lots of empty objects by emitting 
  // addEmptyObject or calling the porimitive generator e.g.
  IdList ids;
  ids.push_back( RPC::callFunctionValue<int>("primitivesgenerator","addCube",Vector(1.0f),4.0d));
  ids.push_back( RPC::callFunctionValue<int>("primitivesgenerator","addCube",Vector(2.0f),4.0d));

  // Now use your own signal to make sure the previous signal was consumed by all plugins
  // since the connection for this signal is Qt::QueuedConnection,
  // it will be inserted at the end of the event queue. and events are processed in order
  emit doStuff(ids);

}
\endcode

*/
