Custom property owning objects 10/17710/16
authorPaul Wisbey <p.wisbey@samsung.com>
Fri, 7 Mar 2014 17:24:08 +0000 (17:24 +0000)
committerPaul Wisbey <p.wisbey@samsung.com>
Wed, 12 Mar 2014 09:37:45 +0000 (02:37 -0700)
[Issue#]   n/a
[Problem]  There is no way of using custom properties without an actor.
[Cause]    Can't instantiate a Constrainable object.
[Solution] Add method to create Constrainable objects.

Signed-off-by: Paul Wisbey <p.wisbey@samsung.com>
Change-Id: I0233ec5621ffdbe032d2e6e6bec8ec12d2a5463f

17 files changed:
automated-tests/dali-test-suite/actors/.gitignore
automated-tests/dali-test-suite/actors/file.list
automated-tests/dali-test-suite/actors/tslist
automated-tests/dali-test-suite/actors/utc-Dali-Constrainable.cpp [new file with mode: 0644]
capi/dali/public-api/object/constrainable.h
dali/internal/event/common/proxy-object.cpp
dali/internal/event/common/proxy-object.h
dali/internal/event/effects/shader-effect-impl.cpp
dali/internal/event/effects/shader-effect-impl.h
dali/internal/event/object/custom-object-internal.cpp [new file with mode: 0644]
dali/internal/event/object/custom-object-internal.h [new file with mode: 0644]
dali/internal/file.list
dali/internal/update/common/property-owner.cpp
dali/internal/update/common/property-owner.h
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/public-api/object/constrainable.cpp

index fed2e60..2002e7a 100644 (file)
@@ -13,6 +13,7 @@ utc-Dali-LightActor
 utc-Dali-Layer
 utc-Dali-Stage
 utc-Dali-CustomActor
+utc-Dali-Constrainable
 utc-Dali-RenderableActor
 utc-Dali-BaseHandle
 utc-Dali-Handle
index b1a5432..e4c750c 100644 (file)
@@ -10,5 +10,6 @@ TARGETS += \
        utc-Dali-Stage \
        utc-Dali-TextActor \
        utc-Dali-CustomActor \
+       utc-Dali-Constrainable \
        utc-Dali-BaseHandle \
        utc-Dali-Handle \
index bd8e428..12b42e9 100644 (file)
@@ -8,6 +8,7 @@
 /dali-test-suite/actors/utc-Dali-Stage
 /dali-test-suite/actors/utc-Dali-TextActor
 /dali-test-suite/actors/utc-Dali-CustomActor
+/dali-test-suite/actors/utc-Dali-Constrainable
 /dali-test-suite/actors/utc-Dali-RenderableActor
 /dali-test-suite/actors/utc-Dali-BaseHandle
 /dali-test-suite/actors/utc-Dali-Handle
diff --git a/automated-tests/dali-test-suite/actors/utc-Dali-Constrainable.cpp b/automated-tests/dali-test-suite/actors/utc-Dali-Constrainable.cpp
new file mode 100644 (file)
index 0000000..48bd659
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.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://floralicense.org/license/
+//
+// 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 <iostream>
+
+#include <stdlib.h>
+#include <tet_api.h>
+
+#include <dali/public-api/dali-core.h>
+
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+static void Startup();
+static void Cleanup();
+
+extern "C"
+{
+  void (*tet_startup)() = Startup;
+  void (*tet_cleanup)() = Cleanup;
+}
+
+enum
+{
+  POSITIVE_TC_IDX = 0x01,
+  NEGATIVE_TC_IDX,
+};
+
+#define MAX_NUMBER_OF_TESTS 10000
+extern "C" {
+  struct tet_testlist tet_testlist[MAX_NUMBER_OF_TESTS];
+}
+
+// Add test functionality for all APIs in the class (Positive and Negative)
+TEST_FUNCTION( UtcDaliConstrainableDownCast, POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliConstrainableDownCastNegative, NEGATIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliConstrainableCustomProperty, POSITIVE_TC_IDX );
+
+
+// Called only once before first test is run.
+static void Startup()
+{
+}
+
+// Called only once after last test is run
+static void Cleanup()
+{
+}
+
+static void UtcDaliConstrainableDownCast()
+{
+  TestApplication application;
+
+  Handle handle = Constrainable::New();
+
+  Constrainable customHandle1 = Constrainable::DownCast( handle );
+  DALI_TEST_CHECK( customHandle1 );
+
+  Constrainable customHandle2 = DownCast< Constrainable >( handle );
+  DALI_TEST_CHECK( customHandle2 );
+}
+
+static void UtcDaliConstrainableDownCastNegative()
+{
+  TestApplication application;
+
+  Image image = Image::New( "temp" );
+  Constrainable customHandle1 = Constrainable::DownCast( image );
+  DALI_TEST_CHECK( ! customHandle1 );
+
+  Constrainable empty;
+  Constrainable customHandle2 = Constrainable::DownCast( empty );
+  DALI_TEST_CHECK( ! customHandle2 );
+}
+
+static void UtcDaliConstrainableCustomProperty()
+{
+  TestApplication application;
+
+  Constrainable handle = Constrainable::New();
+
+  float startValue(1.0f);
+  Property::Index index = handle.RegisterProperty( "test-property", startValue );
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == startValue );
+  application.Render(0);
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == startValue );
+
+  handle.SetProperty( index, 5.0f );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == 5.0f );
+  application.Render(0);
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == 5.0f );
+}
+
index 86eab80..4fbdd7e 100644 (file)
@@ -46,6 +46,12 @@ class Constrainable : public Handle
 public:
 
   /**
+   * Create a constrainable object.
+   * @return A handle to a newly allocated object.
+   */
+  static Constrainable New();
+
+  /**
    * This constructor provides an uninitialized Dali::Constrainable.
    * This should be initialized with a Dali New() method before use.
    * Methods called on an uninitialized Dali::Constrainable will assert.
@@ -60,6 +66,13 @@ public:
   Constrainable();
 
   /**
+   * Downcast a handle to a custom object.
+   * @param[in] handle The handle to cast.
+   * @return A handle to a custom object or an empty handle.
+   */
+  static Constrainable DownCast( BaseHandle handle );
+
+  /**
    * Dali::Handle is intended as a base class
    */
   virtual ~Constrainable();
