#define __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * 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.
#include <dali/internal/update/common/property-owner.h>
#include <dali/internal/update/animation/property-accessor.h>
#include <dali/internal/update/animation/property-component-accessor.h>
+#include <dali/internal/update/common/property-resetter.h>
#include <dali/internal/update/manager/update-manager.h>
namespace Dali
{
/**
- * AnimatorConnector is used to connect SceneGraph::Animators for newly created scene-graph objects.
+ * AnimatorConnector is used to connect SceneGraph::Animators and
+ * PropertyResetters for newly created scene-graph objects.
*
* SceneGraph::Animators weakly reference scene objects, and are automatically deleted when orphaned.
* Therefore the AnimatorConnector is NOT responsible for disconnecting animators.
mObject->RemoveObserver( *this );
}
- //If there is not a SceneGraph::Animator, the AnimatorConnector is responsible for deleting the mAnimatorFunction
- //otherwise, the animator function ownership is transferred to the SceneGraph::Animator
+ // If there is not a SceneGraph::Animator, the AnimatorConnector is responsible for deleting the mAnimatorFunction
+ // otherwise, the animator function ownership is transferred to the SceneGraph::Animator
if( !mAnimator )
{
delete mAnimatorFunction;
}
/**
- * Helper function to create a Scenegraph::Animator and add it to its correspondent SceneGraph::Animation.
+ * Helper function to create a Scenegraph::Animator and PropertyResetter and add it to its correspondent
+ * SceneGraph::Animation.
+ *
* @note This function will only be called the first time the object is added to the scene or at creation time if
* the object was already in the scene
*/
//Get the PropertyOwner the animator is going to animate
const SceneGraph::PropertyOwner* propertyOwner = mObject->GetSceneObject();
- //Get SceneGraph::BaseProperty
+ // Get SceneGraph::BaseProperty
const SceneGraph::PropertyBase* baseProperty = mObject->GetSceneObjectAnimatableProperty( mPropertyIndex );
- //Check if property is a component of another property
+ OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
+
+ // Check if property is a component of another property
const int componentIndex = mObject->GetPropertyComponentIndex( mPropertyIndex );
if( componentIndex != Property::INVALID_COMPONENT_INDEX )
{
if( mComponentIndex == Property::INVALID_COMPONENT_INDEX )
{
- ///Animating the whole property
+ // Animating the whole property
- //Cast to AnimatableProperty
+ // Cast to AnimatableProperty
const PropertyInterfaceType* animatableProperty = dynamic_cast< const PropertyInterfaceType* >( baseProperty );
if( animatableProperty == NULL )
if( baseProperty->IsTransformManagerProperty() )
{
mAnimator = SceneGraph::AnimatorTransformProperty< PropertyType,TransformManagerPropertyAccessor<PropertyType> >::New( *propertyOwner, *baseProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
+ // Don't reset transform manager properties - TransformManager will do it more efficiently
}
else
{
}
else
{
- //Create the animator
- mAnimator = AnimatorType::New( *propertyOwner, *animatableProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
+ // Create the animator and resetter
+ mAnimator = AnimatorType::New( *propertyOwner, *animatableProperty, mAnimatorFunction,
+ mAlphaFunction, mTimePeriod );
+ resetter = SceneGraph::AnimatorResetter::New( *propertyOwner, *baseProperty, *mAnimator );
}
-
}
else
{
{
- ///Animating a component of the property
+ // Animating a component of the property
if ( PropertyTypes::Get< Vector2 >() == baseProperty->GetType() )
{
// Animate float component of Vector2 property
break;
}
}
+
+ if( mAnimator != nullptr )
+ {
+ resetter = SceneGraph::AnimatorResetter::New( *propertyOwner, *baseProperty, *mAnimator );
+ }
}
else if ( PropertyTypes::Get< Vector3 >() == baseProperty->GetType() )
{
DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
}
+ // Don't manually reset transform property - TransformManager will do it more efficiently
}
else
{
- //Dynamic cast will fail if BaseProperty is not a Vector3 AnimatableProperty
+ // Dynamic cast will fail if BaseProperty is not a Vector3 AnimatableProperty
DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
switch( mComponentIndex )
break;
}
}
+
+ if( mAnimator != nullptr )
+ {
+ resetter = SceneGraph::AnimatorResetter::New( *propertyOwner, *baseProperty, *mAnimator );
+ }
}
}
else if ( PropertyTypes::Get< Vector4 >() == baseProperty->GetType() )
break;
}
}
+ if( mAnimator != nullptr )
+ {
+ resetter = SceneGraph::AnimatorResetter::New( *propertyOwner, *baseProperty, *mAnimator );
+ }
}
}
}
const SceneGraph::Animation* animation = mParent->GetSceneObject();
DALI_ASSERT_DEBUG( NULL != animation );
AddAnimatorMessage( mParent->GetEventThreadServices(), *animation, *mAnimator );
+
+ // Add the new SceneGraph::PropertyResetter to the update manager via message
+ if( resetter != nullptr )
+ {
+ AddResetterMessage( mParent->GetEventThreadServices().GetUpdateManager(), resetter );
+ }
}
protected:
#define __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
#include <dali/internal/update/common/animatable-property.h>
#include <dali/internal/update/common/property-owner.h>
#include <dali/internal/update/common/property-owner-messages.h>
+#include <dali/internal/update/common/property-resetter.h>
#include <dali/internal/update/animation/scene-graph-constraint.h>
#include <dali/internal/update/animation/property-accessor.h>
#include <dali/internal/update/animation/property-component-accessor.h>
+#include <memory>
namespace Dali
{
Constraint& operator=( const Constraint& rhs );
/**
- * Create and connect a constraint for a scene-object.
+ * Create and connect a constraint and property resetter for a scene-graph property
*/
void ConnectConstraint()
{
- // Should not come here if target-object has been destroyed
+ // Should not come here if target object has been destroyed
DALI_ASSERT_DEBUG( NULL != mTargetObject );
// Guard against double connections
if ( func )
{
- // Create the SceneGraphConstraint, and connect to the scene-graph
+ // Create the SceneGraphConstraint and PropertyResetter, and connect them to the scene-graph
const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
+ OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
// The targetProperty should exist, when targetObject exists
DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
if( targetProperty->IsTransformManagerProperty() ) //It is a property managed by the transform manager
{
// Connect the constraint
- mSceneGraphConstraint = SceneGraph::Constraint<PropertyType,TransformManagerPropertyAccessor<PropertyType> >::New( *targetProperty,
- propertyOwners,
- func,
- mRemoveAction );
+ mSceneGraphConstraint =
+ SceneGraph::Constraint<PropertyType, TransformManagerPropertyAccessor<PropertyType> >::New( *targetProperty,
+ propertyOwners,
+ func,
+ mRemoveAction );
+ // Don't create a resetter for transform manager property, it's less efficient
}
else //SceneGraph property
{
propertyOwners,
func,
mRemoveAction );
+ // Connect the resetter
+ resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
+
}
OwnerPointer< SceneGraph::ConstraintBase > transferOwnership( const_cast< SceneGraph::ConstraintBase* >( mSceneGraphConstraint ) );
ApplyConstraintMessage( GetEventThreadServices(), *targetObject, transferOwnership );
+
+ if( resetter != nullptr )
+ {
+ AddResetterMessage( GetEventThreadServices().GetUpdateManager(), resetter );
+ }
}
}
// Create the SceneGraphConstraint, and connect to the scene-graph
const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
+ OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
// The targetProperty should exist, when targetObject exists
DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
+ resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
}
else
{
typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector2> > SceneGraphConstraint;
mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
}
+ if( mSceneGraphConstraint )
+ {
+ resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
+ }
}
else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
{
typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,2> > SceneGraphConstraint;
mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
}
+ // Do not create a resetter for transform manager property
}
else
{
typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
}
+ if( mSceneGraphConstraint )
+ {
+ resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
+ }
}
}
else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
}
+
+ if( mSceneGraphConstraint )
+ {
+ resetter = SceneGraph::ConstraintResetter::New( *targetObject, *targetProperty, *mSceneGraphConstraint );
+ }
}
}
OwnerPointer< SceneGraph::ConstraintBase > transferOwnership( const_cast< SceneGraph::ConstraintBase* >( mSceneGraphConstraint ) );
ApplyConstraintMessage( GetEventThreadServices(), *targetObject, transferOwnership );
}
+ if( resetter != nullptr )
+ {
+ AddResetterMessage( GetEventThreadServices().GetUpdateManager(), resetter );
+ }
}
}
#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_ACCESSOR_H__
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * 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.
#define __DALI_INTERNAL_SCENE_GRAPH_ANIMATOR_H__
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
typedef float (*AlphaFunc)(float progress); ///< Definition of an alpha function
/**
+ * 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;
+ };
+
+
+ /**
* Constructor.
*/
AnimatorBase()
- : mDurationSeconds(1.0f),
+ : mLifecycleObserver(nullptr),
+ mDurationSeconds(1.0f),
mIntervalDelaySeconds(0.0f),
mSpeedFactor(1.0f),
mLoopCount(1),
*/
virtual ~AnimatorBase()
{
+ if( mLifecycleObserver != nullptr )
+ {
+ mLifecycleObserver->ObjectDestroyed();
+ }
+ }
+
+ void AddLifecycleObserver( LifecycleObserver& observer )
+ {
+ mLifecycleObserver = &observer;
+ }
+
+ void RemoveLifecycleObserver( LifecycleObserver& observer )
+ {
+ mLifecycleObserver = nullptr;
}
/**
return 3.0f*(1.0f-t)*(1.0f-t)*t*p0 + 3.0f*(1.0f-t)*tSquare*p1 + tSquare*t;
}
+ LifecycleObserver* mLifecycleObserver;
float mDurationSeconds;
float mIntervalDelaySeconds;
float mSpeedFactor;
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
: mRemoveAction( removeAction ),
mFirstApply( true ),
mDisconnected( true ),
- mObservedOwners( ownerSet )
+ mObservedOwners( ownerSet ),
+ mLifecycleObserver( nullptr )
{
#ifdef DEBUG_ENABLED
++mCurrentInstanceCount;
StopObservation();
}
+ if( mLifecycleObserver != nullptr )
+ {
+ mLifecycleObserver->ObjectDestroyed();
+ }
+
#ifdef DEBUG_ENABLED
--mCurrentInstanceCount;
#endif
}
-void ConstraintBase::ResetDefaultProperties( BufferIndex updateBufferIndex )
-{
- DALI_ASSERT_DEBUG( false );
-}
-
unsigned int ConstraintBase::GetCurrentInstanceCount()
{
#ifdef DEBUG_ENABLED
#define __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_BASE_H__
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
class ConstraintBase : public PropertyOwner::Observer
{
public:
+ /**
+ * Observer to determine when the constraint is no longer present
+ */
+ class LifecycleObserver
+ {
+ public:
+ /**
+ * Called shortly before the constraint is destroyed.
+ */
+ virtual void ObjectDestroyed() = 0;
+
+ protected:
+ /**
+ * Virtual destructor, no deletion through this interface
+ */
+ virtual ~LifecycleObserver() = default;
+ };
+
+public:
typedef Dali::Constraint::RemoveAction RemoveAction;
virtual ~ConstraintBase();
/**
+ * Property resetter observes the lifecycle of this object
+ */
+ void AddLifecycleObserver( LifecycleObserver& observer )
+ {
+ mLifecycleObserver = &observer;
+ }
+
+ /**
+ * Property resetter observers the lifecycle of this object
+ */
+ void RemoveLifecycleObserver( LifecycleObserver& observer )
+ {
+ mLifecycleObserver = nullptr;
+ }
+
+ /**
* Initialize the constraint.
* This should by called by a scene-object, when the constraint is connected.
*/
}
/**
- * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
- */
- virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
-
- /**
* Notify the derived class to disconnect from property owners
*/
virtual void OnDisconnect() = 0;
private:
PropertyOwnerContainer mObservedOwners; ///< A set of pointers to each observed object. Not owned.
+ LifecycleObserver* mLifecycleObserver; ///< Resetter observers this object
#ifdef DEBUG_ENABLED
static unsigned int mCurrentInstanceCount; ///< The current number of Constraint instances in existence.
#define __DALI_INTERNAL_SCENE_GRAPH_ANIMATABLE_PROPERTY_H__
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * 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.
if( mBaseValue != value )
{
mBaseValue = value;
+ // It's ok to bake both buffers as render is performed in same thread as update. Reading from event side
+ // has never been atomically safe.
mValue[bufferIndex] = value;
+ mValue[1-bufferIndex] = value;
OnBake();
}
void Bake(BufferIndex bufferIndex, int value)
{
mValue[bufferIndex] = value;
+ mValue[1-bufferIndex] = value;
mBaseValue = mValue[bufferIndex];
OnBake();
*/
void Bake(BufferIndex bufferIndex, float value)
{
+ // It's ok to bake both buffers as render is performed in same thread as update. Reading from event side
+ // has never been atomically safe.
mValue[bufferIndex] = value;
+ mValue[1-bufferIndex] = value;
mBaseValue = mValue[bufferIndex];
OnBake();
*/
void Bake(BufferIndex bufferIndex, const Vector2& value)
{
+ // It's ok to bake both buffers as render is performed in same thread as update. Reading from event side
+ // has never been atomically safe.
mValue[bufferIndex] = value;
+ mValue[1-bufferIndex] = value;
mBaseValue = value;
OnBake();
void BakeX(BufferIndex bufferIndex, float value)
{
mValue[bufferIndex].x = value;
+ mValue[1-bufferIndex].x = value;
mBaseValue.x = value;
OnBake();
void BakeY(BufferIndex bufferIndex, float value)
{
mValue[bufferIndex].y = value;
+ mValue[1-bufferIndex].y = value;
mBaseValue.y = value;
OnBake();
void Bake(BufferIndex bufferIndex, const Vector3& value)
{
mValue[bufferIndex] = value;
+ mValue[1-bufferIndex] = value;
mBaseValue = value;
OnBake();
void BakeX(BufferIndex bufferIndex, float value)
{
mValue[bufferIndex].x = value;
+ mValue[1-bufferIndex].x = value;
mBaseValue.x = value;
OnBake();
void BakeY(BufferIndex bufferIndex, float value)
{
mValue[bufferIndex].y = value;
+ mValue[1-bufferIndex].y = value;
mBaseValue.y = value;
OnBake();
void BakeZ(BufferIndex bufferIndex, float value)
{
mValue[bufferIndex].z = value;
+ mValue[1-bufferIndex].z = value;
mBaseValue.z = value;
OnBake();
void Bake(BufferIndex bufferIndex, const Vector4& value)
{
mValue[bufferIndex] = value;
+ mValue[1-bufferIndex] = value;
mBaseValue = mValue[bufferIndex];
OnBake();
void BakeX(BufferIndex bufferIndex, float value)
{
mValue[bufferIndex].x = value;
+ mValue[1-bufferIndex].x = value;
mBaseValue.x = mValue[bufferIndex].x;
OnBake();
void BakeY(BufferIndex bufferIndex, float value)
{
mValue[bufferIndex].y = value;
+ mValue[1-bufferIndex].y = value;
mBaseValue.y = mValue[bufferIndex].y;
OnBake();
void BakeZ(BufferIndex bufferIndex, float value)
{
mValue[bufferIndex].z = value;
+ mValue[1-bufferIndex].z = value;
mBaseValue.z = mValue[bufferIndex].z;
OnBake();
void BakeW(BufferIndex bufferIndex, float value)
{
mValue[bufferIndex].w = value;
+ mValue[1-bufferIndex].w = value;
mBaseValue.w = mValue[bufferIndex].w;
OnBake();
*/
void Bake(BufferIndex bufferIndex, const Quaternion& value)
{
+ // It's ok to bake both buffers as render is performed in same thread as update. Reading from event side
+ // has never been atomically safe.
mValue[bufferIndex] = value;
+ mValue[1-bufferIndex] = value;
mBaseValue = value;
OnBake();
*/
void Bake(BufferIndex bufferIndex, const Matrix& value)
{
+ // It's ok to bake both buffers as render is performed in same thread as update. Reading from event side
+ // has never been atomically safe.
mValue[bufferIndex] = value;
+ mValue[1-bufferIndex] = value;
mBaseValue = mValue[bufferIndex];
OnBake();
*/
void Bake(BufferIndex bufferIndex, const Matrix3& value)
{
+ // It's ok to bake both buffers as render is performed in same thread as update. Reading from event side
+ // has never been atomically safe.
mValue[bufferIndex] = value;
+ mValue[1-bufferIndex] = value;
mBaseValue = mValue[bufferIndex];
OnBake();
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
mCustomProperties.PushBack( property.Release() );
}
-void PropertyOwner::ResetToBaseValues( BufferIndex updateBufferIndex )
-{
- // Reset custom properties
- const OwnedPropertyIter endIter = mCustomProperties.End();
- for ( OwnedPropertyIter iter = mCustomProperties.Begin(); endIter != iter; ++iter )
- {
- (*iter)->ResetToBaseValue( updateBufferIndex );
- }
-
- // Notification for derived classes, to reset default properties
- ResetDefaultProperties( updateBufferIndex );
-}
ConstraintOwnerContainer& PropertyOwner::GetConstraints()
{
#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_OWNER_H__
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
return mCustomProperties;
}
- /**
- * Reset animatable properties to the corresponding base values.
- * @param[in] currentBufferIndex The buffer to reset.
- * @post The ResetDefaultProperties method is called, during which derived classes can reset default properties.
- */
- void ResetToBaseValues( BufferIndex updateBufferIndex );
// Constraints
// Undefined
PropertyOwner& operator=(const PropertyOwner& rhs);
- /**
- * Called after ResetToBaseValues; derived classes should reset any default properties.
- * @param[in] currentBufferIndex The buffer to reset.
- */
- virtual void ResetDefaultProperties( BufferIndex updateBufferIndex ) {}
-
protected:
OwnedPropertyContainer mCustomProperties; ///< Properties provided with InstallCustomProperty()
--- /dev/null
+#ifndef DALI_INTERNAL_SCENEGRAPH_PROPERTY_RESETTER_H
+#define DALI_INTERNAL_SCENEGRAPH_PROPERTY_RESETTER_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.
+ */
+
+#include <dali/internal/update/animation/scene-graph-animator.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <dali/internal/update/animation/property-accessor.h>
+#include <dali/internal/update/animation/property-component-accessor.h>
+#include <dali/internal/update/common/property-owner.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+/**
+ * Class to reset the watched property to it's base value. Used by UpdateManager to
+ * reset animating and constrained properties. The derived classes AnimatorResetter and
+ * ConstraintResetter are designed to match the lifecycle of the SceneGraph::Animator
+ * and SceneGraph::Constraint respectively.
+ */
+class PropertyResetterBase : public PropertyOwner::Observer
+{
+public:
+ /**
+ * Virtual Destructor
+ */
+ virtual ~PropertyResetterBase()
+ {
+ if( mPropertyOwner != nullptr )
+ {
+ mPropertyOwner->RemoveObserver(*this);
+ }
+ }
+
+ /**
+ * Initialize.
+ *
+ * Watches the property owner to track if it's disconnected or not.
+ */
+ void Initialize()
+ {
+ mPropertyOwner->AddObserver(*this);
+ }
+
+ /**
+ * Reset the property to it's base value if the property owner is still alive and on stage
+ * @param[in] updateBufferIndex the current buffer index
+ */
+ void ResetToBaseValue( BufferIndex updateBufferIndex )
+ {
+ if( mPropertyOwner != nullptr && !mDisconnected )
+ {
+ mBaseProperty->ResetToBaseValue( updateBufferIndex );
+ }
+ };
+
+ /**
+ * Called when mPropertyOwner is connected to the scene graph.
+ *
+ * Note, this resetter object may be created after the property owner has been connected
+ * to the stage, so we track disconnection and re-connection instead of connection
+ *
+ * @param[in] owner The property owner
+ */
+ virtual void PropertyOwnerConnected( PropertyOwner& owner ) override
+ {
+ mDisconnected = false;
+ }
+
+ /**
+ * Called when mPropertyOwner is disconnected from the scene graph.
+ * @param[in] bufferIndex the current buffer index
+ * @param[in] owner The property owner
+ */
+ virtual void PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner ) override
+ {
+ mDisconnected = true;
+ }
+
+ /**
+ * Called shortly before the propertyOwner is destroyed
+ * @param[in] owner The property owner
+ */
+ virtual void PropertyOwnerDestroyed( PropertyOwner& owner ) override
+ {
+ mDisconnected = true;
+ mPropertyOwner = nullptr;
+
+ // Don't need to wait another frame as the property is being destroyed
+ mRunning = 0;
+ }
+
+ /**
+ * Determine if the resetter has finished.
+ *
+ * If an animation or constraint stops, then we need to reset the
+ * property in the next frame as well to ensure both property values
+ * are set appropriately.
+ *
+ * @return true if the resetter has finished.
+ */
+ virtual bool IsFinished()
+ {
+ bool finished = mRunning <= 0;
+ if( mRunning == 1 )
+ {
+ mRunning = 0;
+ }
+ return finished;
+ }
+
+protected:
+
+ /**
+ * Constructor
+ *
+ * @param[in] propertyOwner The property owner storing the base property
+ * @param[in] baseProperty The base property
+ */
+ PropertyResetterBase( PropertyOwner* propertyOwner,
+ PropertyBase* baseProperty )
+ : mPropertyOwner( propertyOwner ),
+ mBaseProperty( baseProperty ),
+ mRunning( 2 ),
+ mDisconnected( false )
+ {
+ }
+
+ PropertyOwner* mPropertyOwner; ///< The property owner
+ PropertyBase* mBaseProperty; ///< The base property being animated or constrained
+ int mRunning; ///< 2 if running, 1 if aging, 0 if stopped
+ bool mDisconnected; ///< True if the property owner has been disconnected
+};
+
+
+/**
+ * Specialization of Resetter based on templated modifier type (either Constraint or Animator)
+ */
+template< typename ModifierType>
+class Resetter : public PropertyResetterBase, public ModifierType::LifecycleObserver
+{
+public:
+
+ /**
+ * New method.
+ * @param[in] propertyOwner The owner of the property
+ * @param[in] baseProperty The property being animated
+ * @param[in] modifier The scene-graph animator/constraint of the property
+ * @return the new property resetter
+ */
+ static PropertyResetterBase* New( const PropertyOwner& propertyOwner,
+ const PropertyBase& baseProperty,
+ const ModifierType& modifier )
+ {
+ return new Resetter<ModifierType>( const_cast<PropertyOwner*>( &propertyOwner ),
+ const_cast<PropertyBase*>( &baseProperty ),
+ const_cast<ModifierType*>( &modifier ) );
+ }
+
+ /**
+ * Virtual destructor.
+ */
+ virtual ~Resetter()
+ {
+ // Disconnect from modifier object. Although this resetter should match the lifecycle of the modifier object,
+ // there are situations where it is deleted first (e.g. if the property owner is destroyed)
+ if( mModifier )
+ {
+ mModifier->RemoveLifecycleObserver(*this);
+ }
+ }
+
+private:
+ /**
+ * Constructor
+ * @param[in] propertyOwner The owner of the property
+ * @param[in] baseProperty The property being animated
+ * @param[in] modifier The scene-graph animator/constraint of the property
+ */
+ Resetter( PropertyOwner* propertyOwner,
+ PropertyBase* baseProperty,
+ ModifierType* modifier )
+ : PropertyResetterBase( propertyOwner, baseProperty ),
+ mModifier( modifier )
+ {
+ // Track the lifecycle of the modifying object
+ mModifier->AddLifecycleObserver(*this);
+ }
+
+ /**
+ * The Animator or Constraint is destroyed
+ */
+ virtual void ObjectDestroyed() override
+ {
+ // When the modifier is destroyed, reduce the running value to ensure we stay alive for
+ // another frame to reset the other buffer.
+ --mRunning;
+ mModifier = nullptr;
+ }
+
+ ModifierType* mModifier;
+};
+
+
+typedef Resetter<SceneGraph::AnimatorBase> AnimatorResetter;
+typedef Resetter<SceneGraph::ConstraintBase> ConstraintResetter;
+
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif //DALI_INTERNAL_SCENEGRAPH_PROPERTY_RESETTER_H
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * 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.
* Constrain the local properties of the PropertyOwner.
* @param propertyOwner to constrain
* @param updateBufferIndex buffer index to use
- * @return The number of constraints that are still being applied
*/
void ConstrainPropertyOwner( PropertyOwner& propertyOwner, BufferIndex updateBufferIndex )
{
Layer& currentLayer,
int inheritedDrawMode )
{
- //Apply constraints to the node
+ // Apply constraints to the node
ConstrainPropertyOwner( node, updateBufferIndex );
// Short-circuit for invisible nodes
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
OwnerContainer< Camera* > cameras; ///< A container of cameras
OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
+ OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
AnimationContainer animations; ///< A container of owned animations
PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
-
OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
OwnerContainer< Shader* > shaders; ///< A container of owned shaders
return false;
}
+void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
+{
+ propertyResetter->Initialize();
+ mImpl->propertyResetters.PushBack( propertyResetter.Release() );
+}
+
void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
{
mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
// Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
mImpl->animationFinishedDuringUpdate = false;
- // Animated properties have to be reset to their original value each frame
-
- // Reset root properties
- if ( mImpl->root )
+ // Reset all animating / constrained properties
+ std::vector<PropertyResetterBase*>toDelete;
+ for( auto&& element : mImpl->propertyResetters )
{
- mImpl->root->ResetToBaseValues( bufferIndex );
+ element->ResetToBaseValue( bufferIndex );
+ if( element->IsFinished() )
+ {
+ toDelete.push_back( element );
+ }
}
- if ( mImpl->systemLevelRoot )
+
+ // If a resetter is no longer required (the animator or constraint has been removed), delete it.
+ for( auto&& elementPtr : toDelete )
{
- mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
+ mImpl->propertyResetters.EraseObject( elementPtr );
}
- // Reset all the nodes
+ // Clear node dirty flags
Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
Vector<Node*>::Iterator endIter = mImpl->nodes.End();
for( ;iter != endIter; ++iter )
{
- (*iter)->ResetToBaseValues( bufferIndex );
+ (*iter)->ResetDirtyFlags( bufferIndex );
}
-
- // Reset system-level render-task list properties to base values
- ResetToBaseValues( mImpl->systemLevelTaskList.GetTasks(), bufferIndex );
-
- // Reset render-task list properties to base values.
- ResetToBaseValues( mImpl->taskList.GetTasks(), bufferIndex );
-
- // Reset custom object properties to base values
- ResetToBaseValues( mImpl->customObjects, bufferIndex );
-
- // Reset animatable renderer properties to base values
- ResetToBaseValues( mImpl->renderers, bufferIndex );
-
- // Reset animatable shader properties to base values
- ResetToBaseValues( mImpl->shaders, bufferIndex );
}
bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
//Update renderers and apply constraints
UpdateRenderers( bufferIndex );
- //Update the trnasformations of all the nodes
+ //Update the transformations of all the nodes
mImpl->transformManager.Update();
//Process Property Notifications
#define DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
#include <dali/internal/common/shader-saver.h>
#include <dali/internal/event/common/event-thread-services.h>
#include <dali/internal/update/animation/scene-graph-animation.h>
+#include <dali/internal/update/common/property-resetter.h>
#include <dali/internal/update/common/scene-graph-buffers.h>
#include <dali/internal/update/common/scene-graph-property-notification.h>
#include <dali/internal/update/nodes/node.h>
*/
bool IsAnimationRunning() const;
+ /**
+ * Add a property resetter. UpdateManager takes ownership of the object.
+ * It will be killed by UpdateManager when the associated animator or
+ * constraint has finished; or the property owner of the property is destroyed.
+ */
+ void AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter );
+
// Property Notification
/**
new (slot) LocalType( &manager, &UpdateManager::SetDepthIndices, nodeDepths );
}
+inline void AddResetterMessage( UpdateManager& manager, OwnerPointer<PropertyResetterBase> resetter )
+{
+ typedef MessageValue1< UpdateManager, OwnerPointer<PropertyResetterBase> > LocalType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = manager.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::AddPropertyResetter, resetter );
+}
+
+
} // namespace SceneGraph
} // namespace Internal
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
return flags;
}
-void Node::ResetDefaultProperties( BufferIndex updateBufferIndex )
+void Node::ResetDirtyFlags( BufferIndex updateBufferIndex )
{
- mVisible.ResetToBaseValue( updateBufferIndex );
- mColor.ResetToBaseValue( updateBufferIndex );
-
mDirtyFlags = NothingFlag;
}
#define DALI_INTERNAL_SCENE_GRAPH_NODE_H
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
*/
void CreateTransform( SceneGraph::TransformManager* transformManager );
+ /**
+ * Reset dirty flags
+ */
+ void ResetDirtyFlags( BufferIndex updateBufferIndex );
+
protected:
/**
Node& operator=(const Node& rhs);
/**
- * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
- */
- virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
-
- /**
* Recursive helper to disconnect a Node and its children.
* Disconnected Nodes have no parent or children.
* @param[in] updateBufferIndex The current update buffer index.
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
mRequiresSync = requiresSync;
}
-void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
-{
- // Reset default properties
- mViewportPosition.ResetToBaseValue( updateBufferIndex );
- mViewportSize.ResetToBaseValue( updateBufferIndex );
- mClearColor.ResetToBaseValue( updateBufferIndex );
-}
RenderTask::RenderTask()
: mViewportPosition( Vector2::ZERO),
#define DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_H
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
// Undefined
RenderTask& operator=(const RenderTask&);
-private: // PropertyOwner
-
- virtual void ResetDefaultProperties( BufferIndex currentBufferIndex );
public: // Animatable Properties
AnimatableProperty< Vector2 > mViewportPosition; ///< viewportPosition