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;
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;
111 namespace // unnamed namespace
115 * We want to discourage the use of property strings (minimize string comparisons),
116 * particularly for the default properties.
118 const Internal::PropertyDetails DEFAULT_PROPERTY_DETAILS[] =
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
165 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( Internal::PropertyDetails );
167 } // unnamed namespace
172 unsigned int Actor::mActorCounter = 0;
173 ActorContainer Actor::mNullChildren;
175 #ifdef DYNAMICS_SUPPORT
177 // Encapsulate actor related dynamics data
180 DynamicsData( Actor* slotOwner )
181 : slotDelegate( slotOwner )
185 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
186 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
188 DynamicsBodyPtr body;
189 JointContainer joints;
190 ReferencedJointContainer referencedJoints;
192 SlotDelegate< Actor > slotDelegate;
195 #endif // DYNAMICS_SUPPORT
200 using namespace Dali;
202 BaseHandle CreateActor()
204 return Dali::Actor::New();
207 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
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);
215 TypeAction a1(mType, Dali::Actor::ACTION_SHOW, &Actor::DoAction);
216 TypeAction a2(mType, Dali::Actor::ACTION_HIDE, &Actor::DoAction);
220 Actor::DefaultPropertyLookup* Actor::mDefaultPropertyLookup = NULL;
222 ActorPtr Actor::New()
224 ActorPtr actor( new Actor( BASIC ) );
226 // Second-phase construction
232 const std::string& Actor::GetName() const
237 void Actor::SetName(const std::string& name)
243 // ATTENTION: string for debug purposes is not thread safe.
244 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
248 unsigned int Actor::GetId() const
253 void Actor::Attach( ActorAttachment& attachment )
255 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
259 attachment.Connect();
262 mAttachment = ActorAttachmentPtr(&attachment);
265 ActorAttachmentPtr Actor::GetAttachment()
270 bool Actor::OnStage() const
275 Dali::Layer Actor::GetLayer()
279 // Short-circuit for Layer derived actors
282 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
285 // Find the immediate Layer parent
286 for (Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent())
288 if( parent->IsLayer() )
290 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
297 void Actor::Add(Actor& child)
299 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
300 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
304 mChildren = new ActorContainer;
307 Actor* const oldParent( child.mParent );
309 // child might already be ours
310 if( this != oldParent )
312 // if we already have parent, unparent us first
315 oldParent->Remove( child ); // This causes OnChildRemove callback
318 // Guard against Add() during previous OnChildRemove callback
319 if ( !child.mParent )
321 // Do this first, since user callbacks from within SetParent() may need to remove child
322 mChildren->push_back(Dali::Actor(&child));
324 // SetParent asserts that child can be added
325 child.SetParent(this);
327 // Notification for derived classes
333 void Actor::Insert(unsigned int index, Actor& child)
335 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
336 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
340 mChildren = new ActorContainer;
343 Actor* const oldParent( child.mParent );
345 // since an explicit position has been given, always insert, even if already a child
348 oldParent->Remove( child ); // This causes OnChildRemove callback
351 // Guard against Add() during previous OnChildRemove callback
352 if ( !child.mParent )
354 // Do this first, since user callbacks from within SetParent() may need to remove child
355 if (index < GetChildCount())
357 ActorIter it = mChildren->begin();
358 std::advance(it, index);
359 mChildren->insert(it, Dali::Actor(&child));
363 mChildren->push_back(Dali::Actor(&child));
365 // SetParent asserts that child can be added
366 child.SetParent(this, index);
368 // Notification for derived classes
373 void Actor::Remove(Actor& child)
375 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
385 // Find the child in mChildren, and unparent it
386 ActorIter end = mChildren->end();
387 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
389 Actor& actor = GetImplementation(*iter);
391 if( &actor == &child )
393 // Keep handle for OnChildRemove notification
394 removed = Dali::Actor( &actor );
396 // Do this first, since user callbacks from within SetParent() may need to add the child
397 mChildren->erase(iter);
399 DALI_ASSERT_DEBUG( actor.GetParent() == this );
400 actor.SetParent( NULL );
408 // Notification for derived classes
409 OnChildRemove( GetImplementation(removed) );
413 void Actor::Unparent()
417 mParent->Remove( *this );
421 unsigned int Actor::GetChildCount() const
423 return ( NULL != mChildren ) ? mChildren->size() : 0;
426 Dali::Actor Actor::GetChildAt(unsigned int index) const
428 DALI_ASSERT_ALWAYS( index < GetChildCount() );
430 return ( ( mChildren ) ? (*mChildren)[index] : Dali::Actor() );
433 ActorContainer Actor::GetChildren()
435 if( NULL != mChildren )
440 // return copy of mNullChildren
441 return mNullChildren;
444 const ActorContainer& Actor::GetChildren() const
446 if( NULL != mChildren )
451 // return const reference to mNullChildren
452 return mNullChildren;
455 ActorPtr Actor::FindChildByName(const std::string& actorName)
458 if (actorName == mName)
464 ActorIter end = mChildren->end();
465 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
467 child = GetImplementation(*iter).FindChildByName(actorName);
478 Dali::Actor Actor::FindChildByAlias(const std::string& actorAlias)
480 Dali::Actor child = DoGetChildByAlias(actorAlias);
482 // If not found then search by name.
485 Internal::ActorPtr child_ptr = FindChildByName(actorAlias);
488 child = Dali::Actor(child_ptr.Get());
495 Dali::Actor Actor::DoGetChildByAlias(const std::string& actorAlias)
497 Dali::Actor child = GetChildByAlias(actorAlias);
499 if (!child && mChildren )
501 ActorIter end = mChildren->end();
502 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
504 child = GetImplementation(*iter).DoGetChildByAlias(actorAlias);
516 ActorPtr Actor::FindChildById(const unsigned int id)
525 ActorIter end = mChildren->end();
526 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
528 child = GetImplementation(*iter).FindChildById(id);
539 void Actor::SetParentOrigin( const Vector3& origin )
543 // mNode is being used in a separate thread; queue a message to set the value & base value
544 SetParentOriginMessage( mStage->GetUpdateInterface(), *mNode, origin );
547 // Cache for event-thread access
550 // not allocated, check if different from default
551 if( ParentOrigin::DEFAULT != origin )
553 mParentOrigin = new Vector3( origin );
558 // check if different from current costs more than just set
559 *mParentOrigin = origin;
563 void Actor::SetParentOriginX( float x )
565 const Vector3& current = GetCurrentParentOrigin();
567 SetParentOrigin( Vector3( x, current.y, current.z ) );
570 void Actor::SetParentOriginY( float y )
572 const Vector3& current = GetCurrentParentOrigin();
574 SetParentOrigin( Vector3( current.x, y, current.z ) );
577 void Actor::SetParentOriginZ( float z )
579 const Vector3& current = GetCurrentParentOrigin();
581 SetParentOrigin( Vector3( current.x, current.y, z ) );
584 const Vector3& Actor::GetCurrentParentOrigin() const
586 // Cached for event-thread access
587 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
590 void Actor::SetAnchorPoint(const Vector3& anchor)
594 // mNode is being used in a separate thread; queue a message to set the value & base value
595 SetAnchorPointMessage( mStage->GetUpdateInterface(), *mNode, anchor );
598 // Cache for event-thread access
601 // not allocated, check if different from default
602 if( AnchorPoint::DEFAULT != anchor )
604 mAnchorPoint = new Vector3( anchor );
609 // check if different from current costs more than just set
610 *mAnchorPoint = anchor;
614 void Actor::SetAnchorPointX( float x )
616 const Vector3& current = GetCurrentAnchorPoint();
618 SetAnchorPoint( Vector3( x, current.y, current.z ) );
621 void Actor::SetAnchorPointY( float y )
623 const Vector3& current = GetCurrentAnchorPoint();
625 SetAnchorPoint( Vector3( current.x, y, current.z ) );
628 void Actor::SetAnchorPointZ( float z )
630 const Vector3& current = GetCurrentAnchorPoint();
632 SetAnchorPoint( Vector3( current.x, current.y, z ) );
635 const Vector3& Actor::GetCurrentAnchorPoint() const
637 // Cached for event-thread access
638 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
641 void Actor::SetPosition(float x, float y)
643 SetPosition(Vector3(x, y, 0.0f));
646 void Actor::SetPosition(float x, float y, float z)
648 SetPosition(Vector3(x, y, z));
651 void Actor::SetPosition(const Vector3& position)
655 // mNode is being used in a separate thread; queue a message to set the value & base value
656 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
660 void Actor::SetX(float x)
664 // mNode is being used in a separate thread; queue a message to set the value & base value
665 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
669 void Actor::SetY(float y)
673 // mNode is being used in a separate thread; queue a message to set the value & base value
674 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
678 void Actor::SetZ(float z)
682 // mNode is being used in a separate thread; queue a message to set the value & base value
683 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
687 void Actor::MoveBy(const Vector3& distance)
691 // mNode is being used in a separate thread; queue a message to set the value & base value
692 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
696 const Vector3& Actor::GetCurrentPosition() const
700 // mNode is being used in a separate thread; copy the value from the previous update
701 return mNode->GetPosition(mStage->GetEventBufferIndex());
704 return Vector3::ZERO;
707 const Vector3& Actor::GetCurrentWorldPosition() const
711 // mNode is being used in a separate thread; copy the value from the previous update
712 return mNode->GetWorldPosition( mStage->GetEventBufferIndex() );
715 return Vector3::ZERO;
718 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
720 // this flag is not animatable so keep the value
721 mPositionInheritanceMode = mode;
724 // mNode is being used in a separate thread; queue a message to set the value
725 SetPositionInheritanceModeMessage( mStage->GetUpdateInterface(), *mNode, mode );
729 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
731 // Cached for event-thread access
732 return mPositionInheritanceMode;
735 void Actor::SetRotation(const Radian& angle, const Vector3& axis)
737 Vector4 normalizedAxis(axis.x, axis.y, axis.z, 0.0f);
738 normalizedAxis.Normalize();
740 Quaternion rotation(Quaternion::FromAxisAngle(normalizedAxis, angle));
742 SetRotation(rotation);
745 void Actor::SetRotation(const Quaternion& rotation)
749 // mNode is being used in a separate thread; queue a message to set the value & base value
750 SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, &mNode->mRotation, &AnimatableProperty<Quaternion>::Bake, rotation );
754 void Actor::RotateBy(const Radian& angle, const Vector3& axis)
758 // mNode is being used in a separate thread; queue a message to set the value & base value
759 SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, &mNode->mRotation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
763 void Actor::RotateBy(const Quaternion& relativeRotation)
767 // mNode is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, &mNode->mRotation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
772 const Quaternion& Actor::GetCurrentRotation() const
776 // mNode is being used in a separate thread; copy the value from the previous update
777 return mNode->GetRotation(mStage->GetEventBufferIndex());
780 return Quaternion::IDENTITY;
783 const Quaternion& Actor::GetCurrentWorldRotation() const
787 // mNode is being used in a separate thread; copy the value from the previous update
788 return mNode->GetWorldRotation( mStage->GetEventBufferIndex() );
791 return Quaternion::IDENTITY;
794 void Actor::SetScale(float scale)
796 SetScale(Vector3(scale, scale, scale));
799 void Actor::SetScale(float x, float y, float z)
801 SetScale(Vector3(x, y, z));
804 void Actor::SetScale(const Vector3& scale)
808 // mNode is being used in a separate thread; queue a message to set the value & base value
809 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
813 void Actor::SetScaleX( float x )
817 // mNode is being used in a separate thread; queue a message to set the value & base value
818 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
822 void Actor::SetScaleY( float y )
826 // mNode is being used in a separate thread; queue a message to set the value & base value
827 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
831 void Actor::SetScaleZ( float z )
835 // mNode is being used in a separate thread; queue a message to set the value & base value
836 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
840 void Actor::SetInitialVolume(const Vector3& volume)
844 // mNode is being used in a separate thread; queue a message to set the value
845 SetInitialVolumeMessage( mStage->GetUpdateInterface(), *mNode, volume );
849 void Actor::SetTransmitGeometryScaling(bool transmitGeometryScaling)
853 // mNode is being used in a separate thread; queue a message to set the value
854 SetTransmitGeometryScalingMessage( mStage->GetUpdateInterface(), *mNode, transmitGeometryScaling );
858 bool Actor::GetTransmitGeometryScaling() const
862 // mNode is being used in a separate thread; copy the value from the previous update
863 return mNode->GetTransmitGeometryScaling();
869 void Actor::ScaleBy(const Vector3& relativeScale)
873 // mNode is being used in a separate thread; queue a message to set the value & base value
874 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
878 const Vector3& Actor::GetCurrentScale() const
882 // mNode is being used in a separate thread; copy the value from the previous update
883 return mNode->GetScale(mStage->GetEventBufferIndex());
889 const Vector3& Actor::GetCurrentWorldScale() const
893 // mNode is being used in a separate thread; copy the value from the previous update
894 return mNode->GetWorldScale( mStage->GetEventBufferIndex() );
900 void Actor::SetInheritScale( bool inherit )
902 // non animateable so keep local copy
903 mInheritScale = inherit;
906 // mNode is being used in a separate thread; queue a message to set the value
907 SetInheritScaleMessage( mStage->GetUpdateInterface(), *mNode, inherit );
911 bool Actor::IsScaleInherited() const
913 return mInheritScale;
916 Matrix Actor::GetCurrentWorldMatrix() const
920 // World matrix is no longer updated unless there is something observing the node.
921 // Need to calculate it from node's world position, rotation and scale:
922 BufferIndex updateBufferIndex = mStage->GetEventBufferIndex();
923 Matrix worldMatrix(false);
924 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
925 mNode->GetWorldRotation( updateBufferIndex ),
926 mNode->GetWorldPosition( updateBufferIndex ) );
930 return Matrix::IDENTITY;
933 void Actor::SetVisible(bool visible)
937 // mNode is being used in a separate thread; queue a message to set the value & base value
938 SceneGraph::NodePropertyMessage<bool>::Send( mStage->GetUpdateManager(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
942 bool Actor::IsVisible() const
946 // mNode is being used in a separate thread; copy the value from the previous update
947 return mNode->IsVisible( mStage->GetEventBufferIndex() );
953 void Actor::SetOpacity(float opacity)
957 // mNode is being used in a separate thread; queue a message to set the value & base value
958 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
962 void Actor::OpacityBy(float relativeOpacity)
966 // mNode is being used in a separate thread; queue a message to set the value & base value
967 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeWRelative, relativeOpacity );
971 float Actor::GetCurrentOpacity() const
975 // mNode is being used in a separate thread; copy the value from the previous update
976 return mNode->GetOpacity(mStage->GetEventBufferIndex());
982 const Vector4& Actor::GetCurrentWorldColor() const
986 return mNode->GetWorldColor( mStage->GetEventBufferIndex() );
992 void Actor::SetColor(const Vector4& color)
996 // mNode is being used in a separate thread; queue a message to set the value & base value
997 SceneGraph::NodePropertyMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1001 void Actor::SetColorRed( float red )
1005 // mNode is being used in a separate thread; queue a message to set the value & base value
1006 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1010 void Actor::SetColorGreen( float green )
1014 // mNode is being used in a separate thread; queue a message to set the value & base value
1015 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1019 void Actor::SetColorBlue( float blue )
1023 // mNode is being used in a separate thread; queue a message to set the value & base value
1024 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1028 void Actor::ColorBy(const Vector4& relativeColor)
1032 // mNode is being used in a separate thread; queue a message to set the value & base value
1033 SceneGraph::NodePropertyMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeRelative, relativeColor );
1037 const Vector4& Actor::GetCurrentColor() const
1041 // mNode is being used in a separate thread; copy the value from the previous update
1042 return mNode->GetColor(mStage->GetEventBufferIndex());
1045 return Color::WHITE;
1048 void Actor::SetInheritRotation(bool inherit)
1050 // non animateable so keep local copy
1051 mInheritRotation = inherit;
1054 // mNode is being used in a separate thread; queue a message to set the value
1055 SetInheritRotationMessage( mStage->GetUpdateInterface(), *mNode, inherit );
1059 bool Actor::IsRotationInherited() const
1061 return mInheritRotation;
1064 void Actor::SetColorMode(ColorMode colorMode)
1066 // non animateable so keep local copy
1067 mColorMode = colorMode;
1070 // mNode is being used in a separate thread; queue a message to set the value
1071 SetColorModeMessage( mStage->GetUpdateInterface(), *mNode, colorMode );
1075 ColorMode Actor::GetColorMode() const
1077 // we have cached copy
1081 void Actor::SetSize(float width, float height)
1083 SetSize( Vector2( width, height ) );
1086 void Actor::SetSize(float width, float height, float depth)
1088 SetSize( Vector3( width, height, depth ) );
1091 void Actor::SetSize(const Vector2& size)
1093 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1096 float Actor::CalculateSizeZ( const Vector2& size ) const
1098 return std::min( size.width, size.height );
1101 void Actor::SetSize(const Vector3& size)
1107 // mNode is being used in a separate thread; queue a message to set the value & base value
1108 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mSize );
1110 // Notification for derived classes
1113 // Emit signal for application developer
1115 if( !mSetSizeSignalV2.Empty() )
1117 Dali::Actor handle( this );
1118 mSetSizeSignalV2.Emit( handle, mSize );
1123 void Actor::NotifySizeAnimation(Animation& animation, const Vector3& targetSize)
1127 // Notify deriving classes
1128 OnSizeAnimation( animation, targetSize );
1131 void Actor::SetWidth( float width )
1135 // mNode is being used in a separate thread; queue a message to set the value & base value
1136 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1140 void Actor::SetHeight( float height )
1144 // mNode is being used in a separate thread; queue a message to set the value & base value
1145 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1149 void Actor::SetDepth( float depth )
1153 // mNode is being used in a separate thread; queue a message to set the value & base value
1154 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1158 const Vector3& Actor::GetSize() const
1163 const Vector3& Actor::GetCurrentSize() const
1167 // mNode is being used in a separate thread; copy the value from the previous update
1168 return mNode->GetSize( mStage->GetEventBufferIndex() );
1171 return Vector3::ZERO;
1174 Vector3 Actor::GetNaturalSize() const
1176 // It is up to deriving classes to return the appropriate natural size
1177 return Vector3( 0.0f, 0.0f, 0.0f );
1181 #ifdef DYNAMICS_SUPPORT
1183 //--------------- Dynamics ---------------
1185 void Actor::DisableDynamics()
1187 if( NULL != mDynamicsData )
1189 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1191 // ensure dynamics object are disconnected from scene
1192 DisconnectDynamics();
1194 // delete joint owned by this actor
1195 while( !mDynamicsData->joints.empty() )
1197 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1200 // delete other joints referencing this actor
1201 while( !mDynamicsData->referencedJoints.empty() )
1203 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1204 ActorPtr jointOwner( joint->GetActor( true ) );
1207 jointOwner->RemoveDynamicsJoint( joint );
1211 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1214 // delete the DynamicsBody object
1215 mDynamicsData->body.Reset();
1217 // Discard Dynamics data structure
1218 delete mDynamicsData;
1219 mDynamicsData = NULL;
1223 DynamicsBodyPtr Actor::GetDynamicsBody() const
1225 DynamicsBodyPtr body;
1227 if( NULL != mDynamicsData )
1229 body = mDynamicsData->body;
1235 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1237 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1239 if( NULL == mDynamicsData )
1241 mDynamicsData = new DynamicsData( this );
1244 if( !mDynamicsData->body )
1246 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1250 DynamicsWorldPtr world( mStage->GetDynamicsWorld() );
1253 if( mParent == world->GetRootActor().Get() )
1255 mDynamicsData->body->Connect(*mStage);
1261 return mDynamicsData->body;
1264 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1266 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1267 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1270 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1272 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1273 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1275 DynamicsJointPtr joint;
1277 DynamicsWorldPtr world( mStage->GetDynamicsWorld() );
1281 if( NULL != mDynamicsData )
1283 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1285 if( mDynamicsData->joints.end() != it )
1287 // use existing joint
1293 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1294 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1298 bodyA = EnableDynamics( new DynamicsBodyConfig );
1303 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1306 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1307 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1309 if( OnStage() && attachedActor->OnStage() )
1311 joint->Connect(*mStage);
1314 attachedActor->ReferenceJoint( joint );
1316 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1317 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1324 const int Actor::GetNumberOfJoints() const
1326 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1329 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1331 DynamicsJointPtr joint;
1333 if( NULL != mDynamicsData )
1335 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1337 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1339 for( int i = 0; i < index; ++i )
1351 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1353 DynamicsJointPtr joint;
1355 if( NULL != mDynamicsData )
1357 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1359 if( mDynamicsData->joints.end() != it )
1361 // use existing joint
1369 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1371 if( NULL != mDynamicsData )
1373 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1374 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1376 for( ; it != endIt; ++it )
1378 if( it->second == joint.Get() )
1380 ActorPtr attachedActor( it->first );
1382 if( OnStage() && attachedActor && attachedActor->OnStage() )
1384 joint->Disconnect(*mStage);
1389 attachedActor->ReleaseJoint( joint );
1390 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1391 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1394 mDynamicsData->joints.erase(it);
1401 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1403 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1405 if( NULL != mDynamicsData )
1407 mDynamicsData->referencedJoints.push_back(joint);
1411 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1413 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1415 if( NULL != mDynamicsData )
1417 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1419 if( it != mDynamicsData->referencedJoints.end() )
1421 mDynamicsData->referencedJoints.erase( it );
1426 void Actor::SetDynamicsRoot(bool flag)
1428 if( mIsDynamicsRoot != flag )
1430 mIsDynamicsRoot = flag;
1432 if( OnStage() && mChildren )
1434 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1435 ActorIter end = mChildren->end();
1436 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1438 Actor& child = GetImplementation(*iter);
1440 if( child.GetDynamicsBody() )
1442 if( mIsDynamicsRoot )
1444 child.ConnectDynamics();
1448 child.DisconnectDynamics();
1456 bool Actor::IsDynamicsRoot() const
1458 return mIsDynamicsRoot;
1461 void Actor::AttachedActorOnStage( Dali::Actor actor )
1463 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1467 ActorPtr attachedActor( &GetImplementation(actor) );
1469 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1470 if( NULL != mDynamicsData )
1472 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1473 if( mDynamicsData->joints.end() != it )
1475 DynamicsJointPtr joint( it->second );
1476 joint->Connect(*mStage);
1482 void Actor::AttachedActorOffStage( Dali::Actor actor )
1484 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1488 ActorPtr attachedActor( &GetImplementation(actor) );
1490 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1491 if( NULL != mDynamicsData )
1493 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1494 if( mDynamicsData->joints.end() != it )
1496 DynamicsJointPtr joint( it->second );
1497 joint->Disconnect(*mStage);
1503 void Actor::ConnectDynamics()
1505 if( NULL != mDynamicsData && mDynamicsData->body )
1507 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1509 mDynamicsData->body->Connect(*mStage);
1511 // Connect all joints where attachedActor is also on stage
1512 if( !mDynamicsData->joints.empty() )
1514 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1515 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1517 for( ; it != endIt; ++it )
1519 Actor* attachedActor( it->first );
1520 if( NULL != attachedActor && attachedActor->OnStage() )
1522 DynamicsJointPtr joint( it->second );
1524 joint->Connect(*mStage);
1532 void Actor::DisconnectDynamics()
1534 if( NULL != mDynamicsData && mDynamicsData->body )
1538 mDynamicsData->body->Disconnect(*mStage);
1540 // Disconnect all joints
1541 if( !mDynamicsData->joints.empty() )
1543 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1544 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1546 for( ; it != endIt; ++it )
1548 DynamicsJointPtr joint( it->second );
1550 joint->Disconnect(*mStage);
1557 #endif // DYNAMICS_SUPPORT
1559 void Actor::SetOverlay(bool enable)
1561 // Setting STENCIL will override OVERLAY
1562 if( DrawMode::STENCIL != mDrawMode )
1564 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1568 bool Actor::IsOverlay() const
1570 return ( DrawMode::OVERLAY == mDrawMode );
1573 void Actor::SetDrawMode( DrawMode::Type drawMode )
1575 // this flag is not animatable so keep the value
1576 mDrawMode = drawMode;
1579 // mNode is being used in a separate thread; queue a message to set the value
1580 SetDrawModeMessage( mStage->GetUpdateInterface(), *mNode, drawMode );
1584 DrawMode::Type Actor::GetDrawMode() const
1589 bool Actor::ScreenToLocal( float& localX,
1592 float screenY ) const
1594 // only valid when on-stage
1597 const RenderTaskList& taskList = mStage->GetRenderTaskList();
1599 Vector2 converted( screenX, screenY );
1601 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1602 const int taskCount = taskList.GetTaskCount();
1603 for( int i = taskCount - 1; i >= 0; --i )
1605 Dali::RenderTask task = taskList.GetTask( i );
1606 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1608 // found a task where this conversion was ok so return
1616 bool Actor::ScreenToLocal( RenderTask& renderTask,
1620 float screenY ) const
1622 bool retval = false;
1623 // only valid when on-stage
1626 CameraActor* camera = renderTask.GetCameraActor();
1630 renderTask.GetViewport( viewport );
1632 // need to translate coordinates to render tasks coordinate space
1633 Vector2 converted( screenX, screenY );
1634 if( renderTask.TranslateCoordinates( converted ) )
1636 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1643 bool Actor::ScreenToLocal( const Matrix& viewMatrix,
1644 const Matrix& projectionMatrix,
1645 const Viewport& viewport,
1649 float screenY ) const
1651 // Early-out if mNode is NULL
1657 BufferIndex bufferIndex( mStage->GetEventBufferIndex() );
1659 // Calculate the ModelView matrix
1660 Matrix modelView(false/*don't init*/);
1661 // need to use the components as world matrix is only updated for actors that need it
1662 modelView.SetTransformComponents( mNode->GetWorldScale(bufferIndex), mNode->GetWorldRotation(bufferIndex), mNode->GetWorldPosition(bufferIndex) );
1663 Matrix::Multiply(modelView, modelView, viewMatrix);
1665 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1666 Matrix invertedMvp(false/*don't init*/);
1667 Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
1668 bool success = invertedMvp.Invert();
1670 // Convert to GL coordinates
1671 Vector4 screenPos( screenX - viewport.x, viewport.height - (screenY - viewport.y), 0.f, 1.f );
1676 success = Unproject(screenPos, invertedMvp, viewport.width, viewport.height, nearPos);
1683 success = Unproject(screenPos, invertedMvp, viewport.width, viewport.height, farPos);
1689 if (XyPlaneIntersect(nearPos, farPos, local))
1691 Vector3 size = GetCurrentSize();
1692 localX = local.x + size.x * 0.5f;
1693 localY = local.y + size.y * 0.5f;
1704 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1707 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1709 Mathematical Formulation
1711 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1713 ( p - c ) dot ( p - c ) = r^2
1715 Given a ray with a point of origin 'o', and a direction vector 'd':
1717 ray(t) = o + td, t >= 0
1719 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1721 (o + td - c ) dot ( o + td - c ) = r^2
1723 To solve for t we first expand the above into a more recognisable quadratic equation form
1725 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1734 B = 2( o - c ) dot d
1735 C = ( o - c ) dot ( o - c ) - r^2
1737 which can be solved using a standard quadratic formula.
1739 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1741 Practical Simplification
1743 In a renderer, we often differentiate between world space and object space. In the object space
1744 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1745 into object space, the mathematical solution presented above can be simplified significantly.
1747 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1751 and we can find the t at which the (transformed) ray intersects the sphere by
1753 ( o + td ) dot ( o + td ) = r^2
1755 According to the reasoning above, we expand the above quadratic equation into the general form
1759 which now has coefficients:
1766 // Early out if mNode is NULL
1772 BufferIndex bufferIndex( mStage->GetEventBufferIndex() );
1774 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1775 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1776 Vector3 rayOriginLocal(rayOrigin.x - translation.x,
1777 rayOrigin.y - translation.y,
1778 rayOrigin.z - translation.z);
1780 // Compute the radius is not needed, square radius it's enough.
1781 const Vector3& size( mNode->GetSize( bufferIndex ) );
1783 // Scale the sphere.
1784 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1786 const float width = size.width * scale.width;
1787 const float height = size.height * scale.height;
1789 float squareSphereRadius = 0.5f * ( width * width + height * height );
1791 float a = rayDir.Dot( rayDir ); // a
1792 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1793 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1795 return ( b2*b2 - a*c ) >= 0.f;
1798 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1805 BufferIndex bufferIndex( mStage->GetEventBufferIndex() );
1807 // Transforms the ray to the local reference system.
1809 // Calculate the inverse of Model matrix
1810 Matrix invModelMatrix(false/*don't init*/);
1811 // need to use the components as world matrix is only updated for actors that need it
1812 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale(bufferIndex), mNode->GetWorldRotation(bufferIndex), mNode->GetWorldPosition(bufferIndex) );
1814 Vector4 rayOriginLocal(invModelMatrix * rayOrigin);
1815 Vector4 rayDirLocal(invModelMatrix * rayDir - invModelMatrix.GetTranslation());
1817 // Test with the actor's XY plane (Normal = 0 0 1 1).
1819 float a = -rayOriginLocal.z;
1820 float b = rayDirLocal.z;
1822 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1824 // Ray travels distance * rayDirLocal to intersect with plane.
1827 const Vector3& size = mNode->GetSize( bufferIndex );
1829 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1830 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1832 // Test with the actor's geometry.
1833 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1840 void Actor::SetLeaveRequired(bool required)
1842 mLeaveRequired = required;
1845 bool Actor::GetLeaveRequired() const
1847 return mLeaveRequired;
1850 void Actor::SetKeyboardFocusable( bool focusable )
1852 mKeyboardFocusable = focusable;
1855 bool Actor::IsKeyboardFocusable() const
1857 return mKeyboardFocusable;
1860 bool Actor::GetTouchRequired() const
1862 return !mTouchedSignalV2.Empty() || mDerivedRequiresTouch;
1865 bool Actor::GetHoverRequired() const
1867 return !mHoveredSignalV2.Empty() || mDerivedRequiresHover;
1870 bool Actor::GetMouseWheelEventRequired() const
1872 return !mMouseWheelEventSignalV2.Empty() || mDerivedRequiresMouseWheelEvent;
1875 bool Actor::IsHittable() const
1877 return IsSensitive() &&
1879 ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) &&
1883 ActorGestureData& Actor::GetGestureData()
1885 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1886 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1887 if ( NULL == mGestureData )
1889 mGestureData = new ActorGestureData;
1891 return *mGestureData;
1894 bool Actor::IsGestureRequred( Gesture::Type type ) const
1896 return mGestureData && mGestureData->IsGestureRequred( type );
1899 bool Actor::EmitTouchEventSignal(const TouchEvent& event)
1901 bool consumed = false;
1903 if ( !mTouchedSignalV2.Empty() )
1905 Dali::Actor handle( this );
1906 consumed = mTouchedSignalV2.Emit( handle, event );
1911 // Notification for derived classes
1912 consumed = OnTouchEvent( event );
1918 bool Actor::EmitHoverEventSignal(const HoverEvent& event)
1920 bool consumed = false;
1922 if ( !mHoveredSignalV2.Empty() )
1924 Dali::Actor handle( this );
1925 consumed = mHoveredSignalV2.Emit( handle, event );
1930 // Notification for derived classes
1931 consumed = OnHoverEvent( event );
1937 bool Actor::EmitMouseWheelEventSignal(const MouseWheelEvent& event)
1939 bool consumed = false;
1941 if ( !mMouseWheelEventSignalV2.Empty() )
1943 Dali::Actor handle( this );
1944 consumed = mMouseWheelEventSignalV2.Emit( handle, event );
1949 // Notification for derived classes
1950 consumed = OnMouseWheelEvent(event);
1956 Dali::Actor::TouchSignalV2& Actor::TouchedSignal()
1958 return mTouchedSignalV2;
1961 Dali::Actor::HoverSignalV2& Actor::HoveredSignal()
1963 return mHoveredSignalV2;
1966 Dali::Actor::MouseWheelEventSignalV2& Actor::MouseWheelEventSignal()
1968 return mMouseWheelEventSignalV2;
1971 Dali::Actor::SetSizeSignalV2& Actor::SetSizeSignal()
1973 return mSetSizeSignalV2;
1976 Dali::Actor::OnStageSignalV2& Actor::OnStageSignal()
1978 return mOnStageSignalV2;
1981 Dali::Actor::OffStageSignalV2& Actor::OffStageSignal()
1983 return mOffStageSignalV2;
1986 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1988 bool connected( true );
1989 Actor* actor = dynamic_cast<Actor*>(object);
1991 if(Dali::Actor::SIGNAL_TOUCHED == signalName)
1993 actor->TouchedSignal().Connect( tracker, functor );
1995 else if(Dali::Actor::SIGNAL_HOVERED == signalName)
1997 actor->HoveredSignal().Connect( tracker, functor );
1999 else if(Dali::Actor::SIGNAL_MOUSE_WHEEL_EVENT == signalName)
2001 actor->MouseWheelEventSignal().Connect( tracker, functor );
2003 else if(Dali::Actor::SIGNAL_SET_SIZE == signalName)
2005 actor->SetSizeSignal().Connect( tracker, functor );
2007 else if(Dali::Actor::SIGNAL_ON_STAGE == signalName)
2009 actor->OnStageSignal().Connect( tracker, functor );
2011 else if(Dali::Actor::SIGNAL_OFF_STAGE == signalName)
2013 actor->OffStageSignal().Connect( tracker, functor );
2017 // signalName does not match any signal
2024 Actor::Actor( DerivedType derivedType )
2029 mParentOrigin( NULL ),
2030 mAnchorPoint( NULL ),
2031 #ifdef DYNAMICS_SUPPORT
2032 mDynamicsData( NULL ),
2034 mGestureData( NULL ),
2036 mSize( 0.0f, 0.0f, 0.0f ),
2038 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2039 mIsRoot( ROOT_LAYER == derivedType ),
2040 mIsRenderable( RENDERABLE == derivedType ),
2041 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2042 mIsOnStage( false ),
2043 mIsDynamicsRoot(false),
2045 mLeaveRequired( false ),
2046 mKeyboardFocusable( false ),
2047 mDerivedRequiresTouch( false ),
2048 mDerivedRequiresHover( false ),
2049 mDerivedRequiresMouseWheelEvent( false ),
2050 mOnStageSignalled( false ),
2051 mInheritRotation( true ),
2052 mInheritScale( true ),
2053 mDrawMode( DrawMode::NORMAL ),
2054 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2055 mColorMode( Node::DEFAULT_COLOR_MODE )
2059 void Actor::Initialize()
2061 mStage = Stage::GetCurrent();
2064 SceneGraph::Node* node = CreateNode();
2066 AddNodeMessage( mStage->GetUpdateManager(), *node ); // Pass ownership to scene-graph
2067 mNode = node; // Keep raw-pointer to Node
2069 if(!mDefaultPropertyLookup)
2071 mDefaultPropertyLookup = new DefaultPropertyLookup();
2073 for (int i=0; i<DEFAULT_PROPERTY_COUNT; ++i)
2075 (*mDefaultPropertyLookup)[DEFAULT_PROPERTY_DETAILS[i].name] = i;
2086 // Remove mParent pointers from children even if we're destroying core,
2087 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2090 ActorConstIter endIter = mChildren->end();
2091 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2093 Actor& actor = GetImplementation( *iter );
2094 actor.SetParent( NULL );
2099 // Guard to allow handle destruction after Core has been destroyed
2100 if( Stage::IsInstalled() )
2104 DestroyNodeMessage( mStage->GetUpdateManager(), *mNode );
2105 mNode = NULL; // Node is about to be destroyed
2111 #ifdef DYNAMICS_SUPPORT
2113 delete mDynamicsData;
2116 // Cleanup optional gesture data
2117 delete mGestureData;
2119 // Cleanup optional parent origin and anchor
2120 delete mParentOrigin;
2121 delete mAnchorPoint;
2124 void Actor::ConnectToStage( Stage& stage, int index )
2126 // This container is used instead of walking the Actor hierachy.
2127 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2128 ActorContainer connectionList;
2130 // This stage is atomic i.e. not interrupted by user callbacks
2131 RecursiveConnectToStage( stage, connectionList, index );
2133 // Notify applications about the newly connected actors.
2134 const ActorIter endIter = connectionList.end();
2135 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2137 Actor& actor = GetImplementation(*iter);
2138 actor.NotifyStageConnection();
2142 void Actor::RecursiveConnectToStage( Stage& stage, ActorContainer& connectionList, int index )
2144 DALI_ASSERT_ALWAYS( !OnStage() );
2148 ConnectToSceneGraph(index);
2150 // Notification for internal derived classes
2151 OnStageConnectionInternal();
2153 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2154 connectionList.push_back( Dali::Actor(this) );
2156 // Recursively connect children
2159 ActorConstIter endIter = mChildren->end();
2160 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2162 Actor& actor = GetImplementation( *iter );
2163 actor.RecursiveConnectToStage( stage, connectionList );
2169 * This method is called when the Actor is connected to the Stage.
2170 * The parent must have added its Node to the scene-graph.
2171 * The child must connect its Node to the parent's Node.
2172 * This is resursive; the child calls ConnectToStage() for its children.
2174 void Actor::ConnectToSceneGraph(int index)
2176 DALI_ASSERT_DEBUG( mNode != NULL);
2177 DALI_ASSERT_DEBUG( mParent != NULL);
2178 DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2182 // Reparent Node in next Update
2183 ConnectNodeMessage( mStage->GetUpdateManager(), *(mParent->mNode), *mNode, index );
2186 // Notify attachment
2189 mAttachment->Connect();
2192 #ifdef DYNAMICS_SUPPORT
2194 if( NULL != mDynamicsData )
2200 // Notification for ProxyObject::Observers
2204 void Actor::NotifyStageConnection()
2206 // Actors can be removed (in a callback), before the on-stage stage is reported.
2207 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2208 if ( OnStage() && !mOnStageSignalled )
2210 // Notification for external (CustomActor) derived classes
2211 OnStageConnectionExternal();
2213 if ( !mOnStageSignalV2.Empty() )
2215 Dali::Actor handle( this );
2216 mOnStageSignalV2.Emit( handle );
2219 // Guard against Remove during callbacks
2222 mOnStageSignalled = true; // signal required next time Actor is removed
2227 void Actor::DisconnectFromStage()
2229 // This container is used instead of walking the Actor hierachy.
2230 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2231 ActorContainer disconnectionList;
2233 // This stage is atomic i.e. not interrupted by user callbacks
2234 RecursiveDisconnectFromStage( disconnectionList );
2236 // Notify applications about the newly disconnected actors.
2237 const ActorIter endIter = disconnectionList.end();
2238 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2240 Actor& actor = GetImplementation(*iter);
2241 actor.NotifyStageDisconnection();
2245 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2247 DALI_ASSERT_ALWAYS( OnStage() );
2249 // Recursively disconnect children
2252 ActorConstIter endIter = mChildren->end();
2253 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2255 Actor& actor = GetImplementation( *iter );
2256 actor.RecursiveDisconnectFromStage( disconnectionList );
2260 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2261 disconnectionList.push_back( Dali::Actor(this) );
2263 // Notification for internal derived classes
2264 OnStageDisconnectionInternal();
2266 DisconnectFromSceneGraph();
2272 * This method is called by an actor or its parent, before a node removal message is sent.
2273 * This is recursive; the child calls DisconnectFromStage() for its children.
2275 void Actor::DisconnectFromSceneGraph()
2277 // Notification for ProxyObject::Observers
2278 OnSceneObjectRemove();
2280 // Notify attachment
2283 mAttachment->Disconnect();
2286 #ifdef DYNAMICS_SUPPORT
2288 if( NULL != mDynamicsData )
2290 DisconnectDynamics();
2295 void Actor::NotifyStageDisconnection()
2297 // Actors can be added (in a callback), before the off-stage state is reported.
2298 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2299 // only do this step if there is a stage, i.e. Core is not being shut down
2300 if ( Stage::IsInstalled() && !OnStage() && mOnStageSignalled )
2302 // Notification for external (CustomeActor) derived classes
2303 OnStageDisconnectionExternal();
2305 if( !mOffStageSignalV2.Empty() )
2307 Dali::Actor handle( this );
2308 mOffStageSignalV2.Emit( handle );
2311 // Guard against Add during callbacks
2314 mOnStageSignalled = false; // signal required next time Actor is added
2319 bool Actor::IsNodeConnected() const
2321 bool connected( false );
2326 if( mNode->IsRoot() || mNode->GetParent() )
2335 bool Actor::IsSceneObjectRemovable() const
2340 unsigned int Actor::GetDefaultPropertyCount() const
2342 return DEFAULT_PROPERTY_COUNT;
2345 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2347 indices.reserve( DEFAULT_PROPERTY_COUNT );
2349 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2351 indices.push_back( i );
2355 const std::string& Actor::GetDefaultPropertyName( Property::Index index ) const
2357 if( index < DEFAULT_PROPERTY_COUNT )
2359 return DEFAULT_PROPERTY_DETAILS[index].name;
2363 // index out of range..return empty string
2364 return String::EMPTY;
2368 Property::Index Actor::GetDefaultPropertyIndex(const std::string& name) const
2370 Property::Index index = Property::INVALID_INDEX;
2372 DALI_ASSERT_DEBUG( NULL != mDefaultPropertyLookup );
2374 // Look for name in default properties
2375 DefaultPropertyLookup::const_iterator result = mDefaultPropertyLookup->find( name );
2376 if ( mDefaultPropertyLookup->end() != result )
2378 index = result->second;
2384 bool Actor::IsDefaultPropertyWritable(Property::Index index) const
2386 if( index < DEFAULT_PROPERTY_COUNT )
2388 return DEFAULT_PROPERTY_DETAILS[index].writable;
2396 bool Actor::IsDefaultPropertyAnimatable(Property::Index index) const
2398 if( index < DEFAULT_PROPERTY_COUNT )
2400 return DEFAULT_PROPERTY_DETAILS[index].animatable;
2408 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2410 if( index < DEFAULT_PROPERTY_COUNT )
2412 return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
2420 Property::Type Actor::GetDefaultPropertyType(Property::Index index) const
2422 if( index < DEFAULT_PROPERTY_COUNT )
2424 return DEFAULT_PROPERTY_DETAILS[index].type;
2428 // index out of range...return Property::NONE
2429 return Property::NONE;
2433 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2437 case Dali::Actor::PARENT_ORIGIN:
2439 SetParentOrigin( property.Get<Vector3>() );
2443 case Dali::Actor::PARENT_ORIGIN_X:
2445 SetParentOriginX( property.Get<float>() );
2449 case Dali::Actor::PARENT_ORIGIN_Y:
2451 SetParentOriginY( property.Get<float>() );
2455 case Dali::Actor::PARENT_ORIGIN_Z:
2457 SetParentOriginZ( property.Get<float>() );
2461 case Dali::Actor::ANCHOR_POINT:
2463 SetAnchorPoint( property.Get<Vector3>() );
2467 case Dali::Actor::ANCHOR_POINT_X:
2469 SetAnchorPointX( property.Get<float>() );
2473 case Dali::Actor::ANCHOR_POINT_Y:
2475 SetAnchorPointY( property.Get<float>() );
2479 case Dali::Actor::ANCHOR_POINT_Z:
2481 SetAnchorPointZ( property.Get<float>() );
2485 case Dali::Actor::SIZE:
2487 SetSize( property.Get<Vector3>() );
2491 case Dali::Actor::SIZE_WIDTH:
2493 SetWidth( property.Get<float>() );
2497 case Dali::Actor::SIZE_HEIGHT:
2499 SetHeight( property.Get<float>() );
2503 case Dali::Actor::SIZE_DEPTH:
2505 SetDepth( property.Get<float>() );
2509 case Dali::Actor::POSITION:
2511 SetPosition( property.Get<Vector3>() );
2515 case Dali::Actor::POSITION_X:
2517 SetX( property.Get<float>() );
2521 case Dali::Actor::POSITION_Y:
2523 SetY( property.Get<float>() );
2527 case Dali::Actor::POSITION_Z:
2529 SetZ( property.Get<float>() );
2533 case Dali::Actor::ROTATION:
2535 SetRotation( property.Get<Quaternion>() );
2539 case Dali::Actor::SCALE:
2541 SetScale( property.Get<Vector3>() );
2545 case Dali::Actor::SCALE_X:
2547 SetScaleX( property.Get<float>() );
2551 case Dali::Actor::SCALE_Y:
2553 SetScaleY( property.Get<float>() );
2557 case Dali::Actor::SCALE_Z:
2559 SetScaleZ( property.Get<float>() );
2563 case Dali::Actor::VISIBLE:
2565 SetVisible( property.Get<bool>() );
2569 case Dali::Actor::COLOR:
2571 SetColor( property.Get<Vector4>() );
2575 case Dali::Actor::COLOR_RED:
2577 SetColorRed( property.Get<float>() );
2581 case Dali::Actor::COLOR_GREEN:
2583 SetColorGreen( property.Get<float>() );
2587 case Dali::Actor::COLOR_BLUE:
2589 SetColorBlue( property.Get<float>() );
2593 case Dali::Actor::COLOR_ALPHA:
2595 SetOpacity( property.Get<float>() );
2599 case Dali::Actor::NAME:
2601 SetName( property.Get<std::string>() );
2605 case Dali::Actor::SENSITIVE:
2607 SetSensitive( property.Get<bool>() );
2611 case Dali::Actor::LEAVE_REQUIRED:
2613 SetLeaveRequired( property.Get<bool>() );
2617 case Dali::Actor::INHERIT_ROTATION:
2619 SetInheritRotation( property.Get<bool>() );
2623 case Dali::Actor::INHERIT_SCALE:
2625 SetInheritScale( property.Get<bool>() );
2629 case Dali::Actor::COLOR_MODE:
2631 SetColorMode( Scripting::GetColorMode( property.Get<std::string>() ) );
2635 case Dali::Actor::POSITION_INHERITANCE:
2637 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get<std::string>() ) );
2641 case Dali::Actor::DRAW_MODE:
2643 SetDrawMode( Scripting::GetDrawMode( property.Get<std::string>() ) );
2649 DALI_ASSERT_ALWAYS(false && "Actor::Property is out of bounds"); // should not come here
2655 void Actor::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
2657 // TODO: This should be deprecated
2658 OnPropertySet(index, value);
2660 if(entry.IsAnimatable())
2662 switch ( entry.type )
2664 case Property::BOOLEAN:
2666 AnimatableProperty<bool>* property = dynamic_cast< AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
2667 DALI_ASSERT_DEBUG( NULL != property );
2669 // property is being used in a separate thread; queue a message to set the property
2670 SceneGraph::NodePropertyMessage<bool>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2675 case Property::FLOAT:
2677 AnimatableProperty<float>* property = dynamic_cast< AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
2678 DALI_ASSERT_DEBUG( NULL != property );
2680 // property is being used in a separate thread; queue a message to set the property
2681 SceneGraph::NodePropertyMessage<float>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2686 case Property::INTEGER:
2688 AnimatableProperty<int>* property = dynamic_cast< AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
2689 DALI_ASSERT_DEBUG( NULL != property );
2691 // property is being used in a separate thread; queue a message to set the property
2692 SceneGraph::NodePropertyMessage<int>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2697 case Property::VECTOR2:
2699 AnimatableProperty<Vector2>* property = dynamic_cast< AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
2700 DALI_ASSERT_DEBUG( NULL != property );
2702 // property is being used in a separate thread; queue a message to set the property
2703 SceneGraph::NodePropertyMessage<Vector2>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2708 case Property::VECTOR3:
2710 AnimatableProperty<Vector3>* property = dynamic_cast< AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
2711 DALI_ASSERT_DEBUG( NULL != property );
2713 // property is being used in a separate thread; queue a message to set the property
2714 SceneGraph::NodePropertyMessage<Vector3>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2719 case Property::VECTOR4:
2721 AnimatableProperty<Vector4>* property = dynamic_cast< AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
2722 DALI_ASSERT_DEBUG( NULL != property );
2724 // property is being used in a separate thread; queue a message to set the property
2725 SceneGraph::NodePropertyMessage<Vector4>::Send( mStage->GetUpdateManager(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2730 case Property::ROTATION:
2732 AnimatableProperty<Quaternion>* property = dynamic_cast< AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
2733 DALI_ASSERT_DEBUG( NULL != property );
2735 // property is being used in a separate thread; queue a message to set the property
2736 SceneGraph::NodePropertyMessage<Quaternion>::Send( mStage->GetUpdateManager(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2741 case Property::MATRIX:
2743 AnimatableProperty<Matrix>* property = dynamic_cast< AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
2744 DALI_ASSERT_DEBUG( NULL != property );
2746 // property is being used in a separate thread; queue a message to set the property
2747 SceneGraph::NodePropertyMessage<Matrix>::Send( mStage->GetUpdateManager(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2752 case Property::MATRIX3:
2754 AnimatableProperty<Matrix3>* property = dynamic_cast< AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
2755 DALI_ASSERT_DEBUG( NULL != property );
2757 // property is being used in a separate thread; queue a message to set the property
2758 SceneGraph::NodePropertyMessage<Matrix3>::Send( mStage->GetUpdateManager(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2765 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2772 Property::Value Actor::GetDefaultProperty(Property::Index index) const
2774 Property::Value value;
2778 case Dali::Actor::PARENT_ORIGIN:
2780 value = GetCurrentParentOrigin();
2784 case Dali::Actor::PARENT_ORIGIN_X:
2786 value = GetCurrentParentOrigin().x;
2790 case Dali::Actor::PARENT_ORIGIN_Y:
2792 value = GetCurrentParentOrigin().y;
2796 case Dali::Actor::PARENT_ORIGIN_Z:
2798 value = GetCurrentParentOrigin().z;
2802 case Dali::Actor::ANCHOR_POINT:
2804 value = GetCurrentAnchorPoint();
2808 case Dali::Actor::ANCHOR_POINT_X:
2810 value = GetCurrentAnchorPoint().x;
2814 case Dali::Actor::ANCHOR_POINT_Y:
2816 value = GetCurrentAnchorPoint().y;
2820 case Dali::Actor::ANCHOR_POINT_Z:
2822 value = GetCurrentAnchorPoint().z;
2826 case Dali::Actor::SIZE:
2828 value = GetCurrentSize();
2832 case Dali::Actor::SIZE_WIDTH:
2834 value = GetCurrentSize().width;
2838 case Dali::Actor::SIZE_HEIGHT:
2840 value = GetCurrentSize().height;
2844 case Dali::Actor::SIZE_DEPTH:
2846 value = GetCurrentSize().depth;
2850 case Dali::Actor::POSITION:
2852 value = GetCurrentPosition();
2856 case Dali::Actor::POSITION_X:
2858 value = GetCurrentPosition().x;
2862 case Dali::Actor::POSITION_Y:
2864 value = GetCurrentPosition().y;
2868 case Dali::Actor::POSITION_Z:
2870 value = GetCurrentPosition().z;
2874 case Dali::Actor::WORLD_POSITION:
2876 value = GetCurrentWorldPosition();
2880 case Dali::Actor::WORLD_POSITION_X:
2882 value = GetCurrentWorldPosition().x;
2886 case Dali::Actor::WORLD_POSITION_Y:
2888 value = GetCurrentWorldPosition().y;
2892 case Dali::Actor::WORLD_POSITION_Z:
2894 value = GetCurrentWorldPosition().z;
2898 case Dali::Actor::ROTATION:
2900 value = GetCurrentRotation();
2904 case Dali::Actor::WORLD_ROTATION:
2906 value = GetCurrentWorldRotation();
2910 case Dali::Actor::SCALE:
2912 value = GetCurrentScale();
2916 case Dali::Actor::SCALE_X:
2918 value = GetCurrentScale().x;
2922 case Dali::Actor::SCALE_Y:
2924 value = GetCurrentScale().y;
2928 case Dali::Actor::SCALE_Z:
2930 value = GetCurrentScale().z;
2934 case Dali::Actor::WORLD_SCALE:
2936 value = GetCurrentWorldScale();
2940 case Dali::Actor::VISIBLE:
2942 value = IsVisible();
2946 case Dali::Actor::COLOR:
2948 value = GetCurrentColor();
2952 case Dali::Actor::COLOR_RED:
2954 value = GetCurrentColor().r;
2958 case Dali::Actor::COLOR_GREEN:
2960 value = GetCurrentColor().g;
2964 case Dali::Actor::COLOR_BLUE:
2966 value = GetCurrentColor().b;
2970 case Dali::Actor::COLOR_ALPHA:
2972 value = GetCurrentColor().a;
2976 case Dali::Actor::WORLD_COLOR:
2978 value = GetCurrentWorldColor();
2982 case Dali::Actor::WORLD_MATRIX:
2984 value = GetCurrentWorldMatrix();
2988 case Dali::Actor::NAME:
2994 case Dali::Actor::SENSITIVE:
2996 value = IsSensitive();
3000 case Dali::Actor::LEAVE_REQUIRED:
3002 value = GetLeaveRequired();
3006 case Dali::Actor::INHERIT_ROTATION:
3008 value = IsRotationInherited();
3012 case Dali::Actor::INHERIT_SCALE:
3014 value = IsScaleInherited();
3018 case Dali::Actor::COLOR_MODE:
3020 value = Scripting::GetColorMode( GetColorMode() );
3024 case Dali::Actor::POSITION_INHERITANCE:
3026 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3030 case Dali::Actor::DRAW_MODE:
3032 value = Scripting::GetDrawMode( GetDrawMode() );
3038 DALI_ASSERT_ALWAYS(false && "Actor Property index invalid" ); // should not come here
3046 void Actor::InstallSceneObjectProperty( PropertyBase& newProperty, const std::string& name, unsigned int index )
3050 // mNode is being used in a separate thread; queue a message to add the property
3051 InstallCustomPropertyMessage( mStage->GetUpdateInterface(), *mNode, newProperty ); // Message takes ownership
3055 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3057 // This method should only return an object connected to the scene-graph
3058 return OnStage() ? mNode : NULL;
3061 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3063 DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
3065 const PropertyBase* property( NULL );
3067 // This method should only return a property of an object connected to the scene-graph
3073 if ( static_cast<unsigned int>(index) >= DEFAULT_PROPERTY_MAX_COUNT )
3075 CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
3077 DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "index is invalid" );
3079 property = dynamic_cast<const PropertyBase*>( entry->second.GetSceneGraphProperty() );
3081 else if( NULL != mNode )
3085 case Dali::Actor::SIZE:
3086 property = &mNode->mSize;
3089 case Dali::Actor::SIZE_WIDTH:
3090 property = &mNode->mSize;
3093 case Dali::Actor::SIZE_HEIGHT:
3094 property = &mNode->mSize;
3097 case Dali::Actor::SIZE_DEPTH:
3098 property = &mNode->mSize;
3101 case Dali::Actor::POSITION:
3102 property = &mNode->mPosition;
3105 case Dali::Actor::POSITION_X:
3106 property = &mNode->mPosition;
3109 case Dali::Actor::POSITION_Y:
3110 property = &mNode->mPosition;
3113 case Dali::Actor::POSITION_Z:
3114 property = &mNode->mPosition;
3117 case Dali::Actor::ROTATION:
3118 property = &mNode->mRotation;
3121 case Dali::Actor::SCALE:
3122 property = &mNode->mScale;
3125 case Dali::Actor::SCALE_X:
3126 property = &mNode->mScale;
3129 case Dali::Actor::SCALE_Y:
3130 property = &mNode->mScale;
3133 case Dali::Actor::SCALE_Z:
3134 property = &mNode->mScale;
3137 case Dali::Actor::VISIBLE:
3138 property = &mNode->mVisible;
3141 case Dali::Actor::COLOR:
3142 property = &mNode->mColor;
3145 case Dali::Actor::COLOR_RED:
3146 property = &mNode->mColor;
3149 case Dali::Actor::COLOR_GREEN:
3150 property = &mNode->mColor;
3153 case Dali::Actor::COLOR_BLUE:
3154 property = &mNode->mColor;
3157 case Dali::Actor::COLOR_ALPHA:
3158 property = &mNode->mColor;
3169 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3171 const PropertyInputImpl* property( NULL );
3173 // This method should only return a property of an object connected to the scene-graph
3179 if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3181 CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
3183 DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "property index is invalid" );
3185 property = entry->second.GetSceneGraphProperty();
3187 else if( NULL != mNode )
3191 case Dali::Actor::PARENT_ORIGIN:
3192 property = &mNode->mParentOrigin;
3195 case Dali::Actor::PARENT_ORIGIN_X:
3196 property = &mNode->mParentOrigin;
3199 case Dali::Actor::PARENT_ORIGIN_Y:
3200 property = &mNode->mParentOrigin;
3203 case Dali::Actor::PARENT_ORIGIN_Z:
3204 property = &mNode->mParentOrigin;
3207 case Dali::Actor::ANCHOR_POINT:
3208 property = &mNode->mAnchorPoint;
3211 case Dali::Actor::ANCHOR_POINT_X:
3212 property = &mNode->mAnchorPoint;
3215 case Dali::Actor::ANCHOR_POINT_Y:
3216 property = &mNode->mAnchorPoint;
3219 case Dali::Actor::ANCHOR_POINT_Z:
3220 property = &mNode->mAnchorPoint;
3223 case Dali::Actor::SIZE:
3224 property = &mNode->mSize;
3227 case Dali::Actor::SIZE_WIDTH:
3228 property = &mNode->mSize;
3231 case Dali::Actor::SIZE_HEIGHT:
3232 property = &mNode->mSize;
3235 case Dali::Actor::SIZE_DEPTH:
3236 property = &mNode->mSize;
3239 case Dali::Actor::POSITION:
3240 property = &mNode->mPosition;
3243 case Dali::Actor::POSITION_X:
3244 property = &mNode->mPosition;
3247 case Dali::Actor::POSITION_Y:
3248 property = &mNode->mPosition;
3251 case Dali::Actor::POSITION_Z:
3252 property = &mNode->mPosition;
3255 case Dali::Actor::WORLD_POSITION:
3256 property = &mNode->mWorldPosition;
3259 case Dali::Actor::WORLD_POSITION_X:
3260 property = &mNode->mWorldPosition;
3263 case Dali::Actor::WORLD_POSITION_Y:
3264 property = &mNode->mWorldPosition;
3267 case Dali::Actor::WORLD_POSITION_Z:
3268 property = &mNode->mWorldPosition;
3271 case Dali::Actor::ROTATION:
3272 property = &mNode->mRotation;
3275 case Dali::Actor::WORLD_ROTATION:
3276 property = &mNode->mWorldRotation;
3279 case Dali::Actor::SCALE:
3280 property = &mNode->mScale;
3283 case Dali::Actor::SCALE_X:
3284 property = &mNode->mScale;
3287 case Dali::Actor::SCALE_Y:
3288 property = &mNode->mScale;
3291 case Dali::Actor::SCALE_Z:
3292 property = &mNode->mScale;
3295 case Dali::Actor::WORLD_SCALE:
3296 property = &mNode->mWorldScale;
3299 case Dali::Actor::VISIBLE:
3300 property = &mNode->mVisible;
3303 case Dali::Actor::COLOR:
3304 property = &mNode->mColor;
3307 case Dali::Actor::COLOR_RED:
3308 property = &mNode->mColor;
3311 case Dali::Actor::COLOR_GREEN:
3312 property = &mNode->mColor;
3315 case Dali::Actor::COLOR_BLUE:
3316 property = &mNode->mColor;
3319 case Dali::Actor::COLOR_ALPHA:
3320 property = &mNode->mColor;
3323 case Dali::Actor::WORLD_COLOR:
3324 property = &mNode->mWorldColor;
3327 case Dali::Actor::WORLD_MATRIX:
3328 property = &mNode->mWorldMatrix;
3339 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3341 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3345 case Dali::Actor::PARENT_ORIGIN_X:
3346 case Dali::Actor::ANCHOR_POINT_X:
3347 case Dali::Actor::SIZE_WIDTH:
3348 case Dali::Actor::POSITION_X:
3349 case Dali::Actor::SCALE_X:
3350 case Dali::Actor::COLOR_RED:
3351 case Dali::Actor::WORLD_POSITION_X:
3357 case Dali::Actor::PARENT_ORIGIN_Y:
3358 case Dali::Actor::ANCHOR_POINT_Y:
3359 case Dali::Actor::SIZE_HEIGHT:
3360 case Dali::Actor::POSITION_Y:
3361 case Dali::Actor::SCALE_Y:
3362 case Dali::Actor::COLOR_GREEN:
3363 case Dali::Actor::WORLD_POSITION_Y:
3369 case Dali::Actor::PARENT_ORIGIN_Z:
3370 case Dali::Actor::ANCHOR_POINT_Z:
3371 case Dali::Actor::SIZE_DEPTH:
3372 case Dali::Actor::POSITION_Z:
3373 case Dali::Actor::SCALE_Z:
3374 case Dali::Actor::COLOR_BLUE:
3375 case Dali::Actor::WORLD_POSITION_Z:
3381 case Dali::Actor::COLOR_ALPHA:
3394 return componentIndex;
3397 void Actor::SetParent(Actor* parent, int index)
3401 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3405 if ( Stage::IsInstalled() && // Don't emit signals or send messages during Core destruction
3408 StagePtr stage = parent->mStage;
3410 // Instruct each actor to create a corresponding node in the scene graph
3411 ConnectToStage(*stage, index);
3414 else // parent being set to NULL
3416 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3420 if ( Stage::IsInstalled() && // Don't emit signals or send messages during Core destruction
3423 DALI_ASSERT_ALWAYS(mNode != NULL);
3427 // Disconnect the Node & its children from the scene-graph.
3428 DisconnectNodeMessage( mStage->GetUpdateManager(), *mNode );
3431 // Instruct each actor to discard pointers to the scene-graph
3432 DisconnectFromStage();
3437 SceneGraph::Node* Actor::CreateNode() const
3442 bool Actor::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
3445 Actor* actor = dynamic_cast<Actor*>(object);
3449 if(Dali::Actor::ACTION_SHOW == actionName)
3451 actor->SetVisible(true);
3454 else if(Dali::Actor::ACTION_HIDE == actionName)
3456 actor->SetVisible(false);
3464 } // namespace Internal