@@ -106,7 +119,6 @@ public:
 
 public:
 
-
   /**
    * This constructor is used by Dali New() methods.
    * @param [in] handle A pointer to a newly allocated Dali resource
index 801a055..6d8603e 100644 (file)
@@ -750,7 +750,99 @@ void ProxyObject::DeleteRemovedConstraints()
       ++iter;
     }
   }
- }
+}
+
+void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
+{
+  switch ( entry.type )
+  {
+    case Property::BOOLEAN:
+    {
+      AnimatableProperty<bool>* property = dynamic_cast< AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<bool>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<bool>() );
+      break;
+    }
+
+    case Property::FLOAT:
+    {
+      AnimatableProperty<float>* property = dynamic_cast< AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<float>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<float>() );
+      break;
+    }
+
+    case Property::VECTOR2:
+    {
+      AnimatableProperty<Vector2>* property = dynamic_cast< AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Vector2>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector2>() );
+      break;
+    }
+
+    case Property::VECTOR3:
+    {
+      AnimatableProperty<Vector3>* property = dynamic_cast< AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Vector3>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector3>() );
+      break;
+    }
+
+    case Property::VECTOR4:
+    {
+      AnimatableProperty<Vector4>* property = dynamic_cast< AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Vector4>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector4>() );
+      break;
+    }
+
+    case Property::ROTATION:
+    {
+      AnimatableProperty<Quaternion>* property = dynamic_cast< AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Quaternion>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Quaternion>() );
+      break;
+    }
+
+    case Property::MATRIX:
+    {
+      AnimatableProperty<Matrix>* property = dynamic_cast< AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Matrix>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Matrix>() );
+      break;
+    }
+
+    case Property::MATRIX3:
+    {
+      AnimatableProperty<Matrix3>* property = dynamic_cast< AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Matrix3>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Matrix3>() );
+      break;
+    }
+
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false && "Property type enumeration out of bounds"); // should not come here
+      break;
+    }
+  }
+}
 
 CustomPropertyLookup& ProxyObject::GetCustomPropertyLookup() const
 {
index 95f37a1..5b985c0 100644 (file)
@@ -378,7 +378,7 @@ private: // Default property extensions for derived classes
    * @param [in] entry An entry from the CustomPropertyLookup.
    * @param [in] value The new value of the property.
    */
