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