DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::COLOR ).Get< Vector4 >(), Color::WHITE, TEST_LOCATION );
DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::SCALE ).Get< Vector3 >(), Vector3::ONE, TEST_LOCATION );
+ // Render for a couple more frames to ensure the values are reset properly (some values are double-buffered)
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::POSITION ).Get< Vector3 >(), Vector3::ZERO, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::SIZE ).Get< Vector3 >(), Vector3( actorSize ), TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::COLOR ).Get< Vector4 >(), Color::WHITE, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::SCALE ).Get< Vector3 >(), Vector3::ONE, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::POSITION ).Get< Vector3 >(), Vector3::ZERO, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::SIZE ).Get< Vector3 >(), Vector3( actorSize ), TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::COLOR ).Get< Vector4 >(), Color::WHITE, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentProperty( Actor::Property::SCALE ).Get< Vector3 >(), Vector3::ONE, TEST_LOCATION );
+
END_TEST;
}
return mImpl.GetColor( id, color );
}
-bool UpdateProxy::SetColor( uint32_t id, const Vector4& color ) const
+bool UpdateProxy::SetColor( uint32_t id, const Vector4& color )
{
return mImpl.SetColor( id, color );
}
-bool UpdateProxy::BakeColor( uint32_t id, const Vector4& color ) const
+bool UpdateProxy::BakeColor( uint32_t id, const Vector4& color )
{
return mImpl.BakeColor( id, color );
}
* @return Whether the method call was successful or not.
* @note This will get reset to the internally calculated or previously baked value in the next frame, so will have to be set again.
*/
- bool SetColor( uint32_t id, const Vector4& color ) const;
+ bool SetColor( uint32_t id, const Vector4& color );
/**
* @brief Allows baking an Actor's local color from the Frame callback function.
* @return Whether the method call was successful or not.
* @note The value is saved so will cause undesired effects if this property is being animated.
*/
- bool BakeColor( uint32_t id, const Vector4& color ) const;
+ bool BakeColor( uint32_t id, const Vector4& color );
public: // Not intended for application developers
namespace SceneGraph
{
-FrameCallbackProcessor::FrameCallbackProcessor( TransformManager& transformManager )
+FrameCallbackProcessor::FrameCallbackProcessor( UpdateManager& updateManager, TransformManager& transformManager )
: mFrameCallbacks(),
+ mUpdateManager( updateManager ),
mTransformManager( transformManager ),
mNodeHierarchyChanged( true )
{
{
Node& node = const_cast< Node& >( *rootNode ); // Was sent as const from event thread, we need to be able to use non-const version here.
- frameCallback->ConnectToSceneGraph( mTransformManager, node );
+ frameCallback->ConnectToSceneGraph( mUpdateManager, mTransformManager, node );
mFrameCallbacks.emplace_back( frameCallback );
}
class Node;
class TransformManager;
+class UpdateManager;
/**
* This class processes all the registered frame-callbacks.
/**
* Construct a new FrameCallbackProcessor.
+ * @param[in] updateManager A reference to the UpdateManager
+ * @param[in] transformManager A reference to the TransformManager
*/
- FrameCallbackProcessor( TransformManager& transformManager );
+ FrameCallbackProcessor( UpdateManager& updateManager, TransformManager& transformManager );
/**
* Non-virtual Destructor.
std::vector< OwnerPointer< FrameCallback > > mFrameCallbacks; ///< A container of all the frame-callbacks & accompanying update-proxies.
+ UpdateManager& mUpdateManager;
+
TransformManager& mTransformManager;
bool mNodeHierarchyChanged; ///< Set to true if the node hierarchy changes
}
}
-void FrameCallback::ConnectToSceneGraph( TransformManager& transformManager, Node& rootNode )
+void FrameCallback::ConnectToSceneGraph( UpdateManager& updateManager, TransformManager& transformManager, Node& rootNode )
{
- mUpdateProxy = std::unique_ptr< UpdateProxy >( new UpdateProxy( transformManager, rootNode ) );
+ mUpdateProxy = std::unique_ptr< UpdateProxy >( new UpdateProxy( updateManager, transformManager, rootNode ) );
rootNode.AddObserver( *this );
}
/**
* Called from the update-thread when connecting to the scene-graph.
- * @param[in] transformManager The transform Manager
+ * @param[in] updateManager The Update Manager
+ * @param[in] transformManager The Transform Manager
* @param[in] rootNode The rootNode of this frame-callback
*/
- void ConnectToSceneGraph( TransformManager& transformManager, Node& rootNode );
+ void ConnectToSceneGraph( UpdateManager& updateManager, TransformManager& transformManager, Node& rootNode );
// Movable but not copyable
/**
* Lazy init for FrameCallbackProcessor.
+ * @param[in] updateManager A reference to the update-manager
*/
- FrameCallbackProcessor& GetFrameCallbackProcessor()
+ FrameCallbackProcessor& GetFrameCallbackProcessor( UpdateManager& updateManager )
{
if( ! frameCallbackProcessor )
{
- frameCallbackProcessor = new FrameCallbackProcessor( transformManager );
+ frameCallbackProcessor = new FrameCallbackProcessor( updateManager, transformManager );
}
return *frameCallbackProcessor;
}
}
}
+ // Call the frame-callback-processor if set
+ if( mImpl->frameCallbackProcessor )
+ {
+ mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
+ }
+
//Update node hierarchy, apply constraints and perform sorting / culling.
//This will populate each Layer with a list of renderers which are ready.
UpdateNodes( bufferIndex );
//Update renderers and apply constraints
UpdateRenderers( bufferIndex );
- // Call the frame-callback-processor if set
- if( mImpl->frameCallbackProcessor )
- {
- mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
- }
-
//Update the transformations of all the nodes
mImpl->transformManager.Update();
void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
{
- mImpl->GetFrameCallbackProcessor().AddFrameCallback( frameCallback, rootNode );
+ mImpl->GetFrameCallbackProcessor( *this ).AddFrameCallback( frameCallback, rootNode );
}
void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
{
- mImpl->GetFrameCallbackProcessor().RemoveFrameCallback( frameCallback );
+ mImpl->GetFrameCallbackProcessor( *this ).RemoveFrameCallback( frameCallback );
}
void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
// CLASS HEADER
#include <dali/internal/update/manager/update-proxy-impl.h>
+// INTERNAL INCLUDES
+#include <dali/internal/update/manager/update-proxy-property-modifier.h>
+
namespace Dali
{
} // unnamed namespace
-UpdateProxy::UpdateProxy( SceneGraph::TransformManager& transformManager, SceneGraph::Node& rootNode )
+UpdateProxy::UpdateProxy( SceneGraph::UpdateManager& updateManager, SceneGraph::TransformManager& transformManager, SceneGraph::Node& rootNode )
: mNodeContainer(),
mLastCachedIdNodePair( { 0u, NULL } ),
mCurrentBufferIndex( 0u ),
+ mUpdateManager( updateManager ),
mTransformManager( transformManager ),
- mRootNode( rootNode )
+ mRootNode( rootNode ),
+ mPropertyModifier( nullptr )
{
}
return success;
}
-bool UpdateProxy::SetColor( uint32_t id, const Vector4& color ) const
+bool UpdateProxy::SetColor( uint32_t id, const Vector4& color )
{
bool success = false;
SceneGraph::Node* node = GetNodeWithId( id );
if( node )
{
node->mColor.Set( mCurrentBufferIndex, color );
+ node->SetDirtyFlag( SceneGraph::NodePropertyFlags::COLOR );
+ AddResetter( *node, node->mColor );
success = true;
}
return success;
}
-bool UpdateProxy::BakeColor( uint32_t id, const Vector4& color ) const
+bool UpdateProxy::BakeColor( uint32_t id, const Vector4& color )
{
bool success = false;
SceneGraph::Node* node = GetNodeWithId( id );
{
mLastCachedIdNodePair = { 0u, NULL };
mNodeContainer.clear();
+ mPropertyModifier.reset();
}
SceneGraph::Node* UpdateProxy::GetNodeWithId( uint32_t id ) const
return node;
}
+void UpdateProxy::AddResetter( SceneGraph::Node& node, SceneGraph::PropertyBase& propertyBase )
+{
+ if( ! mPropertyModifier )
+ {
+ mPropertyModifier = PropertyModifierPtr( new PropertyModifier( mUpdateManager ) );
+ }
+ mPropertyModifier->AddResetter( node, propertyBase );
+}
+
} // namespace Internal
} // namespace Dali
// EXTERNAL INCLUDES
#include <cstdint>
+#include <memory>
// INTERNAL INCLUDES
#include <dali/public-api/common/vector-wrapper.h>
namespace Internal
{
+namespace SceneGraph
+{
+class UpdateManager;
+}
+
/**
* @brief The implementation of Dali::UpdateProxy.
*
/**
* @brief Constructor.
+ * @param[in] updateManager Ref to the UpdateManager in order to add property resetters
* @param[in] transformManager Ref to the TransformManager in order to set/get transform properties of nodes
* @param[in] rootNode The root node for this proxy
*/
- UpdateProxy( SceneGraph::TransformManager& transformManager, SceneGraph::Node& rootNode );
+ UpdateProxy( SceneGraph::UpdateManager& updateManager, SceneGraph::TransformManager& transformManager, SceneGraph::Node& rootNode );
/**
* @brief Destructor.
/**
* @copydoc Dali::UpdateProxy::SetColor()
*/
- bool SetColor( uint32_t id, const Vector4& color ) const;
+ bool SetColor( uint32_t id, const Vector4& color );
/**
* @copydoc Dali::UpdateProxy::BakeColor()
*/
- bool BakeColor( uint32_t id, const Vector4& color ) const;
+ bool BakeColor( uint32_t id, const Vector4& color );
/**
* @brief Retrieves the root-node used by this class
*/
SceneGraph::Node* GetNodeWithId( uint32_t id ) const;
+ /**
+ * @brief Adds a property-resetter for non-transform properties so that they can be reset to their base value every frame.
+ * @param[in] node The node the property belongs to
+ * @param[in] propertyBase The property itself
+ */
+ void AddResetter( SceneGraph::Node& node, SceneGraph::PropertyBase& propertyBase );
+
private:
/**
SceneGraph::Node* node; ///< The node itself
};
+ class PropertyModifier;
+ using PropertyModifierPtr = std::unique_ptr< PropertyModifier >;
+
mutable std::vector< IdNodePair > mNodeContainer; ///< Used to store cached pointers to already searched for Nodes.
mutable IdNodePair mLastCachedIdNodePair; ///< Used to cache the last retrieved id-node pair.
BufferIndex mCurrentBufferIndex;
+ SceneGraph::UpdateManager& mUpdateManager; ///< Reference to the Update Manager.
SceneGraph::TransformManager& mTransformManager; ///< Reference to the Transform Manager.
SceneGraph::Node& mRootNode; ///< The root node of this update proxy.
+
+ PropertyModifierPtr mPropertyModifier; ///< To ensure non-transform property modifications reset to base values.
};
} // namespace Internal
--- /dev/null
+#ifndef DALI_INTERNAL_UPDATE_PROXY_PROPERTY_MODIFIER_H
+#define DALI_INTERNAL_UPDATE_PROXY_PROPERTY_MODIFIER_H
+
+/*
+ * Copyright (c) 2018 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/update/common/property-resetter.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/manager/update-proxy-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class Node;
+class PropertyBase;
+}
+
+/**
+ * Keeps track of any non-transform manager properties that are modified by the UpdateProxy.
+ *
+ * This is required so the Update Manager can then reset the value to the base at the start of every frame.
+ */
+class UpdateProxy::PropertyModifier final
+{
+public:
+
+ using Resetter = SceneGraph::Resetter< PropertyModifier >;
+
+ /**
+ * Observer to determine when the animator is no longer present
+ */
+ class LifecycleObserver
+ {
+ public:
+
+ /**
+ * Called shortly before the animator is destroyed.
+ */
+ virtual void ObjectDestroyed() = 0;
+
+ protected:
+
+ /**
+ * Virtual destructor, no deletion through this interface
+ */
+ virtual ~LifecycleObserver() = default;
+ };
+
+ /**
+ * Default Constructor.
+ * @param[in] updateManager A reference to the update-manager
+ */
+ PropertyModifier( SceneGraph::UpdateManager& updateManager )
+ : mProperties(),
+ mLifecycleObservers(),
+ mUpdateManager( &updateManager )
+ {
+ }
+
+ /**
+ * Non-virtual destructor.
+ */
+ ~PropertyModifier()
+ {
+ for( auto& observer : mLifecycleObservers )
+ {
+ observer->ObjectDestroyed();
+ }
+ }
+
+ // Movable but not copyable
+
+ PropertyModifier( const PropertyModifier& ) = delete; ///< Deleted copy constructor.
+ PropertyModifier& operator=( const PropertyModifier& ) = delete; ///< Deleted assignment operator.
+
+ /**
+ * Move constructor.
+ */
+ PropertyModifier( PropertyModifier&& other )
+ : mProperties( std::move( other.mProperties ) ),
+ mLifecycleObservers( std::move( other.mLifecycleObservers ) ),
+ mUpdateManager( std::move( other.mUpdateManager ) )
+ {
+ // Clear other so that it does not remove any resetters unintentionally
+ other.mLifecycleObservers.clear();
+ }
+
+ /**
+ * Move assignment operator.
+ */
+ PropertyModifier& operator=( PropertyModifier&& other )
+ {
+ if( this != &other )
+ {
+ mProperties = std::move( other.mProperties );
+ mLifecycleObservers = std::move( other.mLifecycleObservers );
+ mUpdateManager = std::move( other.mUpdateManager );
+
+ // Clear other so that it does not remove any resetters unintentionally
+ other.mLifecycleObservers.clear();
+ }
+ return *this;
+ }
+
+ /**
+ * Allows Resetter to track the life-cycle of this object.
+ * @param[in] observer The observer to add.
+ */
+ void AddLifecycleObserver( LifecycleObserver& observer )
+ {
+ mLifecycleObservers.push_back( &observer );
+ }
+
+ /**
+ * The Resetter no longer needs to track the life-cycle of this object.
+ * @param[in] observer The observer that to remove.
+ */
+ void RemoveLifecycleObserver( LifecycleObserver& observer )
+ {
+ std::remove( mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer );
+ }
+
+ /**
+ * Adds a resetter to the given node and property if it hasn't already been added previously.
+ * @param[in] node The associated Node
+ * @param[in] propertyBase The associated PropertyBase
+ */
+ void AddResetter( SceneGraph::Node& node, SceneGraph::PropertyBase& propertyBase )
+ {
+ // Check if we've already added a resetter for this node and property to the update-manager
+ NodePropertyPair pair{ &node, &propertyBase };
+ if( mUpdateManager &&
+ ( mProperties.end() == std::find( mProperties.begin(), mProperties.end(), pair ) ) )
+ {
+ // We haven't, add the pair to our container to ensure we don't add it again
+ // Then create a Resetter which will observe the life of this object
+ // Finally, add the resetter to the Update-Manager
+ // When this object is destroyed, the resetter will be informed and will automatically be removed
+
+ mProperties.emplace_back( std::move( pair ) );
+ OwnerPointer< SceneGraph::PropertyResetterBase > resetter( Resetter::New( node, propertyBase, *this ) );
+ mUpdateManager->AddPropertyResetter( resetter );
+ }
+ }
+
+public:
+
+ /**
+ * Structure to store the Node & property-base pair
+ */
+ struct NodePropertyPair
+ {
+ SceneGraph::Node* node;
+ SceneGraph::PropertyBase* propertyBase;
+
+ NodePropertyPair( const NodePropertyPair& ) = delete; ///< Deleted copy constructor.
+ NodePropertyPair( NodePropertyPair&& ) = default; ///< Default move constructor.
+ NodePropertyPair& operator=( const NodePropertyPair& ) = delete; ///< Deleted assignment operator.
+ NodePropertyPair& operator=( NodePropertyPair&& ) = default; ///< Default move assignment operator.
+
+ /**
+ * Comparison operator
+ */
+ bool operator==( const NodePropertyPair& other )
+ {
+ return ( other.node == node ) &&
+ ( other.propertyBase == propertyBase );
+ }
+ };
+
+ std::vector< NodePropertyPair > mProperties;
+ std::vector< LifecycleObserver* > mLifecycleObservers;
+ SceneGraph::UpdateManager* mUpdateManager;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_UPDATE_PROXY_PROPERTY_MODIFIER_H