-  virtual void SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value ) = 0;
+  virtual void SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value );
 
   /**
    * Retrieve a default property value.
index b25cf01..df53643 100644 (file)
@@ -698,100 +698,6 @@ void ShaderEffect::SetDefaultProperty( Property::Index index, const Property::Va
   }
 }
 
-void ShaderEffect::SetCustomProperty( Property::Index /* index */, const CustomProperty& entry, const Property::Value& value )
-{
-  DALI_ASSERT_ALWAYS(entry.IsAnimatable() && "shader effect has only animatable properties");
-
-  switch ( entry.type )
-  {
-    case Property::BOOLEAN:
-    {
-      AnimatableProperty<bool>* property = dynamic_cast< AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
-      DALI_ASSERT_DEBUG( NULL != property );
-
-      // property is being used in a separate thread; queue a message to set the property
-      BakeMessage<bool>( mUpdateManager.GetEventToUpdate(), *property, value.Get<bool>() );
-      break;
-    }
-
-    case Property::FLOAT:
-    {
-      AnimatableProperty<float>* property = dynamic_cast< AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
-      DALI_ASSERT_DEBUG( NULL != property );
-
-      // property is being used in a separate thread; queue a message to set the property
-      BakeMessage<float>( mUpdateManager.GetEventToUpdate(), *property, value.Get<float>() );
-      break;
-    }
-
-    case Property::VECTOR2:
-    {
-      AnimatableProperty<Vector2>* property = dynamic_cast< AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
-      DALI_ASSERT_DEBUG( NULL != property );
-
-      // property is being used in a separate thread; queue a message to set the property
-      BakeMessage<Vector2>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Vector2>() );
-      break;
-    }
-
-    case Property::VECTOR3:
-    {
-      AnimatableProperty<Vector3>* property = dynamic_cast< AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
-      DALI_ASSERT_DEBUG( NULL != property );
-
-      // property is being used in a separate thread; queue a message to set the property
-      BakeMessage<Vector3>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Vector3>() );
-      break;
-    }
-
-    case Property::VECTOR4:
-    {
-      AnimatableProperty<Vector4>* property = dynamic_cast< AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
-      DALI_ASSERT_DEBUG( NULL != property );
-
-      // property is being used in a separate thread; queue a message to set the property
-      BakeMessage<Vector4>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Vector4>() );
-      break;
-    }
-
-    case Property::ROTATION:
-    {
-      AnimatableProperty<Quaternion>* property = dynamic_cast< AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
-      DALI_ASSERT_DEBUG( NULL != property );
-
-      // property is being used in a separate thread; queue a message to set the property
-      BakeMessage<Quaternion>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Quaternion>() );
-      break;
-    }
-
-    case Property::MATRIX:
-    {
-      AnimatableProperty<Matrix>* property = dynamic_cast< AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
-      DALI_ASSERT_DEBUG( NULL != property );
-
-      // property is being used in a separate thread; queue a message to set the property
-      BakeMessage<Matrix>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Matrix>() );
-      break;
-    }
-
-    case Property::MATRIX3:
-    {
-      AnimatableProperty<Matrix3>* property = dynamic_cast< AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
-      DALI_ASSERT_DEBUG( NULL != property );
-
-      // property is being used in a separate thread; queue a message to set the property
-      BakeMessage<Matrix3>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Matrix3>() );
-      break;
-    }
-
-    default:
-    {
-      DALI_ASSERT_ALWAYS(false && "Property type enumeration out of bounds"); // should not come here
-      break;
-    }
-  }
-}
-
 Property::Value ShaderEffect::GetDefaultProperty(Property::Index /*index*/) const
 {
   // none of our properties are readable so return empty
index e0c2773..a40238b 100644 (file)
@@ -228,11 +228,6 @@ public: // Default property extensions from ProxyObject
   virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue );
 
   /**
-   * @copydoc Dali::Internal::ProxyObject::SetCustomProperty()
-   */
-  virtual void SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value );
-
-  /**
    * @copydoc Dali::Internal::ProxyObject::GetDefaultProperty()
    */
   virtual Property::Value GetDefaultProperty( Property::Index index ) const;
diff --git a/dali/internal/event/object/custom-object-internal.cpp b/dali/internal/event/object/custom-object-internal.cpp
new file mode 100644 (file)
index 0000000..7607f80
--- /dev/null
@@ -0,0 +1,156 @@
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.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://floralicense.org/license/
+//
+// 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.
+//
+
+// CLASS HEADER
+#include <dali/internal/event/object/custom-object-internal.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/stage-impl.h>
+#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/manager/update-manager.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+
+using Dali::Internal::SceneGraph::PropertyOwner;
+using Dali::Internal::SceneGraph::PropertyBase;
+using Dali::Internal::SceneGraph::UpdateManager;
+using Dali::Internal::SceneGraph::AnimatableProperty;
+
+namespace
+{
+const std::string INVALID_PROPERTY_NAME;
+}
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+CustomObject* CustomObject::New()
+{
+  return new CustomObject();
+}
+
+bool CustomObject::IsSceneObjectRemovable() const
+{
+  return false;
+}
+
+const SceneGraph::PropertyOwner* CustomObject::GetSceneObject() const
+{
+  return mUpdateObject;
+}
+
+const PropertyBase* CustomObject::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  const PropertyBase* property( NULL );
+
+  CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
+
+  DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "index is invalid" );
+
+  property = dynamic_cast<const PropertyBase*>( entry->second.GetSceneGraphProperty() );
+
+  return property;
+}
+
+const PropertyInputImpl* CustomObject::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  return GetSceneObjectAnimatableProperty( index );
+}
+
+unsigned int CustomObject::GetDefaultPropertyCount() const
+{
+  return 0u;
+}
+
+void CustomObject::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+}
+
+const std::string& CustomObject::GetDefaultPropertyName( Property::Index index ) const
+{
+  return INVALID_PROPERTY_NAME;
+}
+
+Property::Index CustomObject::GetDefaultPropertyIndex(const std::string& name) const
+{
+  return Property::INVALID_INDEX;
+}
+
+bool CustomObject::IsDefaultPropertyWritable(Property::Index index) const
+{
+  return false;
+}
+
+bool CustomObject::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  return false;
+}
+
+Property::Type CustomObject::GetDefaultPropertyType(Property::Index index) const
+{
+  return Property::NONE;
+}
+
+void CustomObject::SetDefaultProperty( Property::Index index, const Property::Value& property )
+{
+  // do nothing
+}
+
+Property::Value CustomObject::GetDefaultProperty(Property::Index index) const
+{
+  return Property::Value();
+}
+
+void CustomObject::InstallSceneObjectProperty( PropertyBase& newProperty, const std::string& name, unsigned int index )
+{
+  if( NULL != mUpdateObject )
+  {
+    // mUpdateObject is being used in a separate thread; queue a message to add the property
+    InstallCustomPropertyMessage( Stage::GetCurrent()->GetUpdateInterface(), *mUpdateObject, newProperty ); // Message takes ownership
+  }
+}
+
+CustomObject::~CustomObject()
+{
+  // Guard to allow handle destruction after Core has been destroyed
+  if( Stage::IsInstalled() )
+  {
+    if( NULL != mUpdateObject )
+    {
+      RemoveObjectMessage( Stage::GetCurrent()->GetUpdateManager(), mUpdateObject );
+      mUpdateObject = NULL; // object is about to be destroyed
+    }
+  }
+}
+
+CustomObject::CustomObject()
+{
+  PropertyOwner* updateObject = PropertyOwner::New();
+
+  // Pass ownership to the update-thread
+  AddObjectMessage( Stage::GetCurrent()->GetUpdateManager(), updateObject );
+
+  // Keep as const since this should only be modified from update-thread
+  mUpdateObject = updateObject;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/object/custom-object-internal.h b/dali/internal/event/object/custom-object-internal.h
new file mode 100644 (file)
index 0000000..c5a9c07
--- /dev/null
@@ -0,0 +1,141 @@
+#ifndef __DALI_INTERNAL_CUSTOM_OBJECT_H__
+#define __DALI_INTERNAL_CUSTOM_OBJECT_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.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://floralicense.org/license/
+//
+// 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/event/common/proxy-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class PropertyOwner;
+}
+
+class CustomObject : public ProxyObject
+{
+public:
+
+  /**
+   * Create a new custom object.
+   * @return A pointer to the newly allocated object.
+   */
+  static CustomObject* New();
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::IsSceneObjectRemovable()
+   */
+  virtual bool IsSceneObjectRemovable() const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyName()
+   */
+  virtual const std::string& GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::InstallSceneObjectProperty()
+   */
+  virtual void InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index );
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~CustomObject();
+
+  /**
+   * Private constructor; see also CustomObject::New()
+   */
+  CustomObject();
+
+  // Undefined
+  CustomObject(const CustomObject&);
+
+  // Undefined
+  CustomObject& operator=(const CustomObject& rhs);
+
+protected:
+
+  SceneGraph::PropertyOwner* mUpdateObject;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CUSTOM_OBJECT_H__
index a7748a8..10a2129 100644 (file)
@@ -96,6 +96,7 @@ internal_src_files = \
   $(internal_src_dir)/event/modeling/model-factory.cpp \
   $(internal_src_dir)/event/modeling/model-impl.cpp \
   $(internal_src_dir)/event/modeling/model-logger.cpp \
