Developer Documentation

Base Interface

The BaseInterface has to be used by every plugin in OpenFlipper. As the minimum a plugin has to implement the BaseInterface::name() and BaseInterface::description() functions from this interface.

To use the BaseInterface:

- include BaseInterface.hh in your plugins header file
- derive your plugin from the class BaseInterface
- add Q_INTERFACES(BaseInterface) to your plugin class
- And add the signals or slots you want to use to your plugin class (You don't need to implement all of them except BaseInterface::description() and BaseInterface::name() )

# Plugin Initialization

The OpenFlipper startup process consists of several steps, which are shown in this image:

OpenFlipper first starts its core system. Therefore it loads the settings, parses command line options and initializes the QT library. Afterwards the object and scenegraph management are initialized. The next step creates the core user interface and the logging system. Now the plugins are loaded in the following way:

1. All the plugins are loaded into memory.
2. For each plugin, the interfaces get connected to the plugin and afterwards the BaseInterface::initializePlugin() function is called. (Here you can setup your internal variables). After execution of this slot your plugin should be fully functional. Only gui elements may be uninitialized and should be created in BaseInterface::pluginsInitialized(). The order how plugins are loaded is not fixed. So you should not rely or communicate with other plugins in this slot.
3. For each plugin the BaseInterface::pluginsInitialized() function is called. Here you can setup your gui elements and start sending signals to the core.
4. For each plugin the INIInterface::loadIniFileOptions() slot is called (if the interface is implemented). This slot can be used to load additional options from INI files. (DEPRECATED! Use the OpenFlipperSettings() class instead)

Note
  - Do not create objects via addEmpty or load objects during OpenFlipper startup, as the rendering system is not ready yet!
  - The ini interface is deprecated for loading or storing plugin options. Please use OpenFlipperSettings() instead.

Afterwards the plugin initialization is complete and the core sets up the final gui.

# Object Update Notification

The objects in OpenFlippers scene are stored and managed in OpenFlippers core. If a plugin changes one of the objects, it has to notify the core about that change. In turn OpenFlipper will then notify all other plugins about this change. This functionality is provided by the signals and slots for update handling .

## General update notifications

If you change data you have to emit one of BaseInterface::updatedObject(int) or BaseInterface::updatedObject(int,const UpdateType&).
BaseInterface::updatedObject(int) forces an update of the whole object while BaseInterface::updatedObject(int,const UpdateType&) can be restricted to a part of the object ( Geometry,Selection, ... ; see UpdateType ) and is therefore faster and should be preferred.

Both signals get the id of the object that has been updated or -1 if all should be updated( you should not use -1 if you know what object changed!).

If the signal is emitted, the core calls BaseInterface::slotObjectUpdated( int , const UpdateType& ) of every plugin. You can implement this slot if you need to react on object changes.

Note
  Don't emit updatedObject from within slotObjectUpdated as this will cause an endless loop!
  If the object id passed to the functions is -1 all objects should be treated as updated.

After all plugins have been informed, the node itself gets updated. This means that for the corresponding object the update function is called (BaseObjectData::update() ). This function is implemented by every object type in OpenFlipper and has to take care of reacting to modifications of the object. E.g. the TriMeshObject, this could mean, that the OpenMesh data has changed (UPDATE_GEOMETRY). The object would than trigger an update of the rendering buffers which are used to draw the mesh.

Note
  You should not call the update functions of an object directly as this means unnecessary overhead (As the core will call the function anyway on an update).

For more details about the UpdateType read the documentation about UpdateType and predefined update types. A description for adding custom update types at runtime is available here.

Note
  If you do not specify an UpdateType, it will fall back to the default value UPDATE_ALL for compatibility reasons which actually updates each of the types. Unless it is really necessary this should generally be avoided since it consumes a lot of computation time. So try to narrow the updated properties as uch as possible!

## Node updates

It is also possible to insert custom nodes into the scenegraph. If you changed these nodes, you also have to inform the core. This is achieved by the BaseInterface::nodeVisibilityChanged() function. As nodes are usually attached to objects in the scene, you should pass the id of the object to the function or -1 if its a global node.

## Object Removal notifications

If the complete scene gets cleared, the slot BaseInterface::slotAllCleared() will be executed after all objects have been removed from the scene. A more fine grained information about objects added or removed from the scene is available via the Load/Save Interface .

## Special Notifications

There are three additional slots that are called by the core, if the object selection(source/target BaseInterface::slotObjectSelectionChanged() ), the object visibility(Show/Hide BaseInterface::slotVisibilityChanged()) or other properties changed (e.g. name BaseInterface::slotObjectPropertiesChanged() )

# Scene Update Notifications

OpenFlipper manages the scene updates in its core. If objects get updated the scene will be automatically redrawn. Nevertheless, you can force an update of the scene by emitting the signal BaseInterface::updateView(). OpenFlipper restricts the number of redraws to avoid useless updates. In the Options you can set a maximal frame rate or disable the restriction. The following image shows how the updates process is managed:

If the view (viewer position /viewing direction) has been changed, the slot BaseInterface::slotViewChanged() will be called, before anything gets rendered. If you need to modify renderings or anything else depending on the current view, you can use this slot and adapt to the new view (e.g. modifying a shader).

Note
  Be careful, not to change the view in this function or you get an endless loop! After the complete scene has been drawn, the core will inform the plugins via the BaseINterface::slotSceneRedrawn().

# Management Functions

There are some basic functions for managing plugins. The BaseInterface::description() function can be used to provide a description for the plugin which will be printed along with the plugin name. The BaseInterface::name() function has to return the name of the plugin. This name will also be used inside the scripting system. Additionally it is possible to provide a plugin version number with BaseInterface::version().

OpenFlippers scripting system can use all public slots defined in your plugin. If it should also provide a small text description for your functions, you could set them with BaseInterface::setSlotDescription(). Even if you do not implement scripting functions in your plugin, the core will then be able to provide this information to the user.

Along with the scripting, OpenFlipper provides a batch mode, running without any user interface. If your plugin will work without an user interface (e.g. only scripting functions), you can define a slot BaseInterface::noguiSupported(). This empty slot is used to tell the core, that the plugin can work in batch mode. Otherwise it will not be loaded when running a batch file.