Add a mechanism to specify a callback on every frame 71/139171/21
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Mon, 17 Jul 2017 18:27:49 +0000 (19:27 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 31 Aug 2018 13:46:34 +0000 (14:46 +0100)
Change-Id: I71642330a7e5c2fc69b2661648d698a6dad8caf9

25 files changed:
automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/utc-Dali-FrameCallbackInterface.cpp [new file with mode: 0644]
build/tizen/dali-core/Makefile.am
dali/devel-api/common/stage-devel.cpp
dali/devel-api/common/stage-devel.h
dali/devel-api/file.list
dali/devel-api/update/frame-callback-interface.h [new file with mode: 0644]
dali/devel-api/update/update-proxy.cpp [new file with mode: 0644]
dali/devel-api/update/update-proxy.h [new file with mode: 0644]
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/actors/layer-impl.cpp
dali/internal/event/common/stage-impl.cpp
dali/internal/event/common/stage-impl.h
dali/internal/file.list
dali/internal/update/manager/frame-callback-processor.cpp [new file with mode: 0644]
dali/internal/update/manager/frame-callback-processor.h [new file with mode: 0644]
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/internal/update/manager/update-proxy-impl.cpp [new file with mode: 0644]
dali/internal/update/manager/update-proxy-impl.h [new file with mode: 0644]
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/internal/update/nodes/scene-graph-layer.cpp
dali/internal/update/nodes/scene-graph-layer.h

index 6fdf651..2c8e72e 100644 (file)
@@ -30,6 +30,7 @@ SET(TC_SOURCES
         utc-Dali-Extents.cpp
         utc-Dali-FrameBuffer.cpp
         utc-Dali-FrameBufferImage.cpp
+        utc-Dali-FrameCallbackInterface.cpp
         utc-Dali-Geometry.cpp
         utc-Dali-Gesture.cpp
         utc-Dali-GestureDetector.cpp
diff --git a/automated-tests/src/dali/utc-Dali-FrameCallbackInterface.cpp b/automated-tests/src/dali/utc-Dali-FrameCallbackInterface.cpp
new file mode 100644 (file)
index 0000000..0a3afb2
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * 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 <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/common/map-wrapper.h>
+#include <dali/devel-api/common/stage-devel.h>
+#include <dali/devel-api/update/frame-callback-interface.h>
+#include <dali/devel-api/update/update-proxy.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_frame_callback_interface_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_frame_callback_interface_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+
+class FrameCallbackBasic : public FrameCallbackInterface
+{
+public:
+
+  FrameCallbackBasic()
+  : mCalled( false )
+  {
+  }
+
+  virtual void Update( Dali::UpdateProxy& updateProxy, float elapsedSeconds )
+  {
+    mCalled = true;
+  }
+
+  bool mCalled;
+};
+
+} // anon namespace
+
+class FrameCallbackOneActor : public FrameCallbackBasic
+{
+public:
+
+  FrameCallbackOneActor( unsigned int actorId )
+  : mActorId( actorId )
+  {
+  }
+
+  virtual void Update( Dali::UpdateProxy& updateProxy, float elapsedSeconds )
+  {
+    FrameCallbackBasic::Update( updateProxy, elapsedSeconds );
+    updateProxy.GetWorldMatrixAndSize( mActorId, mWorldMatrix, mSize );
+    mWorldMatrixGetWorldMatrixCall = updateProxy.GetWorldMatrix( mActorId );
+    mSizeGetSizeCall = updateProxy.GetSize( mActorId );
+    mPositionGetPositionCall = updateProxy.GetPosition( mActorId );
+    updateProxy.GetPositionAndSize( mActorId, mPositionGetPositionAndSizeCall, mSizeGetPositionAndSizeCall );
+    mWorldColor = updateProxy.GetWorldColor( mActorId );
+  }
+
+  const unsigned int mActorId;
+
+  Matrix mWorldMatrix;
+  Matrix mWorldMatrixGetWorldMatrixCall;
+  Vector3 mSize;
+  Vector3 mSizeGetSizeCall;
+  Vector3 mPositionGetPositionCall;
+  Vector3 mPositionGetPositionAndSizeCall;
+  Vector3 mSizeGetPositionAndSizeCall;
+  Vector4 mWorldColor;
+};
+
+class FrameCallbackSetter : public FrameCallbackBasic
+{
+public:
+
+  FrameCallbackSetter(
+      unsigned int actorId,
+      const Matrix& matrixToSet,
+      const Vector3& sizeToSet,
+      const Vector3& positionToSet,
+      const Vector4& colorToSet )
+  : mActorId( actorId ),
+    mMatrixToSet( matrixToSet ),
+    mSizeToSet( sizeToSet ),
+    mPositionToSet( positionToSet ),
+    mColorToSet( colorToSet )
+  {
+  }
+
+  virtual void Update( Dali::UpdateProxy& updateProxy, float elapsedSeconds )
+  {
+    FrameCallbackBasic::Update( updateProxy, elapsedSeconds );
+    updateProxy.SetWorldMatrix( mActorId, mMatrixToSet );
+    updateProxy.SetSize( mActorId, mSizeToSet );
+    updateProxy.GetWorldMatrixAndSize( mActorId, mWorldMatrixAfterSetting, mSizeAfterSetting );
+    updateProxy.SetPosition( mActorId, mPositionToSet );
+    mPositionAfterSetting = updateProxy.GetPosition( mActorId );
+    updateProxy.SetWorldColor( mActorId, mColorToSet );
+    mColorAfterSetting = updateProxy.GetWorldColor( mActorId );
+  }
+
+  const unsigned int mActorId;
+  const Matrix& mMatrixToSet;
+  const Vector3& mSizeToSet;
+  const Vector3& mPositionToSet;
+  const Vector4& mColorToSet;
+
+  Matrix mWorldMatrixAfterSetting;
+  Vector3 mSizeAfterSetting;
+  Vector3 mPositionAfterSetting;
+  Vector4 mColorAfterSetting;
+};
+
+class FrameCallbackMultipleActors : public FrameCallbackBasic
+{
+public:
+
+  FrameCallbackMultipleActors()
+  {
+  }
+
+  virtual void Update( Dali::UpdateProxy& updateProxy, float elapsedSeconds )
+  {
+    FrameCallbackBasic::Update( updateProxy, elapsedSeconds );
+    for( auto&& i : mActorIds )
+    {
+      Matrix matrix( false );
+      Vector3 size;
+      updateProxy.GetWorldMatrixAndSize( i, matrix, size );
+      mWorldMatrices[ i ] = matrix;
+      mSizes[ i ] = size;
+    }
+  }
+
+  Vector< unsigned int > mActorIds;
+
+  std::map< unsigned int, Matrix > mWorldMatrices;
+  std::map< unsigned int, Vector3 > mSizes;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+int UtcDaliFrameCallbackCheckInstallationAndRemoval(void)
+{
+  TestApplication application;
+
+  FrameCallbackBasic frameCallback;
+
+  Stage stage = Stage::GetCurrent();
+  DevelStage::AddFrameCallback( stage, frameCallback, stage.GetRootLayer() );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( frameCallback.mCalled, true, TEST_LOCATION );
+
+  frameCallback.mCalled = false;
+
+  DevelStage::RemoveFrameCallback( stage, frameCallback );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( frameCallback.mCalled, false, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliFrameCallbackGetters(void)
+{
+  TestApplication application;
+  Vector2 actorSize( 200, 300 );
+  Vector4 color( 0.5f, 0.6f, 0.7f, 0.8f );
+  Vector3 position( 10.0f, 20.0f, 30.0f );
+
+  Actor actor = Actor::New();
+  actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  actor.SetSize( actorSize );
+  actor.SetColor( color );
+  actor.SetPosition( position );
+
+  Stage stage = Stage::GetCurrent();
+  stage.Add( actor );
+  Vector2 stageSize = stage.GetSize();
+
+  FrameCallbackOneActor frameCallback( actor.GetId() );
+  DevelStage::AddFrameCallback( stage, frameCallback, stage.GetRootLayer() );
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 expectedPosition( -stageSize.width * 0.5f + actorSize.width * 0.5f + position.x,
+                            -stageSize.height * 0.5f + actorSize.height * 0.5f + position.y,
+                            0.0f + position.z );
+
+  Matrix expectedWorldMatrix( false );
+  expectedWorldMatrix.SetIdentity();
+  expectedWorldMatrix.SetTranslation( expectedPosition );
+
+  DALI_TEST_EQUALS( frameCallback.mCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mWorldMatrix, expectedWorldMatrix, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mWorldMatrixGetWorldMatrixCall, expectedWorldMatrix, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mSize, Vector3( actorSize.width, actorSize.height, 0.0f ), TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mSizeGetSizeCall, Vector3( actorSize.width, actorSize.height, 0.0f ), TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mPositionGetPositionCall, expectedPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mPositionGetPositionAndSizeCall, expectedPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mSizeGetPositionAndSizeCall, Vector3( actorSize.width, actorSize.height, 0.0f ), TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mWorldColor, color, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliFrameCallbackSetters(void)
+{
+  TestApplication application;
+  Vector2 actorSize( 200, 300 );
+
+  Actor actor = Actor::New();
+  actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  actor.SetSize( actorSize );
+
+  Stage stage = Stage::GetCurrent();
+  stage.Add( actor );
+  Vector2 stageSize = stage.GetSize();
+
+  Matrix matrixToSet( Matrix::IDENTITY );
+  matrixToSet.SetTranslation( Vector3( 100.0f, 500.0f, 50.0f ) );
+  Vector3 sizeToSet( 1.0f, 2.0f, 3.0f );
+  Vector3 positionToSet( 10.0f, 20.0f, 30.0f );
+  Vector4 colorToSet( Color::MAGENTA );
+
+  FrameCallbackSetter frameCallback( actor.GetId(), matrixToSet, sizeToSet, positionToSet, colorToSet );
+  DevelStage::AddFrameCallback( stage, frameCallback, stage.GetRootLayer() );
+
+  application.SendNotification();
+  application.Render();
+
+  Matrix expectedWorldMatrix( false );
+  expectedWorldMatrix.SetIdentity();
+  expectedWorldMatrix.SetTranslation( Vector3( -stageSize.width * 0.5f + actorSize.width * 0.5f,
+                                               -stageSize.height * 0.5f + actorSize.height * 0.5f,
+                                               0.0f ) );
+
+  DALI_TEST_EQUALS( frameCallback.mCalled, true, TEST_LOCATION );
+  DALI_TEST_CHECK( expectedWorldMatrix != matrixToSet );
+  DALI_TEST_EQUALS( frameCallback.mWorldMatrixAfterSetting, matrixToSet, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mSizeAfterSetting, sizeToSet, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mPositionAfterSetting, positionToSet, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mColorAfterSetting, colorToSet, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliFrameCallbackMultipleActors(void)
+{
+  /**
+   * Tree:
+   *              root-layer
+   *              /        \
+   *             /          \
+   *            /            \
+   *           /              \
+   *        actorA           actorE
+   *         / \              / \
+   *        /   \            /   \
+   *    actorB  actorD   actorF actorG
+   *      /                        \
+   *   actorC                     actorH
+   *
+   *  Screen positions:
+   *  -----------------------
+   *  |actorA|actorD        |
+   *  |      actorB         |
+   *  |      actorC         |
+   *  |                     |
+   *  |                     |
+   *  |                     |
+   *  |                     |
+   *  |                     |
+   *  |actorF       actorH  |
+   *  |actorE|actorG        |
+   *  -----------------------
+   */
+
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+  const Vector2 stageSize = stage.GetSize();
+
+  std::map< char, Vector3 > sizes;
+  sizes['A'] = Vector3(  50.0f,  50.0f, 0.0f );
+  sizes['B'] = Vector3( 100.0f, 100.0f, 0.0f );
+  sizes['C'] = Vector3( 150.0f, 150.0f, 0.0f );
+  sizes['D'] = Vector3( 200.0f, 200.0f, 0.0f );
+  sizes['E'] = Vector3( 250.0f, 250.0f, 0.0f );
+  sizes['F'] = Vector3( 300.0f, 300.0f, 0.0f );
+  sizes['G'] = Vector3( 350.0f, 350.0f, 0.0f );
+  sizes['H'] = Vector3( 400.0f, 350.0f, 0.0f );
+
+  std::map< char, Matrix > matrices;
+  for( char i = 'A'; i <= 'H'; ++i )
+  {
+    matrices[i] = Matrix::IDENTITY;
+  }
+
+  matrices['A'].SetTranslation( Vector3( -stageSize.width * 0.5f + sizes['A'].width * 0.5f,
+                                         -stageSize.height * 0.5f + sizes['A'].height * 0.5f,
+                                         0.0f ) );
+  matrices['B'].SetTranslation( Vector3( matrices['A'].GetTranslation3() + sizes['A'] * 0.5f + sizes['B'] * 0.5f ) );
+  matrices['C'].SetTranslation( Vector3( matrices['B'].GetTranslation3().x,
+                                         matrices['B'].GetTranslation3().y + sizes['B'].height * 0.5f + sizes['C'].height * 0.5f,
+                                         0.0f ) );
+  matrices['D'].SetTranslation( Vector3( matrices['A'].GetTranslation3().x + sizes['A'].width * 0.5f + sizes['D'].width * 0.5f,
+                                         matrices['A'].GetTranslation3().y,
+                                         0.0f ) );
+  matrices['E'].SetTranslation( Vector3( -stageSize.width * 0.5f + sizes['E'].width * 0.5f,
+                                         stageSize.height * 0.5f - sizes['E'].height * 0.5f,
+                                         0.0f ) );
+  matrices['F'].SetTranslation( Vector3( matrices['E'].GetTranslation3().x,
+                                         matrices['E'].GetTranslation3().y - sizes['E'].height * 0.5f - sizes['F'].height * 0.5f,
+                                         0.0f ) );
+  matrices['G'].SetTranslation( Vector3( matrices['E'].GetTranslation3().x + sizes['E'].width * 0.5f + sizes['G'].width * 0.5f,
+                                         matrices['E'].GetTranslation3().y,
+                                         0.0f ) );
+  matrices['H'].SetTranslation( Vector3( matrices['G'].GetTranslation3().x + sizes['G'].width * 0.5f + sizes['H'].width * 0.5f,
+                                         matrices['G'].GetTranslation3().y - sizes['G'].height * 0.5f - sizes['H'].height * 0.5f,
+                                         0.0f ) );
+
+  Actor actorA = Actor::New();
+  actorA.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  actorA.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  actorA.SetSize( sizes['A'] );
+  stage.Add( actorA );
+
+  Actor actorB = Actor::New();
+  actorB.SetParentOrigin( ParentOrigin::BOTTOM_RIGHT );
+  actorB.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  actorB.SetSize( sizes['B'] );
+  actorA.Add( actorB );
+
+  Actor actorC = Actor::New();
+  actorC.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
+  actorC.SetAnchorPoint( AnchorPoint::TOP_CENTER );
+  actorC.SetSize( sizes['C'] );
+  actorB.Add( actorC );
+
+  Actor actorD = Actor::New();
+  actorD.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
+  actorD.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
+  actorD.SetSize( sizes['D'] );
+  actorA.Add( actorD );
+
+  Actor actorE = Actor::New();
+  actorE.SetParentOrigin( ParentOrigin::BOTTOM_LEFT );
+  actorE.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
+  actorE.SetSize( sizes['E'] );
+  stage.Add( actorE );
+
+  Actor actorF = Actor::New();
+  actorF.SetParentOrigin( ParentOrigin::TOP_CENTER );
+  actorF.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
+  actorF.SetSize( sizes['F'] );
+  actorE.Add( actorF );
+
+  Actor actorG = Actor::New();
+  actorG.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
+  actorG.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
+  actorG.SetSize( sizes['G'] );
+  actorE.Add( actorG );
+
+  Actor actorH = Actor::New();
+  actorH.SetParentOrigin( ParentOrigin::TOP_RIGHT );
+  actorH.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
+  actorH.SetSize( sizes['H'] );
+  actorG.Add( actorH );
+
+  std::map< char, unsigned int > actorIds;
+  actorIds['A'] = actorA.GetId();
+  actorIds['B'] = actorB.GetId();
+  actorIds['C'] = actorC.GetId();
+  actorIds['D'] = actorD.GetId();
+  actorIds['E'] = actorE.GetId();
+  actorIds['F'] = actorF.GetId();
+  actorIds['G'] = actorG.GetId();
+  actorIds['H'] = actorH.GetId();
+
+  FrameCallbackMultipleActors frameCallback;
+  for( auto&& i : actorIds )
+  {
+    frameCallback.mActorIds.PushBack( i.second );
+  }
+
+  DevelStage::AddFrameCallback( stage, frameCallback, stage.GetRootLayer() );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( frameCallback.mCalled, true, TEST_LOCATION );
+
+  for( char i = 'A'; i <= 'H'; ++i )
+  {
+    DALI_TEST_EQUALS( frameCallback.mWorldMatrices[ actorIds[ i ] ], matrices[ i ], TEST_LOCATION );
+    DALI_TEST_EQUALS( frameCallback.mSizes[ actorIds[ i ] ], sizes[ i ], TEST_LOCATION );
+  }
+
+  // Render again to make sure it still gets called and gives the correct values (in case any optimisations break this)
+  frameCallback.mCalled = false;
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( frameCallback.mCalled, true, TEST_LOCATION );
+
+  for( char i = 'A'; i <= 'H'; ++i )
+  {
+    DALI_TEST_EQUALS( frameCallback.mWorldMatrices[ actorIds[ i ] ], matrices[ i ], TEST_LOCATION );
+    DALI_TEST_EQUALS( frameCallback.mSizes[ actorIds[ i ] ], sizes[ i ], TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliFrameCallbackCheckActorNotAdded(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  actor.SetSize( 200, 300 );
+
+  Stage stage = Stage::GetCurrent();
+  FrameCallbackOneActor frameCallback( actor.GetId() );
+  DevelStage::AddFrameCallback( stage, frameCallback, stage.GetRootLayer() );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( frameCallback.mCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mWorldMatrix, Matrix(true) /* Unchanged Matrix */, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mWorldMatrixGetWorldMatrixCall, Matrix::IDENTITY, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mSize, Vector3::ZERO, TEST_LOCATION );
+  DALI_TEST_EQUALS( frameCallback.mSizeGetSizeCall, Vector3::ZERO, TEST_LOCATION );
+
+  END_TEST;
+}
index 5ab447e..c9f9f07 100644 (file)
@@ -1,4 +1,4 @@
-# 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.
@@ -91,6 +91,7 @@ develapirenderingdir = $(develapidir)/rendering
 develapiscriptingdir = $(develapidir)/scripting
 develapisignalsdir = $(develapidir)/signals
 develapithreadingdir = $(develapidir)/threading
+develapiupdatedir = $(develapidir)/update
 
 develapi_HEADERS = $(devel_api_header_files)
 develapiactors_HEADERS = $(devel_api_core_actors_header_files)
@@ -104,6 +105,7 @@ develapirendering_HEADERS = $(devel_api_core_rendering_header_files)
 develapiscripting_HEADERS = $(devel_api_core_scripting_header_files)
 develapisignals_HEADERS = $(devel_api_core_signals_header_files)
 develapithreading_HEADERS = $(devel_api_core_threading_header_files)
+develapiupdate_HEADERS = $(devel_api_core_update_header_files)
 
 #public api
 publicapidir = $(devincludepath)/dali/public-api
index e4c23ad..0046d40 100644 (file)
@@ -40,6 +40,16 @@ Rendering GetRenderingBehavior( Dali::Stage stage )
   return GetImplementation( stage ).GetRenderingBehavior();
 }
 
+void AddFrameCallback( Dali::Stage stage, FrameCallbackInterface& frameCallback, Actor rootActor )
+{
+  GetImplementation( stage ).AddFrameCallback( frameCallback, GetImplementation( rootActor ) );
+}
+
+void RemoveFrameCallback( Dali::Stage stage, FrameCallbackInterface& frameCallback )
+{
+  GetImplementation( stage ).RemoveFrameCallback( frameCallback );
+}
+
 } // namespace DevelStage
 
 } // namespace Dali
index a0e19f4..3735f04 100644 (file)
@@ -24,6 +24,8 @@
 namespace Dali
 {
 
+class FrameCallbackInterface;
+
 namespace DevelStage
 {
 
@@ -65,6 +67,27 @@ DALI_CORE_API void SetRenderingBehavior( Dali::Stage stage, Rendering renderingB
  */
 DALI_CORE_API Rendering GetRenderingBehavior( Dali::Stage stage );
 
+/*
+ * @brief The FrameCallbackInterface implementation added gets called on every frame from the update-thread.
+ *
+ * @param[in] stage The stage to set the FrameCallbackInterface implementation on
+ * @param[in] frameCallback An implementation of the FrameCallbackInterface
+ * @param[in] rootActor The root-actor in the scene that the callback applies to
+ *
+ * @note Only the rootActor and it's children will be parsed by the UpdateProxy.
+ * @note If the rootActor is destroyed, then the callback is automatically removed
+ * @see FrameCallbackInterface
+ */
+DALI_IMPORT_API void AddFrameCallback( Dali::Stage stage, FrameCallbackInterface& frameCallback, Actor rootActor );
+
+/**
+ * @brief Removes the specified FrameCallbackInterface implementation from being called on every frame.
+ *
+ * @param[in] stage The stage to clear the FrameCallbackInterface on
+ * @param[in] frameCallback The FrameCallbackInterface implementation to remove
+ */
+DALI_IMPORT_API void RemoveFrameCallback( Dali::Stage stage, FrameCallbackInterface& frameCallback );
+
 } // namespace DevelStage
 
 } // namespace Dali
index d8c9ef3..0487c33 100644 (file)
@@ -18,7 +18,8 @@ devel_api_src_files = \
   $(devel_api_src_dir)/signals/signal-delegate.cpp \
   $(devel_api_src_dir)/threading/conditional-wait.cpp \
   $(devel_api_src_dir)/threading/mutex.cpp \
-  $(devel_api_src_dir)/threading/thread.cpp
+  $(devel_api_src_dir)/threading/thread.cpp \
+  $(devel_api_src_dir)/update/update-proxy.cpp
 
 # Add devel header files here DALi internal developer files used by Adaptor & Toolkit
 
@@ -71,3 +72,7 @@ devel_api_core_threading_header_files = \
   $(devel_api_src_dir)/threading/conditional-wait.h \
   $(devel_api_src_dir)/threading/mutex.h \
   $(devel_api_src_dir)/threading/thread.h
+
+devel_api_core_update_header_files = \
+  $(devel_api_src_dir)/update/frame-callback-interface.h \
+  $(devel_api_src_dir)/update/update-proxy.h
diff --git a/dali/devel-api/update/frame-callback-interface.h b/dali/devel-api/update/frame-callback-interface.h
new file mode 100644 (file)
index 0000000..d92c7be
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef DALI_FRAME_CALLBACK_INTERFACE_H
+#define DALI_FRAME_CALLBACK_INTERFACE_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/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+class UpdateProxy;
+
+/**
+ * @brief This interface should be implemented if a callback is required on every frame.
+ *
+ * The Update() method is called from the update-thread after the scene has been updated, and is ready to render.
+ *
+ * As this method is called from the update-thread, no event thread APIs (e.g. Actor::Get...) can be called.
+ * This will invariably lead to crashes.
+ *
+ * Instead, setting and retrieving the values should be done by using the UpdateProxy class returned as a parameter to
+ * the Update() method.
+ *
+ * Actors can be identified using Actor IDs which can be retrieved using Actor::GetId() in the event-thread.
+ * However, calling Actor::GetId() will lead to problems if it is called from the update-thread.
+ * Instead, the Actor IDs should be stored by the implementation of this class or passed via a thread-safe manner from
+ * the event-thread.
+ */
+class DALI_CORE_API FrameCallbackInterface
+{
+public:
+
+  /**
+   * @brief Called from the update-thread after the scene has been updated, and is ready to render.
+   * @param[in]  updateProxy  Use this to get/set required values for the Actor.
+   * @param[in]  elapsedSeconds  Time elapsed time since the last frame (in seconds)
+   * @see FrameCallbackInterface
+   */
+  virtual void Update( UpdateProxy& updateProxy, float elapsedSeconds ) = 0;
+
+protected:
+
+  /**
+   * @brief Protected constructor.
+   */
+  FrameCallbackInterface() {}
+
+  /**
+   * @brief Protected virtual destructor.
+   */
+  virtual ~FrameCallbackInterface() {}
+};
+
+} // namespace Dali
+
+#endif // DALI_FRAME_CALLBACK_INTERFACE_H
diff --git a/dali/devel-api/update/update-proxy.cpp b/dali/devel-api/update/update-proxy.cpp
new file mode 100644 (file)
index 0000000..67511b4
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/update/update-proxy.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/manager/update-proxy-impl.h>
+
+namespace Dali
+{
+
+Vector3 UpdateProxy::GetPosition( unsigned int id ) const
+{
+  return mImpl.GetPosition( id );
+}
+
+void UpdateProxy::SetPosition( unsigned int id, const Vector3& position )
+{
+  mImpl.SetPosition( id, position );
+}
+
+const Vector3& UpdateProxy::GetSize( unsigned int id ) const
+{
+  return mImpl.GetSize( id );
+}
+
+void UpdateProxy::SetSize( unsigned int id, const Vector3& size )
+{
+  mImpl.SetSize( id, size );
+}
+
+void UpdateProxy::GetPositionAndSize( unsigned int id, Vector3& position, Vector3& size ) const
+{
+  mImpl.GetPositionAndSize( id, position, size );
+}
+
+Vector4 UpdateProxy::GetWorldColor( unsigned int id ) const
+{
+  return mImpl.GetWorldColor( id );
+}
+
+void UpdateProxy::SetWorldColor( unsigned int id, const Vector4& color ) const
+{
+  mImpl.SetWorldColor( id, color );
+}
+
+void UpdateProxy::GetWorldMatrixAndSize( unsigned int id, Matrix& worldMatrix, Vector3& size ) const
+{
+  mImpl.GetWorldMatrixAndSize( id, worldMatrix, size );
+}
+
+const Matrix& UpdateProxy::GetWorldMatrix( unsigned int id ) const
+{
+  return mImpl.GetWorldMatrix( id );
+}
+
+void UpdateProxy::SetWorldMatrix( unsigned int id, const Matrix& worldMatrix )
+{
+  mImpl.SetWorldMatrix( id, worldMatrix );
+}
+
+UpdateProxy::UpdateProxy( Internal::UpdateProxy& impl )
+: mImpl( impl )
+{
+}
+
+UpdateProxy::~UpdateProxy()
+{
+}
+
+} // namespace Dali
diff --git a/dali/devel-api/update/update-proxy.h b/dali/devel-api/update/update-proxy.h
new file mode 100644 (file)
index 0000000..2ea1194
--- /dev/null
@@ -0,0 +1,159 @@
+#ifndef DALI_UPDATE_PROXY_H
+#define DALI_UPDATE_PROXY_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/public-api/common/dali-common.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector3.h>
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class UpdateProxy;
+}
+
+/**
+ * @brief This class is used to access data of the actors from the update-thread.
+ *
+ * The Actor API _CANNOT_ be called directly from the update-thread.
+ * This class can be used as a proxy to that required Actor data.
+ * An actor's data can be accessed using the Actor's Unique ID.
+ * The unique ID should be passed to the callback using this class in a thread-safe manner
+ * (as you cannot call Actor::GetId from the update-thread).
+ */
+class DALI_CORE_API UpdateProxy
+{
+public:
+
+  /**
+   * @brief Given the Actor ID, this retrieves that Actor's position.
+   * @param[in]  id  The Actor ID
+   * @return If valid Actor ID, then the Actor's position is returned.
+   */
+  Vector3 GetPosition( unsigned int id ) const;
+
+  /**
+   * @brief Allows setting an Actor's position from the Frame callback function.
+   * @param[in]  id        The Actor ID
+   * @param[in]  position  The position to set.
+   * @note This will get reset to the internally calculated value in the next frame, so will have to be set again.
+   */
+  void SetPosition( unsigned int id, const Vector3& position );
+
+  /**
+   * @brief Given the Actor ID, this retrieves that Actor's size.
+   * @param[in]  id  The Actor ID
+   * @return If valid Actor ID, then Actor's size is returned, otherwise Vector3::ZERO.
+   */
+  const Vector3& GetSize( unsigned int id ) const;
+
+  /**
+   * @brief Allows setting an Actor's size from the Frame callback function.
+   * @param[in]  id    The Actor ID
+   * @param[in]  size  The size to set.
+   * @note This will get reset to the internally calculated value in the next frame, so will have to be set again.
+   */
+  void SetSize( unsigned int id, const Vector3& size );
+
+  /**
+   * @brief Given the Actor ID, this retrieves that Actor's position and size.
+   * @param[in]   id        The Actor ID
+   * @param[out]  position  If valid Actor ID, then Actor's position is set
+   * @param[out]  size      If valid Actor ID, then Actor's size is set
+   */
+  void GetPositionAndSize( unsigned int id, Vector3& position, Vector3& size ) const;
+
+  /**
+   * @brief Given the Actor ID, this retrieves that Actor's color.
+   * @param[in]   id        The Actor ID
+   * @return If valid Actor ID, then Actor's color is returned, otherwise Vector4::ZERO.
+   */
+  Vector4 GetWorldColor( unsigned int id ) const;
+
+  /**
+   * @brief Allows setting an Actor's color from the Frame callback function.
+   * @param[in]  id     The Actor ID
+   * @param[in]  color  The color to set
+   * @note This will get reset to the internally calculated value in the next frame, so will have to be set again.
+   */
+  void SetWorldColor( unsigned int id, const Vector4& color ) const;
+
+  /**
+   * @brief Given the Actor ID, this retrieves that Actor's world-matrix and size.
+   * @param[in]   id           The Actor ID
+   * @param[out]  worldMatrix  If valid Actor ID, then Actor's world matrix is set
+   * @param[out]  size         If valid Actor ID, then Actor's size is set
+   */
+  void GetWorldMatrixAndSize( unsigned int id, Matrix& worldMatrix, Vector3& size ) const;
+
+  /**
+   * @brief Given the Actor ID, this retrieves that Actor's world-matrix.
+   * @param[in]  id  The Actor ID
+   * @return If valid Actor ID, then Actor's world matrix is returned, otherwise Matrix::IDENTITY.
+   */
+  const Matrix& GetWorldMatrix( unsigned int id ) const;
+
+  /**
+   * @brief Allows the setting an Actor's world-matrix from the Frame callback function.
+   * @param[in]  id           The Actor ID
+   * @param[in]  worldMatrix  The world matrix to set.
+   * @note This will get reset to the internally calculated value in the next frame, so will have to be set again.
+   * @note This will only set the world matrix for that particular actor.
+   *       The world matrices of the children will not change and will have to be manually changed in the callback
+   *       as well (if required).
+   */
+  void SetWorldMatrix( unsigned int id, const Matrix& worldMatrix );
+
+public: // Not intended for application developers
+
+  /// @cond internal
+
+  /**
+   * @brief Constructor.
+   * @param[in]  impl  A reference to the internal object.
+   */
+  DALI_INTERNAL UpdateProxy( Internal::UpdateProxy& impl );
+
+  /**
+   * @brief Destructor.
+   */
+  DALI_INTERNAL ~UpdateProxy();
+
+  // Not copyable or movable
+
+  UpdateProxy( const UpdateProxy& )            = delete; ///< Deleted copy constructor
+  UpdateProxy( UpdateProxy&& )                 = delete; ///< Deleted move constructor
+  UpdateProxy& operator=( const UpdateProxy& ) = delete; ///< Deleted copy assignment operator
+  UpdateProxy& operator=( UpdateProxy&& )      = delete; ///< Deleted move assignment operator
+
+  /// @endcond
+
+private:
+
+  /// @cond internal
+  Internal::UpdateProxy& mImpl;
+  /// @endcond
+};
+
+} // namespace Dali
+
+#endif // DALI_UPDATE_PROXY_H
index 147fcf8..bbf91e8 100644 (file)
@@ -3893,7 +3893,7 @@ void Actor::SetParent( Actor* parent )
 
 SceneGraph::Node* Actor::CreateNode() const
 {
-  return Node::New();
+  return Node::New( mId );
 }
 
 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
index 69c14bc..9cd762b 100644 (file)
@@ -1719,6 +1719,15 @@ public:
   virtual int GetPropertyComponentIndex( Property::Index index ) const;
 
   /**
+   * Retrieve the actor's node.
+   * @return The node used by this actor
+   */
+  const SceneGraph::Node& GetNode() const
+  {
+    return *mNode;
+  }
+
+  /**
    * @copydoc Dali::DevelActor::Raise()
    */
   void Raise();
index 3e1236b..5e51230 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -314,7 +314,7 @@ bool Layer::IsHoverConsumed() const
 
 SceneGraph::Node* Layer::CreateNode() const
 {
-  return SceneGraph::Layer::New();
+  return SceneGraph::Layer::New( mId );
 }
 
 void Layer::OnStageConnectionInternal()
index 0ef555b..bc4ed02 100644 (file)
@@ -656,6 +656,16 @@ Dali::DevelStage::KeyEventGeneratedSignalType& Stage::KeyEventGeneratedSignal()
   return mKeyEventGeneratedSignal;
 }
 
+void Stage::AddFrameCallback( FrameCallbackInterface& frameCallback, Actor& rootActor )
+{
+  AddFrameCallbackMessage( mUpdateManager, frameCallback, rootActor.GetNode() );
+}
+
+void Stage::RemoveFrameCallback( FrameCallbackInterface& frameCallback )
+{
+  RemoveFrameCallbackMessage( mUpdateManager, frameCallback );
+}
+
 Dali::Stage::EventProcessingFinishedSignalType& Stage::EventProcessingFinishedSignal()
 {
   return mEventProcessingFinishedSignal;
index 0f036e3..f64343c 100644 (file)
@@ -399,6 +399,16 @@ public:
   Dali::DevelStage::KeyEventGeneratedSignalType& KeyEventGeneratedSignal();
 
   /**
+   * @copydoc Dali::DevelStage::AddFrameCallback()
+   */
+  void AddFrameCallback( FrameCallbackInterface& frameCallback, Actor& rootActor );
+
+  /**
+   * @copydoc Dali::DevelStage::RemoveFrameCallback()
+   */
+  void RemoveFrameCallback( FrameCallbackInterface& frameCallback );
+
+  /**
    * Connects a callback function with the object's signals.
    * @param[in] object The object providing the signal.
    * @param[in] tracker Used to disconnect the signal.
index bae7b47..72e8e0f 100644 (file)
@@ -127,12 +127,14 @@ internal_src_files = \
   $(internal_src_dir)/update/gestures/pan-gesture-profiling.cpp \
   $(internal_src_dir)/update/gestures/scene-graph-pan-gesture.cpp \
   $(internal_src_dir)/update/queue/update-message-queue.cpp \
+  $(internal_src_dir)/update/manager/frame-callback-processor.cpp \
   $(internal_src_dir)/update/manager/render-instruction-processor.cpp \
   $(internal_src_dir)/update/manager/render-task-processor.cpp \
   $(internal_src_dir)/update/manager/transform-manager.cpp \
   $(internal_src_dir)/update/manager/update-algorithms.cpp \
   $(internal_src_dir)/update/manager/update-manager.cpp \
   $(internal_src_dir)/update/manager/update-manager-debug.cpp \
+  $(internal_src_dir)/update/manager/update-proxy-impl.cpp \
   $(internal_src_dir)/update/render-tasks/scene-graph-camera.cpp \
   $(internal_src_dir)/update/nodes/node.cpp \
   $(internal_src_dir)/update/nodes/node-messages.cpp \
diff --git a/dali/internal/update/manager/frame-callback-processor.cpp b/dali/internal/update/manager/frame-callback-processor.cpp
new file mode 100644 (file)
index 0000000..87f3b89
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/manager/frame-callback-processor.h>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/update/frame-callback-interface.h>
+#include <dali/devel-api/update/update-proxy.h>
+#include <dali/internal/update/manager/update-proxy-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+namespace
+{
+
+template< typename FrameCallbackInfoT >
+class MatchRootNode
+{
+public:
+
+  MatchRootNode( PropertyOwner& rootNode )
+  : mRootNode( rootNode )
+  {
+  }
+
+  bool operator() ( const FrameCallbackInfoT& info )
+  {
+    return &info.updateProxyImpl->GetRootNode() == &mRootNode;
+  }
+
+private:
+
+  PropertyOwner& mRootNode;
+};
+
+} // unnamed namespace
+
+FrameCallbackProcessor::FrameCallbackProcessor( TransformManager& transformManager, Node& rootNode )
+: mFrameCallbacks(),
+  mTransformManager( transformManager ),
+  mRootNode( rootNode )
+{
+}
+
+FrameCallbackProcessor::~FrameCallbackProcessor()
+{
+}
+
+void FrameCallbackProcessor::AddFrameCallback( FrameCallbackInterface* frameCallback, const Node* rootNode )
+{
+  Node& node = const_cast< Node& >( *rootNode ); // Was sent as const from event thread, we need to be able to use non-const version here.
+
+  FrameCallbackInfo info;
+  info.frameCallback = frameCallback;
+  info.updateProxyImpl = new UpdateProxy( mTransformManager, node );
+
+  // We want to be notified when the node is destroyed (if we're not observing it already)
+  auto iter = std::find_if( mFrameCallbacks.begin(), mFrameCallbacks.end(), MatchRootNode< FrameCallbackInfo >( node ) );
+  if( iter == mFrameCallbacks.end() )
+  {
+    node.AddObserver( *this );
+  }
+
+  mFrameCallbacks.push_back( info );
+}
+
+void FrameCallbackProcessor::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
+{
+  auto iter = std::remove_if( mFrameCallbacks.begin(), mFrameCallbacks.end(),
+                              [ this, frameCallback ]
+                                ( const FrameCallbackInfo& info )
+                                {
+                                  info.updateProxyImpl->GetRootNode().RemoveObserver( *this );
+                                  delete info.updateProxyImpl;
+                                  return info.frameCallback == frameCallback;
+                                } );
+  mFrameCallbacks.erase( iter, mFrameCallbacks.end() );
+}
+
+void FrameCallbackProcessor::Update( BufferIndex bufferIndex, float elapsedSeconds )
+{
+  for( auto&& iter : mFrameCallbacks )
+  {
+    UpdateProxy& updateProxyImpl = *iter.updateProxyImpl;
+    updateProxyImpl.SetCurrentBufferIndex( bufferIndex );
+    Dali::UpdateProxy updateProxy( updateProxyImpl );
+    iter.frameCallback->Update( updateProxy, elapsedSeconds );
+  }
+}
+
+void FrameCallbackProcessor::PropertyOwnerDestroyed( PropertyOwner& owner )
+{
+  auto iter = std::remove_if( mFrameCallbacks.begin(), mFrameCallbacks.end(), MatchRootNode< FrameCallbackInfo >( owner )  );
+  mFrameCallbacks.erase( iter, mFrameCallbacks.end() );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/manager/frame-callback-processor.h b/dali/internal/update/manager/frame-callback-processor.h
new file mode 100644 (file)
index 0000000..90d9c7d
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_FRAME_CALLBACK_PROCESSOR_H
+#define DALI_INTERNAL_SCENE_GRAPH_FRAME_CALLBACK_PROCESSOR_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/public-api/common/vector-wrapper.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/update/common/property-owner.h>
+
+namespace Dali
+{
+
+class FrameCallbackInterface;
+
+namespace Internal
+{
+
+class UpdateProxy;
+
+namespace SceneGraph
+{
+
+class Node;
+class TransformManager;
+
+/**
+ * This class processes all the registered frame-callbacks.
+ */
+class FrameCallbackProcessor : public PropertyOwner::Observer
+{
+public:
+
+  /**
+   * Construct a new FrameCallbackProcessor.
+   */
+  FrameCallbackProcessor( TransformManager& transformManager, Node& rootNode );
+
+  /**
+   * Non-virtual Destructor.
+   */
+  ~FrameCallbackProcessor();
+
+  // Movable but not copyable
+
+  FrameCallbackProcessor( const FrameCallbackProcessor& )            = delete;  ///< Deleted copy constructor.
+  FrameCallbackProcessor( FrameCallbackProcessor&& )                 = default; ///< Default move constructor.
+  FrameCallbackProcessor& operator=( const FrameCallbackProcessor& ) = delete;  ///< Deleted copy assignment operator.
+  FrameCallbackProcessor& operator=( FrameCallbackProcessor&& )      = default; ///< Default move assignment operator.
+
+  /**
+   * Adds an implementation of the FrameCallbackInterface.
+   * @param[in]  frameCallback  A pointer to the implementation of the FrameCallbackInterface
+   * @param[in]  rootNode       A pointer to the root node to apply the FrameCallback to
+   */
+  void AddFrameCallback( FrameCallbackInterface* frameCallback, const Node* rootNode );
+
+  /**
+   * Removes the specified implementation of FrameCallbackInterface.
+   * @param[in]  frameCallback  A pointer to the implementation of the FrameCallbackInterface to remove.
+   */
+  void RemoveFrameCallback( FrameCallbackInterface* frameCallback );
+
+  /**
+   * Called on Update by the UpdateManager.
+   * @param[in]  bufferIndex     The bufferIndex to use
+   * @param[in]  elapsedSeconds  Time elapsed time since the last frame (in seconds)
+   */
+  void Update( BufferIndex bufferIndex, float elapsedSeconds );
+
+private:
+
+  // From PropertyOwner::Observer
+
+  /**
+   * @copydoc PropertyOwner::Observer::PropertyOwnerConnected()
+   */
+  virtual void PropertyOwnerConnected( PropertyOwner& owner ) { /* Nothing to do */ }
+
+  /**
+   * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected()
+   */
+  virtual void PropertyOwnerDisconnected( BufferIndex updateBufferIndex, PropertyOwner& owner ) { /* Nothing to do */ }
+
+  /**
+   * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected()
+   *
+   * Will use this to disconnect the frame-callback if the accompanying node is destroyed
+   */
+  virtual void PropertyOwnerDestroyed( PropertyOwner& owner );
+
+private:
+
+  struct FrameCallbackInfo
+  {
+    FrameCallbackInterface* frameCallback;
+    UpdateProxy* updateProxyImpl;
+  };
+
+  std::vector< FrameCallbackInfo > mFrameCallbacks;
+
+  TransformManager& mTransformManager;
+  Node& mRootNode;
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_FRAME_CALLBACK_PROCESSOR_H
index 49a28a4..10f290f 100644 (file)
@@ -44,6 +44,7 @@
 #include <dali/internal/update/controllers/render-message-dispatcher.h>
 #include <dali/internal/update/controllers/scene-controller-impl.h>
 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
+#include <dali/internal/update/manager/frame-callback-processor.h>
 #include <dali/internal/update/manager/render-task-processor.h>
 #include <dali/internal/update/manager/sorted-layers.h>
 #include <dali/internal/update/manager/update-algorithms.h>
@@ -195,6 +196,7 @@ struct UpdateManager::Impl
     shaders(),
     panGestureProcessor( NULL ),
     messageQueue( renderController, sceneGraphBuffers ),
+    frameCallbackProcessor( NULL ),
     keepRenderingSeconds( 0.0f ),
     nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
     frameCounter( 0 ),
@@ -256,6 +258,18 @@ struct UpdateManager::Impl
     delete sceneController;
   }
 
+  /**
+   * Lazy init for FrameCallbackProcessor.
+   */
+  FrameCallbackProcessor& GetFrameCallbackProcessor()
+  {
+    if( ! frameCallbackProcessor )
+    {
+      frameCallbackProcessor = new FrameCallbackProcessor( transformManager, *root );
+    }
+    return *frameCallbackProcessor;
+  }
+
   SceneGraphBuffers                    sceneGraphBuffers;             ///< Used to keep track of which buffers are being written or read
   RenderMessageDispatcher              renderMessageDispatcher;       ///< Used for passing messages to the render-thread
   NotificationManager&                 notificationManager;           ///< Queues notification messages for the event-thread.
@@ -300,6 +314,8 @@ struct UpdateManager::Impl
   std::vector<Internal::ShaderDataPtr> updateCompiledShaders;         ///< Shaders to be sent from Update to Event
   Mutex                                compiledShaderMutex;           ///< lock to ensure no corruption on the renderCompiledShaders
 
+  OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor;        ///< Owned FrameCallbackProcessor, only created if required.
+
   float                                keepRenderingSeconds;          ///< Set via Dali::Stage::KeepRendering
   int                                  nodeDirtyFlags;                ///< cumulative node dirty flags from previous frame
   int                                  frameCounter;                  ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
@@ -879,6 +895,12 @@ unsigned int UpdateManager::Update( float elapsedSeconds,
     //Update the transformations of all the nodes
     mImpl->transformManager.Update();
 
+    // Call the frame-callback-processor if set
+    if( mImpl->frameCallbackProcessor )
+    {
+      mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
+    }
+
     //Process Property Notifications
     ProcessPropertyNotifications( bufferIndex );
 
@@ -1070,6 +1092,16 @@ bool UpdateManager::IsDefaultSurfaceRectChanged()
   return surfaceRectChanged;
 }
 
+void UpdateManager::AddFrameCallback( FrameCallbackInterface* frameCallback, const Node* rootNode )
+{
+  mImpl->GetFrameCallbackProcessor().AddFrameCallback( frameCallback, rootNode );
+}
+
+void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
+{
+  mImpl->GetFrameCallbackProcessor().RemoveFrameCallback( frameCallback );
+}
+
 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
 {
   // Message has ownership of Sampler while in transit from update to render
index 705eecf..d87d280 100644 (file)
@@ -45,6 +45,8 @@
 namespace Dali
 {
 
+class FrameCallbackInterface;
+
 namespace Integration
 {
 class GlSyncAbstraction;
@@ -610,6 +612,19 @@ public:
    */
   bool IsDefaultSurfaceRectChanged();
 
+  /**
+   * Adds an implementation of the FrameCallbackInterface.
+   * @param[in] frameCallback A pointer to the implementation of the FrameCallbackInterface
+   * @param[in] rootNode A pointer to the root node to apply the FrameCallback to
+   */
+  void AddFrameCallback( FrameCallbackInterface* frameCallback, const Node* rootNode );
+
+  /**
+   * Removes the specified implementation of FrameCallbackInterface.
+   * @param[in] frameCallback A pointer to the implementation of the FrameCallbackInterface to remove.
+   */
+  void RemoveFrameCallback( FrameCallbackInterface* frameCallback );
+
 private:
 
   // Undefined
@@ -1337,6 +1352,27 @@ inline void AddResetterMessage( UpdateManager& manager, OwnerPointer<PropertyRes
   new (slot) LocalType( &manager, &UpdateManager::AddPropertyResetter, resetter );
 }
 
+inline void AddFrameCallbackMessage( UpdateManager& manager, FrameCallbackInterface& frameCallback, const Node& rootNode )
+{
+  typedef MessageValue2< UpdateManager, FrameCallbackInterface*, const Node* > 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::AddFrameCallback, &frameCallback, &rootNode );
+}
+
+inline void RemoveFrameCallbackMessage( UpdateManager& manager, FrameCallbackInterface& frameCallback )
+{
+  typedef MessageValue1< UpdateManager, FrameCallbackInterface* > 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::RemoveFrameCallback, &frameCallback );
+}
 
 } // namespace SceneGraph
 
diff --git a/dali/internal/update/manager/update-proxy-impl.cpp b/dali/internal/update/manager/update-proxy-impl.cpp
new file mode 100644 (file)
index 0000000..85404a9
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/manager/update-proxy-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+SceneGraph::Node* FindNodeInSceneGraph( unsigned int id, SceneGraph::Node& node )
+{
+  SceneGraph::Node* matchingNode = NULL;
+
+  if( node.mId == id )
+  {
+    matchingNode = &node;
+  }
+  else
+  {
+    for( auto&& i : node.GetChildren() )
+    {
+      matchingNode = FindNodeInSceneGraph( id, *i );
+      if( matchingNode )
+      {
+        break;
+      }
+    }
+  }
+
+  return matchingNode;
+}
+
+} // unnamed namespace
+
+UpdateProxy::UpdateProxy( SceneGraph::TransformManager& transformManager, SceneGraph::Node& rootNode )
+: mNodeContainer(),
+  mLastCachedIdNodePair( { 0u, NULL } ),
+  mCurrentBufferIndex( 0u ),
+  mTransformManager( transformManager ),
+  mRootNode( rootNode )
+{
+}
+
+UpdateProxy::~UpdateProxy()
+{
+}
+
+Vector3 UpdateProxy::GetPosition( unsigned int id ) const
+{
+  const Dali::Matrix& matrix = GetWorldMatrix( id );
+  return matrix.GetTranslation3();
+}
+
+void UpdateProxy::SetPosition( unsigned int id, const Vector3& position )
+{
+  const SceneGraph::Node* node = GetNodeWithId( id );
+  if( node )
+  {
+    Matrix& matrix = mTransformManager.GetWorldMatrix( node->mTransformId );
+    matrix.SetTranslation( position );
+  }
+}
+
+const Vector3& UpdateProxy::GetSize( unsigned int id ) const
+{
+  const SceneGraph::Node* node = GetNodeWithId( id );
+  if( node )
+  {
+    return mTransformManager.GetVector3PropertyValue( node->mTransformId, SceneGraph::TRANSFORM_PROPERTY_SIZE );
+  }
+
+  return Vector3::ZERO;
+}
+
+void UpdateProxy::SetSize( unsigned int id, const Vector3& size )
+{
+  SceneGraph::Node* node = GetNodeWithId( id );
+  if( node )
+  {
+    mTransformManager.SetVector3PropertyValue( node->mTransformId, SceneGraph::TRANSFORM_PROPERTY_SIZE, size );
+  }
+}
+
+void UpdateProxy::GetPositionAndSize( unsigned int id, Vector3& position, Vector3& size ) const
+{
+  Matrix worldMatrix( false );
+  GetWorldMatrixAndSize( id, worldMatrix, size );
+  position = worldMatrix.GetTranslation3();
+}
+
+Vector4 UpdateProxy::GetWorldColor( unsigned int id ) const
+{
+  SceneGraph::Node* node = GetNodeWithId( id );
+  if( node )
+  {
+    return node->mWorldColor.Get( mCurrentBufferIndex );
+  }
+
+  return Vector4::ZERO;
+}
+
+void UpdateProxy::SetWorldColor( unsigned int id, const Vector4& color ) const
+{
+  SceneGraph::Node* node = GetNodeWithId( id );
+  if( node )
+  {
+    Vector4& currentColor = node->mWorldColor.Get( mCurrentBufferIndex );
+    currentColor = color;
+  }
+}
+
+void UpdateProxy::GetWorldMatrixAndSize( unsigned int id, Matrix& worldMatrix, Vector3& size ) const
+{
+  const SceneGraph::Node* node = GetNodeWithId( id );
+  if( node )
+  {
+    mTransformManager.GetWorldMatrixAndSize( node->mTransformId, worldMatrix, size );
+  }
+}
+
+const Matrix& UpdateProxy::GetWorldMatrix( unsigned int id ) const
+{
+  const SceneGraph::Node* node = GetNodeWithId( id );
+  if( node )
+  {
+    return mTransformManager.GetWorldMatrix( node->mTransformId );
+  }
+
+  return Matrix::IDENTITY;
+}
+
+void UpdateProxy::SetWorldMatrix( unsigned int id, const Matrix& worldMatrix )
+{
+  SceneGraph::Node* node = GetNodeWithId( id );
+  if( node )
+  {
+    Matrix& currentMatrix = mTransformManager.GetWorldMatrix( node->mTransformId );
+    currentMatrix = worldMatrix;
+  }
+}
+
+SceneGraph::Node* UpdateProxy::GetNodeWithId( unsigned int id ) const
+{
+  SceneGraph::Node* node = NULL;
+
+  // Cache the last accessed node so we don't have to traverse
+  if( mLastCachedIdNodePair.node && mLastCachedIdNodePair.id == id )
+  {
+    node = mLastCachedIdNodePair.node;
+  }
+  else
+  {
+    // Find node in vector
+    for( auto&& pair : mNodeContainer )
+    {
+      if( pair.id == id )
+      {
+        node = pair.node;
+        mLastCachedIdNodePair = pair;
+        break;
+      }
+    }
+
+    if( ! node )
+    {
+      // Node not in vector, find in scene-graph
+      node = FindNodeInSceneGraph( id, mRootNode );
+      if( node )
+      {
+        mNodeContainer.push_back( { id, node } );
+        mLastCachedIdNodePair = *mNodeContainer.rbegin();
+      }
+    }
+  }
+
+  return node;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/manager/update-proxy-impl.h b/dali/internal/update/manager/update-proxy-impl.h
new file mode 100644 (file)
index 0000000..f730a75
--- /dev/null
@@ -0,0 +1,164 @@
+#ifndef DALI_INTERNAL_UPDATE_PROXY_IMPL_H
+#define DALI_INTERNAL_UPDATE_PROXY_IMPL_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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/update/manager/transform-manager.h>
+#include <dali/internal/update/nodes/node.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * @brief The implementation of Dali::UpdateProxy.
+ *
+ * Ref-counting is not required for this object.
+ *
+ * @see Dali::UpdateProxy
+ */
+class UpdateProxy
+{
+public:
+
+  /**
+   * @brief Constructor.
+   * @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 );
+
+  /**
+   * @brief Destructor.
+   */
+  ~UpdateProxy();
+
+  // Movable but not copyable
+
+  UpdateProxy( const UpdateProxy& )            = delete;  ///< Deleted copy constructor.
+  UpdateProxy( UpdateProxy&& )                 = default; ///< Default move constructor.
+  UpdateProxy& operator=( const UpdateProxy& ) = delete;  ///< Deleted copy assignment operator.
+  UpdateProxy& operator=( UpdateProxy&& )      = default; ///< Default move assignment operator.
+
+  /**
+   * @copydoc Dali::UpdateProxy::GetPosition()
+   */
+  Vector3 GetPosition( unsigned int id ) const;
+
+  /**
+   * @copydoc Dali::UpdateProxy::SetPosition()
+   */
+  void SetPosition( unsigned int id, const Vector3& position );
+
+  /**
+   * @copydoc Dali::UpdateProxy::GetSize()
+   */
+  const Vector3& GetSize( unsigned int id ) const;
+
+  /**
+   * @copydoc Dali::UpdateProxy::SetSize()
+   */
+  void SetSize( unsigned int id, const Vector3& size );
+
+  /**
+   * @copydoc Dali::UpdateProxy::GetPositionAndSize()
+   */
+  void GetPositionAndSize( unsigned int id, Vector3& position, Vector3& size ) const;
+
+  /**
+   * @copydoc Dali::UpdateProxy::GetColor()
+   */
+  Vector4 GetWorldColor( unsigned int id ) const;
+
+  /**
+   * @copydoc Dali::UpdateProxy::SetColor()
+   */
+  void SetWorldColor( unsigned int id, const Vector4& color ) const;
+
+  /**
+   * @copydoc Dali::UpdateProxy::GetWorldMatrixAndSize()
+   */
+  void GetWorldMatrixAndSize( unsigned int id, Matrix& worldMatrix, Vector3& size ) const;
+
+  /**
+   * @copydoc Dali::UpdateProxy::GetWorldMatrix()
+   */
+  const Matrix& GetWorldMatrix( unsigned int id ) const;
+
+  /**
+   * @copydoc Dali::UpdateProxy::SetWorldMatrix()
+   */
+  void SetWorldMatrix( unsigned int id, const Matrix& worldMatrix );
+
+  /**
+   * @brief Retrieves the root-node used by this class
+   * @return The root node used by this class.
+   */
+  SceneGraph::Node& GetRootNode() const
+  {
+    return mRootNode;
+  }
+
+  void SetCurrentBufferIndex( BufferIndex bufferIndex )
+  {
+    mCurrentBufferIndex = bufferIndex;
+  }
+
+private:
+
+  /**
+   * @brief Retrieves the node with the specified ID.
+   * @param[in]  id  The ID of the node required
+   * @return A pointer to the required node if found.
+   * @note This caches the last accessed node.
+   */
+  SceneGraph::Node* GetNodeWithId( unsigned int id ) const;
+
+private:
+
+  /**
+   * Structure to store the ID & Node pair
+   */
+  struct IdNodePair
+  {
+    unsigned int id; ///< The ID of the node
+    SceneGraph::Node* node; ///< The node itself
+  };
+
+  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.
+  unsigned int mCurrentBufferIndex;
+
+  SceneGraph::TransformManager& mTransformManager; ///< Reference to the Transform Manager.
+  SceneGraph::Node& mRootNode; ///< The root node of this update proxy.
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_UPDATE_PROXY_IMPL_H
index aa7f777..52f443a 100644 (file)
@@ -55,9 +55,9 @@ const PositionInheritanceMode Node::DEFAULT_POSITION_INHERITANCE_MODE( INHERIT_P
 const ColorMode Node::DEFAULT_COLOR_MODE( USE_OWN_MULTIPLY_PARENT_ALPHA );
 
 
-Node* Node::New()
+Node* Node::New( unsigned int id )
 {
-  return new ( gNodeMemoryPool.AllocateRawThreadSafe() ) Node();
+  return new ( gNodeMemoryPool.AllocateRawThreadSafe() ) Node( id );
 }
 
 void Node::Delete( Node* node )
@@ -78,7 +78,7 @@ void Node::Delete( Node* node )
   }
 }
 
-Node::Node()
+Node::Node( unsigned int id )
 : mTransformManager( NULL ),
   mTransformId( INVALID_TRANSFORM_ID ),
   mParentOrigin( TRANSFORM_PROPERTY_PARENT_ORIGIN ),
@@ -95,6 +95,7 @@ Node::Node()
   mWorldMatrix(),
   mWorldColor( Color::WHITE ),
   mClippingSortModifier( 0u ),
+  mId( id ),
   mParent( NULL ),
   mExclusiveRenderTask( NULL ),
   mChildren(),
index 71102fb..b7631ca 100644 (file)
@@ -102,8 +102,9 @@ public:
 
   /**
    * Construct a new Node.
+   * @param[in] id The unique ID of the node
    */
-  static Node* New();
+  static Node* New( unsigned int id );
 
   /**
    * Deletes a Node.
@@ -785,8 +786,9 @@ protected:
 
   /**
    * Protected constructor; See also Node::New()
+   * @param[in] id The Unique ID of the actor creating the node
    */
-  Node();
+  Node( unsigned int id );
 
   /**
    * Protected virtual destructor; See also Node::Delete( Node* )
@@ -867,6 +869,7 @@ public: // Default properties
   InheritedColor                     mWorldColor;             ///< Full inherited color
 
   uint32_t                           mClippingSortModifier;   ///< Contains bit-packed clipping information for quick access when sorting
+  const unsigned int                 mId;                     ///< The Unique ID of the node.
 
 protected:
 
index 46bb14c..73709d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -31,15 +31,16 @@ namespace Internal
 namespace SceneGraph
 {
 
-SceneGraph::Layer* Layer::New()
+SceneGraph::Layer* Layer::New( unsigned int id )
 {
   // Layers are currently heap allocated, unlike Nodes which are in a memory pool
   // However Node::Delete( layer ) will correctly delete a layer / node depending on type
-  return new Layer();
+  return new Layer( id );
 }
 
-Layer::Layer()
-: mSortFunction( Internal::Layer::ZValue ),
+Layer::Layer( unsigned int id )
+: Node( id ),
+  mSortFunction( Internal::Layer::ZValue ),
   mClippingBox( 0,0,0,0 ),
   mLastCamera( NULL ),
   mBehavior( Dali::Layer::LAYER_2D ),
index f56bdd3..eec47c4 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_LAYER_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.
@@ -77,9 +77,10 @@ public:
 
   /**
    * Construct a new Layer.
+   * @param[in] id The Unique ID of the actor creating the node
    * @return A smart-pointer to a newly allocated Node
    */
-  static SceneGraph::Layer* New();
+  static SceneGraph::Layer* New( unsigned int id );
 
   /**
    * From Node, to convert a node to a layer.
@@ -205,9 +206,10 @@ private:
 
   /**
    * Private constructor.
+   * @param[in] id The Unique ID of the actor creating the node
    * See also Layer::New()
    */
-  Layer();
+  Layer( unsigned int id );
 
   // Undefined
   Layer(const Layer&);