+  $(internal_src_dir)/event/object/custom-object-internal.cpp \
   $(internal_src_dir)/event/render-tasks/render-task-impl.cpp \
   $(internal_src_dir)/event/render-tasks/render-task-list-impl.cpp \
   $(internal_src_dir)/event/resources/archive.cpp \
index a67e390..d2283e0 100644 (file)
@@ -33,6 +33,11 @@ namespace Internal
 namespace SceneGraph
 {
 
+PropertyOwner* PropertyOwner::New()
+{
+  return new PropertyOwner();
+}
+
 PropertyOwner::~PropertyOwner()
 {
   DisconnectFromSceneGraph();
index 9e68bd2..b3dfa12 100644 (file)
@@ -46,7 +46,7 @@ typedef OwnerContainer< PropertyBase* > OwnedPropertyContainer;
 typedef OwnedPropertyContainer::Iterator  OwnedPropertyIter;
 
 /**
- * Base for scene-graph objects which own properties.
+ * An update-thread object which own properties.
  * This allows observers to track the lifetime of the object & its properties.
  */
 class PropertyOwner
@@ -64,6 +64,12 @@ public:
   };
 
   /**
+   * Create a property owner.
+   * @return A newly allocated object.
+   */
+  static PropertyOwner* New();
+
+  /**
    * Virtual destructor; this is intended as a base class.
    */
   virtual ~PropertyOwner();
@@ -166,7 +172,7 @@ private:
    * Called after ResetToBaseValues; derived classes should reset any default properties.
    * @param[in] currentBufferIndex The buffer to reset.
    */
-  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex ) = 0;
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex ) {}
 
 protected:
 
index 4e8aebc..921030b 100644 (file)
@@ -265,6 +265,8 @@ struct UpdateManager::Impl
   SortedLayerPointers                 sortedLayers;                  ///< A container of Layer pointers sorted by depth
   SortedLayerPointers                 systemLevelSortedLayers;       ///< A separate container of system-level Layers
 
