Commit c21dc183 authored by Jan Möbius's avatar Jan Möbius

Documentation on scene update

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@13791 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 3b91c9ac
......@@ -351,6 +351,8 @@ The objects in OpenFlippers scene are stored and managed in OpenFlippers core. I
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 \ref BaseInterfaceUpdateSlots "update handling" .
\subsection baseInterfacegeneralObjectUpdates General update notifications
\image html ObjectUpdateNotification.png
If you change data you have to emit one of BaseInterface::updatedObject(int) or BaseInterface::updatedObject(int,const UpdateType&).
......@@ -363,36 +365,43 @@ Both signals get the id of the object that has been updated or -1 if all should
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!
\note If the object id passed to the functions is -1 all objects should be treated as updated.
After all plugins have been informed, the scene will be redrawn.
For more details about the UpdateType read the documentation about UpdateType and \ref DefaultUpdateTypes "predefined update types".
A description for adding custom update types at runtime is available \ref UpdateTypeFunctions "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!
\subsection baseInterfaceNodeUpdates 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 they 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 (which should not be used!).
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.
\subsection baseInterfaceObjectRemoval 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 \ref loadSaveInterfacePage .
\subsection baseInterfaceSpecialNotifications 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() )
Remarks:
<ul>
<li>If the object id passed to the functions is -1 all objects should be treated as updated.
<li>Never emit the signal BaseInterface::updatedObject() inside the updated object slots as this causes endless loops!
</ul>
\section baseInterfaceSceneUpdateNotification 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().
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:
\image html updateView.jpg
\image html SceneViewUpdate.png
If the view (viewer position /viewing direction) has been changed, the slot BaseInterface::slotViewChanged() will be called. Be carefull, not to
change the view in this function or you get an endless loop!
If the view (viewer position /viewing direction) has been changed, the slot BaseInterface::slotViewChanged() will be called. 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!
\section baseInterfaceManagementFunctions Management Functions
There are some basic functions for managing plugins. The BaseInterface::description() function can be used
......
......@@ -818,47 +818,46 @@ Core::slotAddHiddenPickMode( const std::string& _mode ) {
/** Update the view in the examiner widget
*/
void Core::updateView() {
void Core::updateView()
{
if ( OpenFlipper::Options::doSlotDebugging() ) {
if ( sender() != 0 ) {
if ( sender()->metaObject() != 0 ) {
emit log(LOGINFO,tr("updateView() called by ") + QString( sender()->metaObject()->className() ) );
if (OpenFlipper::Options::doSlotDebugging()) {
if (sender() != 0) {
if (sender()->metaObject() != 0) {
emit log(LOGINFO, tr("updateView() called by ") + QString(sender()->metaObject()->className()));
}
}
}
if ( !OpenFlipper::Options::gui() )
if (!OpenFlipper::Options::gui())
return;
if ( OpenFlipperSettings().value("Core/Gui/glViewer/restrictFrameRate",false).toBool() ) {
int elapsed = redrawTime_->elapsed ();
if (OpenFlipperSettings().value("Core/Gui/glViewer/restrictFrameRate", false).toBool()) {
int elapsed = redrawTime_->elapsed();
if ( elapsed < 1000 / OpenFlipperSettings().value("Core/Gui/glViewer/maxFrameRate",35).toInt() )
{
if (elapsed < 1000 / OpenFlipperSettings().value("Core/Gui/glViewer/maxFrameRate", 35).toInt()) {
// redraw time not reached ... waiting for timer event for next redraw
if ( redrawTimer_->isActive() ) {
if ( OpenFlipper::Options::doSlotDebugging() )
emit log(LOGINFO,tr("Too early for redraw! Delaying request from ") +
QString( sender()->metaObject()->className() ) );
if (redrawTimer_->isActive()) {
if (OpenFlipper::Options::doSlotDebugging())
emit log(LOGINFO,
tr("Too early for redraw! Delaying request from ") + QString(sender()->metaObject()->className()));
return;
}
// Start the timer
redrawTimer_->start( (1000 / OpenFlipperSettings().value("Core/Gui/glViewer/maxFrameRate",35).toInt() ) - elapsed);
redrawTimer_->start((1000 / OpenFlipperSettings().value("Core/Gui/glViewer/maxFrameRate", 35).toInt()) - elapsed);
return;
}
else if ( redrawTimer_->isActive() )
redrawTimer_->stop ();
} else if (redrawTimer_->isActive())
redrawTimer_->stop();
}
redrawTime_->restart ();
redrawTime_->restart();
if ( !OpenFlipper::Options::loadingSettings() && !OpenFlipper::Options::redrawDisabled() ) {
if (!OpenFlipper::Options::loadingSettings() && !OpenFlipper::Options::redrawDisabled()) {
for ( unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i )
for (unsigned int i = 0; i < OpenFlipper::Options::examinerWidgets(); ++i)
coreWidget_->examiner_widgets_[i]->updateGL();
}
}
......
......@@ -55,7 +55,7 @@
*
* \subsection ref5 References:
* \ref BaseInterface::updateView(),<br>
* \image html updateView.jpg
* \image html SceneViewUpdate.png
*
*/
......@@ -6,6 +6,10 @@
* - \ref plugin_startup
* - \ref plugin_prog_sec
* - \ref plugin_prog_geometryData
* - \ref addingEmptyObjects
* - \ref LoadingExistingObjects
* - \ref RemovingObjectsFromScene
* - \ref modifyingObjects
* \section tuts Tutorials
* - \ref ex1
* - \ref ex1c
......@@ -125,68 +129,17 @@
* from within a plugin. In our tutorial \ref ex2 we roughly mentioned that the communication between OpenFlipper
* and it's plugins is accomplished through either one of the provided \ref interfaces or the \ref PluginFunctions.
*
* \subsection updatingObjects Updating objects
* \section modifyingObjects Modifying Objects in OpenFlipper
* In the previous section we got objects from OpenFlippers object management system. These objects directly contain
* data in their original data structure (e.g. a pointer to an OpenMesh). In your plugin you can modify this data
* directly in the data structure. For a mesh, you can for example add new faces or remove faces,... . After you modified
* data, you have to inform OpenFlippers core system (and thereby the other plugins) what you did.
*
* Once your plugin has manipulated object data we have to inform OpenFlipper's core about the changes.
* When doing this, OpenFlipper distinguishes between five basic types of changes:
* This information system is implemented in the BaseInterface. Additional information can be found here: \ref baseInterfaceObjectUpdateNotification
*
* - Object selections
* - Visibility
* - Geometry
* - Topology
* - Selections (Vertices, Edges, Faces)
*
* When changing geometry, OpenFlipper's core will be forced to redraw the object that has been
* changed by emitting signal
*
* \ref BaseInterface::updatedObject(int _id, UpdateType _type)
*
* where \c _id is the object's id and _type is the type of changes that have been made.
* Note: UpdateType offers the following values
*
* - UPDATE_ALL
* - UPDATE_OBJECT_SELECTION
* - UPDATE_VISIBILITY
* - UPDATE_GEOMETRY
* - UPDATE_TOPOLOGY
* - UPDATE_SELECTION (ALL THREE KINDS)
* - UPDATE_SELECTION_VERTICES
* - UPDATE_SELECTION_EDGES
* - UPDATE_SELECTION_FACES
* - UPDATE_UNUSED
*
* If the second parameter of this signal is not specified, 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.
*
* Additionally, when overriding the slot BaseInterface::slotObjectUpdated(int, const UpdateType),
* a plugin receives the updated object's id (first parameter) and the type
* of changes (second parameter).
*
* See \ref BaseInterface for more information.
*
* When changing object properties it won't be necessary to redraw the scene
* since it can be expensive in computation power. In this case, one should emit
*
* \ref BaseInterface::objectPropertiesChanged(int _id)
*
* where \c _id once again is the object's id.
*
* If a plugin changed an object's visibility (hide, show), it should emit
*
* \ref BaseInterface::visibilityChanged(int _id)
*
* for the core to update the visibility state of object with identifier \c _id.
*
* Last, when changing an object's selection, it
* will be updated by emitting
*
* \ref BaseInterface::objectSelectionChanged(int _id)
*
* where \c _id as in the examples above is the object's identifier.
*
* Also see \ref BaseInterface.
* \section sceneUpdate Updating the current view
* If you modified an object and informed the core that the object has changed, the scene will be automatically redrawn. A more detailed description
* can be found in the BaseInterface: \ref baseInterfaceSceneUpdateNotification
*
* \section pluginProgramming_related_pages Related pages
* - \subpage pluginExamples
......
% This file describes how the scene updates are handled in OpenFlipper
% Author: Jan Möbius
\tikzstyle{abstract}=[rectangle, draw=black, rounded corners, fill=blue!30!white, drop shadow,
text centered, text=black, text width=7cm]
\tikzstyle{timernode}=[rectangle, draw=black, rounded corners, fill=blue!10!white, drop shadow,
text centered, text=black, text width=3cm]
\tikzstyle{flow}=[->, >= triangle 90, very thick]
\tikzstyle{CoreGroup} = [fill=orange!30!white,rectangle,rounded corners,draw,inner sep =0.4cm]
\tikzstyle{PluginGroup} = [fill=orange!50!white,rectangle,rounded corners,draw,inner sep =0.4cm]
\begin{center}
\begin{tikzpicture}[node distance=1cm]
\node (signalUpdatedObject) [abstract, rectangle ]
{
\textbf{signal BaseInterface::updatedObject()}
};
\node (Plugins) [above=of signalUpdatedObject,yshift=-0.3cm] {\textbf{\huge{OpenFlipper Plugins}} };
\node (signalUpdateView) [abstract, rectangle, below= of signalUpdatedObject ]
{
\textbf{signal BaseInterface::updateView()}
};
\node (coreUpdateHandling) [abstract, rectangle, left= of signalUpdateView, xshift=-2cm ]
{
\textbf{Update Handling}
};
\node (AuxNode) [above=of coreUpdateHandling]{};
\node (Core) [above=of coreUpdateHandling ,yshift=1.3cm] {\textbf{\huge{OpenFlipper Core}} };
\node (redraw) [abstract, rectangle, below= of coreUpdateHandling , yshift=-2cm]
{
\textbf{Redraw Scene}
};
\node (timer) [timernode, rectangle, above= of redraw,xshift=-2cm]
{
\textbf{Redraw Timer}
};
\node [label=above:emitted] (X) at ($ (coreUpdateHandling)!.5!(signalUpdateView) $) {};
\node [label=above:emitted] (X) at ($ (AuxNode)!.5!(signalUpdatedObject) $) {};
\node [label=right:update time reached] (X) at ($ (coreUpdateHandling)!.57!(redraw) $) {};
\node [label=left:too many updates] (X) at ($ (coreUpdateHandling)!.4!(timer) $) {};
\draw[flow] (signalUpdatedObject.west) -- ++(0,0) -| (coreUpdateHandling.north);
\draw[flow] (coreUpdateHandling.south) -- ++(0,0) -| (redraw.north);
\draw[flow] (coreUpdateHandling.south) -- ++(0,-0.9) -| (timer.north);
\draw[flow] (signalUpdateView.west) -- ++(0,0) |- (coreUpdateHandling.east);
\draw[flow] (timer.south) -- ++(0,-0.4) -| (redraw.north);
\begin{pgfonlayer}{background}
\node[CoreGroup,fit=(Core) (redraw) ] (Core) {};
\node[PluginGroup,fit=(Plugins) (signalUpdateView) ] (Plugin) {};
\end{pgfonlayer}
\end{tikzpicture}
\end{center}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment