Cleaning up the property framework; removal of duplicate methods and incorrect assers
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/actors/actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <algorithm>
24
25 // INTERNAL INCLUDES
26
27 #include <dali/public-api/common/dali-common.h>
28 #include <dali/public-api/common/constants.h>
29 #include <dali/public-api/math/vector2.h>
30 #include <dali/public-api/math/vector3.h>
31 #include <dali/public-api/math/radian.h>
32 #include <dali/public-api/object/type-registry.h>
33 #include <dali/public-api/scripting/scripting.h>
34
35 #include <dali/internal/common/internal-constants.h>
36 #include <dali/internal/event/render-tasks/render-task-impl.h>
37 #include <dali/internal/event/actors/camera-actor-impl.h>
38 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
39 #include <dali/internal/event/common/property-index-ranges.h>
40 #include <dali/internal/event/common/stage-impl.h>
41 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
42 #include <dali/internal/event/animation/constraint-impl.h>
43 #include <dali/internal/event/common/projection.h>
44 #include <dali/internal/update/common/animatable-property.h>
45 #include <dali/internal/update/nodes/node-messages.h>
46 #include <dali/internal/update/nodes/node-declarations.h>
47 #include <dali/internal/update/animation/scene-graph-constraint.h>
48 #include <dali/internal/event/events/actor-gesture-data.h>
49 #include <dali/internal/common/message.h>
50 #include <dali/integration-api/debug.h>
51
52 #ifdef DYNAMICS_SUPPORT
53 #include <dali/internal/event/dynamics/dynamics-body-config-impl.h>
54 #include <dali/internal/event/dynamics/dynamics-body-impl.h>
55 #include <dali/internal/event/dynamics/dynamics-joint-impl.h>
56 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
57 #endif
58
59 using Dali::Internal::SceneGraph::Node;
60 using Dali::Internal::SceneGraph::AnimatableProperty;
61 using Dali::Internal::SceneGraph::PropertyBase;
62
63 namespace Dali
64 {
65
66 const Property::Index Actor::PARENT_ORIGIN              = 0;
67 const Property::Index Actor::PARENT_ORIGIN_X            = 1;
68 const Property::Index Actor::PARENT_ORIGIN_Y            = 2;
69 const Property::Index Actor::PARENT_ORIGIN_Z            = 3;
70 const Property::Index Actor::ANCHOR_POINT               = 4;
71 const Property::Index Actor::ANCHOR_POINT_X             = 5;
72 const Property::Index Actor::ANCHOR_POINT_Y             = 6;
73 const Property::Index Actor::ANCHOR_POINT_Z             = 7;
74 const Property::Index Actor::SIZE                       = 8;
75 const Property::Index Actor::SIZE_WIDTH                 = 9;
76 const Property::Index Actor::SIZE_HEIGHT                = 10;
77 const Property::Index Actor::SIZE_DEPTH                 = 11;
78 const Property::Index Actor::POSITION                   = 12;
79 const Property::Index Actor::POSITION_X                 = 13;
80 const Property::Index Actor::POSITION_Y                 = 14;
81 const Property::Index Actor::POSITION_Z                 = 15;
82 const Property::Index Actor::WORLD_POSITION             = 16;
83 const Property::Index Actor::WORLD_POSITION_X           = 17;
84 const Property::Index Actor::WORLD_POSITION_Y           = 18;
85 const Property::Index Actor::WORLD_POSITION_Z           = 19;
86 const Property::Index Actor::ROTATION                   = 20;
87 const Property::Index Actor::WORLD_ROTATION             = 21;
88 const Property::Index Actor::SCALE                      = 22;
89 const Property::Index Actor::SCALE_X                    = 23;
90 const Property::Index Actor::SCALE_Y                    = 24;
91 const Property::Index Actor::SCALE_Z                    = 25;
92 const Property::Index Actor::WORLD_SCALE                = 26;
93 const Property::Index Actor::VISIBLE                    = 27;
94 const Property::Index Actor::COLOR                      = 28;
95 const Property::Index Actor::COLOR_RED                  = 29;
96 const Property::Index Actor::COLOR_GREEN                = 30;
97 const Property::Index Actor::COLOR_BLUE                 = 31;
98 const Property::Index Actor::COLOR_ALPHA                = 32;
99 const Property::Index Actor::WORLD_COLOR                = 33;
100 const Property::Index Actor::WORLD_MATRIX               = 34;
101 const Property::Index Actor::NAME                       = 35;
102 const Property::Index Actor::SENSITIVE                  = 36;
103 const Property::Index Actor::LEAVE_REQUIRED             = 37;
104 const Property::Index Actor::INHERIT_ROTATION           = 38;
105 const Property::Index Actor::INHERIT_SCALE              = 39;
106 const Property::Index Actor::COLOR_MODE                 = 40;
107 const Property::Index Actor::POSITION_INHERITANCE       = 41;
108 const Property::Index Actor::DRAW_MODE                  = 42;
109
110 namespace // unnamed namespace
111 {
112
113 /**
114  * We want to discourage the use of property strings (minimize string comparisons),
115  * particularly for the default properties.
116  */
117 const Internal::PropertyDetails DEFAULT_PROPERTY_DETAILS[] =
118 {
119   // Name                     Type              writable animatable constraint-input
120   { "parent-origin",          Property::VECTOR3,  true,    false,   true  },  // PARENT_ORIGIN
121   { "parent-origin-x",        Property::FLOAT,    true,    false,   true  },  // PARENT_ORIGIN_X
122   { "parent-origin-y",        Property::FLOAT,    true,    false,   true  },  // PARENT_ORIGIN_Y
123   { "parent-origin-z",        Property::FLOAT,    true,    false,   true  },  // PARENT_ORIGIN_Z
124   { "anchor-point",           Property::VECTOR3,  true,    false,   true  },  // ANCHOR_POINT
125   { "anchor-point-x",         Property::FLOAT,    true,    false,   true  },  // ANCHOR_POINT_X
126   { "anchor-point-y",         Property::FLOAT,    true,    false,   true  },  // ANCHOR_POINT_Y
127   { "anchor-point-z",         Property::FLOAT,    true,    false,   true  },  // ANCHOR_POINT_Z
128   { "size",                   Property::VECTOR3,  true,    true,    true  },  // SIZE
129   { "size-width",             Property::FLOAT,    true,    true,    true  },  // SIZE_WIDTH
130   { "size-height",            Property::FLOAT,    true,    true,    true  },  // SIZE_HEIGHT
131   { "size-depth",             Property::FLOAT,    true,    true,    true  },  // SIZE_DEPTH
132   { "position",               Property::VECTOR3,  true,    true,    true  },  // POSITION
133   { "position-x",             Property::FLOAT,    true,    true,    true  },  // POSITION_X
134   { "position-y",             Property::FLOAT,    true,    true,    true  },  // POSITION_Y
135   { "position-z",             Property::FLOAT,    true,    true,    true  },  // POSITION_Z
136   { "world-position",         Property::VECTOR3,  false,   false,   true  },  // WORLD_POSITION
137   { "world-position-x",       Property::FLOAT,    false,   false,   true  },  // WORLD_POSITION_X
138   { "world-position-y",       Property::FLOAT,    false,   false,   true  },  // WORLD_POSITION_Y
139   { "world-position-z",       Property::FLOAT,    false,   false,   true  },  // WORLD_POSITION_Z
140   { "rotation",               Property::ROTATION, true,    true,    true  },  // ROTATION
141   { "world-rotation",         Property::ROTATION, false,   false,   true  },  // WORLD_ROTATION
142   { "scale",                  Property::VECTOR3,  true,    true,    true  },  // SCALE
143   { "scale-x",                Property::FLOAT,    true,    true,    true  },  // SCALE_X
144   { "scale-y",                Property::FLOAT,    true,    true,    true  },  // SCALE_Y
145   { "scale-z",                Property::FLOAT,    true,    true,    true  },  // SCALE_Z
146   { "world-scale",            Property::VECTOR3,  false,   false,   true  },  // WORLD_SCALE
147   { "visible",                Property::BOOLEAN,  true,    true,    true  },  // VISIBLE
148   { "color",                  Property::VECTOR4,  true,    true,    true  },  // COLOR
149   { "color-red",              Property::FLOAT,    true,    true,    true  },  // COLOR_RED
150   { "color-green",            Property::FLOAT,    true,    true,    true  },  // COLOR_GREEN
151   { "color-blue",             Property::FLOAT,    true,    true,    true  },  // COLOR_BLUE
152   { "color-alpha",            Property::FLOAT,    true,    true,    true  },  // COLOR_ALPHA
153   { "world-color",            Property::VECTOR4,  false,   false,   true  },  // WORLD_COLOR
154   { "world-matrix",           Property::MATRIX,   false,   false,   true  },  // WORLD_MATRIX
155   { "name",                   Property::STRING,   true,    false,   false },  // NAME
156   { "sensitive",              Property::BOOLEAN,  true,    false,   false },  // SENSITIVE
157   { "leave-required",         Property::BOOLEAN,  true,    false,   false },  // LEAVE_REQUIRED
158   { "inherit-rotation",       Property::BOOLEAN,  true,    false,   false },  // INHERIT_ROTATION
159   { "inherit-scale",          Property::BOOLEAN,  true,    false,   false },  // INHERIT_SCALE
160   { "color-mode",             Property::STRING,   true,    false,   false },  // COLOR_MODE
161   { "position-inheritance",   Property::STRING,   true,    false,   false },  // POSITION_INHERITANCE
162   { "draw-mode",              Property::STRING,   true,    false,   false },  // DRAW_MODE
163 };
164 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( Internal::PropertyDetails );
165
166 } // unnamed namespace
167
168 namespace Internal
169 {
170
171 unsigned int Actor::mActorCounter = 0;
172 ActorContainer Actor::mNullChildren;
173
174 #ifdef DYNAMICS_SUPPORT
175
176 // Encapsulate actor related dynamics data
177 struct DynamicsData
178 {
179   DynamicsData( Actor* slotOwner )
180   : slotDelegate( slotOwner )
181   {
182   }
183
184   typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
185   typedef std::vector<DynamicsJointPtr>      ReferencedJointContainer;
186
187   DynamicsBodyPtr          body;
188   JointContainer           joints;
189   ReferencedJointContainer referencedJoints;
190
191   SlotDelegate< Actor > slotDelegate;
192 };
193
194 #endif // DYNAMICS_SUPPORT
195
196 namespace
197 {
198
199 using namespace Dali;
200
201 BaseHandle CreateActor()
202 {
203   return Dali::Actor::New();
204 }
205
206 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
207
208 SignalConnectorType signalConnector1(mType, Dali::Actor::SIGNAL_TOUCHED,    &Actor::DoConnectSignal);
209 SignalConnectorType signalConnector2(mType, Dali::Actor::SIGNAL_HOVERED,    &Actor::DoConnectSignal);
210 SignalConnectorType signalConnector3(mType, Dali::Actor::SIGNAL_SET_SIZE,   &Actor::DoConnectSignal);
211 SignalConnectorType signalConnector4(mType, Dali::Actor::SIGNAL_ON_STAGE,   &Actor::DoConnectSignal);
212 SignalConnectorType signalConnector5(mType, Dali::Actor::SIGNAL_OFF_STAGE,  &Actor::DoConnectSignal);
213
214 TypeAction a1(mType, Dali::Actor::ACTION_SHOW, &Actor::DoAction);
215 TypeAction a2(mType, Dali::Actor::ACTION_HIDE, &Actor::DoAction);
216
217 }
218
219 ActorPtr Actor::New()
220 {
221   ActorPtr actor( new Actor( BASIC ) );
222
223   // Second-phase construction
224   actor->Initialize();
225
226   return actor;
227 }
228
229 const std::string& Actor::GetName() const
230 {
231   return mName;
232 }
233
234 void Actor::SetName(const std::string& name)
235 {
236   mName = name;
237
238   if( NULL != mNode )
239   {
240     // ATTENTION: string for debug purposes is not thread safe.
241     DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
242   }
243 }
244
245 unsigned int Actor::GetId() const
246 {
247   return mId;
248 }
249
250 void Actor::Attach( ActorAttachment& attachment )
251 {
252   DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
253
254   if( OnStage() )
255   {
256     attachment.Connect();
257   }
258
259   mAttachment = ActorAttachmentPtr(&attachment);
260 }
261
262 ActorAttachmentPtr Actor::GetAttachment()
263 {
264   return mAttachment;
265 }
266
267 bool Actor::OnStage() const
268 {
269   return mIsOnStage;
270 }
271
272 Dali::Layer Actor::GetLayer()
273 {
274   Dali::Layer layer;
275
276   // Short-circuit for Layer derived actors
277   if( mIsLayer )
278   {
279     layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
280   }
281
282   // Find the immediate Layer parent
283   for (Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent())
284   {
285     if( parent->IsLayer() )
286     {
287       layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
288     }
289   }
290
291   return layer;
292 }
293
294 void Actor::Add(Actor& child)
295 {
296   DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
297   DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
298
299   if( !mChildren )
300   {
301     mChildren = new ActorContainer;
302   }
303
304   Actor* const oldParent( child.mParent );
305
306   // child might already be ours
307   if( this != oldParent )
308   {
309     // if we already have parent, unparent us first
310     if( oldParent )
311     {
312       oldParent->Remove( child ); // This causes OnChildRemove callback
313     }
314
315     // Guard against Add() during previous OnChildRemove callback
316     if ( !child.mParent )
317     {
318       // Do this first, since user callbacks from within SetParent() may need to remove child
319       mChildren->push_back(Dali::Actor(&child));
320
321       // SetParent asserts that child can be added
322       child.SetParent(this);
323
324       // Notification for derived classes
325       OnChildAdd(child);
326     }
327   }
328 }
329
330 void Actor::Insert(unsigned int index, Actor& child)
331 {
332   DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
333   DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
334
335   if( !mChildren )
336   {
337     mChildren = new ActorContainer;
338   }
339
340   Actor* const oldParent( child.mParent );
341
342   // since an explicit position has been given, always insert, even if already a child
343   if( oldParent )
344   {
345     oldParent->Remove( child ); // This causes OnChildRemove callback
346   }
347
348   // Guard against Add() during previous OnChildRemove callback
349   if ( !child.mParent )
350   {
351     // Do this first, since user callbacks from within SetParent() may need to remove child
352     if (index < GetChildCount())
353     {
354       ActorIter it = mChildren->begin();
355       std::advance(it, index);
356       mChildren->insert(it, Dali::Actor(&child));
357     }
358     else
359     {
360       mChildren->push_back(Dali::Actor(&child));
361     }
362     // SetParent asserts that child can be added
363     child.SetParent(this, index);
364
365     // Notification for derived classes
366     OnChildAdd(child);
367   }
368 }
369
370 void Actor::Remove(Actor& child)
371 {
372   DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
373
374   Dali::Actor removed;
375
376   if( !mChildren )
377   {
378     // no children
379     return;
380   }
381
382   // Find the child in mChildren, and unparent it
383   ActorIter end = mChildren->end();
384   for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
385   {
386     Actor& actor = GetImplementation(*iter);
387
388     if( &actor == &child )
389     {
390       // Keep handle for OnChildRemove notification
391       removed = Dali::Actor( &actor );
392
393       // Do this first, since user callbacks from within SetParent() may need to add the child
394       mChildren->erase(iter);
395
396       DALI_ASSERT_DEBUG( actor.GetParent() == this );
397       actor.SetParent( NULL );
398
399       break;
400     }
401   }
402
403   if ( removed )
404   {
405     // Notification for derived classes
406     OnChildRemove( GetImplementation(removed) );
407   }
408 }
409
410 void Actor::Unparent()
411 {
412   if( mParent )
413   {
414     mParent->Remove( *this );
415   }
416 }
417
418 unsigned int Actor::GetChildCount() const
419 {
420   return ( NULL != mChildren ) ? mChildren->size() : 0;
421 }
422
423 Dali::Actor Actor::GetChildAt(unsigned int index) const
424 {
425   DALI_ASSERT_ALWAYS( index < GetChildCount() );
426
427   return ( ( mChildren ) ? (*mChildren)[index] : Dali::Actor() );
428 }
429
430 ActorContainer Actor::GetChildren()
431 {
432   if( NULL != mChildren )
433   {
434     return *mChildren;
435   }
436
437   // return copy of mNullChildren
438   return mNullChildren;
439 }
440
441 const ActorContainer& Actor::GetChildren() const
442 {
443   if( NULL != mChildren )
444   {
445     return *mChildren;
446   }
447
448   // return const reference to mNullChildren
449   return mNullChildren;
450 }
451
452 ActorPtr Actor::FindChildByName(const std::string& actorName)
453 {
454   ActorPtr child=0;
455   if (actorName == mName)
456   {
457     child = this;
458   }
459   else if( mChildren )
460   {
461     ActorIter end = mChildren->end();
462     for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
463     {
464       child = GetImplementation(*iter).FindChildByName(actorName);
465
466       if (child)
467       {
468         break;
469       }
470     }
471   }
472   return child;
473 }
474
475 Dali::Actor Actor::FindChildByAlias(const std::string& actorAlias)
476 {
477   Dali::Actor child = DoGetChildByAlias(actorAlias);
478
479   // If not found then search by name.
480   if (!child)
481   {
482     Internal::ActorPtr child_ptr = FindChildByName(actorAlias);
483     if (child_ptr)
484     {
485       child = Dali::Actor(child_ptr.Get());
486     }
487   }
488
489   return child;
490 }
491
492 Dali::Actor Actor::DoGetChildByAlias(const std::string& actorAlias)
493 {
494   Dali::Actor child = GetChildByAlias(actorAlias);
495
496   if (!child && mChildren )
497   {
498     ActorIter end = mChildren->end();
499     for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
500     {
501       child = GetImplementation(*iter).DoGetChildByAlias(actorAlias);
502
503       if (child)
504       {
505         break;
506       }
507     }
508   }
509
510   return child;
511 }
512
513 ActorPtr Actor::FindChildById(const unsigned int id)
514 {
515   ActorPtr child = 0;
516   if (id == mId)
517   {
518     child = this;
519   }
520   else if( mChildren )
521   {
522     ActorIter end = mChildren->end();
523     for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
524     {
525       child = GetImplementation(*iter).FindChildById(id);
526
527       if (child)
528       {
529         break;
530       }
531     }
532   }
533   return child;
534 }
535
536 void Actor::SetParentOrigin( const Vector3& origin )
537 {
538   if( NULL != mNode )
539   {
540     // mNode is being used in a separate thread; queue a message to set the value & base value
541     SetParentOriginMessage( mStage->GetUpdateInterface(), *mNode, origin );
542   }
543
544   // Cache for event-thread access
545   if( !mParentOrigin )
546   {
547     // not allocated, check if different from default
548     if( ParentOrigin::DEFAULT != origin )
549     {
550       mParentOrigin = new Vector3( origin );
551     }
552   }
553   else
554   {
555     // check if different from current costs more than just set
556     *mParentOrigin = origin;
557   }
558 }
559
560 void Actor::SetParentOriginX( float x )
561 {
562   const Vector3& current = GetCurrentParentOrigin();
563
564   SetParentOrigin( Vector3( x, current.y, current.z ) );
565 }
566
567 void Actor::SetParentOriginY( float y )
568 {
569   const Vector3& current = GetCurrentParentOrigin();
570
571   SetParentOrigin( Vector3( current.x, y, current.z ) );
572 }
573
574 void Actor::SetParentOriginZ( float z )
575 {
576   const Vector3& current = GetCurrentParentOrigin();
577
578   SetParentOrigin( Vector3( current.x, current.y, z ) );
579 }
580
581 const Vector3& Actor::GetCurrentParentOrigin() const
582 {
583   // Cached for event-thread access
584   return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
585 }
586
587 void Actor::SetAnchorPoint(const Vector3& anchor)
588 {
589   if( NULL != mNode )
590   {
591     // mNode is being used in a separate thread; queue a message to set the value & base value
592     SetAnchorPointMessage( mStage->GetUpdateInterface(), *mNode, anchor );
593   }
594
595   // Cache for event-thread access
596   if( !mAnchorPoint )
597   {
598     // not allocated, check if different from default
599     if( AnchorPoint::DEFAULT != anchor )
600     {
601       mAnchorPoint = new Vector3( anchor );
602     }
603   }
604   else
605   {
606     // check if different from current costs more than just set
607     *mAnchorPoint = anchor;
608   }
609 }
610
611 void Actor::SetAnchorPointX( float x )
612 {
613   const Vector3& current = GetCurrentAnchorPoint();
614
615   SetAnchorPoint( Vector3( x, current.y, current.z ) );
616 }
617
618 void Actor::SetAnchorPointY( float y )
619 {
620   const Vector3& current = GetCurrentAnchorPoint();
621
622   SetAnchorPoint( Vector3( current.x, y, current.z ) );
623 }
624
625 void Actor::SetAnchorPointZ( float z )
626 {
627   const Vector3& current = GetCurrentAnchorPoint();
628
629   SetAnchorPoint( Vector3( current.x, current.y, z ) );
630 }
631
632 const Vector3& Actor::GetCurrentAnchorPoint() const
633 {
634   // Cached for event-thread access
635   return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
636 }
637
638 void Actor::SetPosition(float x, float y)
639 {
640   SetPosition(Vector3(x, y, 0.0f));
641 }
642
643 void Actor::SetPosition(float x, float y, float z)
644 {
645   SetPosition(Vector3(x, y, z));
646 }
647
648 void Actor::SetPosition(const Vector3& position)
649 {
650   if( NULL != mNode )
651   {
652     // mNode is being used in a separate thread; queue a message to set the value & base value
653     SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
654   }
655 }
656
657 void Actor::SetX(float x)
658 {
659   if( NULL != mNode )
660   {
661     // mNode is being used in a separate thread; queue a message to set the value & base value
662     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
663   }
664 }
665
666 void Actor::SetY(float y)
667 {
668   if( NULL != mNode )
669   {
670     // mNode is being used in a separate thread; queue a message to set the value & base value
671     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
672   }
673 }
674
675 void Actor::SetZ(float z)
676 {
677   if( NULL != mNode )
678   {
679     // mNode is being used in a separate thread; queue a message to set the value & base value
680     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
681   }
682 }
683
684 void Actor::MoveBy(const Vector3& distance)
685 {
686   if( NULL != mNode )
687   {
688     // mNode is being used in a separate thread; queue a message to set the value & base value
689     SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
690   }
691 }
692
693 const Vector3& Actor::GetCurrentPosition() const
694 {
695   if( NULL != mNode )
696   {
697     // mNode is being used in a separate thread; copy the value from the previous update
698     return mNode->GetPosition(mStage->GetEventBufferIndex());
699   }
700
701   return Vector3::ZERO;
702 }
703
704 const Vector3& Actor::GetCurrentWorldPosition() const
705 {
706   if( NULL != mNode )
707   {
708     // mNode is being used in a separate thread; copy the value from the previous update
709     return mNode->GetWorldPosition( mStage->GetEventBufferIndex() );
710   }
711
712   return Vector3::ZERO;
713 }
714
715 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
716 {
717   // this flag is not animatable so keep the value
718   mPositionInheritanceMode = mode;
719   if( NULL != mNode )
720   {
721     // mNode is being used in a separate thread; queue a message to set the value
722     SetPositionInheritanceModeMessage( mStage->GetUpdateInterface(), *mNode, mode );
723   }
724 }
725
726 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
727 {
728   // Cached for event-thread access
729   return mPositionInheritanceMode;
730 }
731
732 void Actor::SetRotation(const Radian& angle, const Vector3& axis)
733 {
734   Vector4 normalizedAxis(axis.x, axis.y, axis.z, 0.0f);
735   normalizedAxis.Normalize();
736
737   Quaternion rotation(Quaternion::FromAxisAngle(normalizedAxis, angle));
738
739   SetRotation(rotation);
740 }
741
742 void Actor::SetRotation(const Quaternion& rotation)
743 {
744   if( NULL != mNode )
745   {
746     // mNode is being used in a separate thread; queue a message to set the value & base value
747     SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, &mNode->mRotation, &AnimatableProperty<Quaternion>::Bake, rotation );
748   }
749 }
750
751 void Actor::RotateBy(const Radian& angle, const Vector3& axis)
752 {
753   if( NULL != mNode )
754   {
755     // mNode is being used in a separate thread; queue a message to set the value & base value
756     SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, &mNode->mRotation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
757   }
758 }
759
760 void Actor::RotateBy(const Quaternion& relativeRotation)
761 {
762   if( NULL != mNode )
763   {
764     // mNode is being used in a separate thread; queue a message to set the value & base value
765     SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, &mNode->mRotation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
766   }
767 }
768
769 const Quaternion& Actor::GetCurrentRotation() const
770 {
771   if( NULL != mNode )
772   {
773     // mNode is being used in a separate thread; copy the value from the previous update
774     return mNode->GetRotation(mStage->GetEventBufferIndex());
775   }
776
777   return Quaternion::IDENTITY;
778 }
779
780 const Quaternion& Actor::GetCurrentWorldRotation() const
781 {
782   if( NULL != mNode )
783   {
784     // mNode is being used in a separate thread; copy the value from the previous update
785     return mNode->GetWorldRotation( mStage->GetEventBufferIndex() );
786   }
787
788   return Quaternion::IDENTITY;
789 }
790
791 void Actor::SetScale(float scale)
792 {
793   SetScale(Vector3(scale, scale, scale));
794 }
795
796 void Actor::SetScale(float x, float y, float z)
797 {
798   SetScale(Vector3(x, y, z));
799 }
800
801 void Actor::SetScale(const Vector3& scale)
802 {
803   if( NULL != mNode )
804   {
805     // mNode is being used in a separate thread; queue a message to set the value & base value
806     SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
807   }
808 }
809
810 void Actor::SetScaleX( float x )
811 {
812   if( NULL != mNode )
813   {
814     // mNode is being used in a separate thread; queue a message to set the value & base value
815     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
816   }
817 }
818
819 void Actor::SetScaleY( float y )
820 {
821   if( NULL != mNode )
822   {
823     // mNode is being used in a separate thread; queue a message to set the value & base value
824     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
825   }
826 }
827
828 void Actor::SetScaleZ( float z )
829 {
830   if( NULL != mNode )
831   {
832     // mNode is being used in a separate thread; queue a message to set the value & base value
833     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
834   }
835 }
836
837 void Actor::SetInitialVolume(const Vector3& volume)
838 {
839   if( NULL != mNode )
840   {
841     // mNode is being used in a separate thread; queue a message to set the value
842     SetInitialVolumeMessage( mStage->GetUpdateInterface(), *mNode, volume );
843   }
844 }
845
846 void Actor::SetTransmitGeometryScaling(bool transmitGeometryScaling)
847 {
848   if( NULL != mNode )
849   {
850     // mNode is being used in a separate thread; queue a message to set the value
851     SetTransmitGeometryScalingMessage( mStage->GetUpdateInterface(), *mNode, transmitGeometryScaling );
852   }
853 }
854
855 bool Actor::GetTransmitGeometryScaling() const
856 {
857   if( NULL != mNode )
858   {
859     // mNode is being used in a separate thread; copy the value from the previous update
860     return mNode->GetTransmitGeometryScaling();
861   }
862
863   return false;
864 }
865
866 void Actor::ScaleBy(const Vector3& relativeScale)
867 {
868   if( NULL != mNode )
869   {
870     // mNode is being used in a separate thread; queue a message to set the value & base value
871     SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
872   }
873 }
874
875 const Vector3& Actor::GetCurrentScale() const
876 {
877   if( NULL != mNode )
878   {
879     // mNode is being used in a separate thread; copy the value from the previous update
880     return mNode->GetScale(mStage->GetEventBufferIndex());
881   }
882
883   return Vector3::ONE;
884 }
885
886 const Vector3& Actor::GetCurrentWorldScale() const
887 {
888   if( NULL != mNode )
889   {
890     // mNode is being used in a separate thread; copy the value from the previous update
891     return mNode->GetWorldScale( mStage->GetEventBufferIndex() );
892   }
893
894   return Vector3::ONE;
895 }
896
897 void Actor::SetInheritScale( bool inherit )
898 {
899   // non animateable so keep local copy
900   mInheritScale = inherit;
901   if( NULL != mNode )
902   {
903     // mNode is being used in a separate thread; queue a message to set the value
904     SetInheritScaleMessage( mStage->GetUpdateInterface(), *mNode, inherit );
905   }
906 }
907
908 bool Actor::IsScaleInherited() const
909 {
910   return mInheritScale;
911 }
912
913 Matrix Actor::GetCurrentWorldMatrix() const
914 {
915   if( NULL != mNode )
916   {
917     // World matrix is no longer updated unless there is something observing the node.
918     // Need to calculate it from node's world position, rotation and scale:
919     BufferIndex updateBufferIndex = mStage->GetEventBufferIndex();
920     Matrix worldMatrix(false);
921     worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
922                                         mNode->GetWorldRotation( updateBufferIndex ),
923                                         mNode->GetWorldPosition( updateBufferIndex ) );
924     return worldMatrix;
925   }
926
927   return Matrix::IDENTITY;
928 }
929
930 void Actor::SetVisible(bool visible)
931 {
932   if( NULL != mNode )
933   {
934     // mNode is being used in a separate thread; queue a message to set the value & base value
935     SceneGraph::NodePropertyMessage<bool>::Send( mStage->GetUpdateManager(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
936   }
937 }
938
939 bool Actor::IsVisible() const
940 {
941   if( NULL != mNode )
942   {
943     // mNode is being used in a separate thread; copy the value from the previous update
944     return mNode->IsVisible( mStage->GetEventBufferIndex() );
945   }
946
947   return true;
948 }
949
950 void Actor::SetOpacity(float opacity)
951 {
952   if( NULL != mNode )
953   {
954     // mNode is being used in a separate thread; queue a message to set the value & base value
955     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
956   }
957 }
958
959 void Actor::OpacityBy(float relativeOpacity)
960 {
961   if( NULL != mNode )
962   {
963     // mNode is being used in a separate thread; queue a message to set the value & base value
964     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeWRelative, relativeOpacity );
965   }
966 }
967
968 float Actor::GetCurrentOpacity() const
969 {
970   if( NULL != mNode )
971   {
972     // mNode is being used in a separate thread; copy the value from the previous update
973     return mNode->GetOpacity(mStage->GetEventBufferIndex());
974   }
975
976   return 1.0f;
977 }
978
979 const Vector4& Actor::GetCurrentWorldColor() const
980 {
981   if( NULL != mNode )
982   {
983     return mNode->GetWorldColor( mStage->GetEventBufferIndex() );
984   }
985
986   return Color::WHITE;
987 }
988
989 void Actor::SetColor(const Vector4& color)
990 {
991   if( NULL != mNode )
992   {
993     // mNode is being used in a separate thread; queue a message to set the value & base value
994     SceneGraph::NodePropertyMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
995   }
996 }
997
998 void Actor::SetColorRed( float red )
999 {
1000   if( NULL != mNode )
1001   {
1002     // mNode is being used in a separate thread; queue a message to set the value & base value
1003     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1004   }
1005 }
1006
1007 void Actor::SetColorGreen( float green )
1008 {
1009   if( NULL != mNode )
1010   {
1011     // mNode is being used in a separate thread; queue a message to set the value & base value
1012     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1013   }
1014 }
1015
1016 void Actor::SetColorBlue( float blue )
1017 {
1018   if( NULL != mNode )
1019   {
1020     // mNode is being used in a separate thread; queue a message to set the value & base value
1021     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1022   }
1023 }
1024
1025 void Actor::ColorBy(const Vector4& relativeColor)
1026 {
1027   if( NULL != mNode )
1028   {
1029     // mNode is being used in a separate thread; queue a message to set the value & base value
1030     SceneGraph::NodePropertyMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeRelative, relativeColor );
1031   }
1032 }
1033
1034 const Vector4& Actor::GetCurrentColor() const
1035 {
1036   if( NULL != mNode )
1037   {
1038     // mNode is being used in a separate thread; copy the value from the previous update
1039     return mNode->GetColor(mStage->GetEventBufferIndex());
1040   }
1041
1042   return Color::WHITE;
1043 }
1044
1045 void Actor::SetInheritRotation(bool inherit)
1046 {
1047   // non animateable so keep local copy
1048   mInheritRotation = inherit;
1049   if( NULL != mNode )
1050   {
1051     // mNode is being used in a separate thread; queue a message to set the value
1052     SetInheritRotationMessage( mStage->GetUpdateInterface(), *mNode, inherit );
1053   }
1054 }
1055
1056 bool Actor::IsRotationInherited() const
1057 {
1058   return mInheritRotation;
1059 }
1060
1061 void Actor::SetColorMode(ColorMode colorMode)
1062 {
1063   // non animateable so keep local copy
1064   mColorMode = colorMode;
1065   if( NULL != mNode )
1066   {
1067     // mNode is being used in a separate thread; queue a message to set the value
1068     SetColorModeMessage( mStage->GetUpdateInterface(), *mNode, colorMode );
1069   }
1070 }
1071
1072 ColorMode Actor::GetColorMode() const
1073 {
1074   // we have cached copy
1075   return mColorMode;
1076 }
1077
1078 void Actor::SetSize(float width, float height)
1079 {
1080   SetSize( Vector2( width, height ) );
1081 }
1082
1083 void Actor::SetSize(float width, float height, float depth)
1084 {
1085   SetSize( Vector3( width, height, depth ) );
1086 }
1087
1088 void Actor::SetSize(const Vector2& size)
1089 {
1090   SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1091 }
1092
1093 float Actor::CalculateSizeZ( const Vector2& size ) const
1094 {
1095   return std::min( size.width, size.height );
1096 }
1097
1098 void Actor::SetSize(const Vector3& size)
1099 {
1100   if( NULL != mNode )
1101   {
1102     mSize = size;
1103
1104     // mNode is being used in a separate thread; queue a message to set the value & base value
1105     SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mSize );
1106
1107     // Notification for derived classes
1108     OnSizeSet( mSize );
1109
1110     // Emit signal for application developer
1111
1112     if( !mSetSizeSignalV2.Empty() )
1113     {
1114       Dali::Actor handle( this );
1115       mSetSizeSignalV2.Emit( handle, mSize );
1116     }
1117   }
1118 }
1119
1120 void Actor::NotifySizeAnimation(Animation& animation, const Vector3& targetSize)
1121 {
1122   mSize = targetSize;
1123
1124   // Notify deriving classes
1125   OnSizeAnimation( animation, targetSize );
1126 }
1127
1128 void Actor::SetWidth( float width )
1129 {
1130   if( NULL != mNode )
1131   {
1132     // mNode is being used in a separate thread; queue a message to set the value & base value
1133     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1134   }
1135 }
1136
1137 void Actor::SetHeight( float height )
1138 {
1139   if( NULL != mNode )
1140   {
1141     // mNode is being used in a separate thread; queue a message to set the value & base value
1142     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1143   }
1144 }
1145
1146 void Actor::SetDepth( float depth )
1147 {
1148   if( NULL != mNode )
1149   {
1150     // mNode is being used in a separate thread; queue a message to set the value & base value
1151     SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1152   }
1153 }
1154
1155 const Vector3& Actor::GetSize() const
1156 {
1157   return mSize;
1158 }
1159
1160 const Vector3& Actor::GetCurrentSize() const
1161 {
1162   if( NULL != mNode )
1163   {
1164     // mNode is being used in a separate thread; copy the value from the previous update
1165     return mNode->GetSize( mStage->GetEventBufferIndex() );
1166   }
1167
1168   return Vector3::ZERO;
1169 }
1170
1171 Vector3 Actor::GetNaturalSize() const
1172 {
1173   // It is up to deriving classes to return the appropriate natural size
1174   return Vector3( 0.0f, 0.0f, 0.0f );
1175 }
1176
1177
1178 #ifdef DYNAMICS_SUPPORT
1179
1180 //--------------- Dynamics ---------------
1181
1182 void Actor::DisableDynamics()
1183 {
1184   if( NULL != mDynamicsData )
1185   {
1186     DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1187
1188     // ensure dynamics object are disconnected from scene
1189     DisconnectDynamics();
1190
1191     // delete joint owned by this actor
1192     while( !mDynamicsData->joints.empty() )
1193     {
1194       RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1195     }
1196
1197     // delete other joints referencing this actor
1198     while( !mDynamicsData->referencedJoints.empty() )
1199     {
1200       DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1201       ActorPtr jointOwner( joint->GetActor( true ) );
1202       if( jointOwner )
1203       {
1204         jointOwner->RemoveDynamicsJoint( joint );
1205       }
1206       else
1207       {
1208         mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1209       }
1210     }
1211     // delete the DynamicsBody object
1212     mDynamicsData->body.Reset();
1213
1214     // Discard Dynamics data structure
1215     delete mDynamicsData;
1216     mDynamicsData = NULL;
1217   }
1218 }
1219
1220 DynamicsBodyPtr Actor::GetDynamicsBody() const
1221 {
1222   DynamicsBodyPtr body;
1223
1224   if( NULL != mDynamicsData )
1225   {
1226     body = mDynamicsData->body;
1227   }
1228
1229   return body;
1230 }
1231
1232 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1233 {
1234   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1235
1236   if( NULL == mDynamicsData )
1237   {
1238     mDynamicsData = new DynamicsData( this );
1239   }
1240
1241   if( !mDynamicsData->body )
1242   {
1243     mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1244
1245     if( OnStage() )
1246     {
1247       DynamicsWorldPtr world( mStage->GetDynamicsWorld() );
1248       if( world )
1249       {
1250         if( mParent == world->GetRootActor().Get() )
1251         {
1252           mDynamicsData->body->Connect(*mStage);
1253         }
1254       }
1255     }
1256   }
1257
1258   return mDynamicsData->body;
1259 }
1260
1261 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1262 {
1263   DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1264   return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1265 }
1266
1267 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1268 {
1269   DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1270   DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1271
1272   DynamicsJointPtr joint;
1273
1274   DynamicsWorldPtr world( mStage->GetDynamicsWorld() );
1275
1276   if( world )
1277   {
1278     if( NULL != mDynamicsData )
1279     {
1280       DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1281
1282       if( mDynamicsData->joints.end() != it )
1283       {
1284         // use existing joint
1285         joint = it->second;
1286       }
1287
1288       if( !joint )
1289       {
1290         DynamicsBodyPtr bodyA( GetDynamicsBody() );
1291         DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1292
1293         if( !bodyA )
1294         {
1295           bodyA = EnableDynamics( new DynamicsBodyConfig );
1296         }
1297
1298         if( !bodyB )
1299         {
1300           bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1301         }
1302
1303         joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1304         mDynamicsData->joints[ attachedActor.Get() ] = joint;
1305
1306         if( OnStage() && attachedActor->OnStage() )
1307         {
1308           joint->Connect(*mStage);
1309         }
1310
1311         attachedActor->ReferenceJoint( joint );
1312
1313         attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1314         attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1315       }
1316     }
1317   }
1318   return joint;
1319 }
1320
1321 const int Actor::GetNumberOfJoints() const
1322 {
1323   return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1324 }
1325
1326 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1327 {
1328   DynamicsJointPtr joint;
1329
1330   if( NULL != mDynamicsData )
1331   {
1332     if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1333     {
1334       DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1335
1336       for( int i = 0; i < index; ++i  )
1337       {
1338         ++it;
1339       }
1340
1341       joint = it->second;
1342     }
1343   }
1344
1345   return joint;
1346 }
1347
1348 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1349 {
1350   DynamicsJointPtr joint;
1351
1352   if( NULL != mDynamicsData )
1353   {
1354     DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1355
1356     if( mDynamicsData->joints.end() != it )
1357     {
1358       // use existing joint
1359       joint = it->second;
1360     }
1361   }
1362
1363   return joint;
1364 }
1365
1366 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1367 {
1368   if( NULL != mDynamicsData )
1369   {
1370     DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1371     DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1372
1373     for( ; it != endIt; ++it )
1374     {
1375       if( it->second == joint.Get() )
1376       {
1377         ActorPtr attachedActor( it->first );
1378
1379         if( OnStage() && attachedActor && attachedActor->OnStage() )
1380         {
1381           joint->Disconnect(*mStage);
1382         }
1383
1384         if( attachedActor )
1385         {
1386           attachedActor->ReleaseJoint( joint );
1387           attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1388           attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1389         }
1390
1391         mDynamicsData->joints.erase(it);
1392         break;
1393       }
1394     }
1395   }
1396 }
1397
1398 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1399 {
1400   DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1401
1402   if( NULL != mDynamicsData )
1403   {
1404     mDynamicsData->referencedJoints.push_back(joint);
1405   }
1406 }
1407
1408 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1409 {
1410   DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1411
1412   if( NULL != mDynamicsData )
1413   {
1414     DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1415
1416     if( it != mDynamicsData->referencedJoints.end() )
1417     {
1418       mDynamicsData->referencedJoints.erase( it );
1419     }
1420   }
1421 }
1422
1423 void Actor::SetDynamicsRoot(bool flag)
1424 {
1425   if( mIsDynamicsRoot != flag )
1426   {
1427     mIsDynamicsRoot = flag;
1428
1429     if( OnStage() && mChildren )
1430     {
1431       // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1432       ActorIter end = mChildren->end();
1433       for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1434       {
1435         Actor& child = GetImplementation(*iter);
1436
1437         if( child.GetDynamicsBody() )
1438         {
1439           if( mIsDynamicsRoot )
1440           {
1441             child.ConnectDynamics();
1442           }
1443           else
1444           {
1445             child.DisconnectDynamics();
1446           }
1447         }
1448       }
1449     }
1450   }
1451 }
1452
1453 bool Actor::IsDynamicsRoot() const
1454 {
1455   return mIsDynamicsRoot;
1456 }
1457
1458 void Actor::AttachedActorOnStage( Dali::Actor actor )
1459 {
1460   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1461
1462   if( OnStage() )
1463   {
1464     ActorPtr attachedActor( &GetImplementation(actor) );
1465
1466     DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1467     if( NULL != mDynamicsData )
1468     {
1469       DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find(  attachedActor.Get() ) );
1470       if( mDynamicsData->joints.end() != it )
1471       {
1472         DynamicsJointPtr joint( it->second );
1473         joint->Connect(*mStage);
1474       }
1475     }
1476   }
1477 }
1478
1479 void Actor::AttachedActorOffStage( Dali::Actor actor )
1480 {
1481   DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1482
1483   if( OnStage() )
1484   {
1485     ActorPtr attachedActor( &GetImplementation(actor) );
1486
1487     DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1488     if( NULL != mDynamicsData )
1489     {
1490       DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find(  attachedActor.Get() ) );
1491       if( mDynamicsData->joints.end() != it )
1492       {
1493         DynamicsJointPtr joint( it->second );
1494         joint->Disconnect(*mStage);
1495       }
1496     }
1497   }
1498 }
1499
1500 void Actor::ConnectDynamics()
1501 {
1502   if( NULL != mDynamicsData && mDynamicsData->body )
1503   {
1504     if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1505     {
1506       mDynamicsData->body->Connect(*mStage);
1507
1508       // Connect all joints where attachedActor is also on stage
1509       if( !mDynamicsData->joints.empty() )
1510       {
1511         DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1512         DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1513
1514         for( ; it != endIt; ++it )
1515         {
1516           Actor* attachedActor( it->first );
1517           if( NULL != attachedActor && attachedActor->OnStage() )
1518           {
1519             DynamicsJointPtr joint( it->second );
1520
1521             joint->Connect(*mStage);
1522           }
1523         }
1524       }
1525     }
1526   }
1527 }
1528
1529 void Actor::DisconnectDynamics()
1530 {
1531   if( NULL != mDynamicsData && mDynamicsData->body )
1532   {
1533     if( OnStage() )
1534     {
1535       mDynamicsData->body->Disconnect(*mStage);
1536
1537       // Disconnect all joints
1538       if( !mDynamicsData->joints.empty() )
1539       {
1540         DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1541         DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1542
1543         for( ; it != endIt; ++it )
1544         {
1545           DynamicsJointPtr joint( it->second );
1546
1547           joint->Disconnect(*mStage);
1548         }
1549       }
1550     }
1551   }
1552 }
1553
1554 #endif // DYNAMICS_SUPPORT
1555
1556 void Actor::SetOverlay(bool enable)
1557 {
1558   // Setting STENCIL will override OVERLAY
1559   if( DrawMode::STENCIL != mDrawMode )
1560   {
1561     SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1562   }
1563 }
1564
1565 bool Actor::IsOverlay() const
1566 {
1567   return ( DrawMode::OVERLAY == mDrawMode );
1568 }
1569
1570 void Actor::SetDrawMode( DrawMode::Type drawMode )
1571 {
1572   // this flag is not animatable so keep the value
1573   mDrawMode = drawMode;
1574   if( NULL != mNode )
1575   {
1576     // mNode is being used in a separate thread; queue a message to set the value
1577     SetDrawModeMessage( mStage->GetUpdateInterface(), *mNode, drawMode );
1578   }
1579 }
1580
1581 DrawMode::Type Actor::GetDrawMode() const
1582 {
1583   return mDrawMode;
1584 }
1585
1586 bool Actor::ScreenToLocal( float& localX,
1587                            float& localY,
1588                            float screenX,
1589                            float screenY ) const
1590 {
1591   // only valid when on-stage
1592   if ( OnStage() )
1593   {
1594     const RenderTaskList& taskList = mStage->GetRenderTaskList();
1595
1596     Vector2 converted( screenX, screenY );
1597
1598     // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1599     const int taskCount = taskList.GetTaskCount();
1600     for( int i = taskCount - 1; i >= 0; --i )
1601     {
1602       Dali::RenderTask task = taskList.GetTask( i );
1603       if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1604       {
1605         // found a task where this conversion was ok so return
1606         return true;
1607       }
1608     }
1609   }
1610   return false;
1611 }
1612
1613 bool Actor::ScreenToLocal( RenderTask& renderTask,
1614                            float& localX,
1615                            float& localY,
1616                            float screenX,
1617                            float screenY ) const
1618 {
1619   bool retval = false;
1620   // only valid when on-stage
1621   if ( OnStage() )
1622   {
1623     CameraActor* camera = renderTask.GetCameraActor();
1624     if( camera )
1625     {
1626       Viewport viewport;
1627       renderTask.GetViewport( viewport );
1628
1629       // need to translate coordinates to render tasks coordinate space
1630       Vector2 converted( screenX, screenY );
1631       if( renderTask.TranslateCoordinates( converted ) )
1632       {
1633         retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1634       }
1635     }
1636   }
1637   return retval;
1638 }
1639
1640 bool Actor::ScreenToLocal( const Matrix& viewMatrix,
1641                            const Matrix& projectionMatrix,
1642                            const Viewport& viewport,
1643                            float& localX,
1644                            float& localY,
1645                            float screenX,
1646                            float screenY ) const
1647 {
1648   // Early-out if mNode is NULL
1649   if( !OnStage() )
1650   {
1651     return false;
1652   }
1653
1654   BufferIndex bufferIndex( mStage->GetEventBufferIndex() );
1655
1656   // Calculate the ModelView matrix
1657   Matrix modelView(false/*don't init*/);
1658   // need to use the components as world matrix is only updated for actors that need it
1659   modelView.SetTransformComponents( mNode->GetWorldScale(bufferIndex), mNode->GetWorldRotation(bufferIndex), mNode->GetWorldPosition(bufferIndex) );
1660   Matrix::Multiply(modelView, modelView, viewMatrix);
1661
1662   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1663   Matrix invertedMvp(false/*don't init*/);
1664   Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
1665   bool success = invertedMvp.Invert();
1666
1667   // Convert to GL coordinates
1668   Vector4 screenPos( screenX - viewport.x, viewport.height - (screenY - viewport.y), 0.f, 1.f );
1669
1670   Vector4 nearPos;
1671   if (success)
1672   {
1673     success = Unproject(screenPos, invertedMvp, viewport.width, viewport.height, nearPos);
1674   }
1675
1676   Vector4 farPos;
1677   if (success)
1678   {
1679     screenPos.z = 1.0f;
1680     success = Unproject(screenPos, invertedMvp, viewport.width, viewport.height, farPos);
1681   }
1682
1683   if (success)
1684   {
1685     Vector4 local;
1686     if (XyPlaneIntersect(nearPos, farPos, local))
1687     {
1688       Vector3 size = GetCurrentSize();
1689       localX = local.x + size.x * 0.5f;
1690       localY = local.y + size.y * 0.5f;
1691     }
1692     else
1693     {
1694       success = false;
1695     }
1696   }
1697
1698   return success;
1699 }
1700
1701 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1702 {
1703   /*
1704     http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1705
1706     Mathematical Formulation
1707
1708     Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1709
1710     ( p - c ) dot ( p - c ) = r^2
1711
1712     Given a ray with a point of origin 'o', and a direction vector 'd':
1713
1714     ray(t) = o + td, t >= 0
1715
1716     we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1717
1718     (o + td - c ) dot ( o + td - c ) = r^2
1719
1720     To solve for t we first expand the above into a more recognisable quadratic equation form
1721
1722     ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1723
1724     or
1725
1726     At2 + Bt + C = 0
1727
1728     where
1729
1730     A = d dot d
1731     B = 2( o - c ) dot d
1732     C = ( o - c ) dot ( o - c ) - r^2
1733
1734     which can be solved using a standard quadratic formula.
1735
1736     Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1737
1738     Practical Simplification
1739
1740     In a renderer, we often differentiate between world space and object space. In the object space
1741     of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1742     into object space, the mathematical solution presented above can be simplified significantly.
1743
1744     If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1745
1746     p dot p = r^2
1747
1748     and we can find the t at which the (transformed) ray intersects the sphere by
1749
1750     ( o + td ) dot ( o + td ) = r^2
1751
1752     According to the reasoning above, we expand the above quadratic equation into the general form
1753
1754     At2 + Bt + C = 0
1755
1756     which now has coefficients:
1757
1758     A = d dot d
1759     B = 2( d dot o )
1760     C = o dot o - r^2
1761    */
1762
1763   // Early out if mNode is NULL
1764   if( !mNode )
1765   {
1766     return false;
1767   }
1768
1769   BufferIndex bufferIndex( mStage->GetEventBufferIndex() );
1770
1771   // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1772   const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1773   Vector3 rayOriginLocal(rayOrigin.x - translation.x,
1774                          rayOrigin.y - translation.y,
1775                          rayOrigin.z - translation.z);
1776
1777   // Compute the radius is not needed, square radius it's enough.
1778   const Vector3& size( mNode->GetSize( bufferIndex ) );
1779
1780   // Scale the sphere.
1781   const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1782
1783   const float width = size.width * scale.width;
1784   const float height = size.height * scale.height;
1785
1786   float squareSphereRadius = 0.5f * ( width * width + height * height );
1787
1788   float a = rayDir.Dot( rayDir );                                       // a
1789   float b2 = rayDir.Dot( rayOriginLocal );                              // b/2
1790   float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius;  // c
1791
1792   return ( b2*b2 - a*c ) >= 0.f;
1793 }
1794
1795 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1796 {
1797   bool hit = false;
1798
1799   if( OnStage() &&
1800       NULL != mNode )
1801   {
1802     BufferIndex bufferIndex( mStage->GetEventBufferIndex() );
1803
1804     // Transforms the ray to the local reference system.
1805
1806     // Calculate the inverse of Model matrix
1807     Matrix invModelMatrix(false/*don't init*/);
1808     // need to use the components as world matrix is only updated for actors that need it
1809     invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale(bufferIndex), mNode->GetWorldRotation(bufferIndex), mNode->GetWorldPosition(bufferIndex) );
1810
1811     Vector4 rayOriginLocal(invModelMatrix * rayOrigin);
1812     Vector4 rayDirLocal(invModelMatrix * rayDir - invModelMatrix.GetTranslation());
1813
1814     // Test with the actor's XY plane (Normal = 0 0 1 1).
1815
1816     float a = -rayOriginLocal.z;
1817     float b = rayDirLocal.z;
1818
1819     if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1820     {
1821       // Ray travels distance * rayDirLocal to intersect with plane.
1822       distance = a / b;
1823
1824       const Vector3& size = mNode->GetSize( bufferIndex );
1825
1826       hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1827       hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1828
1829       // Test with the actor's geometry.
1830       hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1831     }
1832   }
1833
1834   return hit;
1835 }
1836
1837 void Actor::SetLeaveRequired(bool required)
1838 {
1839   mLeaveRequired = required;
1840 }
1841
1842 bool Actor::GetLeaveRequired() const
1843 {
1844   return mLeaveRequired;
1845 }
1846
1847 void Actor::SetKeyboardFocusable( bool focusable )
1848 {
1849   mKeyboardFocusable = focusable;
1850 }
1851
1852 bool Actor::IsKeyboardFocusable() const
1853 {
1854   return mKeyboardFocusable;
1855 }
1856
1857 bool Actor::GetTouchRequired() const
1858 {
1859   return !mTouchedSignalV2.Empty() || mDerivedRequiresTouch;
1860 }
1861
1862 bool Actor::GetHoverRequired() const
1863 {
1864   return !mHoveredSignalV2.Empty() || mDerivedRequiresHover;
1865 }
1866
1867 bool Actor::GetMouseWheelEventRequired() const
1868 {
1869   return !mMouseWheelEventSignalV2.Empty() || mDerivedRequiresMouseWheelEvent;
1870 }
1871
1872 bool Actor::IsHittable() const
1873 {
1874   return IsSensitive() &&
1875          IsVisible() &&
1876          ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) &&
1877          IsNodeConnected();
1878 }
1879
1880 ActorGestureData& Actor::GetGestureData()
1881 {
1882   // Likely scenario is that once gesture-data is created for this actor, the actor will require
1883   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1884   if ( NULL == mGestureData )
1885   {
1886     mGestureData = new ActorGestureData;
1887   }
1888   return *mGestureData;
1889 }
1890
1891 bool Actor::IsGestureRequred( Gesture::Type type ) const
1892 {
1893   return mGestureData && mGestureData->IsGestureRequred( type );
1894 }
1895
1896 bool Actor::EmitTouchEventSignal(const TouchEvent& event)
1897 {
1898   bool consumed = false;
1899
1900   if ( !mTouchedSignalV2.Empty() )
1901   {
1902     Dali::Actor handle( this );
1903     consumed = mTouchedSignalV2.Emit( handle, event );
1904   }
1905
1906   if (!consumed)
1907   {
1908     // Notification for derived classes
1909     consumed = OnTouchEvent( event );
1910   }
1911
1912   return consumed;
1913 }
1914
1915 bool Actor::EmitHoverEventSignal(const HoverEvent& event)
1916 {
1917   bool consumed = false;
1918
1919   if ( !mHoveredSignalV2.Empty() )
1920   {
1921     Dali::Actor handle( this );
1922     consumed = mHoveredSignalV2.Emit( handle, event );
1923   }
1924
1925   if (!consumed)
1926   {
1927     // Notification for derived classes
1928     consumed = OnHoverEvent( event );
1929   }
1930
1931   return consumed;
1932 }
1933
1934 bool Actor::EmitMouseWheelEventSignal(const MouseWheelEvent& event)
1935 {
1936   bool consumed = false;
1937
1938   if ( !mMouseWheelEventSignalV2.Empty() )
1939   {
1940     Dali::Actor handle( this );
1941     consumed = mMouseWheelEventSignalV2.Emit( handle, event );
1942   }
1943
1944   if (!consumed)
1945   {
1946     // Notification for derived classes
1947     consumed = OnMouseWheelEvent(event);
1948   }
1949
1950   return consumed;
1951 }
1952
1953 Dali::Actor::TouchSignalV2& Actor::TouchedSignal()
1954 {
1955   return mTouchedSignalV2;
1956 }
1957
1958 Dali::Actor::HoverSignalV2& Actor::HoveredSignal()
1959 {
1960   return mHoveredSignalV2;
1961 }
1962
1963 Dali::Actor::MouseWheelEventSignalV2& Actor::MouseWheelEventSignal()
1964 {
1965   return mMouseWheelEventSignalV2;
1966 }
1967
1968 Dali::Actor::SetSizeSignalV2& Actor::SetSizeSignal()
1969 {
1970   return mSetSizeSignalV2;
1971 }
1972
1973 Dali::Actor::OnStageSignalV2& Actor::OnStageSignal()
1974 {
1975   return mOnStageSignalV2;
1976 }
1977
1978 Dali::Actor::OffStageSignalV2& Actor::OffStageSignal()
1979 {
1980   return mOffStageSignalV2;
1981 }
1982
1983 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1984 {
1985   bool connected( true );
1986   Actor* actor = dynamic_cast<Actor*>(object);
1987
1988   if(Dali::Actor::SIGNAL_TOUCHED == signalName)
1989   {
1990     actor->TouchedSignal().Connect( tracker, functor );
1991   }
1992   else if(Dali::Actor::SIGNAL_HOVERED == signalName)
1993   {
1994     actor->HoveredSignal().Connect( tracker, functor );
1995   }
1996   else if(Dali::Actor::SIGNAL_MOUSE_WHEEL_EVENT == signalName)
1997   {
1998     actor->MouseWheelEventSignal().Connect( tracker, functor );
1999   }
2000   else if(Dali::Actor::SIGNAL_SET_SIZE == signalName)
2001   {
2002     actor->SetSizeSignal().Connect( tracker, functor );
2003   }
2004   else if(Dali::Actor::SIGNAL_ON_STAGE == signalName)
2005   {
2006     actor->OnStageSignal().Connect( tracker, functor );
2007   }
2008   else if(Dali::Actor::SIGNAL_OFF_STAGE == signalName)
2009   {
2010     actor->OffStageSignal().Connect( tracker, functor );
2011   }
2012   else
2013   {
2014     // signalName does not match any signal
2015     connected = false;
2016   }
2017
2018   return connected;
2019 }
2020
2021 Actor::Actor( DerivedType derivedType )
2022 : mStage( NULL ),
2023   mParent( NULL ),
2024   mChildren( NULL ),
2025   mNode( NULL ),
2026   mParentOrigin( NULL ),
2027   mAnchorPoint( NULL ),
2028 #ifdef DYNAMICS_SUPPORT
2029   mDynamicsData( NULL ),
2030 #endif
2031   mGestureData( NULL ),
2032   mAttachment(),
2033   mSize( 0.0f, 0.0f, 0.0f ),
2034   mName(),
2035   mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2036   mIsRoot( ROOT_LAYER == derivedType ),
2037   mIsRenderable( RENDERABLE == derivedType ),
2038   mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2039   mIsOnStage( false ),
2040   mIsDynamicsRoot(false),
2041   mSensitive( true ),
2042   mLeaveRequired( false ),
2043   mKeyboardFocusable( false ),
2044   mDerivedRequiresTouch( false ),
2045   mDerivedRequiresHover( false ),
2046   mDerivedRequiresMouseWheelEvent( false ),
2047   mOnStageSignalled( false ),
2048   mInheritRotation( true ),
2049   mInheritScale( true ),
2050   mDrawMode( DrawMode::NORMAL ),
2051   mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2052   mColorMode( Node::DEFAULT_COLOR_MODE )
2053 {
2054 }
2055
2056 void Actor::Initialize()
2057 {
2058   mStage = Stage::GetCurrent();
2059
2060   // Node creation
2061   SceneGraph::Node* node = CreateNode();
2062
2063   AddNodeMessage( mStage->GetUpdateManager(), *node ); // Pass ownership to scene-graph
2064   mNode = node; // Keep raw-pointer to Node
2065
2066   OnInitialize();
2067
2068   RegisterObject();
2069 }
2070
2071 Actor::~Actor()
2072 {
2073   // Remove mParent pointers from children even if we're destroying core,
2074   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2075   if( mChildren )
2076   {
2077     ActorConstIter endIter = mChildren->end();
2078     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2079     {
2080       Actor& actor = GetImplementation( *iter );
2081       actor.SetParent( NULL );
2082     }
2083   }
2084   delete mChildren;
2085
2086   // Guard to allow handle destruction after Core has been destroyed
2087   if( Stage::IsInstalled() )
2088   {
2089     if( NULL != mNode )
2090     {
2091       DestroyNodeMessage( mStage->GetUpdateManager(), *mNode );
2092       mNode = NULL; // Node is about to be destroyed
2093     }
2094
2095     UnregisterObject();
2096   }
2097
2098 #ifdef DYNAMICS_SUPPORT
2099   // Cleanup dynamics
2100   delete mDynamicsData;
2101 #endif
2102
2103   // Cleanup optional gesture data
2104   delete mGestureData;
2105
2106   // Cleanup optional parent origin and anchor
2107   delete mParentOrigin;
2108   delete mAnchorPoint;
2109 }
2110
2111 void Actor::ConnectToStage( Stage& stage, int index )
2112 {
2113   // This container is used instead of walking the Actor hierachy.
2114   // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2115   ActorContainer connectionList;
2116
2117   // This stage is atomic i.e. not interrupted by user callbacks
2118   RecursiveConnectToStage( stage, connectionList, index );
2119
2120   // Notify applications about the newly connected actors.
2121   const ActorIter endIter = connectionList.end();
2122   for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2123   {
2124     Actor& actor = GetImplementation(*iter);
2125     actor.NotifyStageConnection();
2126   }
2127 }
2128
2129 void Actor::RecursiveConnectToStage( Stage& stage, ActorContainer& connectionList, int index )
2130 {
2131   DALI_ASSERT_ALWAYS( !OnStage() );
2132
2133   mIsOnStage = true;
2134
2135   ConnectToSceneGraph(index);
2136
2137   // Notification for internal derived classes
2138   OnStageConnectionInternal();
2139
2140   // This stage is atomic; avoid emitting callbacks until all Actors are connected
2141   connectionList.push_back( Dali::Actor(this) );
2142
2143   // Recursively connect children
2144   if( mChildren )
2145   {
2146     ActorConstIter endIter = mChildren->end();
2147     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2148     {
2149       Actor& actor = GetImplementation( *iter );
2150       actor.RecursiveConnectToStage( stage, connectionList );
2151     }
2152   }
2153 }
2154
2155 /**
2156  * This method is called when the Actor is connected to the Stage.
2157  * The parent must have added its Node to the scene-graph.
2158  * The child must connect its Node to the parent's Node.
2159  * This is resursive; the child calls ConnectToStage() for its children.
2160  */
2161 void Actor::ConnectToSceneGraph(int index)
2162 {
2163   DALI_ASSERT_DEBUG( mNode != NULL);
2164   DALI_ASSERT_DEBUG( mParent != NULL);
2165   DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2166
2167   if( NULL != mNode )
2168   {
2169     // Reparent Node in next Update
2170     ConnectNodeMessage( mStage->GetUpdateManager(), *(mParent->mNode), *mNode, index );
2171   }
2172
2173   // Notify attachment
2174   if (mAttachment)
2175   {
2176     mAttachment->Connect();
2177   }
2178
2179 #ifdef DYNAMICS_SUPPORT
2180   // Notify dynamics
2181   if( NULL != mDynamicsData )
2182   {
2183     ConnectDynamics();
2184   }
2185 #endif
2186
2187   // Notification for ProxyObject::Observers
2188   OnSceneObjectAdd();
2189 }
2190
2191 void Actor::NotifyStageConnection()
2192 {
2193   // Actors can be removed (in a callback), before the on-stage stage is reported.
2194   // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2195   if ( OnStage() && !mOnStageSignalled )
2196   {
2197     // Notification for external (CustomActor) derived classes
2198     OnStageConnectionExternal();
2199
2200     if ( !mOnStageSignalV2.Empty() )
2201     {
2202       Dali::Actor handle( this );
2203       mOnStageSignalV2.Emit( handle );
2204     }
2205
2206     // Guard against Remove during callbacks
2207     if ( OnStage()  )
2208     {
2209       mOnStageSignalled = true; // signal required next time Actor is removed
2210     }
2211   }
2212 }
2213
2214 void Actor::DisconnectFromStage()
2215 {
2216   // This container is used instead of walking the Actor hierachy.
2217   // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2218   ActorContainer disconnectionList;
2219
2220   // This stage is atomic i.e. not interrupted by user callbacks
2221   RecursiveDisconnectFromStage( disconnectionList );
2222
2223   // Notify applications about the newly disconnected actors.
2224   const ActorIter endIter = disconnectionList.end();
2225   for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2226   {
2227     Actor& actor = GetImplementation(*iter);
2228     actor.NotifyStageDisconnection();
2229   }
2230 }
2231
2232 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2233 {
2234   DALI_ASSERT_ALWAYS( OnStage() );
2235
2236   // Recursively disconnect children
2237   if( mChildren )
2238   {
2239     ActorConstIter endIter = mChildren->end();
2240     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2241     {
2242       Actor& actor = GetImplementation( *iter );
2243       actor.RecursiveDisconnectFromStage( disconnectionList );
2244     }
2245   }
2246
2247   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2248   disconnectionList.push_back( Dali::Actor(this) );
2249
2250   // Notification for internal derived classes
2251   OnStageDisconnectionInternal();
2252
2253   DisconnectFromSceneGraph();
2254
2255   mIsOnStage = false;
2256 }
2257
2258 /**
2259  * This method is called by an actor or its parent, before a node removal message is sent.
2260  * This is recursive; the child calls DisconnectFromStage() for its children.
2261  */
2262 void Actor::DisconnectFromSceneGraph()
2263 {
2264   // Notification for ProxyObject::Observers
2265   OnSceneObjectRemove();
2266
2267   // Notify attachment
2268   if (mAttachment)
2269   {
2270     mAttachment->Disconnect();
2271   }
2272
2273 #ifdef DYNAMICS_SUPPORT
2274   // Notify dynamics
2275   if( NULL != mDynamicsData )
2276   {
2277     DisconnectDynamics();
2278   }
2279 #endif
2280 }
2281
2282 void Actor::NotifyStageDisconnection()
2283 {
2284   // Actors can be added (in a callback), before the off-stage state is reported.
2285   // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2286   // only do this step if there is a stage, i.e. Core is not being shut down
2287   if ( Stage::IsInstalled() && !OnStage() && mOnStageSignalled )
2288   {
2289     // Notification for external (CustomeActor) derived classes
2290     OnStageDisconnectionExternal();
2291
2292     if( !mOffStageSignalV2.Empty() )
2293     {
2294       Dali::Actor handle( this );
2295       mOffStageSignalV2.Emit( handle );
2296     }
2297
2298     // Guard against Add during callbacks
2299     if ( !OnStage()  )
2300     {
2301       mOnStageSignalled = false; // signal required next time Actor is added
2302     }
2303   }
2304 }
2305
2306 bool Actor::IsNodeConnected() const
2307 {
2308   bool connected( false );
2309
2310   if( OnStage() &&
2311       NULL != mNode )
2312   {
2313     if( mNode->IsRoot() || mNode->GetParent() )
2314     {
2315       connected = true;
2316     }
2317   }
2318
2319   return connected;
2320 }
2321
2322 unsigned int Actor::GetDefaultPropertyCount() const
2323 {
2324   return DEFAULT_PROPERTY_COUNT;
2325 }
2326
2327 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2328 {
2329   indices.reserve( DEFAULT_PROPERTY_COUNT );
2330
2331   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2332   {
2333     indices.push_back( i );
2334   }
2335 }
2336
2337 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2338 {
2339   if( index < DEFAULT_PROPERTY_COUNT )
2340   {
2341     return DEFAULT_PROPERTY_DETAILS[index].name;
2342   }
2343   else
2344   {
2345     return NULL;
2346   }
2347 }
2348
2349 Property::Index Actor::GetDefaultPropertyIndex(const std::string& name) const
2350 {
2351   Property::Index index = Property::INVALID_INDEX;
2352
2353   // Look for name in default properties
2354   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2355   {
2356     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2357     if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
2358     {
2359       index = i;
2360       break;
2361     }
2362   }
2363
2364   return index;
2365 }
2366
2367 bool Actor::IsDefaultPropertyWritable(Property::Index index) const
2368 {
2369   if( index < DEFAULT_PROPERTY_COUNT )
2370   {
2371     return DEFAULT_PROPERTY_DETAILS[index].writable;
2372   }
2373   else
2374   {
2375     return false;
2376   }
2377 }
2378
2379 bool Actor::IsDefaultPropertyAnimatable(Property::Index index) const
2380 {
2381   if( index < DEFAULT_PROPERTY_COUNT )
2382   {
2383     return DEFAULT_PROPERTY_DETAILS[index].animatable;
2384   }
2385   else
2386   {
2387     return false;
2388   }
2389 }
2390
2391 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2392 {
2393   if( index < DEFAULT_PROPERTY_COUNT )
2394   {
2395     return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
2396   }
2397   else
2398   {
2399     return false;
2400   }
2401 }
2402
2403 Property::Type Actor::GetDefaultPropertyType(Property::Index index) const
2404 {
2405   if( index < DEFAULT_PROPERTY_COUNT )
2406   {
2407     return DEFAULT_PROPERTY_DETAILS[index].type;
2408   }
2409   else
2410   {
2411     // index out of range...return Property::NONE
2412     return Property::NONE;
2413   }
2414 }
2415
2416 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2417 {
2418   switch ( index )
2419   {
2420     case Dali::Actor::PARENT_ORIGIN:
2421     {
2422       SetParentOrigin( property.Get<Vector3>() );
2423       break;
2424     }
2425
2426     case Dali::Actor::PARENT_ORIGIN_X:
2427     {
2428       SetParentOriginX( property.Get<float>() );
2429       break;
2430     }
2431
2432     case Dali::Actor::PARENT_ORIGIN_Y:
2433     {
2434       SetParentOriginY( property.Get<float>() );
2435       break;
2436     }
2437
2438     case Dali::Actor::PARENT_ORIGIN_Z:
2439     {
2440       SetParentOriginZ( property.Get<float>() );
2441       break;
2442     }
2443
2444     case Dali::Actor::ANCHOR_POINT:
2445     {
2446       SetAnchorPoint( property.Get<Vector3>() );
2447       break;
2448     }
2449
2450     case Dali::Actor::ANCHOR_POINT_X:
2451     {
2452       SetAnchorPointX( property.Get<float>() );
2453       break;
2454     }
2455
2456     case Dali::Actor::ANCHOR_POINT_Y:
2457     {
2458       SetAnchorPointY( property.Get<float>() );
2459       break;
2460     }
2461
2462     case Dali::Actor::ANCHOR_POINT_Z:
2463     {
2464       SetAnchorPointZ( property.Get<float>() );
2465       break;
2466     }
2467
2468     case Dali::Actor::SIZE:
2469     {
2470       SetSize( property.Get<Vector3>() );
2471       break;
2472     }
2473
2474     case Dali::Actor::SIZE_WIDTH:
2475     {
2476       SetWidth( property.Get<float>() );
2477       break;
2478     }
2479
2480     case Dali::Actor::SIZE_HEIGHT:
2481     {
2482       SetHeight( property.Get<float>() );
2483       break;
2484     }
2485
2486     case Dali::Actor::SIZE_DEPTH:
2487     {
2488       SetDepth( property.Get<float>() );
2489       break;
2490     }
2491
2492     case Dali::Actor::POSITION:
2493     {
2494       SetPosition( property.Get<Vector3>() );
2495       break;
2496     }
2497
2498     case Dali::Actor::POSITION_X:
2499     {
2500       SetX( property.Get<float>() );
2501       break;
2502     }
2503
2504     case Dali::Actor::POSITION_Y:
2505     {
2506       SetY( property.Get<float>() );
2507       break;
2508     }
2509
2510     case Dali::Actor::POSITION_Z:
2511     {
2512       SetZ( property.Get<float>() );
2513       break;
2514     }
2515
2516     case Dali::Actor::ROTATION:
2517     {
2518       SetRotation( property.Get<Quaternion>() );
2519       break;
2520     }
2521
2522     case Dali::Actor::SCALE:
2523     {
2524       SetScale( property.Get<Vector3>() );
2525       break;
2526     }
2527
2528     case Dali::Actor::SCALE_X:
2529     {
2530       SetScaleX( property.Get<float>() );
2531       break;
2532     }
2533
2534     case Dali::Actor::SCALE_Y:
2535     {
2536       SetScaleY( property.Get<float>() );
2537       break;
2538     }
2539
2540     case Dali::Actor::SCALE_Z:
2541     {
2542       SetScaleZ( property.Get<float>() );
2543       break;
2544     }
2545
2546     case Dali::Actor::VISIBLE:
2547     {
2548       SetVisible( property.Get<bool>() );
2549       break;
2550     }
2551
2552     case Dali::Actor::COLOR:
2553     {
2554       SetColor( property.Get<Vector4>() );
2555       break;
2556     }
2557
2558     case Dali::Actor::COLOR_RED:
2559     {
2560       SetColorRed( property.Get<float>() );
2561       break;
2562     }
2563
2564     case Dali::Actor::COLOR_GREEN:
2565     {
2566       SetColorGreen( property.Get<float>() );
2567       break;
2568     }
2569
2570     case Dali::Actor::COLOR_BLUE:
2571     {
2572       SetColorBlue( property.Get<float>() );
2573       break;
2574     }
2575
2576     case Dali::Actor::COLOR_ALPHA:
2577     {
2578       SetOpacity( property.Get<float>() );
2579       break;
2580     }
2581
2582     case Dali::Actor::NAME:
2583     {
2584       SetName( property.Get<std::string>() );
2585       break;
2586     }
2587
2588     case Dali::Actor::SENSITIVE:
2589     {
2590       SetSensitive( property.Get<bool>() );
2591       break;
2592     }
2593
2594     case Dali::Actor::LEAVE_REQUIRED:
2595     {
2596       SetLeaveRequired( property.Get<bool>() );
2597       break;
2598     }
2599
2600     case Dali::Actor::INHERIT_ROTATION:
2601     {
2602       SetInheritRotation( property.Get<bool>() );
2603       break;
2604     }
2605
2606     case Dali::Actor::INHERIT_SCALE:
2607     {
2608       SetInheritScale( property.Get<bool>() );
2609       break;
2610     }
2611
2612     case Dali::Actor::COLOR_MODE:
2613     {
2614       SetColorMode( Scripting::GetColorMode( property.Get<std::string>() ) );
2615       break;
2616     }
2617
2618     case Dali::Actor::POSITION_INHERITANCE:
2619     {
2620       SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get<std::string>() ) );
2621       break;
2622     }
2623
2624     case Dali::Actor::DRAW_MODE:
2625     {
2626       SetDrawMode( Scripting::GetDrawMode( property.Get<std::string>() ) );
2627       break;
2628     }
2629
2630     default:
2631     {
2632       // this can happen in the case of a non-animatable default property so just do nothing
2633       break;
2634     }
2635   }
2636 }
2637
2638 // TODO: This method needs to be removed
2639 void Actor::SetSceneGraphProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
2640 {
2641   OnPropertySet(index, value);
2642
2643   switch ( entry.type )
2644   {
2645     case Property::BOOLEAN:
2646     {
2647       const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
2648       DALI_ASSERT_DEBUG( NULL != property );
2649
2650       // property is being used in a separate thread; queue a message to set the property
2651       SceneGraph::NodePropertyMessage<bool>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2652
2653       break;
2654     }
2655
2656     case Property::FLOAT:
2657     {
2658       const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
2659       DALI_ASSERT_DEBUG( NULL != property );
2660
2661       // property is being used in a separate thread; queue a message to set the property
2662       SceneGraph::NodePropertyMessage<float>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2663
2664       break;
2665     }
2666
2667     case Property::INTEGER:
2668     {
2669       const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
2670       DALI_ASSERT_DEBUG( NULL != property );
2671
2672       // property is being used in a separate thread; queue a message to set the property
2673       SceneGraph::NodePropertyMessage<int>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2674
2675       break;
2676     }
2677
2678     case Property::VECTOR2:
2679     {
2680       const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
2681       DALI_ASSERT_DEBUG( NULL != property );
2682
2683       // property is being used in a separate thread; queue a message to set the property
2684       SceneGraph::NodePropertyMessage<Vector2>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2685
2686       break;
2687     }
2688
2689     case Property::VECTOR3:
2690     {
2691       const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
2692       DALI_ASSERT_DEBUG( NULL != property );
2693
2694       // property is being used in a separate thread; queue a message to set the property
2695       SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2696
2697       break;
2698     }
2699
2700     case Property::VECTOR4:
2701     {
2702       const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
2703       DALI_ASSERT_DEBUG( NULL != property );
2704
2705       // property is being used in a separate thread; queue a message to set the property
2706       SceneGraph::NodePropertyMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2707
2708       break;
2709     }
2710
2711     case Property::ROTATION:
2712     {
2713       const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
2714       DALI_ASSERT_DEBUG( NULL != property );
2715
2716       // property is being used in a separate thread; queue a message to set the property
2717       SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, property,&AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
2718
2719       break;
2720     }
2721
2722     case Property::MATRIX:
2723     {
2724       const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
2725       DALI_ASSERT_DEBUG( NULL != property );
2726
2727       // property is being used in a separate thread; queue a message to set the property
2728       SceneGraph::NodePropertyMessage<Matrix>::Send( mStage->GetUpdateManager(), mNode, property,&AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
2729
2730       break;
2731     }
2732
2733     case Property::MATRIX3:
2734     {
2735       const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
2736       DALI_ASSERT_DEBUG( NULL != property );
2737
2738       // property is being used in a separate thread; queue a message to set the property
2739       SceneGraph::NodePropertyMessage<Matrix3>::Send( mStage->GetUpdateManager(), mNode, property,&AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
2740
2741       break;
2742     }
2743
2744     default:
2745     {
2746       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2747       break;
2748     }
2749   }
2750 }
2751
2752 Property::Value Actor::GetDefaultProperty(Property::Index index) const
2753 {
2754   Property::Value value;
2755
2756   switch ( index )
2757   {
2758     case Dali::Actor::PARENT_ORIGIN:
2759     {
2760       value = GetCurrentParentOrigin();
2761       break;
2762     }
2763
2764     case Dali::Actor::PARENT_ORIGIN_X:
2765     {
2766       value = GetCurrentParentOrigin().x;
2767       break;
2768     }
2769
2770     case Dali::Actor::PARENT_ORIGIN_Y:
2771     {
2772       value = GetCurrentParentOrigin().y;
2773       break;
2774     }
2775
2776     case Dali::Actor::PARENT_ORIGIN_Z:
2777     {
2778       value = GetCurrentParentOrigin().z;
2779       break;
2780     }
2781
2782     case Dali::Actor::ANCHOR_POINT:
2783     {
2784       value = GetCurrentAnchorPoint();
2785       break;
2786     }
2787
2788     case Dali::Actor::ANCHOR_POINT_X:
2789     {
2790       value = GetCurrentAnchorPoint().x;
2791       break;
2792     }
2793
2794     case Dali::Actor::ANCHOR_POINT_Y:
2795     {
2796       value = GetCurrentAnchorPoint().y;
2797       break;
2798     }
2799
2800     case Dali::Actor::ANCHOR_POINT_Z:
2801     {
2802       value = GetCurrentAnchorPoint().z;
2803       break;
2804     }
2805
2806     case Dali::Actor::SIZE:
2807     {
2808       value = GetCurrentSize();
2809       break;
2810     }
2811
2812     case Dali::Actor::SIZE_WIDTH:
2813     {
2814       value = GetCurrentSize().width;
2815       break;
2816     }
2817
2818     case Dali::Actor::SIZE_HEIGHT:
2819     {
2820       value = GetCurrentSize().height;
2821       break;
2822     }
2823
2824     case Dali::Actor::SIZE_DEPTH:
2825     {
2826       value = GetCurrentSize().depth;
2827       break;
2828     }
2829
2830     case Dali::Actor::POSITION:
2831     {
2832       value = GetCurrentPosition();
2833       break;
2834     }
2835
2836     case Dali::Actor::POSITION_X:
2837     {
2838       value = GetCurrentPosition().x;
2839       break;
2840     }
2841
2842     case Dali::Actor::POSITION_Y:
2843     {
2844       value = GetCurrentPosition().y;
2845       break;
2846     }
2847
2848     case Dali::Actor::POSITION_Z:
2849     {
2850       value = GetCurrentPosition().z;
2851       break;
2852     }
2853
2854     case Dali::Actor::WORLD_POSITION:
2855     {
2856       value = GetCurrentWorldPosition();
2857       break;
2858     }
2859
2860     case Dali::Actor::WORLD_POSITION_X:
2861     {
2862       value = GetCurrentWorldPosition().x;
2863       break;
2864     }
2865
2866     case Dali::Actor::WORLD_POSITION_Y:
2867     {
2868       value = GetCurrentWorldPosition().y;
2869       break;
2870     }
2871
2872     case Dali::Actor::WORLD_POSITION_Z:
2873     {
2874       value = GetCurrentWorldPosition().z;
2875       break;
2876     }
2877
2878     case Dali::Actor::ROTATION:
2879     {
2880       value = GetCurrentRotation();
2881       break;
2882     }
2883
2884     case Dali::Actor::WORLD_ROTATION:
2885     {
2886       value = GetCurrentWorldRotation();
2887       break;
2888     }
2889
2890     case Dali::Actor::SCALE:
2891     {
2892       value = GetCurrentScale();
2893       break;
2894     }
2895
2896     case Dali::Actor::SCALE_X:
2897     {
2898       value = GetCurrentScale().x;
2899       break;
2900     }
2901
2902     case Dali::Actor::SCALE_Y:
2903     {
2904       value = GetCurrentScale().y;
2905       break;
2906     }
2907
2908     case Dali::Actor::SCALE_Z:
2909     {
2910       value = GetCurrentScale().z;
2911       break;
2912     }
2913
2914     case Dali::Actor::WORLD_SCALE:
2915     {
2916       value = GetCurrentWorldScale();
2917       break;
2918     }
2919
2920     case Dali::Actor::VISIBLE:
2921     {
2922       value = IsVisible();
2923       break;
2924     }
2925
2926     case Dali::Actor::COLOR:
2927     {
2928       value = GetCurrentColor();
2929       break;
2930     }
2931
2932     case Dali::Actor::COLOR_RED:
2933     {
2934       value = GetCurrentColor().r;
2935       break;
2936     }
2937
2938     case Dali::Actor::COLOR_GREEN:
2939     {
2940       value = GetCurrentColor().g;
2941       break;
2942     }
2943
2944     case Dali::Actor::COLOR_BLUE:
2945     {
2946       value = GetCurrentColor().b;
2947       break;
2948     }
2949
2950     case Dali::Actor::COLOR_ALPHA:
2951     {
2952       value = GetCurrentColor().a;
2953       break;
2954     }
2955
2956     case Dali::Actor::WORLD_COLOR:
2957     {
2958       value = GetCurrentWorldColor();
2959       break;
2960     }
2961
2962     case Dali::Actor::WORLD_MATRIX:
2963     {
2964       value = GetCurrentWorldMatrix();
2965       break;
2966     }
2967
2968     case Dali::Actor::NAME:
2969     {
2970       value = GetName();
2971       break;
2972     }
2973
2974     case Dali::Actor::SENSITIVE:
2975     {
2976       value = IsSensitive();
2977       break;
2978     }
2979
2980     case Dali::Actor::LEAVE_REQUIRED:
2981     {
2982       value = GetLeaveRequired();
2983       break;
2984     }
2985
2986     case Dali::Actor::INHERIT_ROTATION:
2987     {
2988       value = IsRotationInherited();
2989       break;
2990     }
2991
2992     case Dali::Actor::INHERIT_SCALE:
2993     {
2994       value = IsScaleInherited();
2995       break;
2996     }
2997
2998     case Dali::Actor::COLOR_MODE:
2999     {
3000       value = Scripting::GetColorMode( GetColorMode() );
3001       break;
3002     }
3003
3004     case Dali::Actor::POSITION_INHERITANCE:
3005     {
3006       value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3007       break;
3008     }
3009
3010     case Dali::Actor::DRAW_MODE:
3011     {
3012       value = Scripting::GetDrawMode( GetDrawMode() );
3013       break;
3014     }
3015
3016     default:
3017     {
3018       DALI_ASSERT_ALWAYS(false && "Actor Property index invalid" ); // should not come here
3019       break;
3020     }
3021   }
3022
3023   return value;
3024 }
3025
3026 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3027 {
3028   return mNode;
3029 }
3030
3031 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3032 {
3033   // This method should only return an object connected to the scene-graph
3034   return OnStage() ? mNode : NULL;
3035 }
3036
3037 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3038 {
3039   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
3040
3041   const PropertyBase* property( NULL );
3042
3043   // This method should only return a property of an object connected to the scene-graph
3044   if ( !OnStage() )
3045   {
3046     return property;
3047   }
3048
3049   if ( static_cast<unsigned int>(index) >= DEFAULT_PROPERTY_MAX_COUNT )
3050   {
3051     CustomProperty* custom = FindCustomProperty( index );
3052     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3053
3054     property = custom->GetSceneGraphProperty();
3055   }
3056   else if( NULL != mNode )
3057   {
3058     switch ( index )
3059     {
3060       case Dali::Actor::SIZE:
3061         property = &mNode->mSize;
3062         break;
3063
3064       case Dali::Actor::SIZE_WIDTH:
3065         property = &mNode->mSize;
3066         break;
3067
3068       case Dali::Actor::SIZE_HEIGHT:
3069         property = &mNode->mSize;
3070         break;
3071
3072       case Dali::Actor::SIZE_DEPTH:
3073         property = &mNode->mSize;
3074         break;
3075
3076       case Dali::Actor::POSITION:
3077         property = &mNode->mPosition;
3078         break;
3079
3080       case Dali::Actor::POSITION_X:
3081         property = &mNode->mPosition;
3082         break;
3083
3084       case Dali::Actor::POSITION_Y:
3085         property = &mNode->mPosition;
3086         break;
3087
3088       case Dali::Actor::POSITION_Z:
3089         property = &mNode->mPosition;
3090         break;
3091
3092       case Dali::Actor::ROTATION:
3093         property = &mNode->mRotation;
3094         break;
3095
3096       case Dali::Actor::SCALE:
3097         property = &mNode->mScale;
3098         break;
3099
3100       case Dali::Actor::SCALE_X:
3101         property = &mNode->mScale;
3102         break;
3103
3104       case Dali::Actor::SCALE_Y:
3105         property = &mNode->mScale;
3106         break;
3107
3108       case Dali::Actor::SCALE_Z:
3109         property = &mNode->mScale;
3110         break;
3111
3112       case Dali::Actor::VISIBLE:
3113         property = &mNode->mVisible;
3114         break;
3115
3116       case Dali::Actor::COLOR:
3117         property = &mNode->mColor;
3118         break;
3119
3120       case Dali::Actor::COLOR_RED:
3121         property = &mNode->mColor;
3122         break;
3123
3124       case Dali::Actor::COLOR_GREEN:
3125         property = &mNode->mColor;
3126         break;
3127
3128       case Dali::Actor::COLOR_BLUE:
3129         property = &mNode->mColor;
3130         break;
3131
3132       case Dali::Actor::COLOR_ALPHA:
3133         property = &mNode->mColor;
3134         break;
3135
3136       default:
3137         break;
3138     }
3139   }
3140
3141   return property;
3142 }
3143
3144 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3145 {
3146   const PropertyInputImpl* property( NULL );
3147
3148   // This method should only return a property of an object connected to the scene-graph
3149   if ( !OnStage() )
3150   {
3151     return property;
3152   }
3153
3154   if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3155   {
3156     CustomProperty* custom = FindCustomProperty( index );
3157     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3158     property = custom->GetSceneGraphProperty();
3159   }
3160   else if( NULL != mNode )
3161   {
3162     switch ( index )
3163     {
3164       case Dali::Actor::PARENT_ORIGIN:
3165         property = &mNode->mParentOrigin;
3166         break;
3167
3168       case Dali::Actor::PARENT_ORIGIN_X:
3169         property = &mNode->mParentOrigin;
3170         break;
3171
3172       case Dali::Actor::PARENT_ORIGIN_Y:
3173         property = &mNode->mParentOrigin;
3174         break;
3175
3176       case Dali::Actor::PARENT_ORIGIN_Z:
3177         property = &mNode->mParentOrigin;
3178         break;
3179
3180       case Dali::Actor::ANCHOR_POINT:
3181         property = &mNode->mAnchorPoint;
3182         break;
3183
3184       case Dali::Actor::ANCHOR_POINT_X:
3185         property = &mNode->mAnchorPoint;
3186         break;
3187
3188       case Dali::Actor::ANCHOR_POINT_Y:
3189         property = &mNode->mAnchorPoint;
3190         break;
3191
3192       case Dali::Actor::ANCHOR_POINT_Z:
3193         property = &mNode->mAnchorPoint;
3194         break;
3195
3196       case Dali::Actor::SIZE:
3197         property = &mNode->mSize;
3198         break;
3199
3200       case Dali::Actor::SIZE_WIDTH:
3201         property = &mNode->mSize;
3202         break;
3203
3204       case Dali::Actor::SIZE_HEIGHT:
3205         property = &mNode->mSize;
3206         break;
3207
3208       case Dali::Actor::SIZE_DEPTH:
3209         property = &mNode->mSize;
3210         break;
3211
3212       case Dali::Actor::POSITION:
3213         property = &mNode->mPosition;
3214         break;
3215
3216       case Dali::Actor::POSITION_X:
3217         property = &mNode->mPosition;
3218         break;
3219
3220       case Dali::Actor::POSITION_Y:
3221         property = &mNode->mPosition;
3222         break;
3223
3224       case Dali::Actor::POSITION_Z:
3225         property = &mNode->mPosition;
3226         break;
3227
3228       case Dali::Actor::WORLD_POSITION:
3229         property = &mNode->mWorldPosition;
3230         break;
3231
3232       case Dali::Actor::WORLD_POSITION_X:
3233         property = &mNode->mWorldPosition;
3234         break;
3235
3236       case Dali::Actor::WORLD_POSITION_Y:
3237         property = &mNode->mWorldPosition;
3238         break;
3239
3240       case Dali::Actor::WORLD_POSITION_Z:
3241         property = &mNode->mWorldPosition;
3242         break;
3243
3244       case Dali::Actor::ROTATION:
3245         property = &mNode->mRotation;
3246         break;
3247
3248       case Dali::Actor::WORLD_ROTATION:
3249         property = &mNode->mWorldRotation;
3250         break;
3251
3252       case Dali::Actor::SCALE:
3253         property = &mNode->mScale;
3254         break;
3255
3256       case Dali::Actor::SCALE_X:
3257         property = &mNode->mScale;
3258         break;
3259
3260       case Dali::Actor::SCALE_Y:
3261         property = &mNode->mScale;
3262         break;
3263
3264       case Dali::Actor::SCALE_Z:
3265         property = &mNode->mScale;
3266         break;
3267
3268       case Dali::Actor::WORLD_SCALE:
3269         property = &mNode->mWorldScale;
3270         break;
3271
3272       case Dali::Actor::VISIBLE:
3273         property = &mNode->mVisible;
3274         break;
3275
3276       case Dali::Actor::COLOR:
3277         property = &mNode->mColor;
3278         break;
3279
3280       case Dali::Actor::COLOR_RED:
3281         property = &mNode->mColor;
3282         break;
3283
3284       case Dali::Actor::COLOR_GREEN:
3285         property = &mNode->mColor;
3286         break;
3287
3288       case Dali::Actor::COLOR_BLUE:
3289         property = &mNode->mColor;
3290         break;
3291
3292       case Dali::Actor::COLOR_ALPHA:
3293         property = &mNode->mColor;
3294         break;
3295
3296       case Dali::Actor::WORLD_COLOR:
3297         property = &mNode->mWorldColor;
3298         break;
3299
3300       case Dali::Actor::WORLD_MATRIX:
3301         property = &mNode->mWorldMatrix;
3302         break;
3303
3304       default:
3305         break;
3306     }
3307   }
3308
3309   return property;
3310 }
3311
3312 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3313 {
3314   int componentIndex( Property::INVALID_COMPONENT_INDEX );
3315
3316   switch ( index )
3317   {
3318     case Dali::Actor::PARENT_ORIGIN_X:
3319     case Dali::Actor::ANCHOR_POINT_X:
3320     case Dali::Actor::SIZE_WIDTH:
3321     case Dali::Actor::POSITION_X:
3322     case Dali::Actor::SCALE_X:
3323     case Dali::Actor::COLOR_RED:
3324     case Dali::Actor::WORLD_POSITION_X:
3325     {
3326       componentIndex = 0;
3327       break;
3328     }
3329
3330     case Dali::Actor::PARENT_ORIGIN_Y:
3331     case Dali::Actor::ANCHOR_POINT_Y:
3332     case Dali::Actor::SIZE_HEIGHT:
3333     case Dali::Actor::POSITION_Y:
3334     case Dali::Actor::SCALE_Y:
3335     case Dali::Actor::COLOR_GREEN:
3336     case Dali::Actor::WORLD_POSITION_Y:
3337     {
3338       componentIndex = 1;
3339       break;
3340     }
3341
3342     case Dali::Actor::PARENT_ORIGIN_Z:
3343     case Dali::Actor::ANCHOR_POINT_Z:
3344     case Dali::Actor::SIZE_DEPTH:
3345     case Dali::Actor::POSITION_Z:
3346     case Dali::Actor::SCALE_Z:
3347     case Dali::Actor::COLOR_BLUE:
3348     case Dali::Actor::WORLD_POSITION_Z:
3349     {
3350       componentIndex = 2;
3351       break;
3352     }
3353
3354     case Dali::Actor::COLOR_ALPHA:
3355     {
3356       componentIndex = 3;
3357       break;
3358     }
3359
3360     default:
3361     {
3362       // Do nothing
3363       break;
3364     }
3365   }
3366
3367   return componentIndex;
3368 }
3369
3370 void Actor::SetParent(Actor* parent, int index)
3371 {
3372   if( parent )
3373   {
3374     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3375
3376     mParent = parent;
3377
3378     if ( Stage::IsInstalled() && // Don't emit signals or send messages during Core destruction
3379          parent->OnStage() )
3380     {
3381       StagePtr stage = parent->mStage;
3382
3383       // Instruct each actor to create a corresponding node in the scene graph
3384       ConnectToStage(*stage, index);
3385     }
3386   }
3387   else // parent being set to NULL
3388   {
3389     DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3390
3391     mParent = NULL;
3392
3393     if ( Stage::IsInstalled() && // Don't emit signals or send messages during Core destruction
3394          OnStage() )
3395     {
3396       DALI_ASSERT_ALWAYS(mNode != NULL);
3397
3398       if( NULL != mNode )
3399       {
3400         // Disconnect the Node & its children from the scene-graph.
3401         DisconnectNodeMessage( mStage->GetUpdateManager(), *mNode );
3402       }
3403
3404       // Instruct each actor to discard pointers to the scene-graph
3405       DisconnectFromStage();
3406     }
3407   }
3408 }
3409
3410 SceneGraph::Node* Actor::CreateNode() const
3411 {
3412   return Node::New();
3413 }
3414
3415 bool Actor::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
3416 {
3417   bool done = false;
3418   Actor* actor = dynamic_cast<Actor*>(object);
3419
3420   if( actor )
3421   {
3422     if(Dali::Actor::ACTION_SHOW == actionName)
3423     {
3424       actor->SetVisible(true);
3425       done = true;
3426     }
3427     else if(Dali::Actor::ACTION_HIDE == actionName)
3428     {
3429       actor->SetVisible(false);
3430       done = true;
3431     }
3432   }
3433
3434   return done;
3435 }
3436
3437 } // namespace Internal
3438
3439 } // namespace Dali