--- /dev/null
+#ifndef DALI_INTERNAL_SCENE_GRAPH_OBJECT_OWNER_CONTAINER
+#define DALI_INTERNAL_SCENE_GRAPH_OBJECT_OWNER_CONTAINER
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/update/common/discard-queue.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class UpdateManager;
+
+/**
+ * ObjectOwnerContainer is an object which owns SceneGraph Objects.
+ * It is responsible for ensuring they are placed on a discard queue
+ * when removed from the container.
+ */
+template< class TypePointer >
+class ObjectOwnerContainer
+{
+public:
+ typedef typename Internal::OwnerContainer< TypePointer > ObjectContainer;
+ typedef typename Internal::OwnerContainer< TypePointer >::Iterator Iterator;
+
+ /**
+ * @brief Constructor - createw a new object container
+ *
+ * Object container own update side objects
+ *
+ * @param[in] sceneGraphBuffers Helper to get the correct buffer index
+ * @param[in] discardQueue Queue to discard objects that might still be in use in the render thread.
+ **/
+ ObjectOwnerContainer( SceneGraphBuffers& sceneGraphBuffers, DiscardQueue& discardQueue )
+ : mSceneGraphBuffers( sceneGraphBuffers ),
+ mDiscardQueue( discardQueue )
+ {
+ }
+
+ /**
+ * @brief Add an object to the owner
+ *
+ * @param[in] object Pointer to the object that will be owned
+ **/
+ void Add( TypePointer object )
+ {
+ mObjectContainer.PushBack( object );
+ }
+
+ /**
+ * @brief Remove an object from the owner.
+ *
+ * The object is put on the discard queue.
+ *
+ * @param[in] object Pointer to the object to be removed
+ **/
+ void Remove( TypePointer object )
+ {
+ DALI_ASSERT_DEBUG( object != NULL);
+
+ // Find the object
+ for( Iterator iter = mObjectContainer.Begin(); iter != mObjectContainer.End(); ++iter )
+ {
+ TypePointer current = *iter;
+ if ( current == object )
+ {
+ // Transfer ownership to the discard queue
+ // This keeps the object alive, until the render-thread has finished with it
+ mDiscardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), mObjectContainer.Release( iter ) );
+
+ return;
+ }
+ }
+
+ // Should not reach here
+ DALI_ASSERT_DEBUG(false);
+ }
+
+ /**
+ * @brief Method to call ResetToBaseValues on all the objects owned.
+ *
+ * @param[in] bufferIndex Buffer index for double buffered values.
+ **/
+ void ResetToBaseValues( BufferIndex bufferIndex )
+ {
+ for ( Iterator iter = mObjectContainer.Begin(); iter != mObjectContainer.End(); ++iter)
+ {
+ TypePointer object = (*iter);
+ object->ResetToBaseValues( bufferIndex );
+ }
+ }
+
+ /**
+ * @brief Method to call ConstrainObjects on all the objects owned.
+ *
+ * @param[in] bufferIndex Buffer index for double buffered values.
+ **/
+ unsigned int ConstrainObjects( BufferIndex bufferIndex )
+ {
+ unsigned int numberOfConstrainedObjects = 0;
+
+ for ( Iterator iter = mObjectContainer.Begin(); iter != mObjectContainer.End(); ++iter)
+ {
+ TypePointer object = (*iter);
+ numberOfConstrainedObjects += ConstrainPropertyOwner( *object, bufferIndex );
+ }
+ return numberOfConstrainedObjects;
+ }
+
+private:
+ ObjectContainer mObjectContainer; ///< Container for the objects owned
+ SceneGraphBuffers& mSceneGraphBuffers; ///< Reference to a SceneGraphBuffers to get the indexBuffer
+ DiscardQueue& mDiscardQueue; ///< Discard queue used for removed objects
+};
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_OBJECT_OWNER_CONTAINER
#include <dali/internal/update/animation/scene-graph-animation.h>
#include <dali/internal/update/common/discard-queue.h>
#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/internal/update/common/scene-graph-property-buffer.h>
#include <dali/internal/update/controllers/render-message-dispatcher.h>
#include <dali/internal/update/controllers/scene-controller-impl.h>
#include <dali/internal/update/effects/scene-graph-material.h>
+#include <dali/internal/update/effects/scene-graph-sampler.h>
#include <dali/internal/update/geometry/scene-graph-geometry.h>
#include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
+#include <dali/internal/update/manager/object-owner-container.h>
#include <dali/internal/update/manager/prepare-render-algorithms.h>
#include <dali/internal/update/manager/process-render-tasks.h>
#include <dali/internal/update/manager/sorted-layers.h>
} //namespace
-typedef OwnerContainer< Geometry* > GeometryContainer;
-typedef GeometryContainer::Iterator GeometryIter;
-typedef GeometryContainer::ConstIterator GeometryConstIter;
-
-typedef OwnerContainer< Material* > MaterialContainer;
-typedef MaterialContainer::Iterator MaterialIter;
-typedef MaterialContainer::ConstIterator MaterialConstIter;
-
typedef OwnerContainer< Shader* > ShaderContainer;
typedef ShaderContainer::Iterator ShaderIter;
typedef ShaderContainer::ConstIterator ShaderConstIter;
systemLevelTaskList ( completeStatusManager ),
root( NULL ),
systemLevelRoot( NULL ),
+ geometries( sceneGraphBuffers, discardQueue ),
+ materials( sceneGraphBuffers, discardQueue ),
+ samplers( sceneGraphBuffers, discardQueue ),
+ propertyBuffers( sceneGraphBuffers, discardQueue ),
messageQueue( renderController, sceneGraphBuffers ),
dynamicsChanged( false ),
keepRenderingSeconds( 0.0f ),
AnimationContainer animations; ///< A container of owned animations
PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
- GeometryContainer geometries; ///< A container of geometries
- MaterialContainer materials; ///< A container of materials
+ ObjectOwnerContainer<Geometry*> geometries; ///< A container of geometries
+ ObjectOwnerContainer<Material*> materials; ///< A container of materials
+ ObjectOwnerContainer<Sampler*> samplers; ///< A container of samplers
+ ObjectOwnerContainer<PropertyBuffer*> propertyBuffers; ///< A container of property buffers
ShaderContainer shaders; ///< A container of owned shaders
propertyNotification->SetNotifyMode( notifyMode );
}
-
-void UpdateManager::AddGeometry( Geometry* geometry )
+ObjectOwnerContainer<Geometry*>& UpdateManager::GetGeometryOwner()
{
- DALI_ASSERT_DEBUG( NULL != geometry );
- mImpl->geometries.PushBack( geometry );
+ return mImpl->geometries;
}
-void UpdateManager::RemoveGeometry( Geometry* geometry )
+ObjectOwnerContainer<Material*>& UpdateManager::GetMaterialOwner()
{
- DALI_ASSERT_DEBUG(geometry != NULL);
-
- GeometryContainer& geometries = mImpl->geometries;
-
- // Find the geometry and destroy it
- for ( GeometryIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
- {
- Geometry& current = **iter;
- if ( ¤t == geometry )
- {
- // Transfer ownership to the discard queue
- // This keeps the geometry alive, until the render-thread has finished with it
- mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), geometries.Release( iter ) );
-
- return;
- }
- }
-
- // Should not reach here
- DALI_ASSERT_DEBUG(false);
+ return mImpl->materials;
}
-void UpdateManager::AddMaterial( Material* material )
+ObjectOwnerContainer<Sampler*>& UpdateManager::GetSamplerOwner()
{
- DALI_ASSERT_DEBUG( NULL != material );
-
- mImpl->materials.PushBack( material );
+ return mImpl->samplers;
}
-void UpdateManager::RemoveMaterial( Material* material )
+ObjectOwnerContainer<PropertyBuffer*>& UpdateManager::GetPropertyBufferOwner()
{
- DALI_ASSERT_DEBUG(material != NULL);
-
- MaterialContainer& materials = mImpl->materials;
-
- // Find the material and destroy it
- for ( MaterialIter iter = materials.Begin(); iter != materials.End(); ++iter )
- {
- Material& current = **iter;
- if ( ¤t == material )
- {
- // Transfer ownership to the discard queue
- // This keeps the material alive, until the render-thread has finished with it
- mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), materials.Release( iter ) );
-
- materials.Erase(iter);
- return;
- }
- }
- // Should not reach here
- DALI_ASSERT_DEBUG(false);
+ return mImpl->propertyBuffers;
}
void UpdateManager::AddShader( Shader* shader )
{
PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
+ BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
// Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
mImpl->animationFinishedDuringUpdate = false;
for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
{
Node* node = *iter;
- node->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ node->ResetToBaseValues( bufferIndex );
node->SetActive( false );
// Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
{
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ (*iter)->ResetToBaseValues( bufferIndex );
}
// Reset render-task list properties to base values.
for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
{
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ (*iter)->ResetToBaseValues( bufferIndex );
}
// Reset custom object properties to base values
for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
{
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ (*iter)->ResetToBaseValues( bufferIndex );
}
- // Reset animatable material properties to base values
- for (MaterialIter iter = mImpl->materials.Begin(); iter != mImpl->materials.End(); ++iter)
- {
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
- }
+ mImpl->materials.ResetToBaseValues( bufferIndex );
+ mImpl->geometries.ResetToBaseValues( bufferIndex );
+ mImpl->propertyBuffers.ResetToBaseValues( bufferIndex );
+ mImpl->samplers.ResetToBaseValues( bufferIndex );
- // Reset animatable geometry properties to base values
- for (GeometryIter iter = mImpl->geometries.Begin(); iter != mImpl->geometries.End(); ++iter)
- {
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
- }
// Reset animatable shader properties to base values
for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
{
- (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ (*iter)->ResetToBaseValues( bufferIndex );
}
PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
{
PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
+ BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
mImpl->activeConstraints = 0;
// constrain custom objects... (in construction order)
for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
{
PropertyOwner& object = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->activeConstraints += ConstrainPropertyOwner( object, bufferIndex );
}
// constrain nodes... (in Depth First traversal order)
if ( mImpl->root )
{
- mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), bufferIndex );
}
if ( mImpl->systemLevelRoot )
{
- mImpl->activeConstraints += ConstrainNodes( *(mImpl->systemLevelRoot), mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->activeConstraints += ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
}
// constrain other property-owners after nodes as they are more likely to depend on a node's
for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
{
RenderTask& task = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->activeConstraints += ConstrainPropertyOwner( task, bufferIndex );
}
// Constrain render-tasks
for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
{
RenderTask& task = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->activeConstraints += ConstrainPropertyOwner( task, bufferIndex );
}
// Constrain Materials and geometries
- MaterialContainer& materials = mImpl->materials;
- for ( MaterialIter iter = materials.Begin(); iter != materials.End(); ++iter )
- {
- Material& material = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( material, mSceneGraphBuffers.GetUpdateBufferIndex() );
- }
-
- GeometryContainer& geometries = mImpl->geometries;
- for ( GeometryIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
- {
- Geometry& geometry = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( geometry, mSceneGraphBuffers.GetUpdateBufferIndex() );
- }
+ mImpl->activeConstraints += mImpl->materials.ConstrainObjects( bufferIndex );
+ mImpl->activeConstraints += mImpl->geometries.ConstrainObjects( bufferIndex );
+ mImpl->activeConstraints += mImpl->samplers.ConstrainObjects( bufferIndex );
+ mImpl->activeConstraints += mImpl->propertyBuffers.ConstrainObjects( bufferIndex );
// constrain shaders... (in construction order)
ShaderContainer& shaders = mImpl->shaders;
for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
{
Shader& shader = **iter;
- mImpl->activeConstraints += ConstrainPropertyOwner( shader, mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->activeConstraints += ConstrainPropertyOwner( shader, bufferIndex );
}
PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
PropertyNotificationIter iter = notifications.Begin();
+ BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
while ( iter != notifications.End() )
{
PropertyNotification* notification = *iter;
-
- bool valid = notification->Check( mSceneGraphBuffers.GetUpdateBufferIndex() );
-
+ bool valid = notification->Check( bufferIndex );
if(valid)
{
mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
// Measure the time spent in UpdateManager::Update
PERF_MONITOR_START(PerformanceMonitor::UPDATE);
+ BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
// Update the frame time delta on the render thread.
mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
// 1) Clear nodes/resources which were previously discarded
- mImpl->discardQueue.Clear( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->discardQueue.Clear( bufferIndex );
// 2) Grab any loaded resources
- bool resourceChanged = mImpl->resourceManager.UpdateCache( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
// 3) Process Touches & Gestures
mImpl->touchResampler.Update();
mImpl->messageQueue.ProcessMessages();
// 6) Post Process Ids of resources updated by renderer
- mImpl->resourceManager.PostProcessResources( mSceneGraphBuffers.GetUpdateBufferIndex() );
+ mImpl->resourceManager.PostProcessResources( bufferIndex );
// Although the scene-graph may not require an update, we still need to synchronize double-buffered
// renderer lists if the scene was updated in the previous frame.
// 13) Prepare for the next render
PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
- PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->sortedLayers );
- PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->systemLevelSortedLayers );
+ PrepareRenderables( bufferIndex, mImpl->sortedLayers );
+ PrepareRenderables( bufferIndex, mImpl->systemLevelSortedLayers );
PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
if ( NULL != mImpl->root )
{
- ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
+ ProcessRenderTasks( bufferIndex,
mImpl->completeStatusManager,
mImpl->taskList,
*mImpl->root,
// Process the system-level RenderTasks last
if ( NULL != mImpl->systemLevelRoot )
{
- ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
+ ProcessRenderTasks( bufferIndex,
mImpl->completeStatusManager,
mImpl->systemLevelTaskList,
*mImpl->systemLevelRoot,
renderTask.UpdateState();
if( renderTask.IsWaitingToRender() &&
- renderTask.ReadyToRender(mSceneGraphBuffers.GetUpdateBufferIndex()) /*avoid updating forever when source actor is off-stage*/ )
+ renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
{
mImpl->renderTaskWaiting = true; // keep update/render threads alive
}
#include <dali/internal/update/animation/scene-graph-animation.h>
#include <dali/internal/update/common/scene-graph-buffers.h>
#include <dali/internal/update/common/scene-graph-property-notification.h>
+#include <dali/internal/update/manager/object-owner-container.h>
#include <dali/internal/update/node-attachments/node-attachment.h>
#include <dali/internal/update/nodes/node.h>
#include <dali/internal/update/nodes/scene-graph-layer.h>
#include <dali/internal/render/shaders/scene-graph-shader.h>
-//@todo MESH_REWORK Move messages to a separate file to avoid having dependent headers
-// pollute core & slow the build down.
-#include <dali/internal/update/geometry/scene-graph-geometry.h>
-#include <dali/internal/update/effects/scene-graph-material.h>
-
namespace Dali
{
class RenderQueue;
class DynamicsWorld;
class TextureCache;
+class Geometry;
+class PropertyBuffer;
+class Material;
+class Sampler;
/**
* UpdateManager holds a scene graph i.e. a tree of nodes.
*/
void PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode );
-
/**
- * Add a geometry to the scene graph
- * @param[in] geometry The geometry to add
+ * @brief Get the geometry owner
+ *
+ * @return The geometry owner
*/
- void AddGeometry( Geometry* geometry );
+ ObjectOwnerContainer<Geometry*>& GetGeometryOwner();
/**
- * Remove a geometry from the scene graph
- * @param[in] geometry The geometry to remove
+ * @brief Get the material owner
+ *
+ * @return The material owner
*/
- void RemoveGeometry( Geometry* geometry );
+ ObjectOwnerContainer<Material*>& GetMaterialOwner();
/**
- * Add a material to the scene graph
- * @param[in] material The material to add
+ * @brief Get the sampler owner
+ *
+ * @return The sampler owner
*/
- void AddMaterial( Material* material );
+ ObjectOwnerContainer<Sampler*>& GetSamplerOwner();
/**
- * Remove a material from the scene graph
- * @param[in] material The material to remove
+ * @brief Get the property buffer owner
+ *
+ * @return The property buffer owner
*/
- void RemoveMaterial( Material* material );
+ ObjectOwnerContainer<PropertyBuffer*>& GetPropertyBufferOwner();
+
// Shaders
new (slot) LocalType( &manager, &UpdateManager::PropertyNotificationSetNotify, propertyNotification, notifyMode );
}
-inline void AddGeometryMessage( UpdateManager& manager, Geometry& geometry )
-{
- typedef MessageValue1< UpdateManager, OwnerPointer< Geometry > > LocalType;
-
- // Reserve some memory inside the message queue
- unsigned int* slot = manager.GetEventToUpdate().ReserveMessageSlot( sizeof( LocalType ) );
-
- // Construct message in the message queue memory; note that delete should not be called on the return value
- new (slot) LocalType( &manager, &UpdateManager::AddGeometry, &geometry );
-}
-
-// The render thread can safely change the Geometry
-inline void RemoveGeometryMessage( UpdateManager& manager, Geometry& geometry )
-{
- typedef MessageValue1< UpdateManager, Geometry* > LocalType;
-
- // Reserve some memory inside the message queue
- unsigned int* slot = manager.GetEventToUpdate().ReserveMessageSlot( sizeof( LocalType ) );
-
- // Construct message in the message queue memory; note that delete should not be called on the return value
- new (slot) LocalType( &manager, &UpdateManager::RemoveGeometry, &geometry );
-}
-
-inline void AddMaterialMessage( UpdateManager& manager, Material& material )
-{
- typedef MessageValue1< UpdateManager, OwnerPointer< Material > > LocalType;
-
- // Reserve some memory inside the message queue
- unsigned int* slot = manager.GetEventToUpdate().ReserveMessageSlot( sizeof( LocalType ) );
-
- // Construct message in the message queue memory; note that delete should not be called on the return value
- new (slot) LocalType( &manager, &UpdateManager::AddMaterial, &material );
-}
-
-// The render thread can safely change the Material
-inline void RemoveMaterialMessage( UpdateManager& manager, Material& material )
-{
- typedef MessageValue1< UpdateManager, Material* > LocalType;
-
- // Reserve some memory inside the message queue
- unsigned int* slot = manager.GetEventToUpdate().ReserveMessageSlot( sizeof( LocalType ) );
-
- // Construct message in the message queue memory; note that delete should not be called on the return value
- new (slot) LocalType( &manager, &UpdateManager::RemoveMaterial, &material );
-}
// The render thread can safely change the Shader
#endif // DYNAMICS_SUPPORT
+
+template< typename T >
+inline void AddMessage( UpdateManager& manager, ObjectOwnerContainer<T>& owner, T& object )
+{
+ typedef MessageValue1< ObjectOwnerContainer<T>, OwnerPointer< T > > LocalType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = manager.GetEventToUpdate().ReserveMessageSlot( sizeof( LocalType ) );
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new (slot) LocalType( &owner, &ObjectOwnerContainer<T>::Add, &object );
+}
+
+template< typename T >
+inline void RemoveMessage( UpdateManager& manager, ObjectOwnerContainer<T>& owner, T& object )
+{
+ typedef MessageValue1< ObjectOwnerContainer<T>, OwnerPointer< T > > LocalType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = manager.GetEventToUpdate().ReserveMessageSlot( sizeof( LocalType ) );
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new (slot) LocalType( &owner, &ObjectOwnerContainer<T>::Remove, &object );
+}
+
} // namespace SceneGraph
} // namespace Internal