2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/actors/actor-impl.h>
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>
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>
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>
60 using Dali::Internal::SceneGraph::Node;
61 using Dali::Internal::SceneGraph::AnimatableProperty;
62 using Dali::Internal::SceneGraph::PropertyBase;
69 const Property::Index Actor::PARENT_ORIGIN = 0;
70 const Property::Index Actor::PARENT_ORIGIN_X = 1;
71 const Property::Index Actor::PARENT_ORIGIN_Y = 2;
72 const Property::Index Actor::PARENT_ORIGIN_Z = 3;
73 const Property::Index Actor::ANCHOR_POINT = 4;
74 const Property::Index Actor::ANCHOR_POINT_X = 5;
75 const Property::Index Actor::ANCHOR_POINT_Y = 6;
76 const Property::Index Actor::ANCHOR_POINT_Z = 7;
77 const Property::Index Actor::SIZE = 8;
78 const Property::Index Actor::SIZE_WIDTH = 9;
79 const Property::Index Actor::SIZE_HEIGHT = 10;
80 const Property::Index Actor::SIZE_DEPTH = 11;
81 const Property::Index Actor::POSITION = 12;
82 const Property::Index Actor::POSITION_X = 13;
83 const Property::Index Actor::POSITION_Y = 14;
84 const Property::Index Actor::POSITION_Z = 15;
85 const Property::Index Actor::WORLD_POSITION = 16;
86 const Property::Index Actor::WORLD_POSITION_X = 17;
87 const Property::Index Actor::WORLD_POSITION_Y = 18;
88 const Property::Index Actor::WORLD_POSITION_Z = 19;
89 const Property::Index Actor::ROTATION = 20;
90 const Property::Index Actor::WORLD_ROTATION = 21;
91 const Property::Index Actor::SCALE = 22;
92 const Property::Index Actor::SCALE_X = 23;
93 const Property::Index Actor::SCALE_Y = 24;
94 const Property::Index Actor::SCALE_Z = 25;
95 const Property::Index Actor::WORLD_SCALE = 26;
96 const Property::Index Actor::VISIBLE = 27;
97 const Property::Index Actor::COLOR = 28;
98 const Property::Index Actor::COLOR_RED = 29;
99 const Property::Index Actor::COLOR_GREEN = 30;
100 const Property::Index Actor::COLOR_BLUE = 31;
101 const Property::Index Actor::COLOR_ALPHA = 32;
102 const Property::Index Actor::WORLD_COLOR = 33;
103 const Property::Index Actor::WORLD_MATRIX = 34;
104 const Property::Index Actor::NAME = 35;
105 const Property::Index Actor::SENSITIVE = 36;
106 const Property::Index Actor::LEAVE_REQUIRED = 37;
107 const Property::Index Actor::INHERIT_ROTATION = 38;
108 const Property::Index Actor::INHERIT_SCALE = 39;
109 const Property::Index Actor::COLOR_MODE = 40;
110 const Property::Index Actor::POSITION_INHERITANCE = 41;
111 const Property::Index Actor::DRAW_MODE = 42;
113 namespace // unnamed namespace
117 * We want to discourage the use of property strings (minimize string comparisons),
118 * particularly for the default properties.
120 const Internal::PropertyDetails DEFAULT_PROPERTY_DETAILS[] =
122 // Name Type writable animatable constraint-input
123 { "parent-origin", Property::VECTOR3, true, false, true }, // PARENT_ORIGIN
124 { "parent-origin-x", Property::FLOAT, true, false, true }, // PARENT_ORIGIN_X
125 { "parent-origin-y", Property::FLOAT, true, false, true }, // PARENT_ORIGIN_Y
126 { "parent-origin-z", Property::FLOAT, true, false, true }, // PARENT_ORIGIN_Z
127 { "anchor-point", Property::VECTOR3, true, false, true }, // ANCHOR_POINT
128 { "anchor-point-x", Property::FLOAT, true, false, true }, // ANCHOR_POINT_X
129 { "anchor-point-y", Property::FLOAT, true, false, true }, // ANCHOR_POINT_Y
130 { "anchor-point-z", Property::FLOAT, true, false, true }, // ANCHOR_POINT_Z
131 { "size", Property::VECTOR3, true, true, true }, // SIZE
132 { "size-width", Property::FLOAT, true, true, true }, // SIZE_WIDTH
133 { "size-height", Property::FLOAT, true, true, true }, // SIZE_HEIGHT
134 { "size-depth", Property::FLOAT, true, true, true }, // SIZE_DEPTH
135 { "position", Property::VECTOR3, true, true, true }, // POSITION
136 { "position-x", Property::FLOAT, true, true, true }, // POSITION_X
137 { "position-y", Property::FLOAT, true, true, true }, // POSITION_Y
138 { "position-z", Property::FLOAT, true, true, true }, // POSITION_Z
139 { "world-position", Property::VECTOR3, false, false, true }, // WORLD_POSITION
140 { "world-position-x", Property::FLOAT, false, false, true }, // WORLD_POSITION_X
141 { "world-position-y", Property::FLOAT, false, false, true }, // WORLD_POSITION_Y
142 { "world-position-z", Property::FLOAT, false, false, true }, // WORLD_POSITION_Z
143 { "rotation", Property::ROTATION, true, true, true }, // ROTATION
144 { "world-rotation", Property::ROTATION, false, false, true }, // WORLD_ROTATION
145 { "scale", Property::VECTOR3, true, true, true }, // SCALE
146 { "scale-x", Property::FLOAT, true, true, true }, // SCALE_X
147 { "scale-y", Property::FLOAT, true, true, true }, // SCALE_Y
148 { "scale-z", Property::FLOAT, true, true, true }, // SCALE_Z
149 { "world-scale", Property::VECTOR3, false, false, true }, // WORLD_SCALE
150 { "visible", Property::BOOLEAN, true, true, true }, // VISIBLE
151 { "color", Property::VECTOR4, true, true, true }, // COLOR
152 { "color-red", Property::FLOAT, true, true, true }, // COLOR_RED
153 { "color-green", Property::FLOAT, true, true, true }, // COLOR_GREEN
154 { "color-blue", Property::FLOAT, true, true, true }, // COLOR_BLUE
155 { "color-alpha", Property::FLOAT, true, true, true }, // COLOR_ALPHA
156 { "world-color", Property::VECTOR4, false, false, true }, // WORLD_COLOR
157 { "world-matrix", Property::MATRIX, false, false, true }, // WORLD_MATRIX
158 { "name", Property::STRING, true, false, false }, // NAME
159 { "sensitive", Property::BOOLEAN, true, false, false }, // SENSITIVE
160 { "leave-required", Property::BOOLEAN, true, false, false }, // LEAVE_REQUIRED
161 { "inherit-rotation", Property::BOOLEAN, true, false, false }, // INHERIT_ROTATION
162 { "inherit-scale", Property::BOOLEAN, true, false, false }, // INHERIT_SCALE
163 { "color-mode", Property::STRING, true, false, false }, // COLOR_MODE
164 { "position-inheritance", Property::STRING, true, false, false }, // POSITION_INHERITANCE
165 { "draw-mode", Property::STRING, true, false, false }, // DRAW_MODE
167 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( Internal::PropertyDetails );
169 } // unnamed namespace
174 unsigned int Actor::mActorCounter = 0;
175 ActorContainer Actor::mNullChildren;
177 #ifdef DYNAMICS_SUPPORT
179 // Encapsulate actor related dynamics data
182 DynamicsData( Actor* slotOwner )
183 : slotDelegate( slotOwner )
187 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
188 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
190 DynamicsBodyPtr body;
191 JointContainer joints;
192 ReferencedJointContainer referencedJoints;
194 SlotDelegate< Actor > slotDelegate;
197 #endif // DYNAMICS_SUPPORT
202 using namespace Dali;
204 BaseHandle CreateActor()
206 return Dali::Actor::New();
209 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
211 SignalConnectorType signalConnector1(mType, Dali::Actor::SIGNAL_TOUCHED, &Actor::DoConnectSignal);
212 SignalConnectorType signalConnector2(mType, Dali::Actor::SIGNAL_HOVERED, &Actor::DoConnectSignal);
213 SignalConnectorType signalConnector3(mType, Dali::Actor::SIGNAL_SET_SIZE, &Actor::DoConnectSignal);
214 SignalConnectorType signalConnector4(mType, Dali::Actor::SIGNAL_ON_STAGE, &Actor::DoConnectSignal);
215 SignalConnectorType signalConnector5(mType, Dali::Actor::SIGNAL_OFF_STAGE, &Actor::DoConnectSignal);
217 TypeAction a1(mType, Dali::Actor::ACTION_SHOW, &Actor::DoAction);
218 TypeAction a2(mType, Dali::Actor::ACTION_HIDE, &Actor::DoAction);
222 Actor::DefaultPropertyLookup* Actor::mDefaultPropertyLookup = NULL;
224 ActorPtr Actor::New()
226 ActorPtr actor( new Actor( BASIC ) );
228 // Second-phase construction
234 const std::string& Actor::GetName() const
239 void Actor::SetName(const std::string& name)
245 // ATTENTION: string for debug purposes is not thread safe.
246 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
250 unsigned int Actor::GetId() const
255 void Actor::Attach( ActorAttachment& attachment )
257 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
261 attachment.Connect();
264 mAttachment = ActorAttachmentPtr(&attachment);
267 ActorAttachmentPtr Actor::GetAttachment()
272 bool Actor::OnStage() const
277 Dali::Layer Actor::GetLayer()
281 // Short-circuit for Layer derived actors
284 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
287 // Find the immediate Layer parent
288 for (Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent())
290 if( parent->IsLayer() )
292 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
299 void Actor::Add(Actor& child)
301 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
302 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
306 mChildren = new ActorContainer;
309 Actor* const oldParent( child.mParent );
311 // child might already be ours
312 if( this != oldParent )
314 // if we already have parent, unparent us first
317 oldParent->Remove( child ); // This causes OnChildRemove callback
320 // Guard against Add() during previous OnChildRemove callback
321 if ( !child.mParent )
323 // Do this first, since user callbacks from within SetParent() may need to remove child
324 mChildren->push_back(Dali::Actor(&child));
326 // SetParent asserts that child can be added
327 child.SetParent(this);
329 // Notification for derived classes
335 void Actor::Insert(unsigned int index, Actor& child)
337 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
338 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
342 mChildren = new ActorContainer;
345 Actor* const oldParent( child.mParent );
347 // since an explicit position has been given, always insert, even if already a child
350 oldParent->Remove( child ); // This causes OnChildRemove callback
353 // Guard against Add() during previous OnChildRemove callback
354 if ( !child.mParent )
356 // Do this first, since user callbacks from within SetParent() may need to remove child
357 if (index < GetChildCount())
359 ActorIter it = mChildren->begin();
360 std::advance(it, index);
361 mChildren->insert(it, Dali::Actor(&child));
365 mChildren->push_back(Dali::Actor(&child));
367 // SetParent asserts that child can be added
368 child.SetParent(this, index);
370 // Notification for derived classes
375 void Actor::Remove(Actor& child)
377 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
387 // Find the child in mChildren, and unparent it
388 ActorIter end = mChildren->end();
389 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
391 Actor& actor = GetImplementation(*iter);
393 if( &actor == &child )
395 // Keep handle for OnChildRemove notification
396 removed = Dali::Actor( &actor );
398 // Do this first, since user callbacks from within SetParent() may need to add the child
399 mChildren->erase(iter);
401 DALI_ASSERT_DEBUG( actor.GetParent() == this );
402 actor.SetParent( NULL );
410 // Notification for derived classes
411 OnChildRemove( GetImplementation(removed) );
415 void Actor::Unparent()
419 mParent->Remove( *this );
423 unsigned int Actor::GetChildCount() const
425 return ( NULL != mChildren ) ? mChildren->size() : 0;
428 Dali::Actor Actor::GetChildAt(unsigned int index) const
430 DALI_ASSERT_ALWAYS( index < GetChildCount() );
432 return ( ( mChildren ) ? (*mChildren)[index] : Dali::Actor() );
435 ActorContainer Actor::GetChildren()
437 if( NULL != mChildren )
442 // return copy of mNullChildren
443 return mNullChildren;
446 const ActorContainer& Actor::GetChildren() const
448 if( NULL != mChildren )
453 // return const reference to mNullChildren
454 return mNullChildren;
457 ActorPtr Actor::FindChildByName(const std::string& actorName)
460 if (actorName == mName)
466 ActorIter end = mChildren->end();
467 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
469 child = GetImplementation(*iter).FindChildByName(actorName);
480 Dali::Actor Actor::FindChildByAlias(const std::string& actorAlias)
482 Dali::Actor child = DoGetChildByAlias(actorAlias);
484 // If not found then search by name.
487 Internal::ActorPtr child_ptr = FindChildByName(actorAlias);
490 child = Dali::Actor(child_ptr.Get());
497 Dali::Actor Actor::DoGetChildByAlias(const std::string& actorAlias)
499 Dali::Actor child = GetChildByAlias(actorAlias);
501 if (!child && mChildren )
503 ActorIter end = mChildren->end();
504 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
506 child = GetImplementation(*iter).DoGetChildByAlias(actorAlias);
518 ActorPtr Actor::FindChildById(const unsigned int id)
527 ActorIter end = mChildren->end();
528 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
530 child = GetImplementation(*iter).FindChildById(id);
541 void Actor::SetParentOrigin( const Vector3& origin )
545 // mNode is being used in a separate thread; queue a message to set the value & base value
546 SetParentOriginMessage( mStage->GetUpdateInterface(), *mNode, origin );
549 // Cache for event-thread access
552 // not allocated, check if different from default
553 if( ParentOrigin::DEFAULT != origin )
555 mParentOrigin = new Vector3( origin );
560 // check if different from current costs more than just set
561 *mParentOrigin = origin;
565 void Actor::SetParentOriginX( float x )
567 const Vector3& current = GetCurrentParentOrigin();
569 SetParentOrigin( Vector3( x, current.y, current.z ) );
572 void Actor::SetParentOriginY( float y )
574 const Vector3& current = GetCurrentParentOrigin();
576 SetParentOrigin( Vector3( current.x, y, current.z ) );
579 void Actor::SetParentOriginZ( float z )
581 const Vector3& current = GetCurrentParentOrigin();
583 SetParentOrigin( Vector3( current.x, current.y, z ) );
586 const Vector3& Actor::GetCurrentParentOrigin() const
588 // Cached for event-thread access
589 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
592 void Actor::SetAnchorPoint(const Vector3& anchor)
596 // mNode is being used in a separate thread; queue a message to set the value & base value
597 SetAnchorPointMessage( mStage->GetUpdateInterface(), *mNode, anchor );
600 // Cache for event-thread access
603 // not allocated, check if different from default
604 if( AnchorPoint::DEFAULT != anchor )
606 mAnchorPoint = new Vector3( anchor );
611 // check if different from current costs more than just set
612 *mAnchorPoint = anchor;
616 void Actor::SetAnchorPointX( float x )
618 const Vector3& current = GetCurrentAnchorPoint();
620 SetAnchorPoint( Vector3( x, current.y, current.z ) );
623 void Actor::SetAnchorPointY( float y )
625 const Vector3& current = GetCurrentAnchorPoint();
627 SetAnchorPoint( Vector3( current.x, y, current.z ) );
630 void Actor::SetAnchorPointZ( float z )
632 const Vector3& current = GetCurrentAnchorPoint();
634 SetAnchorPoint( Vector3( current.x, current.y, z ) );
637 const Vector3& Actor::GetCurrentAnchorPoint() const
639 // Cached for event-thread access
640 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
643 void Actor::SetPosition(float x, float y)
645 SetPosition(Vector3(x, y, 0.0f));
648 void Actor::SetPosition(float x, float y, float z)
650 SetPosition(Vector3(x, y, z));
653 void Actor::SetPosition(const Vector3& position)
657 // mNode is being used in a separate thread; queue a message to set the value & base value
658 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
662 void Actor::SetX(float x)
666 // mNode is being used in a separate thread; queue a message to set the value & base value
667 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
671 void Actor::SetY(float y)
675 // mNode is being used in a separate thread; queue a message to set the value & base value
676 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
680 void Actor::SetZ(float z)
684 // mNode is being used in a separate thread; queue a message to set the value & base value
685 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
689 void Actor::MoveBy(const Vector3& distance)
693 // mNode is being used in a separate thread; queue a message to set the value & base value
694 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
698 const Vector3& Actor::GetCurrentPosition() const
702 // mNode is being used in a separate thread; copy the value from the previous update
703 return mNode->GetPosition(mStage->GetEventBufferIndex());
706 return Vector3::ZERO;
709 const Vector3& Actor::GetCurrentWorldPosition() const
713 // mNode is being used in a separate thread; copy the value from the previous update
714 return mNode->GetWorldPosition( mStage->GetEventBufferIndex() );
717 return Vector3::ZERO;
720 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
722 // this flag is not animatable so keep the value
723 mPositionInheritanceMode = mode;
726 // mNode is being used in a separate thread; queue a message to set the value
727 SetPositionInheritanceModeMessage( mStage->GetUpdateInterface(), *mNode, mode );
731 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
733 // Cached for event-thread access
734 return mPositionInheritanceMode;
737 void Actor::SetRotation(const Radian& angle, const Vector3& axis)
739 Vector4 normalizedAxis(axis.x, axis.y, axis.z, 0.0f);
740 normalizedAxis.Normalize();
742 Quaternion rotation(Quaternion::FromAxisAngle(normalizedAxis, angle));
744 SetRotation(rotation);
747 void Actor::SetRotation(const Quaternion& rotation)
751 // mNode is being used in a separate thread; queue a message to set the value & base value
752 SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, &mNode->mRotation, &AnimatableProperty<Quaternion>::Bake, rotation );
756 void Actor::RotateBy(const Radian& angle, const Vector3& axis)
760 // mNode is being used in a separate thread; queue a message to set the value & base value
761 SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, &mNode->mRotation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
765 void Actor::RotateBy(const Quaternion& relativeRotation)
769 // mNode is being used in a separate thread; queue a message to set the value & base value
770 SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, &mNode->mRotation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
774 const Quaternion& Actor::GetCurrentRotation() const
778 // mNode is being used in a separate thread; copy the value from the previous update
779 return mNode->GetRotation(mStage->GetEventBufferIndex());
782 return Quaternion::IDENTITY;
785 const Quaternion& Actor::GetCurrentWorldRotation() const
789 // mNode is being used in a separate thread; copy the value from the previous update
790 return mNode->GetWorldRotation( mStage->GetEventBufferIndex() );
793 return Quaternion::IDENTITY;
796 void Actor::SetScale(float scale)
798 SetScale(Vector3(scale, scale, scale));
801 void Actor::SetScale(float x, float y, float z)
803 SetScale(Vector3(x, y, z));
806 void Actor::SetScale(const Vector3& scale)
810 // mNode is being used in a separate thread; queue a message to set the value & base value
811 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
815 void Actor::SetScaleX( float x )
819 // mNode is being used in a separate thread; queue a message to set the value & base value
820 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
824 void Actor::SetScaleY( float y )
828 // mNode is being used in a separate thread; queue a message to set the value & base value
829 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
833 void Actor::SetScaleZ( float z )
837 // mNode is being used in a separate thread; queue a message to set the value & base value
838 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
842 void Actor::SetInitialVolume(const Vector3& volume)
846 // mNode is being used in a separate thread; queue a message to set the value
847 SetInitialVolumeMessage( mStage->GetUpdateInterface(), *mNode, volume );
851 void Actor::SetTransmitGeometryScaling(bool transmitGeometryScaling)
855 // mNode is being used in a separate thread; queue a message to set the value
856 SetTransmitGeometryScalingMessage( mStage->GetUpdateInterface(), *mNode, transmitGeometryScaling );
860 bool Actor::GetTransmitGeometryScaling() const
864 // mNode is being used in a separate thread; copy the value from the previous update
865 return mNode->GetTransmitGeometryScaling();
871 void Actor::ScaleBy(const Vector3& relativeScale)
875 // mNode is being used in a separate thread; queue a message to set the value & base value
876 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
880 const Vector3& Actor::GetCurrentScale() const
884 // mNode is being used in a separate thread; copy the value from the previous update
885 return mNode->GetScale(mStage->GetEventBufferIndex());
891 const Vector3& Actor::GetCurrentWorldScale() const
895 // mNode is being used in a separate thread; copy the value from the previous update
896 return mNode->GetWorldScale( mStage->GetEventBufferIndex() );
902 void Actor::SetInheritScale( bool inherit )
904 // non animateable so keep local copy
905 mInheritScale = inherit;
908 // mNode is being used in a separate thread; queue a message to set the value
909 SetInheritScaleMessage( mStage->GetUpdateInterface(), *mNode, inherit );
913 bool Actor::IsScaleInherited() const
915 return mInheritScale;
918 Matrix Actor::GetCurrentWorldMatrix() const
922 // World matrix is no longer updated unless there is something observing the node.
923 // Need to calculate it from node's world position, rotation and scale:
924 BufferIndex updateBufferIndex = mStage->GetEventBufferIndex();
925 Matrix worldMatrix(false);
926 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
927 mNode->GetWorldRotation( updateBufferIndex ),
928 mNode->GetWorldPosition( updateBufferIndex ) );
932 return Matrix::IDENTITY;
935 void Actor::SetVisible(bool visible)
939 // mNode is being used in a separate thread; queue a message to set the value & base value
940 SceneGraph::NodePropertyMessage<bool>::Send( mStage->GetUpdateManager(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
944 bool Actor::IsVisible() const
948 // mNode is being used in a separate thread; copy the value from the previous update
949 return mNode->IsVisible( mStage->GetEventBufferIndex() );
955 void Actor::SetOpacity(float opacity)
959 // mNode is being used in a separate thread; queue a message to set the value & base value
960 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
964 void Actor::OpacityBy(float relativeOpacity)
968 // mNode is being used in a separate thread; queue a message to set the value & base value
969 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeWRelative, relativeOpacity );
973 float Actor::GetCurrentOpacity() const
977 // mNode is being used in a separate thread; copy the value from the previous update
978 return mNode->GetOpacity(mStage->GetEventBufferIndex());
984 const Vector4& Actor::GetCurrentWorldColor() const
988 return mNode->GetWorldColor( mStage->GetEventBufferIndex() );
994 void Actor::SetColor(const Vector4& color)
998 // mNode is being used in a separate thread; queue a message to set the value & base value
999 SceneGraph::NodePropertyMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1003 void Actor::SetColorRed( float red )
1007 // mNode is being used in a separate thread; queue a message to set the value & base value
1008 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1012 void Actor::SetColorGreen( float green )
1016 // mNode is being used in a separate thread; queue a message to set the value & base value
1017 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1021 void Actor::SetColorBlue( float blue )
1025 // mNode is being used in a separate thread; queue a message to set the value & base value
1026 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1030 void Actor::ColorBy(const Vector4& relativeColor)
1034 // mNode is being used in a separate thread; queue a message to set the value & base value
1035 SceneGraph::NodePropertyMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeRelative, relativeColor );
1039 const Vector4& Actor::GetCurrentColor() const
1043 // mNode is being used in a separate thread; copy the value from the previous update
1044 return mNode->GetColor(mStage->GetEventBufferIndex());
1047 return Color::WHITE;
1050 void Actor::SetInheritRotation(bool inherit)
1052 // non animateable so keep local copy
1053 mInheritRotation = inherit;
1056 // mNode is being used in a separate thread; queue a message to set the value
1057 SetInheritRotationMessage( mStage->GetUpdateInterface(), *mNode, inherit );
1061 bool Actor::IsRotationInherited() const
1063 return mInheritRotation;
1066 void Actor::SetColorMode(ColorMode colorMode)
1068 // non animateable so keep local copy
1069 mColorMode = colorMode;
1072 // mNode is being used in a separate thread; queue a message to set the value
1073 SetColorModeMessage( mStage->GetUpdateInterface(), *mNode, colorMode );
1077 ColorMode Actor::GetColorMode() const
1079 // we have cached copy
1083 void Actor::SetSize(float width, float height)
1085 SetSize( Vector2( width, height ) );
1088 void Actor::SetSize(float width, float height, float depth)
1090 SetSize( Vector3( width, height, depth ) );
1093 void Actor::SetSize(const Vector2& size)
1095 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1098 float Actor::CalculateSizeZ( const Vector2& size ) const
1100 return std::min( size.width, size.height );
1103 void Actor::SetSize(const Vector3& size)
1109 // mNode is being used in a separate thread; queue a message to set the value & base value
1110 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mSize );
1112 // Notification for derived classes
1115 // Emit signal for application developer
1117 if( !mSetSizeSignalV2.Empty() )
1119 Dali::Actor handle( this );
1120 mSetSizeSignalV2.Emit( handle, mSize );
1125 void Actor::NotifySizeAnimation(Animation& animation, const Vector3& targetSize)
1129 // Notify deriving classes
1130 OnSizeAnimation( animation, targetSize );
1133 void Actor::SetWidth( float width )
1137 // mNode is being used in a separate thread; queue a message to set the value & base value
1138 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1142 void Actor::SetHeight( float height )
1146 // mNode is being used in a separate thread; queue a message to set the value & base value
1147 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1151 void Actor::SetDepth( float depth )
1155 // mNode is being used in a separate thread; queue a message to set the value & base value
1156 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1160 const Vector3& Actor::GetSize() const
1165 const Vector3& Actor::GetCurrentSize() const
1169 // mNode is being used in a separate thread; copy the value from the previous update
1170 return mNode->GetSize( mStage->GetEventBufferIndex() );
1173 return Vector3::ZERO;
1176 Vector3 Actor::GetNaturalSize() const
1178 // It is up to deriving classes to return the appropriate natural size
1179 return Vector3( 0.0f, 0.0f, 0.0f );
1183 #ifdef DYNAMICS_SUPPORT
1185 //--------------- Dynamics ---------------
1187 void Actor::DisableDynamics()
1189 if( NULL != mDynamicsData )
1191 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1193 // ensure dynamics object are disconnected from scene
1194 DisconnectDynamics();
1196 // delete joint owned by this actor
1197 while( !mDynamicsData->joints.empty() )
1199 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1202 // delete other joints referencing this actor
1203 while( !mDynamicsData->referencedJoints.empty() )
1205 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1206 ActorPtr jointOwner( joint->GetActor( true ) );
1209 jointOwner->RemoveDynamicsJoint( joint );
1213 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1216 // delete the DynamicsBody object
1217 mDynamicsData->body.Reset();
1219 // Discard Dynamics data structure
1220 delete mDynamicsData;
1221 mDynamicsData = NULL;
1225 DynamicsBodyPtr Actor::GetDynamicsBody() const
1227 DynamicsBodyPtr body;
1229 if( NULL != mDynamicsData )
1231 body = mDynamicsData->body;
1237 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1239 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1241 if( NULL == mDynamicsData )
1243 mDynamicsData = new DynamicsData( this );
1246 if( !mDynamicsData->body )
1248 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1252 DynamicsWorldPtr world( mStage->GetDynamicsWorld() );
1255 if( mParent == world->GetRootActor().Get() )
1257 mDynamicsData->body->Connect(*mStage);
1263 return mDynamicsData->body;
1266 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1268 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1269 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1272 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1274 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1275 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1277 DynamicsJointPtr joint;
1279 DynamicsWorldPtr world( mStage->GetDynamicsWorld() );
1283 if( NULL != mDynamicsData )
1285 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1287 if( mDynamicsData->joints.end() != it )
1289 // use existing joint
1295 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1296 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1300 bodyA = EnableDynamics( new DynamicsBodyConfig );
1305 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1308 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1309 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1311 if( OnStage() && attachedActor->OnStage() )
1313 joint->Connect(*mStage);
1316 attachedActor->ReferenceJoint( joint );
1318 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1319 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1326 const int Actor::GetNumberOfJoints() const
1328 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1331 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1333 DynamicsJointPtr joint;
1335 if( NULL != mDynamicsData )
1337 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1339 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1341 for( int i = 0; i < index; ++i )
1353 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1355 DynamicsJointPtr joint;
1357 if( NULL != mDynamicsData )
1359 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1361 if( mDynamicsData->joints.end() != it )
1363 // use existing joint
1371 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1373 if( NULL != mDynamicsData )
1375 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1376 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1378 for( ; it != endIt; ++it )
1380 if( it->second == joint.Get() )
1382 ActorPtr attachedActor( it->first );
1384 if( OnStage() && attachedActor && attachedActor->OnStage() )
1386 joint->Disconnect(*mStage);
1391 attachedActor->ReleaseJoint( joint );
1392 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1393 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1396 mDynamicsData->joints.erase(it);
1403 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1405 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1407 if( NULL != mDynamicsData )
1409 mDynamicsData->referencedJoints.push_back(joint);
1413 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1415 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1417 if( NULL != mDynamicsData )
1419 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1421 if( it != mDynamicsData->referencedJoints.end() )
1423 mDynamicsData->referencedJoints.erase( it );
1428 void Actor::SetDynamicsRoot(bool flag)
1430 if( mIsDynamicsRoot != flag )
1432 mIsDynamicsRoot = flag;
1434 if( OnStage() && mChildren )
1436 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1437 ActorIter end = mChildren->end();
1438 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1440 Actor& child = GetImplementation(*iter);
1442 if( child.GetDynamicsBody() )
1444 if( mIsDynamicsRoot )
1446 child.ConnectDynamics();
1450 child.DisconnectDynamics();
1458 bool Actor::IsDynamicsRoot() const
1460 return mIsDynamicsRoot;
1463 void Actor::AttachedActorOnStage( Dali::Actor actor )
1465 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1469 ActorPtr attachedActor( &GetImplementation(actor) );
1471 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1472 if( NULL != mDynamicsData )
1474 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1475 if( mDynamicsData->joints.end() != it )
1477 DynamicsJointPtr joint( it->second );
1478 joint->Connect(*mStage);
1484 void Actor::AttachedActorOffStage( Dali::Actor actor )
1486 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1490 ActorPtr attachedActor( &GetImplementation(actor) );
1492 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1493 if( NULL != mDynamicsData )
1495 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1496 if( mDynamicsData->joints.end() != it )
1498 DynamicsJointPtr joint( it->second );
1499 joint->Disconnect(*mStage);
1505 void Actor::ConnectDynamics()
1507 if( NULL != mDynamicsData && mDynamicsData->body )
1509 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1511 mDynamicsData->body->Connect(*mStage);
1513 // Connect all joints where attachedActor is also on stage
1514 if( !mDynamicsData->joints.empty() )
1516 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1517 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1519 for( ; it != endIt; ++it )
1521 Actor* attachedActor( it->first );
1522 if( NULL != attachedActor && attachedActor->OnStage() )
1524 DynamicsJointPtr joint( it->second );
1526 joint->Connect(*mStage);
1534 void Actor::DisconnectDynamics()
1536 if( NULL != mDynamicsData && mDynamicsData->body )
1540 mDynamicsData->body->Disconnect(*mStage);
1542 // Disconnect all joints
1543 if( !mDynamicsData->joints.empty() )
1545 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1546 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1548 for( ; it != endIt; ++it )
1550 DynamicsJointPtr joint( it->second );
1552 joint->Disconnect(*mStage);
1559 #endif // DYNAMICS_SUPPORT
1561 void Actor::SetOverlay(bool enable)
1563 // Setting STENCIL will override OVERLAY
1564 if( DrawMode::STENCIL != mDrawMode )
1566 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1570 bool Actor::IsOverlay() const
1572 return ( DrawMode::OVERLAY == mDrawMode );
1575 void Actor::SetDrawMode( DrawMode::Type drawMode )
1577 // this flag is not animatable so keep the value
1578 mDrawMode = drawMode;
1581 // mNode is being used in a separate thread; queue a message to set the value
1582 SetDrawModeMessage( mStage->GetUpdateInterface(), *mNode, drawMode );
1586 DrawMode::Type Actor::GetDrawMode() const
1591 bool Actor::ScreenToLocal( float& localX,
1594 float screenY ) const
1596 // only valid when on-stage
1599 const RenderTaskList& taskList = mStage->GetRenderTaskList();
1601 Vector2 converted( screenX, screenY );
1603 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1604 const int taskCount = taskList.GetTaskCount();
1605 for( int i = taskCount - 1; i >= 0; --i )
1607 Dali::RenderTask task = taskList.GetTask( i );
1608 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1610 // found a task where this conversion was ok so return
1618 bool Actor::ScreenToLocal( RenderTask& renderTask,
1622 float screenY ) const
1624 bool retval = false;
1625 // only valid when on-stage
1628 CameraActor* camera = renderTask.GetCameraActor();
1632 renderTask.GetViewport( viewport );
1634 // need to translate coordinates to render tasks coordinate space
1635 Vector2 converted( screenX, screenY );
1636 if( renderTask.TranslateCoordinates( converted ) )
1638 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1645 bool Actor::ScreenToLocal( const Matrix& viewMatrix,
1646 const Matrix& projectionMatrix,
1647 const Viewport& viewport,
1651 float screenY ) const
1653 // Early-out if mNode is NULL
1659 BufferIndex bufferIndex( mStage->GetEventBufferIndex() );
1661 // Calculate the ModelView matrix
1662 Matrix modelView(false/*don't init*/);
1663 // need to use the components as world matrix is only updated for actors that need it
1664 modelView.SetTransformComponents( mNode->GetWorldScale(bufferIndex), mNode->GetWorldRotation(bufferIndex), mNode->GetWorldPosition(bufferIndex) );
1665 Matrix::Multiply(modelView, modelView, viewMatrix);
1667 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1668 Matrix invertedMvp(false/*don't init*/);
1669 Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
1670 bool success = invertedMvp.Invert();
1672 // Convert to GL coordinates
1673 Vector4 screenPos( screenX - viewport.x, viewport.height - (screenY - viewport.y), 0.f, 1.f );
1678 success = Unproject(screenPos, invertedMvp, viewport.width, viewport.height, nearPos);
1685 success = Unproject(screenPos, invertedMvp, viewport.width, viewport.height, farPos);
1691 if (XyPlaneIntersect(nearPos, farPos, local))
1693 Vector3 size = GetCurrentSize();
1694 localX = local.x + size.x * 0.5f;
1695 localY = local.y + size.y * 0.5f;
1706 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1709 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1711 Mathematical Formulation
1713 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1715 ( p - c ) dot ( p - c ) = r^2
1717 Given a ray with a point of origin 'o', and a direction vector 'd':
1719 ray(t) = o + td, t >= 0
1721 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1723 (o + td - c ) dot ( o + td - c ) = r^2
1725 To solve for t we first expand the above into a more recognisable quadratic equation form
1727 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1736 B = 2( o - c ) dot d
1737 C = ( o - c ) dot ( o - c ) - r^2
1739 which can be solved using a standard quadratic formula.
1741 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1743 Practical Simplification
1745 In a renderer, we often differentiate between world space and object space. In the object space
1746 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1747 into object space, the mathematical solution presented above can be simplified significantly.
1749 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1753 and we can find the t at which the (transformed) ray intersects the sphere by
1755 ( o + td ) dot ( o + td ) = r^2
1757 According to the reasoning above, we expand the above quadratic equation into the general form
1761 which now has coefficients:
1768 // Early out if mNode is NULL
1774 BufferIndex bufferIndex( mStage->GetEventBufferIndex() );
1776 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1777 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1778 Vector3 rayOriginLocal(rayOrigin.x - translation.x,
1779 rayOrigin.y - translation.y,
1780 rayOrigin.z - translation.z);
1782 // Compute the radius is not needed, square radius it's enough.
1783 const Vector3& size( mNode->GetSize( bufferIndex ) );
1785 // Scale the sphere.
1786 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1788 const float width = size.width * scale.width;
1789 const float height = size.height * scale.height;
1791 float squareSphereRadius = 0.5f * ( width * width + height * height );
1793 float a = rayDir.Dot( rayDir ); // a
1794 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1795 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1797 return ( b2*b2 - a*c ) >= 0.f;
1800 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1807 BufferIndex bufferIndex( mStage->GetEventBufferIndex() );
1809 // Transforms the ray to the local reference system.
1811 // Calculate the inverse of Model matrix
1812 Matrix invModelMatrix(false/*don't init*/);
1813 // need to use the components as world matrix is only updated for actors that need it
1814 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale(bufferIndex), mNode->GetWorldRotation(bufferIndex), mNode->GetWorldPosition(bufferIndex) );
1816 Vector4 rayOriginLocal(invModelMatrix * rayOrigin);
1817 Vector4 rayDirLocal(invModelMatrix * rayDir - invModelMatrix.GetTranslation());
1819 // Test with the actor's XY plane (Normal = 0 0 1 1).
1821 float a = -rayOriginLocal.z;
1822 float b = rayDirLocal.z;
1824 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1826 // Ray travels distance * rayDirLocal to intersect with plane.
1829 const Vector3& size = mNode->GetSize( bufferIndex );
1831 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1832 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1834 // Test with the actor's geometry.
1835 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1842 void Actor::SetLeaveRequired(bool required)
1844 mLeaveRequired = required;
1847 bool Actor::GetLeaveRequired() const
1849 return mLeaveRequired;
1852 void Actor::SetKeyboardFocusable( bool focusable )
1854 mKeyboardFocusable = focusable;
1857 bool Actor::IsKeyboardFocusable() const
1859 return mKeyboardFocusable;
1862 bool Actor::GetTouchRequired() const
1864 return !mTouchedSignalV2.Empty() || mDerivedRequiresTouch;
1867 bool Actor::GetHoverRequired() const
1869 return !mHoveredSignalV2.Empty() || mDerivedRequiresHover;
1872 bool Actor::GetMouseWheelEventRequired() const
1874 return !mMouseWheelEventSignalV2.Empty() || mDerivedRequiresMouseWheelEvent;
1877 bool Actor::IsHittable() const
1879 return IsSensitive() &&
1881 ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) &&
1885 ActorGestureData& Actor::GetGestureData()
1887 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1888 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1889 if ( NULL == mGestureData )
1891 mGestureData = new ActorGestureData;
1893 return *mGestureData;
1896 bool Actor::IsGestureRequred( Gesture::Type type ) const
1898 return mGestureData && mGestureData->IsGestureRequred( type );
1901 bool Actor::EmitTouchEventSignal(const TouchEvent& event)
1903 bool consumed = false;
1905 if ( !mTouchedSignalV2.Empty() )
1907 Dali::Actor handle( this );
1908 consumed = mTouchedSignalV2.Emit( handle, event );
1913 // Notification for derived classes
1914 consumed = OnTouchEvent( event );
1920 bool Actor::EmitHoverEventSignal(const HoverEvent& event)
1922 bool consumed = false;
1924 if ( !mHoveredSignalV2.Empty() )
1926 Dali::Actor handle( this );
1927 consumed = mHoveredSignalV2.Emit( handle, event );
1932 // Notification for derived classes
1933 consumed = OnHoverEvent( event );
1939 bool Actor::EmitMouseWheelEventSignal(const MouseWheelEvent& event)
1941 bool consumed = false;
1943 if ( !mMouseWheelEventSignalV2.Empty() )
1945 Dali::Actor handle( this );
1946 consumed = mMouseWheelEventSignalV2.Emit( handle, event );
1951 // Notification for derived classes
1952 consumed = OnMouseWheelEvent(event);
1958 Dali::Actor::TouchSignalV2& Actor::TouchedSignal()
1960 return mTouchedSignalV2;
1963 Dali::Actor::HoverSignalV2& Actor::HoveredSignal()
1965 return mHoveredSignalV2;
1968 Dali::Actor::MouseWheelEventSignalV2& Actor::MouseWheelEventSignal()
1970 return mMouseWheelEventSignalV2;
1973 Dali::Actor::SetSizeSignalV2& Actor::SetSizeSignal()
1975 return mSetSizeSignalV2;
1978 Dali::Actor::OnStageSignalV2& Actor::OnStageSignal()
1980 return mOnStageSignalV2;
1983 Dali::Actor::OffStageSignalV2& Actor::OffStageSignal()
1985 return mOffStageSignalV2;
1988 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1990 bool connected( true );
1991 Actor* actor = dynamic_cast<Actor*>(object);
1993 if(Dali::Actor::SIGNAL_TOUCHED == signalName)
1995 actor->TouchedSignal().Connect( tracker, functor );
1997 else if(Dali::Actor::SIGNAL_HOVERED == signalName)
1999 actor->HoveredSignal().Connect( tracker, functor );
2001 else if(Dali::Actor::SIGNAL_MOUSE_WHEEL_EVENT == signalName)
2003 actor->MouseWheelEventSignal().Connect( tracker, functor );
2005 else if(Dali::Actor::SIGNAL_SET_SIZE == signalName)
2007 actor->SetSizeSignal().Connect( tracker, functor );
2009 else if(Dali::Actor::SIGNAL_ON_STAGE == signalName)
2011 actor->OnStageSignal().Connect( tracker, functor );
2013 else if(Dali::Actor::SIGNAL_OFF_STAGE == signalName)
2015 actor->OffStageSignal().Connect( tracker, functor );
2019 // signalName does not match any signal
2026 Actor::Actor( DerivedType derivedType )
2031 mParentOrigin( NULL ),
2032 mAnchorPoint( NULL ),
2033 #ifdef DYNAMICS_SUPPORT
2034 mDynamicsData( NULL ),
2036 mGestureData( NULL ),
2038 mSize( 0.0f, 0.0f, 0.0f ),
2040 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2041 mIsRoot( ROOT_LAYER == derivedType ),
2042 mIsRenderable( RENDERABLE == derivedType ),
2043 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2044 mIsOnStage( false ),
2045 mIsDynamicsRoot(false),
2047 mLeaveRequired( false ),
2048 mKeyboardFocusable( false ),
2049 mDerivedRequiresTouch( false ),
2050 mDerivedRequiresHover( false ),
2051 mDerivedRequiresMouseWheelEvent( false ),
2052 mOnStageSignalled( false ),
2053 mInheritRotation( true ),
2054 mInheritScale( true ),
2055 mDrawMode( DrawMode::NORMAL ),
2056 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2057 mColorMode( Node::DEFAULT_COLOR_MODE )
2061 void Actor::Initialize()
2063 mStage = Stage::GetCurrent();
2066 SceneGraph::Node* node = CreateNode();
2068 AddNodeMessage( mStage->GetUpdateManager(), *node ); // Pass ownership to scene-graph
2069 mNode = node; // Keep raw-pointer to Node
2071 if(!mDefaultPropertyLookup)
2073 mDefaultPropertyLookup = new DefaultPropertyLookup();
2075 for (int i=0; i<DEFAULT_PROPERTY_COUNT; ++i)
2077 (*mDefaultPropertyLookup)[DEFAULT_PROPERTY_DETAILS[i].name] = i;
2088 // Remove mParent pointers from children even if we're destroying core,
2089 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2092 ActorConstIter endIter = mChildren->end();
2093 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2095 Actor& actor = GetImplementation( *iter );
2096 actor.SetParent( NULL );
2101 // Guard to allow handle destruction after Core has been destroyed
2102 if( Stage::IsInstalled() )
2106 DestroyNodeMessage( mStage->GetUpdateManager(), *mNode );
2107 mNode = NULL; // Node is about to be destroyed
2113 #ifdef DYNAMICS_SUPPORT
2115 delete mDynamicsData;
2118 // Cleanup optional gesture data
2119 delete mGestureData;
2121 // Cleanup optional parent origin and anchor
2122 delete mParentOrigin;
2123 delete mAnchorPoint;
2126 void Actor::ConnectToStage( Stage& stage, int index )
2128 // This container is used instead of walking the Actor hierachy.
2129 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2130 ActorContainer connectionList;
2132 // This stage is atomic i.e. not interrupted by user callbacks
2133 RecursiveConnectToStage( stage, connectionList, index );
2135 // Notify applications about the newly connected actors.
2136 const ActorIter endIter = connectionList.end();
2137 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2139 Actor& actor = GetImplementation(*iter);
2140 actor.NotifyStageConnection();
2144 void Actor::RecursiveConnectToStage( Stage& stage, ActorContainer& connectionList, int index )
2146 DALI_ASSERT_ALWAYS( !OnStage() );
2150 ConnectToSceneGraph(index);
2152 // Notification for internal derived classes
2153 OnStageConnectionInternal();
2155 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2156 connectionList.push_back( Dali::Actor(this) );
2158 // Recursively connect children
2161 ActorConstIter endIter = mChildren->end();
2162 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2164 Actor& actor = GetImplementation( *iter );
2165 actor.RecursiveConnectToStage( stage, connectionList );
2171 * This method is called when the Actor is connected to the Stage.
2172 * The parent must have added its Node to the scene-graph.
2173 * The child must connect its Node to the parent's Node.
2174 * This is resursive; the child calls ConnectToStage() for its children.
2176 void Actor::ConnectToSceneGraph(int index)
2178 DALI_ASSERT_DEBUG( mNode != NULL);
2179 DALI_ASSERT_DEBUG( mParent != NULL);
2180 DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2184 // Reparent Node in next Update
2185 ConnectNodeMessage( mStage->GetUpdateManager(), *(mParent->mNode), *mNode, index );
2188 // Notify attachment
2191 mAttachment->Connect();
2194 #ifdef DYNAMICS_SUPPORT
2196 if( NULL != mDynamicsData )
2202 // Notification for ProxyObject::Observers
2206 void Actor::NotifyStageConnection()
2208 // Actors can be removed (in a callback), before the on-stage stage is reported.
2209 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2210 if ( OnStage() && !mOnStageSignalled )
2212 // Notification for external (CustomActor) derived classes
2213 OnStageConnectionExternal();
2215 if ( !mOnStageSignalV2.Empty() )
2217 Dali::Actor handle( this );
2218 mOnStageSignalV2.Emit( handle );
2221 // Guard against Remove during callbacks
2224 mOnStageSignalled = true; // signal required next time Actor is removed
2229 void Actor::DisconnectFromStage()
2231 // This container is used instead of walking the Actor hierachy.
2232 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2233 ActorContainer disconnectionList;
2235 // This stage is atomic i.e. not interrupted by user callbacks
2236 RecursiveDisconnectFromStage( disconnectionList );
2238 // Notify applications about the newly disconnected actors.
2239 const ActorIter endIter = disconnectionList.end();
2240 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2242 Actor& actor = GetImplementation(*iter);
2243 actor.NotifyStageDisconnection();
2247 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2249 DALI_ASSERT_ALWAYS( OnStage() );
2251 // Recursively disconnect children
2254 ActorConstIter endIter = mChildren->end();
2255 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2257 Actor& actor = GetImplementation( *iter );
2258 actor.RecursiveDisconnectFromStage( disconnectionList );
2262 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2263 disconnectionList.push_back( Dali::Actor(this) );
2265 // Notification for internal derived classes
2266 OnStageDisconnectionInternal();
2268 DisconnectFromSceneGraph();
2274 * This method is called by an actor or its parent, before a node removal message is sent.
2275 * This is recursive; the child calls DisconnectFromStage() for its children.
2277 void Actor::DisconnectFromSceneGraph()
2279 // Notification for ProxyObject::Observers
2280 OnSceneObjectRemove();
2282 // Notify attachment
2285 mAttachment->Disconnect();
2288 #ifdef DYNAMICS_SUPPORT
2290 if( NULL != mDynamicsData )
2292 DisconnectDynamics();
2297 void Actor::NotifyStageDisconnection()
2299 // Actors can be added (in a callback), before the off-stage state is reported.
2300 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2301 // only do this step if there is a stage, i.e. Core is not being shut down
2302 if ( Stage::IsInstalled() && !OnStage() && mOnStageSignalled )
2304 // Notification for external (CustomeActor) derived classes
2305 OnStageDisconnectionExternal();
2307 if( !mOffStageSignalV2.Empty() )
2309 Dali::Actor handle( this );
2310 mOffStageSignalV2.Emit( handle );
2313 // Guard against Add during callbacks
2316 mOnStageSignalled = false; // signal required next time Actor is added
2321 bool Actor::IsNodeConnected() const
2323 bool connected( false );
2328 if( mNode->IsRoot() || mNode->GetParent() )
2337 bool Actor::IsSceneObjectRemovable() const
2342 unsigned int Actor::GetDefaultPropertyCount() const
2344 return DEFAULT_PROPERTY_COUNT;
2347 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2349 indices.reserve( DEFAULT_PROPERTY_COUNT );
2351 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2353 indices.push_back( i );
2357 const std::string& Actor::GetDefaultPropertyName( Property::Index index ) const
2359 if( index < DEFAULT_PROPERTY_COUNT )
2361 return DEFAULT_PROPERTY_DETAILS[index].name;
2365 // index out of range..return empty string
2366 return String::EMPTY;
2370 Property::Index Actor::GetDefaultPropertyIndex(const std::string& name) const
2372 Property::Index index = Property::INVALID_INDEX;
2374 DALI_ASSERT_DEBUG( NULL != mDefaultPropertyLookup );
2376 // Look for name in default properties
2377 DefaultPropertyLookup::const_iterator result = mDefaultPropertyLookup->find( name );
2378 if ( mDefaultPropertyLookup->end() != result )
2380 index = result->second;
2386 bool Actor::IsDefaultPropertyWritable(Property::Index index) const
2388 if( index < DEFAULT_PROPERTY_COUNT )
2390 return DEFAULT_PROPERTY_DETAILS[index].writable;
2398 bool Actor::IsDefaultPropertyAnimatable(Property::Index index) const
2400 if( index < DEFAULT_PROPERTY_COUNT )
2402 return DEFAULT_PROPERTY_DETAILS[index].animatable;
2410 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2412 if( index < DEFAULT_PROPERTY_COUNT )
2414 return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
2422 Property::Type Actor::GetDefaultPropertyType(Property::Index index) const
2424 if( index < DEFAULT_PROPERTY_COUNT )
2426 return DEFAULT_PROPERTY_DETAILS[index].type;
2430 // index out of range...return Property::NONE
2431 return Property::NONE;
2435 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2439 case Dali::Actor::PARENT_ORIGIN:
2441 SetParentOrigin( property.Get<Vector3>() );
2445 case Dali::Actor::PARENT_ORIGIN_X:
2447 SetParentOriginX( property.Get<float>() );
2451 case Dali::Actor::PARENT_ORIGIN_Y:
2453 SetParentOriginY( property.Get<float>() );
2457 case Dali::Actor::PARENT_ORIGIN_Z:
2459 SetParentOriginZ( property.Get<float>() );
2463 case Dali::Actor::ANCHOR_POINT:
2465 SetAnchorPoint( property.Get<Vector3>() );
2469 case Dali::Actor::ANCHOR_POINT_X:
2471 SetAnchorPointX( property.Get<float>() );
2475 case Dali::Actor::ANCHOR_POINT_Y:
2477 SetAnchorPointY( property.Get<float>() );
2481 case Dali::Actor::ANCHOR_POINT_Z:
2483 SetAnchorPointZ( property.Get<float>() );
2487 case Dali::Actor::SIZE:
2489 SetSize( property.Get<Vector3>() );
2493 case Dali::Actor::SIZE_WIDTH:
2495 SetWidth( property.Get<float>() );
2499 case Dali::Actor::SIZE_HEIGHT:
2501 SetHeight( property.Get<float>() );
2505 case Dali::Actor::SIZE_DEPTH:
2507 SetDepth( property.Get<float>() );
2511 case Dali::Actor::POSITION:
2513 SetPosition( property.Get<Vector3>() );
2517 case Dali::Actor::POSITION_X:
2519 SetX( property.Get<float>() );
2523 case Dali::Actor::POSITION_Y:
2525 SetY( property.Get<float>() );
2529 case Dali::Actor::POSITION_Z:
2531 SetZ( property.Get<float>() );
2535 case Dali::Actor::ROTATION:
2537 SetRotation( property.Get<Quaternion>() );
2541 case Dali::Actor::SCALE:
2543 SetScale( property.Get<Vector3>() );
2547 case Dali::Actor::SCALE_X:
2549 SetScaleX( property.Get<float>() );
2553 case Dali::Actor::SCALE_Y:
2555 SetScaleY( property.Get<float>() );
2559 case Dali::Actor::SCALE_Z:
2561 SetScaleZ( property.Get<float>() );
2565 case Dali::Actor::VISIBLE:
2567 SetVisible( property.Get<bool>() );
2571 case Dali::Actor::COLOR:
2573 SetColor( property.Get<Vector4>() );
2577 case Dali::Actor::COLOR_RED:
2579 SetColorRed( property.Get<float>() );
2583 case Dali::Actor::COLOR_GREEN:
2585 SetColorGreen( property.Get<float>() );
2589 case Dali::Actor::COLOR_BLUE:
2591 SetColorBlue( property.Get<float>() );
2595 case Dali::Actor::COLOR_ALPHA:
2597 SetOpacity( property.Get<float>() );
2601 case Dali::Actor::NAME:
2603 SetName( property.Get<std::string>() );
2607 case Dali::Actor::SENSITIVE:
2609 SetSensitive( property.Get<bool>() );
2613 case Dali::Actor::LEAVE_REQUIRED:
2615 SetLeaveRequired( property.Get<bool>() );
2619 case Dali::Actor::INHERIT_ROTATION:
2621 SetInheritRotation( property.Get<bool>() );
2625 case Dali::Actor::INHERIT_SCALE:
2627 SetInheritScale( property.Get<bool>() );
2631 case Dali::Actor::COLOR_MODE:
2633 SetColorMode( Scripting::GetColorMode( property.Get<std::string>() ) );
2637 case Dali::Actor::POSITION_INHERITANCE:
2639 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get<std::string>() ) );
2643 case Dali::Actor::DRAW_MODE:
2645 SetDrawMode( Scripting::GetDrawMode( property.Get<std::string>() ) );
2651 DALI_ASSERT_ALWAYS(false && "Actor::Property is out of bounds"); // should not come here
2657 void Actor::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
2659 // TODO: This should be deprecated
2660 OnPropertySet(index, value);
2662 if(entry.IsAnimatable())
2664 switch ( entry.type )
2666 case Property::BOOLEAN:
2668 AnimatableProperty<bool>* property = dynamic_cast< AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
2669 DALI_ASSERT_DEBUG( NULL != property );
2671 // property is being used in a separate thread; queue a message to set the property
2672 SceneGraph::NodePropertyMessage<bool>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2677 case Property::FLOAT:
2679 AnimatableProperty<float>* property = dynamic_cast< AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
2680 DALI_ASSERT_DEBUG( NULL != property );
2682 // property is being used in a separate thread; queue a message to set the property
2683 SceneGraph::NodePropertyMessage<float>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2688 case Property::INTEGER:
2690 AnimatableProperty<int>* property = dynamic_cast< AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
2691 DALI_ASSERT_DEBUG( NULL != property );
2693 // property is being used in a separate thread; queue a message to set the property
2694 SceneGraph::NodePropertyMessage<int>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2699 case Property::VECTOR2:
2701 AnimatableProperty<Vector2>* property = dynamic_cast< AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
2702 DALI_ASSERT_DEBUG( NULL != property );
2704 // property is being used in a separate thread; queue a message to set the property
2705 SceneGraph::NodePropertyMessage<Vector2>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2710 case Property::VECTOR3:
2712 AnimatableProperty<Vector3>* property = dynamic_cast< AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
2713 DALI_ASSERT_DEBUG( NULL != property );
2715 // property is being used in a separate thread; queue a message to set the property
2716 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2721 case Property::VECTOR4:
2723 AnimatableProperty<Vector4>* property = dynamic_cast< AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
2724 DALI_ASSERT_DEBUG( NULL != property );
2726 // property is being used in a separate thread; queue a message to set the property
2727 SceneGraph::NodePropertyMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2732 case Property::ROTATION:
2734 AnimatableProperty<Quaternion>* property = dynamic_cast< AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
2735 DALI_ASSERT_DEBUG( NULL != property );
2737 // property is being used in a separate thread; queue a message to set the property
2738 SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2743 case Property::MATRIX:
2745 AnimatableProperty<Matrix>* property = dynamic_cast< AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
2746 DALI_ASSERT_DEBUG( NULL != property );
2748 // property is being used in a separate thread; queue a message to set the property
2749 SceneGraph::NodePropertyMessage<Matrix>::Send( mStage->GetUpdateManager(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2754 case Property::MATRIX3:
2756 AnimatableProperty<Matrix3>* property = dynamic_cast< AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
2757 DALI_ASSERT_DEBUG( NULL != property );
2759 // property is being used in a separate thread; queue a message to set the property
2760 SceneGraph::NodePropertyMessage<Matrix3>::Send( mStage->GetUpdateManager(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2767 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2774 Property::Value Actor::GetDefaultProperty(Property::Index index) const
2776 Property::Value value;
2780 case Dali::Actor::PARENT_ORIGIN:
2782 value = GetCurrentParentOrigin();
2786 case Dali::Actor::PARENT_ORIGIN_X:
2788 value = GetCurrentParentOrigin().x;
2792 case Dali::Actor::PARENT_ORIGIN_Y:
2794 value = GetCurrentParentOrigin().y;
2798 case Dali::Actor::PARENT_ORIGIN_Z:
2800 value = GetCurrentParentOrigin().z;
2804 case Dali::Actor::ANCHOR_POINT:
2806 value = GetCurrentAnchorPoint();
2810 case Dali::Actor::ANCHOR_POINT_X:
2812 value = GetCurrentAnchorPoint().x;
2816 case Dali::Actor::ANCHOR_POINT_Y:
2818 value = GetCurrentAnchorPoint().y;
2822 case Dali::Actor::ANCHOR_POINT_Z:
2824 value = GetCurrentAnchorPoint().z;
2828 case Dali::Actor::SIZE:
2830 value = GetCurrentSize();
2834 case Dali::Actor::SIZE_WIDTH:
2836 value = GetCurrentSize().width;
2840 case Dali::Actor::SIZE_HEIGHT:
2842 value = GetCurrentSize().height;
2846 case Dali::Actor::SIZE_DEPTH:
2848 value = GetCurrentSize().depth;
2852 case Dali::Actor::POSITION:
2854 value = GetCurrentPosition();
2858 case Dali::Actor::POSITION_X:
2860 value = GetCurrentPosition().x;
2864 case Dali::Actor::POSITION_Y:
2866 value = GetCurrentPosition().y;
2870 case Dali::Actor::POSITION_Z:
2872 value = GetCurrentPosition().z;
2876 case Dali::Actor::WORLD_POSITION:
2878 value = GetCurrentWorldPosition();
2882 case Dali::Actor::WORLD_POSITION_X:
2884 value = GetCurrentWorldPosition().x;
2888 case Dali::Actor::WORLD_POSITION_Y:
2890 value = GetCurrentWorldPosition().y;
2894 case Dali::Actor::WORLD_POSITION_Z:
2896 value = GetCurrentWorldPosition().z;
2900 case Dali::Actor::ROTATION:
2902 value = GetCurrentRotation();
2906 case Dali::Actor::WORLD_ROTATION:
2908 value = GetCurrentWorldRotation();
2912 case Dali::Actor::SCALE:
2914 value = GetCurrentScale();
2918 case Dali::Actor::SCALE_X:
2920 value = GetCurrentScale().x;
2924 case Dali::Actor::SCALE_Y:
2926 value = GetCurrentScale().y;
2930 case Dali::Actor::SCALE_Z:
2932 value = GetCurrentScale().z;
2936 case Dali::Actor::WORLD_SCALE:
2938 value = GetCurrentWorldScale();
2942 case Dali::Actor::VISIBLE:
2944 value = IsVisible();
2948 case Dali::Actor::COLOR:
2950 value = GetCurrentColor();
2954 case Dali::Actor::COLOR_RED:
2956 value = GetCurrentColor().r;
2960 case Dali::Actor::COLOR_GREEN:
2962 value = GetCurrentColor().g;
2966 case Dali::Actor::COLOR_BLUE:
2968 value = GetCurrentColor().b;
2972 case Dali::Actor::COLOR_ALPHA:
2974 value = GetCurrentColor().a;
2978 case Dali::Actor::WORLD_COLOR:
2980 value = GetCurrentWorldColor();
2984 case Dali::Actor::WORLD_MATRIX:
2986 value = GetCurrentWorldMatrix();
2990 case Dali::Actor::NAME:
2996 case Dali::Actor::SENSITIVE:
2998 value = IsSensitive();
3002 case Dali::Actor::LEAVE_REQUIRED:
3004 value = GetLeaveRequired();
3008 case Dali::Actor::INHERIT_ROTATION:
3010 value = IsRotationInherited();
3014 case Dali::Actor::INHERIT_SCALE:
3016 value = IsScaleInherited();
3020 case Dali::Actor::COLOR_MODE:
3022 value = Scripting::GetColorMode( GetColorMode() );
3026 case Dali::Actor::POSITION_INHERITANCE:
3028 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3032 case Dali::Actor::DRAW_MODE:
3034 value = Scripting::GetDrawMode( GetDrawMode() );
3040 DALI_ASSERT_ALWAYS(false && "Actor Property index invalid" ); // should not come here
3048 void Actor::InstallSceneObjectProperty( PropertyBase& newProperty, const std::string& name, unsigned int index )
3052 // mNode is being used in a separate thread; queue a message to add the property
3053 InstallCustomPropertyMessage( mStage->GetUpdateInterface(), *mNode, newProperty ); // Message takes ownership
3057 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3059 // This method should only return an object connected to the scene-graph
3060 return OnStage() ? mNode : NULL;
3063 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3065 DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
3067 const PropertyBase* property( NULL );
3069 // This method should only return a property of an object connected to the scene-graph
3075 if ( static_cast<unsigned int>(index) >= DEFAULT_PROPERTY_MAX_COUNT )
3077 CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
3079 DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "index is invalid" );
3081 property = dynamic_cast<const PropertyBase*>( entry->second.GetSceneGraphProperty() );
3083 else if( NULL != mNode )
3087 case Dali::Actor::SIZE:
3088 property = &mNode->mSize;
3091 case Dali::Actor::SIZE_WIDTH:
3092 property = &mNode->mSize;
3095 case Dali::Actor::SIZE_HEIGHT:
3096 property = &mNode->mSize;
3099 case Dali::Actor::SIZE_DEPTH:
3100 property = &mNode->mSize;
3103 case Dali::Actor::POSITION:
3104 property = &mNode->mPosition;
3107 case Dali::Actor::POSITION_X:
3108 property = &mNode->mPosition;
3111 case Dali::Actor::POSITION_Y:
3112 property = &mNode->mPosition;
3115 case Dali::Actor::POSITION_Z:
3116 property = &mNode->mPosition;
3119 case Dali::Actor::ROTATION:
3120 property = &mNode->mRotation;
3123 case Dali::Actor::SCALE:
3124 property = &mNode->mScale;
3127 case Dali::Actor::SCALE_X:
3128 property = &mNode->mScale;
3131 case Dali::Actor::SCALE_Y:
3132 property = &mNode->mScale;
3135 case Dali::Actor::SCALE_Z:
3136 property = &mNode->mScale;
3139 case Dali::Actor::VISIBLE:
3140 property = &mNode->mVisible;
3143 case Dali::Actor::COLOR:
3144 property = &mNode->mColor;
3147 case Dali::Actor::COLOR_RED:
3148 property = &mNode->mColor;
3151 case Dali::Actor::COLOR_GREEN:
3152 property = &mNode->mColor;
3155 case Dali::Actor::COLOR_BLUE:
3156 property = &mNode->mColor;
3159 case Dali::Actor::COLOR_ALPHA:
3160 property = &mNode->mColor;
3171 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3173 const PropertyInputImpl* property( NULL );
3175 // This method should only return a property of an object connected to the scene-graph
3181 if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3183 CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
3185 DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "property index is invalid" );
3187 property = entry->second.GetSceneGraphProperty();
3189 else if( NULL != mNode )
3193 case Dali::Actor::PARENT_ORIGIN:
3194 property = &mNode->mParentOrigin;
3197 case Dali::Actor::PARENT_ORIGIN_X:
3198 property = &mNode->mParentOrigin;
3201 case Dali::Actor::PARENT_ORIGIN_Y:
3202 property = &mNode->mParentOrigin;
3205 case Dali::Actor::PARENT_ORIGIN_Z:
3206 property = &mNode->mParentOrigin;
3209 case Dali::Actor::ANCHOR_POINT:
3210 property = &mNode->mAnchorPoint;
3213 case Dali::Actor::ANCHOR_POINT_X:
3214 property = &mNode->mAnchorPoint;
3217 case Dali::Actor::ANCHOR_POINT_Y:
3218 property = &mNode->mAnchorPoint;
3221 case Dali::Actor::ANCHOR_POINT_Z:
3222 property = &mNode->mAnchorPoint;
3225 case Dali::Actor::SIZE:
3226 property = &mNode->mSize;
3229 case Dali::Actor::SIZE_WIDTH:
3230 property = &mNode->mSize;
3233 case Dali::Actor::SIZE_HEIGHT:
3234 property = &mNode->mSize;
3237 case Dali::Actor::SIZE_DEPTH:
3238 property = &mNode->mSize;
3241 case Dali::Actor::POSITION:
3242 property = &mNode->mPosition;
3245 case Dali::Actor::POSITION_X:
3246 property = &mNode->mPosition;
3249 case Dali::Actor::POSITION_Y:
3250 property = &mNode->mPosition;
3253 case Dali::Actor::POSITION_Z:
3254 property = &mNode->mPosition;
3257 case Dali::Actor::WORLD_POSITION:
3258 property = &mNode->mWorldPosition;
3261 case Dali::Actor::WORLD_POSITION_X:
3262 property = &mNode->mWorldPosition;
3265 case Dali::Actor::WORLD_POSITION_Y:
3266 property = &mNode->mWorldPosition;
3269 case Dali::Actor::WORLD_POSITION_Z:
3270 property = &mNode->mWorldPosition;
3273 case Dali::Actor::ROTATION:
3274 property = &mNode->mRotation;
3277 case Dali::Actor::WORLD_ROTATION:
3278 property = &mNode->mWorldRotation;
3281 case Dali::Actor::SCALE:
3282 property = &mNode->mScale;
3285 case Dali::Actor::SCALE_X:
3286 property = &mNode->mScale;
3289 case Dali::Actor::SCALE_Y:
3290 property = &mNode->mScale;
3293 case Dali::Actor::SCALE_Z:
3294 property = &mNode->mScale;
3297 case Dali::Actor::WORLD_SCALE:
3298 property = &mNode->mWorldScale;
3301 case Dali::Actor::VISIBLE:
3302 property = &mNode->mVisible;
3305 case Dali::Actor::COLOR:
3306 property = &mNode->mColor;
3309 case Dali::Actor::COLOR_RED:
3310 property = &mNode->mColor;
3313 case Dali::Actor::COLOR_GREEN:
3314 property = &mNode->mColor;
3317 case Dali::Actor::COLOR_BLUE:
3318 property = &mNode->mColor;
3321 case Dali::Actor::COLOR_ALPHA:
3322 property = &mNode->mColor;
3325 case Dali::Actor::WORLD_COLOR:
3326 property = &mNode->mWorldColor;
3329 case Dali::Actor::WORLD_MATRIX:
3330 property = &mNode->mWorldMatrix;
3341 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3343 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3347 case Dali::Actor::PARENT_ORIGIN_X:
3348 case Dali::Actor::ANCHOR_POINT_X:
3349 case Dali::Actor::SIZE_WIDTH:
3350 case Dali::Actor::POSITION_X:
3351 case Dali::Actor::SCALE_X:
3352 case Dali::Actor::COLOR_RED:
3353 case Dali::Actor::WORLD_POSITION_X:
3359 case Dali::Actor::PARENT_ORIGIN_Y:
3360 case Dali::Actor::ANCHOR_POINT_Y:
3361 case Dali::Actor::SIZE_HEIGHT:
3362 case Dali::Actor::POSITION_Y:
3363 case Dali::Actor::SCALE_Y:
3364 case Dali::Actor::COLOR_GREEN:
3365 case Dali::Actor::WORLD_POSITION_Y:
3371 case Dali::Actor::PARENT_ORIGIN_Z:
3372 case Dali::Actor::ANCHOR_POINT_Z:
3373 case Dali::Actor::SIZE_DEPTH:
3374 case Dali::Actor::POSITION_Z:
3375 case Dali::Actor::SCALE_Z:
3376 case Dali::Actor::COLOR_BLUE:
3377 case Dali::Actor::WORLD_POSITION_Z:
3383 case Dali::Actor::COLOR_ALPHA:
3396 return componentIndex;
3399 void Actor::SetParent(Actor* parent, int index)
3403 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3407 if ( Stage::IsInstalled() && // Don't emit signals or send messages during Core destruction
3410 StagePtr stage = parent->mStage;
3412 // Instruct each actor to create a corresponding node in the scene graph
3413 ConnectToStage(*stage, index);
3416 else // parent being set to NULL
3418 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3422 if ( Stage::IsInstalled() && // Don't emit signals or send messages during Core destruction
3425 DALI_ASSERT_ALWAYS(mNode != NULL);
3429 // Disconnect the Node & its children from the scene-graph.
3430 DisconnectNodeMessage( mStage->GetUpdateManager(), *mNode );
3433 // Instruct each actor to discard pointers to the scene-graph
3434 DisconnectFromStage();
3439 SceneGraph::Node* Actor::CreateNode() const
3444 bool Actor::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
3447 Actor* actor = dynamic_cast<Actor*>(object);
3451 if(Dali::Actor::ACTION_SHOW == actionName)
3453 actor->SetVisible(true);
3456 else if(Dali::Actor::ACTION_HIDE == actionName)
3458 actor->SetVisible(false);
3466 } // namespace Internal