+  OwnerContainer< PropertyOwner* >    customObjects;                 ///< A container of owned objects (with custom properties)
+
   AnimationContainer                  animations;                    ///< A container of owned animations
   PropertyNotificationContainer       propertyNotifications;         ///< A container of owner property notifications.
 
@@ -436,6 +438,34 @@ void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
   attachment->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
 }
 
+void UpdateManager::AddObject( PropertyOwner* object )
+{
+  DALI_ASSERT_DEBUG( NULL != object );
+
+  mImpl->customObjects.PushBack( object );
+}
+
+void UpdateManager::RemoveObject( PropertyOwner* object )
+{
+  DALI_ASSERT_DEBUG( NULL != object );
+
+  OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
+
+  // Find the object and destroy it
+  for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
+  {
+    PropertyOwner* current = *iter;
+    if ( current == object )
+    {
+      customObjects.Erase( iter );
+      return;
+    }
+  }
+
+  // Should not reach here
+  DALI_ASSERT_DEBUG(false);
+}
+
 void UpdateManager::AddAnimation( Animation* animation )
 {
   mImpl->animations.PushBack( animation );
@@ -743,6 +773,12 @@ void UpdateManager::ResetProperties()
     (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
   }
 
+  // Reset custom object properties to base values
+  for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
+  {
+    (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
+  }
+
   // Reset animatable shader properties to base values
   for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
   {
@@ -809,6 +845,16 @@ void UpdateManager::ApplyConstraints()
 
   mImpl->activeConstraints = 0;
 
+  // constrain custom objects... (in construction order)
+  OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
+
+  const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
+  for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
+  {
+    PropertyOwner& object = **iter;
+    mImpl->activeConstraints += ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
+  }
+
   // constrain nodes... (in Depth First traversal order)
   if ( mImpl->root )
   {
index c22317a..c8cbaf2 100644 (file)
@@ -211,6 +211,19 @@ public:
    */
   void AttachToNode( Node* node, NodeAttachment* attachment );
 
+  /**
+   * Add a newly created object.
+   * @param[in] object The object to add.
+   * @post The object is owned by UpdateManager.
+   */
+  void AddObject( PropertyOwner* object );
+
+  /**
+   * Remove an object.
+   * @param[in] object The object to remove.
+   */
+  void RemoveObject( PropertyOwner* object );
+
   // Animations
 
   /**
@@ -554,6 +567,28 @@ inline void AttachToNodeMessage( UpdateManager& manager, const Node& constParent
   new (slot) LocalType( &manager, &UpdateManager::AttachToNode, &parent, attachment );
 }
 
+inline void AddObjectMessage( UpdateManager& manager, PropertyOwner* object )
+{
+  typedef MessageValue1< UpdateManager, OwnerPointer<PropertyOwner> > 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::AddObject, object );
+}
+
+inline void RemoveObjectMessage( UpdateManager& manager, PropertyOwner* object )
+{
+  typedef MessageValue1< UpdateManager, PropertyOwner* > 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::RemoveObject, object );
+}
+
 inline void AddAnimationMessage( UpdateManager& manager, Animation* animation )
 {
   typedef MessageValue1< UpdateManager, Animation* > LocalType;
index dfd8d11..67f78d2 100644 (file)
 #include <dali/public-api/animation/active-constraint.h>
 #include <dali/internal/event/common/proxy-object.h>
 #include <dali/internal/event/animation/constraint-impl.h>
+#include <dali/internal/event/object/custom-object-internal.h>
 
 namespace Dali
 {
 
+Constrainable Constrainable::New()
+{
+  return Constrainable( Internal::CustomObject::New() );
+}
+
 Constrainable::Constrainable(Dali::Internal::Object* handle)
 : Handle(handle)
 {
@@ -32,6 +38,11 @@ Constrainable::Constrainable()
 {
 }
 
+Constrainable Constrainable::DownCast( BaseHandle handle )
+{
+  return Constrainable( dynamic_cast<Dali::Internal::ProxyObject*>(handle.GetObjectPtr()) );
+}
+
 Constrainable::~Constrainable()
 {
 }