Dali 3D User Interface Engine
actor-impl.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 // CLASS HEADER
20 
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <algorithm>
24 #include <cfloat>
25 
26 // INTERNAL INCLUDES
27 
35 
55 
59 
60 namespace Dali
61 {
62 namespace ResizePolicy
63 {
64 
65 namespace
66 {
77 
78 } // unnamed namespace
79 } // ResizePolicy
80 
81 namespace SizeScalePolicy
82 {
83 namespace
84 {
85 // Enumeration to / from string conversion tables
91 } // unnamed namespace
92 } // SizeScalePolicy
93 
94 namespace Internal
95 {
96 
97 unsigned int Actor::mActorCounter = 0;
98 
99 namespace
100 {
103 {
104  return Vector3::ONE;
105 }
106 
109 {
110  return Vector2::ZERO;
111 }
112 
115 {
116  return Vector2::ZERO;
117 }
118 
120 
121 } // unnamed namespace
122 
127 {
130  {
131  // Set size negotiation defaults
132  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
133  {
135  negotiatedDimensions[ i ] = 0.0f;
136  dimensionNegotiated[ i ] = false;
137  dimensionDirty[ i ] = false;
140  minimumSize[ i ] = 0.0f;
141  maximumSize[ i ] = FLT_MAX;
142  }
143  }
144 
146 
148 
150 
152 
155 
158 
160 
162 
164 
165  bool relayoutEnabled :1;
166  bool insideRelayout :1;
167 };
168 
169 namespace // unnamed namespace
170 {
171 
172 // Properties
173 
180 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
181 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
182 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
183 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
184 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
185 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
186 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
187 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
188 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
189 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
190 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
191 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
192 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
193 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
194 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
195 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
196 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
197 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
198 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
199 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
200 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
201 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
202 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
203 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
204 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
205 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
206 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
207 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
208 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
209 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
210 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
211 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
212 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
213 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
214 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
215 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
216 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
217 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
218 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
219 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
220 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
221 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
222 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
223 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
224 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
225 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
226 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
227 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
228 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
229 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
230 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
231 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
233 
234 // Signals
235 
236 const char* const SIGNAL_TOUCHED = "touched";
237 const char* const SIGNAL_HOVERED = "hovered";
238 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
239 const char* const SIGNAL_ON_STAGE = "onStage";
240 const char* const SIGNAL_OFF_STAGE = "offStage";
241 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
242 
243 // Actions
244 
245 const char* const ACTION_SHOW = "show";
246 const char* const ACTION_HIDE = "hide";
247 
249 {
250  return Dali::Actor::New();
251 }
252 
254 
261 
264 
272 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
273 {
274  switch( dimension )
275  {
276  case Dimension::WIDTH:
277  {
278  return values.width;
279  }
280  case Dimension::HEIGHT:
281  {
282  return values.height;
283  }
284  default:
285  {
286  break;
287  }
288  }
289  return 0.0f;
290 }
291 
299 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
300 {
301  return GetDimensionValue( values.GetVectorXY(), dimension );
302 }
303 
304 
305 } // unnamed namespace
306 
308 {
309  ActorPtr actor( new Actor( BASIC ) );
310 
311  // Second-phase construction
312  actor->Initialize();
313 
314  return actor;
315 }
316 
317 const std::string& Actor::GetName() const
318 {
319  return mName;
320 }
321 
322 void Actor::SetName( const std::string& name )
323 {
324  mName = name;
325 
326  if( NULL != mNode )
327  {
328  // ATTENTION: string for debug purposes is not thread safe.
329  DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
330  }
331 }
332 
333 unsigned int Actor::GetId() const
334 {
335  return mId;
336 }
337 
338 void Actor::Attach( ActorAttachment& attachment )
339 {
340  DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
341 
342  if( OnStage() )
343  {
344  attachment.Connect();
345  }
346 
347  mAttachment = ActorAttachmentPtr( &attachment );
348 }
349 
351 {
352  return mAttachment;
353 }
354 
355 bool Actor::OnStage() const
356 {
357  return mIsOnStage;
358 }
359 
361 {
362  Dali::Layer layer;
363 
364  // Short-circuit for Layer derived actors
365  if( mIsLayer )
366  {
367  layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
368  }
369 
370  // Find the immediate Layer parent
371  for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
372  {
373  if( parent->IsLayer() )
374  {
375  layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
376  }
377  }
378 
379  return layer;
380 }
381 
382 void Actor::Add( Actor& child )
383 {
384  DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
385  DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
386 
387  if( !mChildren )
388  {
390  }
391 
392  Actor* const oldParent( child.mParent );
393 
394  // child might already be ours
395  if( this != oldParent )
396  {
397  // if we already have parent, unparent us first
398  if( oldParent )
399  {
400  oldParent->Remove( child ); // This causes OnChildRemove callback
401 
402  // Old parent may need to readjust to missing child
403  if( oldParent->RelayoutDependentOnChildren() )
404  {
405  oldParent->RelayoutRequest();
406  }
407  }
408 
409  // Guard against Add() during previous OnChildRemove callback
410  if( !child.mParent )
411  {
412  // Do this first, since user callbacks from within SetParent() may need to remove child
413  mChildren->push_back( ActorPtr( &child ) );
414 
415  // SetParent asserts that child can be added
416  child.SetParent( this );
417 
418  // Notification for derived classes
419  OnChildAdd( child );
420 
421  // Only put in a relayout request if there is a suitable dependency
423  {
424  RelayoutRequest();
425  }
426  }
427  }
428 }
429 
430 void Actor::Remove( Actor& child )
431 {
432  if( (this == &child) || (!mChildren) )
433  {
434  // no children or removing itself
435  return;
436  }
437 
438  ActorPtr removed;
439 
440  // Find the child in mChildren, and unparent it
441  ActorIter end = mChildren->end();
442  for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
443  {
444  ActorPtr actor = (*iter);
445 
446  if( actor.Get() == &child )
447  {
448  // Keep handle for OnChildRemove notification
449  removed = actor;
450 
451  // Do this first, since user callbacks from within SetParent() may need to add the child
452  mChildren->erase( iter );
453 
454  DALI_ASSERT_DEBUG( actor->GetParent() == this );
455  actor->SetParent( NULL );
456 
457  break;
458  }
459  }
460 
461  if( removed )
462  {
463  // Notification for derived classes
464  OnChildRemove( *(removed.Get()) );
465 
466  // Only put in a relayout request if there is a suitable dependency
468  {
469  RelayoutRequest();
470  }
471  }
472 }
473 
475 {
476  if( mParent )
477  {
478  // Remove this actor from the parent. The remove will put a relayout request in for
479  // the parent if required
480  mParent->Remove( *this );
481  // mParent is now NULL!
482  }
483 }
484 
485 unsigned int Actor::GetChildCount() const
486 {
487  return ( NULL != mChildren ) ? mChildren->size() : 0;
488 }
489 
490 ActorPtr Actor::GetChildAt( unsigned int index ) const
491 {
492  DALI_ASSERT_ALWAYS( index < GetChildCount() );
493 
494  return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
495 }
496 
497 ActorPtr Actor::FindChildByName( const std::string& actorName )
498 {
499  ActorPtr child = 0;
500  if( actorName == mName )
501  {
502  child = this;
503  }
504  else if( mChildren )
505  {
506  ActorIter end = mChildren->end();
507  for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
508  {
509  child = (*iter)->FindChildByName( actorName );
510 
511  if( child )
512  {
513  break;
514  }
515  }
516  }
517  return child;
518 }
519 
520 ActorPtr Actor::FindChildById( const unsigned int id )
521 {
522  ActorPtr child = 0;
523  if( id == mId )
524  {
525  child = this;
526  }
527  else if( mChildren )
528  {
529  ActorIter end = mChildren->end();
530  for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
531  {
532  child = (*iter)->FindChildById( id );
533 
534  if( child )
535  {
536  break;
537  }
538  }
539  }
540  return child;
541 }
542 
543 void Actor::SetParentOrigin( const Vector3& origin )
544 {
545  if( NULL != mNode )
546  {
547  // mNode is being used in a separate thread; queue a message to set the value & base value
549  }
550 
551  // Cache for event-thread access
552  if( !mParentOrigin )
553  {
554  // not allocated, check if different from default
555  if( ParentOrigin::DEFAULT != origin )
556  {
557  mParentOrigin = new Vector3( origin );
558  }
559  }
560  else
561  {
562  // check if different from current costs more than just set
563  *mParentOrigin = origin;
564  }
565 }
566 
567 void Actor::SetParentOriginX( float x )
568 {
569  const Vector3& current = GetCurrentParentOrigin();
570 
571  SetParentOrigin( Vector3( x, current.y, current.z ) );
572 }
573 
574 void Actor::SetParentOriginY( float y )
575 {
576  const Vector3& current = GetCurrentParentOrigin();
577 
578  SetParentOrigin( Vector3( current.x, y, current.z ) );
579 }
580 
581 void Actor::SetParentOriginZ( float z )
582 {
583  const Vector3& current = GetCurrentParentOrigin();
584 
585  SetParentOrigin( Vector3( current.x, current.y, z ) );
586 }
587 
589 {
590  // Cached for event-thread access
592 }
593 
594 void Actor::SetAnchorPoint( const Vector3& anchor )
595 {
596  if( NULL != mNode )
597  {
598  // mNode is being used in a separate thread; queue a message to set the value & base value
600  }
601 
602  // Cache for event-thread access
603  if( !mAnchorPoint )
604  {
605  // not allocated, check if different from default
606  if( AnchorPoint::DEFAULT != anchor )
607  {
608  mAnchorPoint = new Vector3( anchor );
609  }
610  }
611  else
612  {
613  // check if different from current costs more than just set
614  *mAnchorPoint = anchor;
615  }
616 }
617 
618 void Actor::SetAnchorPointX( float x )
619 {
620  const Vector3& current = GetCurrentAnchorPoint();
621 
622  SetAnchorPoint( Vector3( x, current.y, current.z ) );
623 }
624 
625 void Actor::SetAnchorPointY( float y )
626 {
627  const Vector3& current = GetCurrentAnchorPoint();
628 
629  SetAnchorPoint( Vector3( current.x, y, current.z ) );
630 }
631 
632 void Actor::SetAnchorPointZ( float z )
633 {
634  const Vector3& current = GetCurrentAnchorPoint();
635 
636  SetAnchorPoint( Vector3( current.x, current.y, z ) );
637 }
638 
640 {
641  // Cached for event-thread access
643 }
644 
645 void Actor::SetPosition( float x, float y )
646 {
647  SetPosition( Vector3( x, y, 0.0f ) );
648 }
649 
650 void Actor::SetPosition( float x, float y, float z )
651 {
652  SetPosition( Vector3( x, y, z ) );
653 }
654 
655 void Actor::SetPosition( const Vector3& position )
656 {
657  mTargetPosition = position;
658 
659  if( NULL != mNode )
660  {
661  // mNode is being used in a separate thread; queue a message to set the value & base value
663  }
664 }
665 
666 void Actor::SetX( float x )
667 {
668  mTargetPosition.x = x;
669 
670  if( NULL != mNode )
671  {
672  // mNode is being used in a separate thread; queue a message to set the value & base value
674  }
675 }
676 
677 void Actor::SetY( float y )
678 {
679  mTargetPosition.y = y;
680 
681  if( NULL != mNode )
682  {
683  // mNode is being used in a separate thread; queue a message to set the value & base value
685  }
686 }
687 
688 void Actor::SetZ( float z )
689 {
690  mTargetPosition.z = z;
691 
692  if( NULL != mNode )
693  {
694  // mNode is being used in a separate thread; queue a message to set the value & base value
696  }
697 }
698 
699 void Actor::TranslateBy( const Vector3& distance )
700 {
701  mTargetPosition += distance;
702 
703  if( NULL != mNode )
704  {
705  // mNode is being used in a separate thread; queue a message to set the value & base value
707  }
708 }
709 
711 {
712  if( NULL != mNode )
713  {
714  // mNode is being used in a separate thread; copy the value from the previous update
715  return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
716  }
717 
718  return Vector3::ZERO;
719 }
720 
722 {
723  return mTargetPosition;
724 }
725 
727 {
728  if( NULL != mNode )
729  {
730  // mNode is being used in a separate thread; copy the value from the previous update
731  return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
732  }
733 
734  return Vector3::ZERO;
735 }
736 
738 {
739  // this flag is not animatable so keep the value
741  if( NULL != mNode )
742  {
743  // mNode is being used in a separate thread; queue a message to set the value
745  }
746 }
747 
749 {
750  // Cached for event-thread access
752 }
753 
754 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
755 {
756  Vector3 normalizedAxis( axis.x, axis.y, axis.z );
757  normalizedAxis.Normalize();
758 
759  Quaternion orientation( angle, normalizedAxis );
760 
761  SetOrientation( orientation );
762 }
763 
764 void Actor::SetOrientation( const Quaternion& orientation )
765 {
766  if( NULL != mNode )
767  {
768  // mNode is being used in a separate thread; queue a message to set the value & base value
770  }
771 }
772 
773 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
774 {
775  if( NULL != mNode )
776  {
777  // mNode is being used in a separate thread; queue a message to set the value & base value
779  }
780 }
781 
782 void Actor::RotateBy( const Quaternion& relativeRotation )
783 {
784  if( NULL != mNode )
785  {
786  // mNode is being used in a separate thread; queue a message to set the value & base value
788  }
789 }
790 
792 {
793  if( NULL != mNode )
794  {
795  // mNode is being used in a separate thread; copy the value from the previous update
796  return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
797  }
798 
799  return Quaternion::IDENTITY;
800 }
801 
803 {
804  if( NULL != mNode )
805  {
806  // mNode is being used in a separate thread; copy the value from the previous update
807  return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
808  }
809 
810  return Quaternion::IDENTITY;
811 }
812 
813 void Actor::SetScale( float scale )
814 {
815  SetScale( Vector3( scale, scale, scale ) );
816 }
817 
818 void Actor::SetScale( float x, float y, float z )
819 {
820  SetScale( Vector3( x, y, z ) );
821 }
822 
823 void Actor::SetScale( const Vector3& scale )
824 {
825  if( NULL != mNode )
826  {
827  // mNode is being used in a separate thread; queue a message to set the value & base value
829  }
830 }
831 
832 void Actor::SetScaleX( float x )
833 {
834  if( NULL != mNode )
835  {
836  // mNode is being used in a separate thread; queue a message to set the value & base value
838  }
839 }
840 
841 void Actor::SetScaleY( float y )
842 {
843  if( NULL != mNode )
844  {
845  // mNode is being used in a separate thread; queue a message to set the value & base value
847  }
848 }
849 
850 void Actor::SetScaleZ( float z )
851 {
852  if( NULL != mNode )
853  {
854  // mNode is being used in a separate thread; queue a message to set the value & base value
856  }
857 }
858 
859 void Actor::ScaleBy(const Vector3& relativeScale)
860 {
861  if( NULL != mNode )
862  {
863  // mNode is being used in a separate thread; queue a message to set the value & base value
865  }
866 }
867 
869 {
870  if( NULL != mNode )
871  {
872  // mNode is being used in a separate thread; copy the value from the previous update
873  return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
874  }
875 
876  return Vector3::ONE;
877 }
878 
880 {
881  if( NULL != mNode )
882  {
883  // mNode is being used in a separate thread; copy the value from the previous update
884  return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
885  }
886 
887  return Vector3::ONE;
888 }
889 
890 void Actor::SetInheritScale( bool inherit )
891 {
892  // non animateable so keep local copy
893  mInheritScale = inherit;
894  if( NULL != mNode )
895  {
896  // mNode is being used in a separate thread; queue a message to set the value
898  }
899 }
900 
902 {
903  return mInheritScale;
904 }
905 
907 {
908  if( NULL != mNode )
909  {
910  // World matrix is no longer updated unless there is something observing the node.
911  // Need to calculate it from node's world position, orientation and scale:
913  Matrix worldMatrix(false);
914  worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
915  mNode->GetWorldOrientation( updateBufferIndex ),
916  mNode->GetWorldPosition( updateBufferIndex ) );
917  return worldMatrix;
918  }
919 
920  return Matrix::IDENTITY;
921 }
922 
923 void Actor::SetVisible( bool visible )
924 {
925  if( NULL != mNode )
926  {
927  // mNode is being used in a separate thread; queue a message to set the value & base value
929  }
930 }
931 
932 bool Actor::IsVisible() const
933 {
934  if( NULL != mNode )
935  {
936  // mNode is being used in a separate thread; copy the value from the previous update
937  return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
938  }
939 
940  return true;
941 }
942 
943 void Actor::SetOpacity( float opacity )
944 {
945  if( NULL != mNode )
946  {
947  // mNode is being used in a separate thread; queue a message to set the value & base value
949  }
950 }
951 
953 {
954  if( NULL != mNode )
955  {
956  // mNode is being used in a separate thread; copy the value from the previous update
957  return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
958  }
959 
960  return 1.0f;
961 }
962 
964 {
965  if( NULL != mNode )
966  {
967  return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
968  }
969 
970  return Color::WHITE;
971 }
972 
973 void Actor::SetColor( const Vector4& color )
974 {
975  if( NULL != mNode )
976  {
977  // mNode is being used in a separate thread; queue a message to set the value & base value
979  }
980 }
981 
982 void Actor::SetColorRed( float red )
983 {
984  if( NULL != mNode )
985  {
986  // mNode is being used in a separate thread; queue a message to set the value & base value
988  }
989 }
990 
991 void Actor::SetColorGreen( float green )
992 {
993  if( NULL != mNode )
994  {
995  // mNode is being used in a separate thread; queue a message to set the value & base value
997  }
998 }
999 
1000 void Actor::SetColorBlue( float blue )
1001 {
1002  if( NULL != mNode )
1003  {
1004  // mNode is being used in a separate thread; queue a message to set the value & base value
1006  }
1007 }
1008 
1010 {
1011  if( NULL != mNode )
1012  {
1013  // mNode is being used in a separate thread; copy the value from the previous update
1014  return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1015  }
1016 
1017  return Color::WHITE;
1018 }
1019 
1020 void Actor::SetInheritOrientation( bool inherit )
1021 {
1022  // non animateable so keep local copy
1023  mInheritOrientation = inherit;
1024  if( NULL != mNode )
1025  {
1026  // mNode is being used in a separate thread; queue a message to set the value
1028  }
1029 }
1030 
1032 {
1033  return mInheritOrientation;
1034 }
1035 
1036 void Actor::SetSizeModeFactor( const Vector3& factor )
1037 {
1039 
1040  mRelayoutData->sizeModeFactor = factor;
1041 }
1042 
1044 {
1045  if ( mRelayoutData )
1046  {
1047  return mRelayoutData->sizeModeFactor;
1048  }
1049 
1050  return GetDefaultSizeModeFactor();
1051 }
1052 
1054 {
1055  // non animateable so keep local copy
1056  mColorMode = colorMode;
1057  if( NULL != mNode )
1058  {
1059  // mNode is being used in a separate thread; queue a message to set the value
1061  }
1062 }
1063 
1065 {
1066  // we have cached copy
1067  return mColorMode;
1068 }
1069 
1070 void Actor::SetSize( float width, float height )
1071 {
1072  SetSize( Vector2( width, height ) );
1073 }
1074 
1075 void Actor::SetSize( float width, float height, float depth )
1076 {
1077  SetSize( Vector3( width, height, depth ) );
1078 }
1079 
1080 void Actor::SetSize( const Vector2& size )
1081 {
1082  SetSize( Vector3( size.width, size.height, 0.f ) );
1083 }
1084 
1085 void Actor::SetSizeInternal( const Vector2& size )
1086 {
1087  SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1088 }
1089 
1090 void Actor::SetSize( const Vector3& size )
1091 {
1093  {
1094  // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1095  SetPreferredSize( size.GetVectorXY() );
1096  }
1097  else
1098  {
1099  SetSizeInternal( size );
1100  }
1101 }
1102 
1103 void Actor::SetSizeInternal( const Vector3& size )
1104 {
1105  // dont allow recursive loop
1106  DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1107  // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
1108  if( ( NULL != mNode )&&
1109  ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1110  ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1111  ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1112  {
1113  mTargetSize = size;
1114 
1115  // mNode is being used in a separate thread; queue a message to set the value & base value
1117 
1118  // Notification for derived classes
1119  mInsideOnSizeSet = true;
1121  mInsideOnSizeSet = false;
1122 
1123  // Raise a relayout request if the flag is not locked
1125  {
1126  RelayoutRequest();
1127  }
1128  }
1129 }
1130 
1131 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1132 {
1133  mTargetSize = targetSize;
1134 
1135  // Notify deriving classes
1136  OnSizeAnimation( animation, mTargetSize );
1137 }
1138 
1139 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1140 {
1141  if ( Dali::Actor::Property::SIZE_WIDTH == property )
1142  {
1143  mTargetSize.width = targetSize;
1144  }
1145  else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1146  {
1147  mTargetSize.height = targetSize;
1148  }
1149  else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1150  {
1151  mTargetSize.depth = targetSize;
1152  }
1153  // Notify deriving classes
1154  OnSizeAnimation( animation, mTargetSize );
1155 }
1156 
1157 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1158 {
1159  mTargetPosition = targetPosition;
1160 }
1161 
1162 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1163 {
1164  if ( Dali::Actor::Property::POSITION_X == property )
1165  {
1166  mTargetPosition.x = targetPosition;
1167  }
1168  else if ( Dali::Actor::Property::POSITION_Y == property )
1169  {
1170  mTargetPosition.y = targetPosition;
1171  }
1172  else if ( Dali::Actor::Property::POSITION_Z == property )
1173  {
1174  mTargetPosition.z = targetPosition;
1175  }
1176 }
1177 
1178 void Actor::SetWidth( float width )
1179 {
1181 
1182  if( NULL != mNode )
1183  {
1184  // mNode is being used in a separate thread; queue a message to set the value & base value
1186  }
1187 }
1188 
1190 {
1192 
1193  if( NULL != mNode )
1194  {
1195  // mNode is being used in a separate thread; queue a message to set the value & base value
1197  }
1198 }
1199 
1200 void Actor::SetDepth( float depth )
1201 {
1202  mTargetSize.depth = depth;
1203 
1204  if( NULL != mNode )
1205  {
1206  // mNode is being used in a separate thread; queue a message to set the value & base value
1208  }
1209 }
1210 
1212 {
1213  return mTargetSize;
1214 }
1215 
1217 {
1218  if( NULL != mNode )
1219  {
1220  // mNode is being used in a separate thread; copy the value from the previous update
1221  return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1222  }
1223 
1224  return Vector3::ZERO;
1225 }
1226 
1228 {
1229  // It is up to deriving classes to return the appropriate natural size
1230  return Vector3( 0.0f, 0.0f, 0.0f );
1231 }
1232 
1234 {
1236 
1237  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1238  {
1239  if( dimension & ( 1 << i ) )
1240  {
1241  mRelayoutData->resizePolicies[ i ] = policy;
1242  }
1243  }
1244 
1245  if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1246  {
1247  if( dimension & Dimension::WIDTH )
1248  {
1249  SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1250  }
1251 
1252  if( dimension & Dimension::HEIGHT )
1253  {
1254  SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1255  }
1256  }
1257 
1258  // If calling SetResizePolicy, assume we want relayout enabled
1259  SetRelayoutEnabled( true );
1260 
1261  OnSetResizePolicy( policy, dimension );
1262 
1263  // Trigger relayout on this control
1264  RelayoutRequest();
1265 }
1266 
1268 {
1269  if ( mRelayoutData )
1270  {
1271  // If more than one dimension is requested, just return the first one found
1272  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1273  {
1274  if( ( dimension & ( 1 << i ) ) )
1275  {
1276  return mRelayoutData->resizePolicies[ i ];
1277  }
1278  }
1279  }
1280 
1281  return ResizePolicy::DEFAULT;
1282 }
1283 
1285 {
1287 
1288  mRelayoutData->sizeSetPolicy = policy;
1289 }
1290 
1292 {
1293  if ( mRelayoutData )
1294  {
1295  return mRelayoutData->sizeSetPolicy;
1296  }
1297 
1299 }
1300 
1302 {
1304 
1305  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1306  {
1307  if( dimension & ( 1 << i ) )
1308  {
1309  mRelayoutData->dimensionDependencies[ i ] = dependency;
1310  }
1311  }
1312 }
1313 
1315 {
1316  if ( mRelayoutData )
1317  {
1318  // If more than one dimension is requested, just return the first one found
1319  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1320  {
1321  if( ( dimension & ( 1 << i ) ) )
1322  {
1323  return mRelayoutData->dimensionDependencies[ i ];
1324  }
1325  }
1326  }
1327 
1328  return Dimension::ALL_DIMENSIONS; // Default
1329 }
1330 
1331 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1332 {
1333  // If relayout data has not been allocated yet and the client is requesting
1334  // to disable it, do nothing
1335  if( mRelayoutData || relayoutEnabled )
1336  {
1338 
1339  mRelayoutData->relayoutEnabled = relayoutEnabled;
1340  }
1341 }
1342 
1344 {
1345  // Assume that if relayout data has not been allocated yet then
1346  // relayout is disabled
1348 }
1349 
1350 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1351 {
1353 
1354  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1355  {
1356  if( dimension & ( 1 << i ) )
1357  {
1358  mRelayoutData->dimensionDirty[ i ] = dirty;
1359  }
1360  }
1361 }
1362 
1363 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1364 {
1365  if ( mRelayoutData )
1366  {
1367  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1368  {
1369  if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1370  {
1371  return true;
1372  }
1373  }
1374  }
1375 
1376  return false;
1377 }
1378 
1380 {
1381  return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1382 }
1383 
1385 {
1386  return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1387 }
1388 
1389 unsigned int Actor::AddRenderer( Renderer& renderer )
1390 {
1391  if( !mRenderers )
1392  {
1394  }
1395 
1396  unsigned int index = mRenderers->size();
1397  RendererPtr rendererPtr = RendererPtr( &renderer );
1398  mRenderers->push_back( rendererPtr );
1400 
1401  if( mIsOnStage)
1402  {
1403  rendererPtr->Connect();
1404  }
1405 
1406  return index;
1407 }
1408 
1409 unsigned int Actor::GetRendererCount() const
1410 {
1411  unsigned int rendererCount(0);
1412  if( mRenderers )
1413  {
1414  rendererCount = mRenderers->size();
1415  }
1416 
1417  return rendererCount;
1418 }
1419 
1420 RendererPtr Actor::GetRendererAt( unsigned int index )
1421 {
1422  RendererPtr renderer;
1423  if( index < GetRendererCount() )
1424  {
1425  renderer = ( *mRenderers )[ index ];
1426  }
1427 
1428  return renderer;
1429 }
1430 
1432 {
1433  if( mRenderers )
1434  {
1435  RendererIter end = mRenderers->end();
1436  for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1437  {
1438  if( (*iter).Get() == &renderer )
1439  {
1440  mRenderers->erase( iter );
1442  break;
1443  }
1444  }
1445  }
1446 }
1447 
1448 void Actor::RemoveRenderer( unsigned int index )
1449 {
1450  if( index < GetRendererCount() )
1451  {
1452  RendererPtr renderer = ( *mRenderers )[ index ];
1453  RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1454  mRenderers->erase( mRenderers->begin()+index );
1455  }
1456 }
1457 
1458 void Actor::SetOverlay( bool enable )
1459 {
1460  // Setting STENCIL will override OVERLAY_2D
1461  if( DrawMode::STENCIL != mDrawMode )
1462  {
1464  }
1465 }
1466 
1467 bool Actor::IsOverlay() const
1468 {
1469  return ( DrawMode::OVERLAY_2D == mDrawMode );
1470 }
1471 
1473 {
1474  // this flag is not animatable so keep the value
1475  mDrawMode = drawMode;
1476  if( NULL != mNode )
1477  {
1478  // mNode is being used in a separate thread; queue a message to set the value
1480  }
1481 }
1482 
1484 {
1485  return mDrawMode;
1486 }
1487 
1488 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1489 {
1490  // only valid when on-stage
1491  StagePtr stage = Stage::GetCurrent();
1492  if( stage && OnStage() )
1493  {
1494  const RenderTaskList& taskList = stage->GetRenderTaskList();
1495 
1496  Vector2 converted( screenX, screenY );
1497 
1498  // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1499  const int taskCount = taskList.GetTaskCount();
1500  for( int i = taskCount - 1; i >= 0; --i )
1501  {
1502  Dali::RenderTask task = taskList.GetTask( i );
1503  if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1504  {
1505  // found a task where this conversion was ok so return
1506  return true;
1507  }
1508  }
1509  }
1510  return false;
1511 }
1512 
1513 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1514 {
1515  bool retval = false;
1516  // only valid when on-stage
1517  if( OnStage() )
1518  {
1519  CameraActor* camera = renderTask.GetCameraActor();
1520  if( camera )
1521  {
1522  Viewport viewport;
1523  renderTask.GetViewport( viewport );
1524 
1525  // need to translate coordinates to render tasks coordinate space
1526  Vector2 converted( screenX, screenY );
1527  if( renderTask.TranslateCoordinates( converted ) )
1528  {
1529  retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1530  }
1531  }
1532  }
1533  return retval;
1534 }
1535 
1536 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1537 {
1538  // Early-out if mNode is NULL
1539  if( !OnStage() )
1540  {
1541  return false;
1542  }
1543 
1544  BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1545 
1546  // Calculate the ModelView matrix
1547  Matrix modelView( false/*don't init*/);
1548  // need to use the components as world matrix is only updated for actors that need it
1549  modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1550  Matrix::Multiply( modelView, modelView, viewMatrix );
1551 
1552  // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1553  Matrix invertedMvp( false/*don't init*/);
1554  Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1555  bool success = invertedMvp.Invert();
1556 
1557  // Convert to GL coordinates
1558  Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1559 
1560  Vector4 nearPos;
1561  if( success )
1562  {
1563  success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1564  }
1565 
1566  Vector4 farPos;
1567  if( success )
1568  {
1569  screenPos.z = 1.0f;
1570  success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1571  }
1572 
1573  if( success )
1574  {
1575  Vector4 local;
1576  if( XyPlaneIntersect( nearPos, farPos, local ) )
1577  {
1578  Vector3 size = GetCurrentSize();
1579  localX = local.x + size.x * 0.5f;
1580  localY = local.y + size.y * 0.5f;
1581  }
1582  else
1583  {
1584  success = false;
1585  }
1586  }
1587 
1588  return success;
1589 }
1590 
1591 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1592 {
1593  /*
1594  http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1595 
1596  Mathematical Formulation
1597 
1598  Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1599 
1600  ( p - c ) dot ( p - c ) = r^2
1601 
1602  Given a ray with a point of origin 'o', and a direction vector 'd':
1603 
1604  ray(t) = o + td, t >= 0
1605 
1606  we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1607 
1608  (o + td - c ) dot ( o + td - c ) = r^2
1609 
1610  To solve for t we first expand the above into a more recognisable quadratic equation form
1611 
1612  ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1613 
1614  or
1615 
1616  At2 + Bt + C = 0
1617 
1618  where
1619 
1620  A = d dot d
1621  B = 2( o - c ) dot d
1622  C = ( o - c ) dot ( o - c ) - r^2
1623 
1624  which can be solved using a standard quadratic formula.
1625 
1626  Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1627 
1628  Practical Simplification
1629 
1630  In a renderer, we often differentiate between world space and object space. In the object space
1631  of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1632  into object space, the mathematical solution presented above can be simplified significantly.
1633 
1634  If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1635 
1636  p dot p = r^2
1637 
1638  and we can find the t at which the (transformed) ray intersects the sphere by
1639 
1640  ( o + td ) dot ( o + td ) = r^2
1641 
1642  According to the reasoning above, we expand the above quadratic equation into the general form
1643 
1644  At2 + Bt + C = 0
1645 
1646  which now has coefficients:
1647 
1648  A = d dot d
1649  B = 2( d dot o )
1650  C = o dot o - r^2
1651  */
1652 
1653  // Early out if mNode is NULL
1654  if( !mNode )
1655  {
1656  return false;
1657  }
1658 
1659  BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1660 
1661  // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1662  const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1663  Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1664 
1665  // Compute the radius is not needed, square radius it's enough.
1666  const Vector3& size( mNode->GetSize( bufferIndex ) );
1667 
1668  // Scale the sphere.
1669  const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1670 
1671  const float width = size.width * scale.width;
1672  const float height = size.height * scale.height;
1673 
1674  float squareSphereRadius = 0.5f * ( width * width + height * height );
1675 
1676  float a = rayDir.Dot( rayDir ); // a
1677  float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1678  float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1679 
1680  return ( b2 * b2 - a * c ) >= 0.f;
1681 }
1682 
1683 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1684 {
1685  bool hit = false;
1686 
1687  if( OnStage() &&
1688  NULL != mNode )
1689  {
1690  // Transforms the ray to the local reference system.
1691  // Calculate the inverse of Model matrix
1692  Matrix invModelMatrix( false/*don't init*/);
1693 
1694  BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1695  // need to use the components as world matrix is only updated for actors that need it
1696  invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1697 
1698  Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1699  Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1700 
1701  // Test with the actor's XY plane (Normal = 0 0 1 1).
1702 
1703  float a = -rayOriginLocal.z;
1704  float b = rayDirLocal.z;
1705 
1706  if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1707  {
1708  // Ray travels distance * rayDirLocal to intersect with plane.
1709  distance = a / b;
1710 
1711  const Vector3& size = mNode->GetSize( bufferIndex );
1712 
1713  hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1714  hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1715 
1716  // Test with the actor's geometry.
1717  hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1718  }
1719  }
1720 
1721  return hit;
1722 }
1723 
1724 void Actor::SetLeaveRequired( bool required )
1725 {
1726  mLeaveRequired = required;
1727 }
1728 
1730 {
1731  return mLeaveRequired;
1732 }
1733 
1734 void Actor::SetKeyboardFocusable( bool focusable )
1735 {
1736  mKeyboardFocusable = focusable;
1737 }
1738 
1740 {
1741  return mKeyboardFocusable;
1742 }
1743 
1745 {
1746  return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1747 }
1748 
1750 {
1751  return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1752 }
1753 
1755 {
1756  return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1757 }
1758 
1759 bool Actor::IsHittable() const
1760 {
1762 }
1763 
1765 {
1766  // Likely scenario is that once gesture-data is created for this actor, the actor will require
1767  // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1768  if( NULL == mGestureData )
1769  {
1771  }
1772  return *mGestureData;
1773 }
1774 
1776 {
1777  return mGestureData && mGestureData->IsGestureRequred( type );
1778 }
1779 
1781 {
1782  bool consumed = false;
1783 
1784  if( !mTouchedSignal.Empty() )
1785  {
1786  Dali::Actor handle( this );
1787  consumed = mTouchedSignal.Emit( handle, event );
1788  }
1789 
1790  if( !consumed )
1791  {
1792  // Notification for derived classes
1793  consumed = OnTouchEvent( event );
1794  }
1795 
1796  return consumed;
1797 }
1798 
1800 {
1801  bool consumed = false;
1802 
1803  if( !mHoveredSignal.Empty() )
1804  {
1805  Dali::Actor handle( this );
1806  consumed = mHoveredSignal.Emit( handle, event );
1807  }
1808 
1809  if( !consumed )
1810  {
1811  // Notification for derived classes
1812  consumed = OnHoverEvent( event );
1813  }
1814 
1815  return consumed;
1816 }
1817 
1819 {
1820  bool consumed = false;
1821 
1822  if( !mWheelEventSignal.Empty() )
1823  {
1824  Dali::Actor handle( this );
1825  consumed = mWheelEventSignal.Emit( handle, event );
1826  }
1827 
1828  if( !consumed )
1829  {
1830  // Notification for derived classes
1831  consumed = OnWheelEvent( event );
1832  }
1833 
1834  return consumed;
1835 }
1836 
1838 {
1839  return mTouchedSignal;
1840 }
1841 
1843 {
1844  return mHoveredSignal;
1845 }
1846 
1848 {
1849  return mWheelEventSignal;
1850 }
1851 
1853 {
1854  return mOnStageSignal;
1855 }
1856 
1858 {
1859  return mOffStageSignal;
1860 }
1861 
1863 {
1864  return mOnRelayoutSignal;
1865 }
1866 
1867 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1868 {
1869  bool connected( true );
1870  Actor* actor = dynamic_cast< Actor* >( object );
1871 
1872  if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1873  {
1874  actor->TouchedSignal().Connect( tracker, functor );
1875  }
1876  else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1877  {
1878  actor->HoveredSignal().Connect( tracker, functor );
1879  }
1880  else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1881  {
1882  actor->WheelEventSignal().Connect( tracker, functor );
1883  }
1884  else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1885  {
1886  actor->OnStageSignal().Connect( tracker, functor );
1887  }
1888  else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1889  {
1890  actor->OffStageSignal().Connect( tracker, functor );
1891  }
1892  else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1893  {
1894  actor->OnRelayoutSignal().Connect( tracker, functor );
1895  }
1896  else
1897  {
1898  // signalName does not match any signal
1899  connected = false;
1900  }
1901 
1902  return connected;
1903 }
1904 
1906 : mParent( NULL ),
1907  mChildren( NULL ),
1908  mRenderers( NULL ),
1909  mNode( NULL ),
1910  mParentOrigin( NULL ),
1911  mAnchorPoint( NULL ),
1912  mRelayoutData( NULL ),
1913  mGestureData( NULL ),
1914  mAttachment(),
1915  mTargetSize( 0.0f, 0.0f, 0.0f ),
1916  mName(),
1917  mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1918  mDepth( 0u ),
1919  mIsRoot( ROOT_LAYER == derivedType ),
1920  mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1921  mIsOnStage( false ),
1922  mSensitive( true ),
1923  mLeaveRequired( false ),
1924  mKeyboardFocusable( false ),
1925  mDerivedRequiresTouch( false ),
1926  mDerivedRequiresHover( false ),
1927  mDerivedRequiresWheelEvent( false ),
1928  mOnStageSignalled( false ),
1929  mInsideOnSizeSet( false ),
1930  mInheritOrientation( true ),
1931  mInheritScale( true ),
1932  mDrawMode( DrawMode::NORMAL ),
1933  mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1934  mColorMode( Node::DEFAULT_COLOR_MODE )
1935 {
1936 }
1937 
1939 {
1940  // Node creation
1941  SceneGraph::Node* node = CreateNode();
1942 
1943  AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1944  mNode = node; // Keep raw-pointer to Node
1945 
1946  OnInitialize();
1947 
1949 }
1950 
1952 {
1953  // Remove mParent pointers from children even if we're destroying core,
1954  // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1955  if( mChildren )
1956  {
1957  ActorConstIter endIter = mChildren->end();
1958  for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1959  {
1960  (*iter)->SetParent( NULL );
1961  }
1962  }
1963  delete mChildren;
1964  delete mRenderers;
1965 
1966  // Guard to allow handle destruction after Core has been destroyed
1968  {
1969  if( NULL != mNode )
1970  {
1971  DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1972  mNode = NULL; // Node is about to be destroyed
1973  }
1974 
1976  }
1977 
1978  // Cleanup optional gesture data
1979  delete mGestureData;
1980 
1981  // Cleanup optional parent origin and anchor
1982  delete mParentOrigin;
1983  delete mAnchorPoint;
1984 
1985  // Delete optional relayout data
1986  if( mRelayoutData )
1987  {
1988  delete mRelayoutData;
1989  }
1990 }
1991 
1992 void Actor::ConnectToStage( unsigned int parentDepth )
1993 {
1994  // This container is used instead of walking the Actor hierarchy.
1995  // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1996  ActorContainer connectionList;
1997 
1998  // This stage is atomic i.e. not interrupted by user callbacks.
1999  RecursiveConnectToStage( connectionList, parentDepth + 1 );
2000 
2001  // Notify applications about the newly connected actors.
2002  const ActorIter endIter = connectionList.end();
2003  for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2004  {
2005  (*iter)->NotifyStageConnection();
2006  }
2007 
2008  RelayoutRequest();
2009 }
2010 
2011 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2012 {
2014 
2015  mIsOnStage = true;
2016  mDepth = depth;
2017 
2019 
2020  // Notification for internal derived classes
2022 
2023  // This stage is atomic; avoid emitting callbacks until all Actors are connected
2024  connectionList.push_back( ActorPtr( this ) );
2025 
2026  // Recursively connect children
2027  if( mChildren )
2028  {
2029  ActorConstIter endIter = mChildren->end();
2030  for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2031  {
2032  (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2033  }
2034  }
2035 }
2036 
2044 {
2046 
2047  if( NULL != mNode )
2048  {
2049  // Reparent Node in next Update
2050  ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2051  }
2052 
2053  // Notify attachment
2054  if( mAttachment )
2055  {
2056  mAttachment->Connect();
2057  }
2058 
2059  unsigned int rendererCount( GetRendererCount() );
2060  for( unsigned int i(0); i<rendererCount; ++i )
2061  {
2062  GetRendererAt(i)->Connect();
2063  }
2064 
2065  // Request relayout on all actors that are added to the scenegraph
2066  RelayoutRequest();
2067 
2068  // Notification for Object::Observers
2069  OnSceneObjectAdd();
2070 }
2071 
2073 {
2074  // Actors can be removed (in a callback), before the on-stage stage is reported.
2075  // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2076  if( OnStage() && !mOnStageSignalled )
2077  {
2078  // Notification for external (CustomActor) derived classes
2080 
2081  if( !mOnStageSignal.Empty() )
2082  {
2083  Dali::Actor handle( this );
2084  mOnStageSignal.Emit( handle );
2085  }
2086 
2087  // Guard against Remove during callbacks
2088  if( OnStage() )
2089  {
2090  mOnStageSignalled = true; // signal required next time Actor is removed
2091  }
2092  }
2093 }
2094 
2096 {
2097  // This container is used instead of walking the Actor hierachy.
2098  // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2099  ActorContainer disconnectionList;
2100 
2101  // This stage is atomic i.e. not interrupted by user callbacks
2102  RecursiveDisconnectFromStage( disconnectionList );
2103 
2104  // Notify applications about the newly disconnected actors.
2105  const ActorIter endIter = disconnectionList.end();
2106  for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2107  {
2108  (*iter)->NotifyStageDisconnection();
2109  }
2110 }
2111 
2113 {
2115 
2116  // Recursively disconnect children
2117  if( mChildren )
2118  {
2119  ActorConstIter endIter = mChildren->end();
2120  for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2121  {
2122  (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2123  }
2124  }
2125 
2126  // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2127  disconnectionList.push_back( ActorPtr( this ) );
2128 
2129  // Notification for internal derived classes
2131 
2133 
2134  mIsOnStage = false;
2135 }
2136 
2142 {
2143  // Notification for Object::Observers
2145 
2146  // Notify attachment
2147  if( mAttachment )
2148  {
2149  mAttachment->Disconnect();
2150  }
2151 
2152  unsigned int rendererCount( GetRendererCount() );
2153  for( unsigned int i(0); i<rendererCount; ++i )
2154  {
2155  GetRendererAt(i)->Disconnect();
2156  }
2157 }
2158 
2160 {
2161  // Actors can be added (in a callback), before the off-stage state is reported.
2162  // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2163  // only do this step if there is a stage, i.e. Core is not being shut down
2165  {
2166  // Notification for external (CustomeActor) derived classes
2168 
2169  if( !mOffStageSignal.Empty() )
2170  {
2171  Dali::Actor handle( this );
2172  mOffStageSignal.Emit( handle );
2173  }
2174 
2175  // Guard against Add during callbacks
2176  if( !OnStage() )
2177  {
2178  mOnStageSignalled = false; // signal required next time Actor is added
2179  }
2180  }
2181 }
2182 
2184 {
2185  bool connected( false );
2186 
2187  if( OnStage() && ( NULL != mNode ) )
2188  {
2189  if( IsRoot() || mNode->GetParent() )
2190  {
2191  connected = true;
2192  }
2193  }
2194 
2195  return connected;
2196 }
2197 
2199 {
2200  return DEFAULT_PROPERTY_COUNT;
2201 }
2202 
2204 {
2205  indices.Reserve( DEFAULT_PROPERTY_COUNT );
2206 
2207  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2208  {
2209  indices.PushBack( i );
2210  }
2211 }
2212 
2214 {
2215  if( index < DEFAULT_PROPERTY_COUNT )
2216  {
2217  return DEFAULT_PROPERTY_DETAILS[ index ].name;
2218  }
2219 
2220  return NULL;
2221 }
2222 
2223 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2224 {
2226 
2227  // Look for name in default properties
2228  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2229  {
2230  const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2231  if( 0 == name.compare( property->name ) )
2232  {
2233  index = i;
2234  break;
2235  }
2236  }
2237 
2238  return index;
2239 }
2240 
2242 {
2243  if( index < DEFAULT_PROPERTY_COUNT )
2244  {
2245  return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2246  }
2247 
2248  return false;
2249 }
2250 
2252 {
2253  if( index < DEFAULT_PROPERTY_COUNT )
2254  {
2255  return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2256  }
2257 
2258  return false;
2259 }
2260 
2262 {
2263  if( index < DEFAULT_PROPERTY_COUNT )
2264  {
2265  return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2266  }
2267 
2268  return false;
2269 }
2270 
2272 {
2273  if( index < DEFAULT_PROPERTY_COUNT )
2274  {
2275  return DEFAULT_PROPERTY_DETAILS[ index ].type;
2276  }
2277 
2278  // index out of range...return Property::NONE
2279  return Property::NONE;
2280 }
2281 
2283 {
2284  switch( index )
2285  {
2287  {
2288  SetParentOrigin( property.Get< Vector3 >() );
2289  break;
2290  }
2291 
2293  {
2294  SetParentOriginX( property.Get< float >() );
2295  break;
2296  }
2297 
2299  {
2300  SetParentOriginY( property.Get< float >() );
2301  break;
2302  }
2303 
2305  {
2306  SetParentOriginZ( property.Get< float >() );
2307  break;
2308  }
2309 
2311  {
2312  SetAnchorPoint( property.Get< Vector3 >() );
2313  break;
2314  }
2315 
2317  {
2318  SetAnchorPointX( property.Get< float >() );
2319  break;
2320  }
2321 
2323  {
2324  SetAnchorPointY( property.Get< float >() );
2325  break;
2326  }
2327 
2329  {
2330  SetAnchorPointZ( property.Get< float >() );
2331  break;
2332  }
2333 
2335  {
2336  SetSize( property.Get< Vector3 >() );
2337  break;
2338  }
2339 
2341  {
2342  SetWidth( property.Get< float >() );
2343  break;
2344  }
2345 
2347  {
2348  SetHeight( property.Get< float >() );
2349  break;
2350  }
2351 
2353  {
2354  SetDepth( property.Get< float >() );
2355  break;
2356  }
2357 
2359  {
2360  SetPosition( property.Get< Vector3 >() );
2361  break;
2362  }
2363 
2365  {
2366  SetX( property.Get< float >() );
2367  break;
2368  }
2369 
2371  {
2372  SetY( property.Get< float >() );
2373  break;
2374  }
2375 
2377  {
2378  SetZ( property.Get< float >() );
2379  break;
2380  }
2381 
2383  {
2384  SetOrientation( property.Get< Quaternion >() );
2385  break;
2386  }
2387 
2389  {
2390  SetScale( property.Get< Vector3 >() );
2391  break;
2392  }
2393 
2395  {
2396  SetScaleX( property.Get< float >() );
2397  break;
2398  }
2399 
2401  {
2402  SetScaleY( property.Get< float >() );
2403  break;
2404  }
2405 
2407  {
2408  SetScaleZ( property.Get< float >() );
2409  break;
2410  }
2411 
2413  {
2414  SetVisible( property.Get< bool >() );
2415  break;
2416  }
2417 
2419  {
2420  SetColor( property.Get< Vector4 >() );
2421  break;
2422  }
2423 
2425  {
2426  SetColorRed( property.Get< float >() );
2427  break;
2428  }
2429 
2431  {
2432  SetColorGreen( property.Get< float >() );
2433  break;
2434  }
2435 
2437  {
2438  SetColorBlue( property.Get< float >() );
2439  break;
2440  }
2441 
2443  {
2444  SetOpacity( property.Get< float >() );
2445  break;
2446  }
2447 
2449  {
2450  SetName( property.Get< std::string >() );
2451  break;
2452  }
2453 
2455  {
2456  SetSensitive( property.Get< bool >() );
2457  break;
2458  }
2459 
2461  {
2462  SetLeaveRequired( property.Get< bool >() );
2463  break;
2464  }
2465 
2467  {
2468  SetInheritOrientation( property.Get< bool >() );
2469  break;
2470  }
2471 
2473  {
2474  SetInheritScale( property.Get< bool >() );
2475  break;
2476  }
2477 
2479  {
2480  SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2481  break;
2482  }
2483 
2485  {
2486  SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2487  break;
2488  }
2489 
2491  {
2492  SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2493  break;
2494  }
2495 
2497  {
2498  SetSizeModeFactor( property.Get< Vector3 >() );
2499  break;
2500  }
2501 
2503  {
2504  ResizePolicy::Type type;
2505  if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2506  {
2508  }
2509  break;
2510  }
2511 
2513  {
2514  ResizePolicy::Type type;
2515  if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2516  {
2518  }
2519  break;
2520  }
2521 
2523  {
2524  SizeScalePolicy::Type type;
2525  if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2526  {
2527  SetSizeScalePolicy( type );
2528  }
2529  break;
2530  }
2531 
2533  {
2534  if( property.Get< bool >() )
2535  {
2537  }
2538  break;
2539  }
2540 
2542  {
2543  if( property.Get< bool >() )
2544  {
2546  }
2547  break;
2548  }
2549 
2551  {
2552  Vector4 padding = property.Get< Vector4 >();
2553  SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2554  SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2555  break;
2556  }
2557 
2559  {
2560  Vector2 size = property.Get< Vector2 >();
2563  break;
2564  }
2565 
2567  {
2568  Vector2 size = property.Get< Vector2 >();
2571  break;
2572  }
2573 
2574  default:
2575  {
2576  // this can happen in the case of a non-animatable default property so just do nothing
2577  break;
2578  }
2579  }
2580 }
2581 
2582 // TODO: This method needs to be removed
2584 {
2585  switch( entry.GetType() )
2586  {
2587  case Property::BOOLEAN:
2588  {
2589  const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2590  DALI_ASSERT_DEBUG( NULL != property );
2591 
2592  // property is being used in a separate thread; queue a message to set the property
2594 
2595  break;
2596  }
2597 
2598  case Property::INTEGER:
2599  {
2600  const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2601  DALI_ASSERT_DEBUG( NULL != property );
2602 
2603  // property is being used in a separate thread; queue a message to set the property
2605 
2606  break;
2607  }
2608 
2609  case Property::FLOAT:
2610  {
2611  const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2612  DALI_ASSERT_DEBUG( NULL != property );
2613 
2614  // property is being used in a separate thread; queue a message to set the property
2616 
2617  break;
2618  }
2619 
2620  case Property::VECTOR2:
2621  {
2622  const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2623  DALI_ASSERT_DEBUG( NULL != property );
2624 
2625  // property is being used in a separate thread; queue a message to set the property
2626  if(entry.componentIndex == 0)
2627  {
2629  }
2630  else if(entry.componentIndex == 1)
2631  {
2633  }
2634  else
2635  {
2637  }
2638 
2639  break;
2640  }
2641 
2642  case Property::VECTOR3:
2643  {
2644  const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2645  DALI_ASSERT_DEBUG( NULL != property );
2646 
2647  // property is being used in a separate thread; queue a message to set the property
2648  if(entry.componentIndex == 0)
2649  {
2651  }
2652  else if(entry.componentIndex == 1)
2653  {
2655  }
2656  else if(entry.componentIndex == 2)
2657  {
2659  }
2660  else
2661  {
2663  }
2664 
2665  break;
2666  }
2667 
2668  case Property::VECTOR4:
2669  {
2670  const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2671  DALI_ASSERT_DEBUG( NULL != property );
2672 
2673  // property is being used in a separate thread; queue a message to set the property
2674  if(entry.componentIndex == 0)
2675  {
2677  }
2678  else if(entry.componentIndex == 1)
2679  {
2681  }
2682  else if(entry.componentIndex == 2)
2683  {
2685  }
2686  else if(entry.componentIndex == 3)
2687  {
2689  }
2690  else
2691  {
2693  }
2694 
2695  break;
2696  }
2697 
2698  case Property::ROTATION:
2699  {
2700  const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2701  DALI_ASSERT_DEBUG( NULL != property );
2702 
2703  // property is being used in a separate thread; queue a message to set the property
2705 
2706  break;
2707  }
2708 
2709  case Property::MATRIX:
2710  {
2711  const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2712  DALI_ASSERT_DEBUG( NULL != property );
2713 
2714  // property is being used in a separate thread; queue a message to set the property
2716 
2717  break;
2718  }
2719 
2720  case Property::MATRIX3:
2721  {
2722  const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2723  DALI_ASSERT_DEBUG( NULL != property );
2724 
2725  // property is being used in a separate thread; queue a message to set the property
2727 
2728  break;
2729  }
2730 
2731  default:
2732  {
2733  DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2734  break;
2735  }
2736  } // entry.GetType
2737 }
2738 
2740 {
2741  Property::Value value;
2742 
2743  switch( index )
2744  {
2746  {
2747  value = GetCurrentParentOrigin();
2748  break;
2749  }
2750 
2752  {
2753  value = GetCurrentParentOrigin().x;
2754  break;
2755  }
2756 
2758  {
2759  value = GetCurrentParentOrigin().y;
2760  break;
2761  }
2762 
2764  {
2765  value = GetCurrentParentOrigin().z;
2766  break;
2767  }
2768 
2770  {
2771  value = GetCurrentAnchorPoint();
2772  break;
2773  }
2774 
2776  {
2777  value = GetCurrentAnchorPoint().x;
2778  break;
2779  }
2780 
2782  {
2783  value = GetCurrentAnchorPoint().y;
2784  break;
2785  }
2786 
2788  {
2789  value = GetCurrentAnchorPoint().z;
2790  break;
2791  }
2792 
2794  {
2795  value = GetTargetSize();
2796  break;
2797  }
2798 
2800  {
2801  value = GetTargetSize().width;
2802  break;
2803  }
2804 
2806  {
2807  value = GetTargetSize().height;
2808  break;
2809  }
2810 
2812  {
2813  value = GetTargetSize().depth;
2814  break;
2815  }
2816 
2818  {
2819  value = GetTargetPosition();
2820  break;
2821  }
2822 
2824  {
2825  value = GetTargetPosition().x;
2826  break;
2827  }
2828 
2830  {
2831  value = GetTargetPosition().y;
2832  break;
2833  }
2834 
2836  {
2837  value = GetTargetPosition().z;
2838  break;
2839  }
2840 
2842  {
2843  value = GetCurrentWorldPosition();
2844  break;
2845  }
2846 
2848  {
2849  value = GetCurrentWorldPosition().x;
2850  break;
2851  }
2852 
2854  {
2855  value = GetCurrentWorldPosition().y;
2856  break;
2857  }
2858 
2860  {
2861  value = GetCurrentWorldPosition().z;
2862  break;
2863  }
2864 
2866  {
2867  value = GetCurrentOrientation();
2868  break;
2869  }
2870 
2872  {
2873  value = GetCurrentWorldOrientation();
2874  break;
2875  }
2876 
2878  {
2879  value = GetCurrentScale();
2880  break;
2881  }
2882 
2884  {
2885  value = GetCurrentScale().x;
2886  break;
2887  }
2888 
2890  {
2891  value = GetCurrentScale().y;
2892  break;
2893  }
2894 
2896  {
2897  value = GetCurrentScale().z;
2898  break;
2899  }
2900 
2902  {
2903  value = GetCurrentWorldScale();
2904  break;
2905  }
2906 
2908  {
2909  value = IsVisible();
2910  break;
2911  }
2912 
2914  {
2915  value = GetCurrentColor();
2916  break;
2917  }
2918 
2920  {
2921  value = GetCurrentColor().r;
2922  break;
2923  }
2924 
2926  {
2927  value = GetCurrentColor().g;
2928  break;
2929  }
2930 
2932  {
2933  value = GetCurrentColor().b;
2934  break;
2935  }
2936 
2938  {
2939  value = GetCurrentColor().a;
2940  break;
2941  }
2942 
2944  {
2945  value = GetCurrentWorldColor();
2946  break;
2947  }
2948 
2950  {
2951  value = GetCurrentWorldMatrix();
2952  break;
2953  }
2954 
2956  {
2957  value = GetName();
2958  break;
2959  }
2960 
2962  {
2963  value = IsSensitive();
2964  break;
2965  }
2966 
2968  {
2969  value = GetLeaveRequired();
2970  break;
2971  }
2972 
2974  {
2975  value = IsOrientationInherited();
2976  break;
2977  }
2978 
2980  {
2981  value = IsScaleInherited();
2982  break;
2983  }
2984 
2986  {
2988  break;
2989  }
2990 
2992  {
2994  break;
2995  }
2996 
2998  {
2999  value = Scripting::GetDrawMode( GetDrawMode() );
3000  break;
3001  }
3002 
3004  {
3005  value = GetSizeModeFactor();
3006  break;
3007  }
3008 
3010  {
3011  value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3012  break;
3013  }
3014 
3016  {
3017  value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3018  break;
3019  }
3020 
3022  {
3023  value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3024  break;
3025  }
3026 
3028  {
3030  break;
3031  }
3032 
3034  {
3036  break;
3037  }
3038 
3040  {
3041  Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3042  Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3043  value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3044  break;
3045  }
3046 
3048  {
3050  break;
3051  }
3052 
3054  {
3056  break;
3057  }
3058 
3059  default:
3060  {
3061  DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3062  break;
3063  }
3064  }
3065 
3066  return value;
3067 }
3068 
3070 {
3071  return mNode;
3072 }
3073 
3075 {
3076  // This method should only return an object connected to the scene-graph
3077  return OnStage() ? mNode : NULL;
3078 }
3079 
3081 {
3082  DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3083 
3084  const PropertyBase* property( NULL );
3085 
3086  // This method should only return a property of an object connected to the scene-graph
3087  if( !OnStage() )
3088  {
3089  return property;
3090  }
3091 
3093  {
3095  DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3096 
3097  property = animatable->GetSceneGraphProperty();
3098  }
3099  else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3100  {
3101  CustomPropertyMetadata* custom = FindCustomProperty( index );
3102  DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3103 
3104  property = custom->GetSceneGraphProperty();
3105  }
3106  else if( NULL != mNode )
3107  {
3108  switch( index )
3109  {
3111  property = &mNode->mSize;
3112  break;
3113 
3115  property = &mNode->mSize;
3116  break;
3117 
3119  property = &mNode->mSize;
3120  break;
3121 
3123  property = &mNode->mSize;
3124  break;
3125 
3127  property = &mNode->mPosition;
3128  break;
3129 
3131  property = &mNode->mPosition;
3132  break;
3133 
3135  property = &mNode->mPosition;
3136  break;
3137 
3139  property = &mNode->mPosition;
3140  break;
3141 
3143  property = &mNode->mOrientation;
3144  break;
3145 
3147  property = &mNode->mScale;
3148  break;
3149 
3151  property = &mNode->mScale;
3152  break;
3153 
3155  property = &mNode->mScale;
3156  break;
3157 
3159  property = &mNode->mScale;
3160  break;
3161 
3163  property = &mNode->mVisible;
3164  break;
3165 
3167  property = &mNode->mColor;
3168  break;
3169 
3171  property = &mNode->mColor;
3172  break;
3173 
3175  property = &mNode->mColor;
3176  break;
3177 
3179  property = &mNode->mColor;
3180  break;
3181 
3183  property = &mNode->mColor;
3184  break;
3185 
3186  default:
3187  break;
3188  }
3189  }
3190 
3191  return property;
3192 }
3193 
3195 {
3196  const PropertyInputImpl* property( NULL );
3197 
3198  // This method should only return a property of an object connected to the scene-graph
3199  if( !OnStage() )
3200  {
3201  return property;
3202  }
3203 
3205  {
3207  DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3208 
3209  property = animatable->GetSceneGraphProperty();
3210  }
3211  else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3212  {
3213  CustomPropertyMetadata* custom = FindCustomProperty( index );
3214  DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3215  property = custom->GetSceneGraphProperty();
3216  }
3217  else if( NULL != mNode )
3218  {
3219  switch( index )
3220  {
3222  property = &mNode->mParentOrigin;
3223  break;
3224 
3226  property = &mNode->mParentOrigin;
3227  break;
3228 
3230  property = &mNode->mParentOrigin;
3231  break;
3232 
3234  property = &mNode->mParentOrigin;
3235  break;
3236 
3238  property = &mNode->mAnchorPoint;
3239  break;
3240 
3242  property = &mNode->mAnchorPoint;
3243  break;
3244 
3246  property = &mNode->mAnchorPoint;
3247  break;
3248 
3250  property = &mNode->mAnchorPoint;
3251  break;
3252 
3254  property = &mNode->mSize;
3255  break;
3256 
3258  property = &mNode->mSize;
3259  break;
3260 
3262  property = &mNode->mSize;
3263  break;
3264 
3266  property = &mNode->mSize;
3267  break;
3268 
3270  property = &mNode->mPosition;
3271  break;
3272 
3274  property = &mNode->mPosition;
3275  break;
3276 
3278  property = &mNode->mPosition;
3279  break;
3280 
3282  property = &mNode->mPosition;
3283  break;
3284 
3286  property = &mNode->mWorldPosition;
3287  break;
3288 
3290  property = &mNode->mWorldPosition;
3291  break;
3292 
3294  property = &mNode->mWorldPosition;
3295  break;
3296 
3298  property = &mNode->mWorldPosition;
3299  break;
3300 
3302  property = &mNode->mOrientation;
3303  break;
3304 
3306  property = &mNode->mWorldOrientation;
3307  break;
3308 
3310  property = &mNode->mScale;
3311  break;
3312 
3314  property = &mNode->mScale;
3315  break;
3316 
3318  property = &mNode->mScale;
3319  break;
3320 
3322  property = &mNode->mScale;
3323  break;
3324 
3326  property = &mNode->mWorldScale;
3327  break;
3328 
3330  property = &mNode->mVisible;
3331  break;
3332 
3334  property = &mNode->mColor;
3335  break;
3336 
3338  property = &mNode->mColor;
3339  break;
3340 
3342  property = &mNode->mColor;
3343  break;
3344 
3346  property = &mNode->mColor;
3347  break;
3348 
3350  property = &mNode->mColor;
3351  break;
3352 
3354  property = &mNode->mWorldColor;
3355  break;
3356 
3358  property = &mNode->mWorldMatrix;
3359  break;
3360 
3361  default:
3362  break;
3363  }
3364  }
3365 
3366  return property;
3367 }
3368 
3370 {
3371  int componentIndex( Property::INVALID_COMPONENT_INDEX );
3372 
3374  {
3375  // check whether the animatable property is registered already, if not then register one.
3376  AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3377  if( animatableProperty )
3378  {
3379  componentIndex = animatableProperty->componentIndex;
3380  }
3381  }
3382  else
3383  {
3384  switch( index )
3385  {
3393  {
3394  componentIndex = 0;
3395  break;
3396  }
3397 
3405  {
3406  componentIndex = 1;
3407  break;
3408  }
3409 
3417  {
3418  componentIndex = 2;
3419  break;
3420  }
3421 
3423  {
3424  componentIndex = 3;
3425  break;
3426  }
3427 
3428  default:
3429  {
3430  // Do nothing
3431  break;
3432  }
3433  }
3434  }
3435 
3436  return componentIndex;
3437 }
3438 
3439 void Actor::SetParent( Actor* parent )
3440 {
3441  if( parent )
3442  {
3443  DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3444 
3445  mParent = parent;
3446 
3447  if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3448  parent->OnStage() )
3449  {
3450  // Instruct each actor to create a corresponding node in the scene graph
3451  ConnectToStage( parent->GetHierarchyDepth() );
3452  }
3453  }
3454  else // parent being set to NULL
3455  {
3456  DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3457 
3458  mParent = NULL;
3459 
3460  if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3461  OnStage() )
3462  {
3463  DALI_ASSERT_ALWAYS( mNode != NULL );
3464 
3465  if( NULL != mNode )
3466  {
3467  // Disconnect the Node & its children from the scene-graph.
3468  DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3469  }
3470 
3471  // Instruct each actor to discard pointers to the scene-graph
3473  }
3474  }
3475 }
3476 
3478 {
3479  return Node::New();
3480 }
3481 
3482 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3483 {
3484  bool done = false;
3485  Actor* actor = dynamic_cast< Actor* >( object );
3486 
3487  if( actor )
3488  {
3489  if( 0 == actionName.compare( ACTION_SHOW ) )
3490  {
3491  actor->SetVisible( true );
3492  done = true;
3493  }
3494  else if( 0 == actionName.compare( ACTION_HIDE ) )
3495  {
3496  actor->SetVisible( false );
3497  done = true;
3498  }
3499  }
3500 
3501  return done;
3502 }
3503 
3505 {
3506  // Assign relayout data.
3507  if( !mRelayoutData )
3508  {
3509  mRelayoutData = new RelayoutData();
3510  }
3511 }
3512 
3514 {
3515  // Check if actor is dependent on parent
3516  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3517  {
3518  if( ( dimension & ( 1 << i ) ) )
3519  {
3520  const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3522  {
3523  return true;
3524  }
3525  }
3526  }
3527 
3528  return false;
3529 }
3530 
3532 {
3533  // Check if actor is dependent on children
3534  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3535  {
3536  if( ( dimension & ( 1 << i ) ) )
3537  {
3538  const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3539  switch( resizePolicy )
3540  {
3542  case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3543  {
3544  return true;
3545  }
3546 
3547  default:
3548  {
3549  break;
3550  }
3551  }
3552  }
3553  }
3554 
3555  return false;
3556 }
3557 
3559 {
3560  return Actor::RelayoutDependentOnChildren( dimension );
3561 }
3562 
3564 {
3565  // Check each possible dimension and see if it is dependent on the input one
3566  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3567  {
3568  if( dimension & ( 1 << i ) )
3569  {
3571  }
3572  }
3573 
3574  return false;
3575 }
3576 
3577 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3578 {
3579  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3580  {
3581  if( dimension & ( 1 << i ) )
3582  {
3583  mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3584  }
3585  }
3586 }
3587 
3589 {
3590  // If more than one dimension is requested, just return the first one found
3591  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3592  {
3593  if( ( dimension & ( 1 << i ) ) )
3594  {
3595  return mRelayoutData->negotiatedDimensions[ i ];
3596  }
3597  }
3598 
3599  return 0.0f; // Default
3600 }
3601 
3602 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3603 {
3605 
3606  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3607  {
3608  if( dimension & ( 1 << i ) )
3609  {
3610  mRelayoutData->dimensionPadding[ i ] = padding;
3611  }
3612  }
3613 }
3614 
3616 {
3617  if ( mRelayoutData )
3618  {
3619  // If more than one dimension is requested, just return the first one found
3620  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3621  {
3622  if( ( dimension & ( 1 << i ) ) )
3623  {
3624  return mRelayoutData->dimensionPadding[ i ];
3625  }
3626  }
3627  }
3628 
3629  return GetDefaultDimensionPadding();
3630 }
3631 
3632 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3633 {
3635 
3636  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3637  {
3638  if( dimension & ( 1 << i ) )
3639  {
3640  mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3641  }
3642  }
3643 }
3644 
3646 {
3647  if ( mRelayoutData )
3648  {
3649  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3650  {
3651  if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3652  {
3653  return true;
3654  }
3655  }
3656  }
3657 
3658  return false;
3659 }
3660 
3662 {
3663  float height = 0.0f;
3664 
3665  const Vector3 naturalSize = GetNaturalSize();
3666  if( naturalSize.width > 0.0f )
3667  {
3668  height = naturalSize.height * width / naturalSize.width;
3669  }
3670  else // we treat 0 as 1:1 aspect ratio
3671  {
3672  height = width;
3673  }
3674 
3675  return height;
3676 }
3677 
3679 {
3680  float width = 0.0f;
3681 
3682  const Vector3 naturalSize = GetNaturalSize();
3683  if( naturalSize.height > 0.0f )
3684  {
3685  width = naturalSize.width * height / naturalSize.height;
3686  }
3687  else // we treat 0 as 1:1 aspect ratio
3688  {
3689  width = height;
3690  }
3691 
3692  return width;
3693 }
3694 
3696 {
3697  // Fill to parent, taking size mode factor into account
3698  switch( child.GetResizePolicy( dimension ) )
3699  {
3701  {
3702  return GetLatestSize( dimension );
3703  }
3704 
3706  {
3707  return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3708  }
3709 
3711  {
3712  return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3713  }
3714 
3715  default:
3716  {
3717  return GetLatestSize( dimension );
3718  }
3719  }
3720 }
3721 
3723 {
3724  // Can be overridden in derived class
3725  return CalculateChildSizeBase( child, dimension );
3726 }
3727 
3729 {
3730  // Can be overridden in derived class
3731  return GetHeightForWidthBase( width );
3732 }
3733 
3735 {
3736  // Can be overridden in derived class
3737  return GetWidthForHeightBase( height );
3738 }
3739 
3740 float Actor::GetLatestSize( Dimension::Type dimension ) const
3741 {
3742  return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3743 }
3744 
3745 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3746 {
3747  Vector2 padding = GetPadding( dimension );
3748 
3749  return GetLatestSize( dimension ) + padding.x + padding.y;
3750 }
3751 
3753 {
3754  Actor* parent = GetParent();
3755  if( parent )
3756  {
3757  Vector2 padding( GetPadding( dimension ) );
3758  Vector2 parentPadding( parent->GetPadding( dimension ) );
3759  return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3760  }
3761 
3762  return 0.0f;
3763 }
3764 
3766 {
3767  float maxDimensionPoint = 0.0f;
3768 
3769  for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3770  {
3771  ActorPtr child = GetChildAt( i );
3772 
3773  if( !child->RelayoutDependentOnParent( dimension ) )
3774  {
3775  // Calculate the min and max points that the children range across
3776  float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3777  float dimensionSize = child->GetRelayoutSize( dimension );
3778  maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3779  }
3780  }
3781 
3782  return maxDimensionPoint;
3783 }
3784 
3785 float Actor::GetSize( Dimension::Type dimension ) const
3786 {
3787  return GetDimensionValue( GetTargetSize(), dimension );
3788 }
3789 
3790 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3791 {
3792  return GetDimensionValue( GetNaturalSize(), dimension );
3793 }
3794 
3795 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3796 {
3797  switch( GetResizePolicy( dimension ) )
3798  {
3800  {
3801  return GetNaturalSize( dimension );
3802  }
3803 
3804  case ResizePolicy::FIXED:
3805  {
3806  return GetDimensionValue( GetPreferredSize(), dimension );
3807  }
3808 
3810  {
3811  return GetDimensionValue( maximumSize, dimension );
3812  }
3813 
3817  {
3818  return NegotiateFromParent( dimension );
3819  }
3820 
3822  {
3823  return NegotiateFromChildren( dimension );
3824  }
3825 
3827  {
3828  const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3829 
3830  // Custom rules
3831  if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3832  {
3834  }
3835 
3836  if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3837  {
3839  }
3840 
3841  break;
3842  }
3843 
3844  default:
3845  {
3846  break;
3847  }
3848  }
3849 
3850  return 0.0f; // Default
3851 }
3852 
3853 float Actor::ClampDimension( float size, Dimension::Type dimension )
3854 {
3855  const float minSize = GetMinimumSize( dimension );
3856  const float maxSize = GetMaximumSize( dimension );
3857 
3858  return std::max( minSize, std::min( size, maxSize ) );
3859 }
3860 
3861 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3862 {
3863  // Check if it needs to be negotiated
3864  if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3865  {
3866  // Check that we havn't gotten into an infinite loop
3867  ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3868  bool recursionFound = false;
3869  for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3870  {
3871  if( *it == searchActor )
3872  {
3873  recursionFound = true;
3874  break;
3875  }
3876  }
3877 
3878  if( !recursionFound )
3879  {
3880  // Record the path that we have taken
3881  recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3882 
3883  // Dimension dependency check
3884  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3885  {
3886  Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3887 
3888  if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3889  {
3890  NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3891  }
3892  }
3893 
3894  // Parent dependency check
3895  Actor* parent = GetParent();
3896  if( parent && RelayoutDependentOnParent( dimension ) )
3897  {
3898  parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3899  }
3900 
3901  // Children dependency check
3902  if( RelayoutDependentOnChildren( dimension ) )
3903  {
3904  for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3905  {
3906  ActorPtr child = GetChildAt( i );
3907 
3908  // Only relayout child first if it is not dependent on this actor
3909  if( !child->RelayoutDependentOnParent( dimension ) )
3910  {
3911  child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3912  }
3913  }
3914  }
3915 
3916  // For deriving classes
3917  OnCalculateRelayoutSize( dimension );
3918 
3919  // All dependencies checked, calculate the size and set negotiated flag
3920  const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3921 
3922  SetNegotiatedDimension( newSize, dimension );
3923  SetLayoutNegotiated( true, dimension );
3924 
3925  // For deriving classes
3926  OnLayoutNegotiated( newSize, dimension );
3927 
3928  // This actor has been successfully processed, pop it off the recursion stack
3929  recursionStack.pop_back();
3930  }
3931  else
3932  {
3933  // TODO: Break infinite loop
3934  SetLayoutNegotiated( true, dimension );
3935  }
3936  }
3937 }
3938 
3939 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3940 {
3941  // Negotiate all dimensions that require it
3942  ActorDimensionStack recursionStack;
3943 
3944  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3945  {
3946  const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3947 
3948  // Negotiate
3949  NegotiateDimension( dimension, allocatedSize, recursionStack );
3950  }
3951 }
3952 
3954 {
3955  switch( mRelayoutData->sizeSetPolicy )
3956  {
3958  {
3959  return size;
3960  }
3961 
3963  {
3964  // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3965  const Vector3 naturalSize = GetNaturalSize();
3966  if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3967  {
3968  const float sizeRatio = size.width / size.height;
3969  const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3970 
3971  if( naturalSizeRatio < sizeRatio )
3972  {
3973  return Vector2( naturalSizeRatio * size.height, size.height );
3974  }
3975  else if( naturalSizeRatio > sizeRatio )
3976  {
3977  return Vector2( size.width, size.width / naturalSizeRatio );
3978  }
3979  else
3980  {
3981  return size;
3982  }
3983  }
3984 
3985  break;
3986  }
3987 
3989  {
3990  // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3991  const Vector3 naturalSize = GetNaturalSize();
3992  if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3993  {
3994  const float sizeRatio = size.width / size.height;
3995  const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3996 
3997  if( naturalSizeRatio < sizeRatio )
3998  {
3999  return Vector2( size.width, size.width / naturalSizeRatio );
4000  }
4001  else if( naturalSizeRatio > sizeRatio )
4002  {
4003  return Vector2( naturalSizeRatio * size.height, size.height );
4004  }
4005  else
4006  {
4007  return size;
4008  }
4009  }
4010  }
4011 
4012  default:
4013  {
4014  break;
4015  }
4016  }
4017 
4018  return size;
4019 }
4020 
4022 {
4023  // Do the set actor size
4025 
4026  // Adjust for size set policy
4027  negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4028 
4029  // Lock the flag to stop recursive relayouts on set size
4030  mRelayoutData->insideRelayout = true;
4031  SetSize( negotiatedSize );
4032  mRelayoutData->insideRelayout = false;
4033 
4034  // Clear flags for all dimensions
4035  SetLayoutDirty( false );
4036 
4037  // Give deriving classes a chance to respond
4038  OnRelayout( negotiatedSize, container );
4039 
4040  if( !mOnRelayoutSignal.Empty() )
4041  {
4042  Dali::Actor handle( this );
4043  mOnRelayoutSignal.Emit( handle );
4044  }
4045 }
4046 
4047 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4048 {
4049  // Do the negotiation
4050  NegotiateDimensions( allocatedSize );
4051 
4052  // Set the actor size
4053  SetNegotiatedSize( container );
4054 
4055  // Negotiate down to children
4056  const Vector2 newBounds = GetTargetSize().GetVectorXY();
4057 
4058  for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4059  {
4060  ActorPtr child = GetChildAt( i );
4061 
4062  // Only relayout if required
4063  if( child->RelayoutRequired() )
4064  {
4065  container.Add( Dali::Actor( child.Get() ), newBounds );
4066  }
4067  }
4068 }
4069 
4071 {
4073  if( relayoutController )
4074  {
4075  Dali::Actor self( this );
4076  relayoutController->RequestRelayout( self, dimension );
4077  }
4078 }
4079 
4081 {
4082 }
4083 
4084 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4085 {
4086 }
4087 
4089 {
4091 
4092  if( size.width > 0.0f )
4093  {
4095  }
4096 
4097  if( size.height > 0.0f )
4098  {
4100  }
4101 
4102  mRelayoutData->preferredSize = size;
4103 
4104  RelayoutRequest();
4105 }
4106 
4108 {
4109  if ( mRelayoutData )
4110  {
4111  return Vector2( mRelayoutData->preferredSize );
4112  }
4113 
4114  return GetDefaultPreferredSize();
4115 }
4116 
4117 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4118 {
4120 
4121  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4122  {
4123  if( dimension & ( 1 << i ) )
4124  {
4125  mRelayoutData->minimumSize[ i ] = size;
4126  }
4127  }
4128 
4129  RelayoutRequest();
4130 }
4131 
4132 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4133 {
4134  if ( mRelayoutData )
4135  {
4136  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4137  {
4138  if( dimension & ( 1 << i ) )
4139  {
4140  return mRelayoutData->minimumSize[ i ];
4141  }
4142  }
4143  }
4144 
4145  return 0.0f; // Default
4146 }
4147 
4148 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4149 {
4151 
4152  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4153  {
4154  if( dimension & ( 1 << i ) )
4155  {
4156  mRelayoutData->maximumSize[ i ] = size;
4157  }
4158  }
4159 
4160  RelayoutRequest();
4161 }
4162 
4163 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4164 {
4165  if ( mRelayoutData )
4166  {
4167  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4168  {
4169  if( dimension & ( 1 << i ) )
4170  {
4171  return mRelayoutData->maximumSize[ i ];
4172  }
4173  }
4174  }
4175 
4176  return FLT_MAX; // Default
4177 }
4178 
4179 } // namespace Internal
4180 
4181 } // namespace Dali
Dali Docs Home
Read more about Dali