f712893241fe760981712238e99adccd0d378940
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / actors / actor-api.cpp
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
19 #include "actor-api.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
23
24 // INTERNAL INCLUDES
25 #include <v8-utils.h>
26 #include <actors/actor-wrapper.h>
27 #include <animation/path-constrainer-wrapper.h>
28
29 namespace Dali
30 {
31
32 namespace V8Plugin
33 {
34
35 namespace  // unanmed namespace
36 {
37 Actor GetActor( v8::Isolate* isolate, const v8::FunctionCallbackInfo<v8::Value>& args )
38 {
39   HandleWrapper* handleWrapper = HandleWrapper::Unwrap( isolate, args.This() );
40   return Actor::DownCast( handleWrapper->mHandle );
41 }
42 } //unanmed namespace
43
44
45 namespace TextLabelApi
46 {
47  Actor New( const v8::FunctionCallbackInfo< v8::Value >& args )
48  {
49    return Dali::Toolkit::TextLabel::New();
50  }
51 }
52
53 /***************************************
54  * ACTOR API FUNCTIONS
55  ****************************************/
56 /**
57  * Constructor
58  *
59  * @for Actor
60  * @constructor
61  * @method Actor
62  * @return {Object} actor
63  */
64 Actor ActorApi::New( const v8::FunctionCallbackInfo< v8::Value >& args )
65 {
66   return Actor::New();
67 }
68
69 /**
70  * get the actors unique id
71  *
72  * @for Actor
73  * @method getId
74  * @return {Integer} id
75  */
76 void ActorApi::GetId( const v8::FunctionCallbackInfo<v8::Value>& args )
77 {
78   v8::Isolate* isolate = args.GetIsolate();
79   v8::HandleScope handleScope( isolate );
80   Actor actor = GetActor( isolate, args );
81
82   args.GetReturnValue().Set( v8::Integer::New( isolate, actor.GetId() ) );
83 }
84
85 /**
86  * Query whether an actor is the root actor, which is owned by the Stage
87  *
88  * @for Actor
89  * @method isRoot
90  * @return {Boolean} true if it is root
91  *
92  */
93 void ActorApi::IsRoot( const v8::FunctionCallbackInfo<v8::Value>& args )
94 {
95   v8::Isolate* isolate = args.GetIsolate();
96   v8::HandleScope handleScope( isolate );
97   Actor actor = GetActor( isolate, args );
98
99   args.GetReturnValue().Set( v8::Boolean::New( isolate, actor.IsRoot() ) );
100 }
101
102 /**
103  *
104  * Query whether the actor is connected to the Stage.
105  * When an actor is connected, it will be directly or indirectly parented to the root Actor.
106  * The root Actor is provided automatically by dali.stage, and is always considered to be connected.
107  *
108  * @for Actor
109  * @method onStage
110  * @return {Boolean} True if the actor is connected to the Stage
111  */
112 void ActorApi::OnStage( const v8::FunctionCallbackInfo<v8::Value>& args )
113 {
114   v8::Isolate* isolate = args.GetIsolate();
115   v8::HandleScope handleScope( isolate );
116   Actor actor = GetActor( isolate, args );
117
118   args.GetReturnValue().Set( v8::Boolean::New( isolate, actor.OnStage() ) );
119 }
120
121 /**
122  * Query whether an actor is a layer
123  *
124  * @for Actor
125  * @method isLayer
126  * @return {Boolean} true if it is a layer
127  */
128 void ActorApi::IsLayer( const v8::FunctionCallbackInfo<v8::Value>& args )
129 {
130   v8::Isolate* isolate = args.GetIsolate();
131   v8::HandleScope handleScope( isolate );
132   Actor actor = GetActor( isolate, args );
133
134   args.GetReturnValue().Set( v8::Boolean::New( isolate, actor.IsLayer() ) );
135 }
136
137 /**
138  * Gets the layer in which the actor is present.
139  *
140  * @for Actor
141  * @method getLayer
142  * @return {Object} Layer
143  */
144 void ActorApi::GetLayer( const v8::FunctionCallbackInfo<v8::Value>& args )
145 {
146   v8::Isolate* isolate = args.GetIsolate();
147   v8::HandleScope handleScope( isolate );
148   Actor actor = GetActor( isolate, args );
149   Layer layer = actor.GetLayer();
150   if( layer ) // actors don't always have a layer
151   {
152     v8::Handle < v8::Object > wrappedLayer = ActorWrapper::ActorWrapper::WrapActor( isolate, layer, ActorWrapper::LAYER_ACTOR );
153     args.GetReturnValue().Set( wrappedLayer );
154   }
155   // else return an empty object
156 }
157
158 /**
159  * Adds a child Actor to this Actor.
160  *
161  * NOTE! if the child already has a parent, it will be removed from old parent
162  * and reparented to this actor. This may change childs position, color, shader effect,
163  * scale etc as it now inherits them from this actor
164  *
165  * Pre-conditions
166  * - The child actor is not the same as the parent actor.
167  * - The actor is not the Root actor
168
169  * Once added The child will be referenced by its parent. This means that the child will be kept alive,
170  * even if the handle passed into this method is reset or destroyed.
171  *
172  * @for Actor
173  * @method add
174  * @param {Object} Actor
175  */
176 void ActorApi::AddActor( const v8::FunctionCallbackInfo<v8::Value>& args )
177 {
178   v8::Isolate* isolate = args.GetIsolate();
179   v8::HandleScope handleScope( isolate );
180   Actor parent = GetActor( isolate, args );
181   bool found(false);
182   Actor child = V8Utils::GetActorParameter( PARAMETER_0, found, isolate, args );
183   if( found )
184   {
185     parent.Add( child );
186   }
187   else
188   {
189     DALI_SCRIPT_EXCEPTION( isolate, "child parameter missing" );
190   }
191 }
192
193 /**
194  * Removes a child Actor from this Actor.
195  *
196  * If the actor was not a child of this actor, this is a no-op.
197  *
198  * Preconditions:
199  * -  The child actor is not the same as the parent actor.
200  *
201  * @for Actor
202  * @param{Object} Actor the child actor
203  * @method Remove
204  */
205 void ActorApi::RemoveActor( const v8::FunctionCallbackInfo<v8::Value>& args )
206 {
207   v8::Isolate* isolate = args.GetIsolate();
208   v8::HandleScope handleScope( isolate );
209   Actor parent = GetActor( isolate, args );
210   bool found( false );
211   Actor child = V8Utils::GetActorParameter( PARAMETER_0, found, isolate, args );
212
213   if( found )
214   {
215     parent.Remove( child );
216   }
217   else
218   {
219     DALI_SCRIPT_EXCEPTION( isolate, "child parameter missing" );
220   }
221 }
222
223 /**
224  * Checks whether an Actor is equal to this Actor.
225  *
226  * @for Actor
227  * @method iIsEqualTo
228  * @param {Object} Actor
229  */
230 void ActorApi::IsEqualTo( const v8::FunctionCallbackInfo<v8::Value>& args )
231 {
232   v8::Isolate* isolate = args.GetIsolate();
233   v8::HandleScope handleScope( isolate );
234   Actor self = GetActor( isolate, args );
235   bool found( false );
236
237   Actor actor = V8Utils::GetActorParameter( PARAMETER_0, found, isolate, args );
238   if( found )
239   {
240     args.GetReturnValue().Set( v8::Boolean::New( isolate, (actor == self) ) );
241   }
242   else
243   {
244     DALI_SCRIPT_EXCEPTION( isolate, "actor parameter missing" );
245   }
246 }
247
248 /** Removes an actor from its parent.
249  *
250  * If the actor has no parent, this method does nothing.
251  *
252  * @for Actor
253  * @method Unparent
254  */
255 void ActorApi::Unparent( const v8::FunctionCallbackInfo< v8::Value >& args)
256 {
257   v8::Isolate* isolate = args.GetIsolate();
258   v8::HandleScope handleScope( isolate );
259   Actor actor = GetActor( isolate, args );
260   actor.Unparent();
261 }
262
263 /**
264  * get number of child actors
265  *
266  * @for Actor
267  * @method getChildCount
268  * @return {Integer} count
269  */
270 void ActorApi::GetChildCount( const v8::FunctionCallbackInfo<v8::Value>& args )
271 {
272   v8::Isolate* isolate = args.GetIsolate();
273   v8::HandleScope handleScope( isolate );
274   Actor actor = GetActor( isolate, args );
275
276   args.GetReturnValue().Set( v8::Integer::New( isolate, actor.GetChildCount() ) );
277 }
278
279 /**
280  * Retrieve and child actor by index.
281  *
282  * @for Actor
283  * @method getChildAt
284  * @param {Integer} actor index
285  * @return {Object} actor on success, empty actor handle if not found
286  */
287 void ActorApi::GetChildAt( const v8::FunctionCallbackInfo<v8::Value>& args )
288 {
289   v8::Isolate* isolate = args.GetIsolate();
290   v8::HandleScope handleScope( isolate );
291   Actor parent = GetActor( isolate, args );
292   bool found( false );
293   int id = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 );
294   if( !found )
295   {
296     DALI_SCRIPT_EXCEPTION( isolate, "Integer parameter missing" );
297     return;
298   }
299   Actor childActor = parent.GetChildAt( id );
300   if( childActor )
301   {
302     // wrap the child
303     v8::Handle < v8::Object > wrappedActor = ActorWrapper::WrapActor( isolate, childActor );
304     args.GetReturnValue().Set( wrappedActor );
305   }
306 }
307
308 /**
309  * Search through this actor's hierarchy for an actor with the given name
310  * The actor itself is also considered in the search
311  *
312  * @for Actor
313  * @method findChildByName
314  * @param {String} actor name
315  * @return {Object} actor on success, empty actor handle if not found
316  */
317 void ActorApi::FindChildByName( const v8::FunctionCallbackInfo<v8::Value>& args )
318 {
319   v8::Isolate* isolate = args.GetIsolate();
320   v8::HandleScope handleScope( isolate );
321   Actor parent = GetActor( isolate, args );
322   bool found( false );
323   std::string name = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
324   if( !found )
325   {
326     DALI_SCRIPT_EXCEPTION( isolate, "string parameter missing" );
327     return;
328   }
329   Actor childActor = parent.FindChildByName( name );
330   if( childActor )
331   {
332     // wrap the child
333     v8::Handle < v8::Object > wrappedLayer = ActorWrapper::WrapActor( isolate, childActor );
334     args.GetReturnValue().Set( wrappedLayer );
335   }
336 }
337
338 /**
339  * Search through this actor's hierarchy for an actor with the given unique ID.
340  * The actor itself is also considered in the search
341  *
342  * @for Actor
343  * @method findChildById
344  * @param {Integer} id
345  * @return {Object} actor on success, empty actor handle if not found
346  */
347 void ActorApi::FindChildById( const v8::FunctionCallbackInfo<v8::Value>& args )
348 {
349   v8::Isolate* isolate = args.GetIsolate();
350   v8::HandleScope handleScope( isolate );
351   Actor parent = GetActor( isolate, args );
352
353   bool found( false );
354   int id = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 );
355   if( !found )
356   {
357     DALI_SCRIPT_EXCEPTION( isolate, "Integer parameter missing" );
358     return;
359   }
360   Actor childActor = parent.FindChildById( id );
361   if( childActor )
362   {
363     // wrap the child
364     v8::Local < v8::Object > wrappedLayer = ActorWrapper::WrapActor( isolate, childActor );
365     args.GetReturnValue().Set( wrappedLayer );
366   }
367 }
368
369
370 /**
371  * retrieve the actor's parent.
372  *
373  * @for Actor
374  * @method getParent
375  * @return {Object} actor on success, empty actor handle if actor has no parent
376  */
377 void ActorApi::GetParent( const v8::FunctionCallbackInfo<v8::Value>& args )
378 {
379   v8::Isolate* isolate = args.GetIsolate();
380   v8::HandleScope handleScope( isolate );
381   Actor actor = GetActor( isolate, args );
382   Actor parent = actor.GetParent();
383
384   if( parent )
385   {
386     v8::Local < v8::Object > wrappedLayer = ActorWrapper::WrapActor( isolate, parent );
387     args.GetReturnValue().Set( wrappedLayer );
388   }
389 }
390 /**
391  * Converts screen coordinates into the actor's coordinate system using the default camera.
392  *
393  * The actor coordinates are relative to the top-left (0.0, 0.0, 0.5)
394  *
395  * @example
396  *    var local = actor.screenToLocal( [ 10, 53 ]);
397  *    var xPos = local.x;
398  *    var yPos = local.y;
399  *
400  *
401  * @for Actor
402  * @method screenToLocal
403  * @param {Object}  ScreenCoordinates array of 2 objects
404  * @return {Object} local coordinates object with x,y properties
405  */
406 void ActorApi::ScreenToLocal( const v8::FunctionCallbackInfo<v8::Value>& args )
407 {
408   v8::Isolate* isolate = args.GetIsolate();
409   v8::HandleScope handleScope( isolate );
410   Actor actor = GetActor( isolate, args );
411
412   //ool ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const;
413   bool found( false );
414
415   int argCount( args.Length() );
416   Vector2 vector;
417
418   if( argCount == 1 )
419   {
420     vector = V8Utils::GetVector2Parameter( PARAMETER_0, found, isolate, args );
421     if( !found )
422     {
423       DALI_SCRIPT_EXCEPTION( isolate, "invalid parameters (x,y)" );
424       return;
425     }
426   }
427   else
428   {
429     DALI_SCRIPT_EXCEPTION( isolate, "invalid parameters (x,y)" );
430     return;
431   }
432   float localX, localY;
433   actor.ScreenToLocal( localX, localY, vector.x, vector.y );
434
435   v8::Local < v8::Object > localCoordinates = v8::Object::New( isolate );
436
437   localCoordinates->Set( v8::String::NewFromUtf8( isolate, "x" ), v8::Number::New( isolate, localX ) );
438   localCoordinates->Set( v8::String::NewFromUtf8( isolate, "y" ), v8::Number::New( isolate, localY ) );
439
440   args.GetReturnValue().Set( localCoordinates );
441
442 }
443
444 /**
445  * Sets whether the actor should be focusable by keyboard navigation.
446  *
447  * @for Actor
448  * @method setKeyboardFocusable
449  * @param {Boolean}  folcusable
450  */
451 void ActorApi::SetKeyboardFocusable( const v8::FunctionCallbackInfo<v8::Value>& args )
452 {
453   v8::Isolate* isolate = args.GetIsolate();
454   v8::HandleScope handleScope( isolate );
455   Actor actor = GetActor( isolate, args );
456   bool parameterFound( false );
457   bool focus = V8Utils::GetBooleanParameter( PARAMETER_0, parameterFound, isolate, args );
458   if( !parameterFound )
459   {
460     DALI_SCRIPT_EXCEPTION( isolate, "boolean parameter missing" );
461     return;
462   }
463
464   actor.SetKeyboardFocusable( focus );
465 }
466
467 /**
468  * Returns whether the actor is focusable by keyboard navigation.
469  *
470  *
471  * @for Actor
472  * @method isKeyboardFocusable
473  * @return {Boolean}  folcusable
474  */
475 void ActorApi::IsKeyboardFocusable( const v8::FunctionCallbackInfo<v8::Value>& args )
476 {
477   v8::Isolate* isolate = args.GetIsolate();
478   v8::HandleScope handleScope( isolate );
479   Actor actor = GetActor( isolate, args );
480
481   args.GetReturnValue().Set( v8::Boolean::New( isolate, actor.IsKeyboardFocusable() ) );
482
483 }
484 /**
485  * retrieve the actor type
486  *
487  * @for Actor
488  * @method getActorType
489  * @return {String} Actor, ImageActor, MeshActor, Layer, CameraActor ...
490  */
491 void ActorApi::GetActorType( const v8::FunctionCallbackInfo<v8::Value>& args )
492 {
493   v8::Isolate* isolate = args.GetIsolate();
494   v8::HandleScope handleScope( isolate );
495   Actor actor = GetActor( isolate, args );
496
497   std::string name = actor.GetTypeName();
498   v8::Local < v8::String > v8String = v8::String::NewFromUtf8( isolate, name.c_str() );
499   args.GetReturnValue().Set( v8String );
500 }
501 /**
502  * Return the natural size of the actor.
503  *
504  * @for Actor
505  * @method getNaturalSize
506  * @return {Object} { x, y, z }
507  */
508 void ActorApi::GetNaturalSize( const v8::FunctionCallbackInfo<v8::Value>& args )
509 {
510   v8::Isolate* isolate = args.GetIsolate();
511   v8::HandleScope handleScope( isolate );
512   Actor actor = GetActor( isolate, args );
513
514   Vector3 size( actor.GetNaturalSize() );
515
516   v8::Local<v8::Object> sizeObject = v8::Object::New( isolate );
517
518   sizeObject->Set( v8::String::NewFromUtf8( isolate, "x" ), v8::Integer::New( isolate, size.width ) );
519   sizeObject->Set( v8::String::NewFromUtf8( isolate, "y" ), v8::Integer::New( isolate, size.height ) );
520   sizeObject->Set( v8::String::NewFromUtf8( isolate, "z" ), v8::Integer::New( isolate, size.depth ) );
521
522   args.GetReturnValue().Set( sizeObject );
523 }
524
525 /**
526  *  Calculate the width of the actor given a height
527  *
528  * The natural size is used for default calculation.
529  * size 0 is treated as aspect ratio 1:1.
530  * @for Actor
531  * @method getWidthForHeight
532  * @param {Float} height to use
533  * @return {Float} Return the width based on the height
534  * @example
535  *   myTextLabel.getWidthForHeight(40);
536  *
537  * // DALi uses this formula internally
538  * // width = naturalSize.width * height / naturalSize.height;
539  *
540  *
541  */
542 void ActorApi::GetWidthForHeight( const v8::FunctionCallbackInfo<v8::Value>& args )
543 {
544   v8::Isolate* isolate = args.GetIsolate();
545   v8::HandleScope handleScope( isolate );
546   Actor actor = GetActor( isolate, args );
547
548   bool found;
549   float height = V8Utils::GetFloatParameter( PARAMETER_0, found, isolate, args, 0.f );
550   if( !found )
551   {
552     DALI_SCRIPT_EXCEPTION( isolate, "missing height parameter");
553     return;
554   }
555   args.GetReturnValue().Set( v8::Number::New( isolate, actor.GetWidthForHeight( height ) ) );
556 }
557
558 /**
559  *  Calculate the height of the actor given a width
560  *
561  * The natural size is used for default calculation.
562  * size 0 is treated as aspect ratio 1:1.
563  * @for Actor
564  * @method getHeightForWidth
565  * @param {Float} width to use
566  * @return {Float} Return the height based on the width
567  * @example
568  *   myTextLabel.getHeightForWidth(250);
569  *
570  * // DALi uses this formula internally
571  * // height = naturalSize.height * width / naturalSize.width
572  */
573 void ActorApi::GetHeightForWidth( const v8::FunctionCallbackInfo<v8::Value>& args )
574 {
575   v8::Isolate* isolate = args.GetIsolate();
576   v8::HandleScope handleScope( isolate );
577   Actor actor = GetActor( isolate, args );
578
579   bool found;
580   float width = V8Utils::GetFloatParameter( PARAMETER_0, found, isolate, args, 0.f );
581   if( !found )
582   {
583     DALI_SCRIPT_EXCEPTION( isolate, "missing width parameter");
584     return;
585   }
586   args.GetReturnValue().Set( v8::Number::New( isolate, actor.GetHeightForWidth( width ) ) );
587 }
588 /**
589  * Move an actor relative to its existing position.
590  * @example
591  *
592  *    // using an array
593  *    actor.translateBy( [20,40,0] );
594  *
595  * @for Actor
596  * @method translateBy
597  * @param {object} an array of 3 numbers
598  */
599 void ActorApi::TranslateBy( const v8::FunctionCallbackInfo<v8::Value>& args )
600 {
601   v8::Isolate* isolate = args.GetIsolate();
602   v8::HandleScope handleScope( isolate );
603   Actor actor = GetActor( isolate, args );
604
605   //Get displacement vector
606   Vector3 vector;
607   int argCount( args.Length() );
608   if( argCount == 1 )
609   {
610     bool found(false);
611     vector = V8Utils::GetVector3Parameter( PARAMETER_0, found, isolate, args );
612     if( !found )
613     {
614       DALI_SCRIPT_EXCEPTION( isolate, "Vector3 move parameter missing" );
615       return;
616     }
617   }
618   else
619   {
620     DALI_SCRIPT_EXCEPTION( isolate, "Vector3 move parameter missing" );
621     return;
622   }
623   actor.TranslateBy( vector );
624
625 }
626
627
628 /**
629  * Apply a relative rotation to an actor.
630  * @example
631  *
632  *     var rotation =new dali.Rotation( pitch, roll, yaw );
633  *     actor.rotateBy( rotation );
634  *
635  * @for Actor
636  * @method rotateBy
637  * @param {object} dali rotation object
638  */
639 void ActorApi::RotateBy( const v8::FunctionCallbackInfo<v8::Value>& args )
640 {
641   v8::Isolate* isolate = args.GetIsolate();
642   v8::HandleScope handleScope( isolate );
643   Actor actor = GetActor( isolate, args );
644
645   bool found( false );
646   Property::Value rotation = V8Utils::GetPropertyValueParameter( PARAMETER_0, found, isolate, args );
647
648   if( rotation.GetType() != Property::ROTATION )
649   {
650     DALI_SCRIPT_EXCEPTION( isolate, "Rotation parameter missing" );
651     return;
652   }
653   // the rotation parameter has to be either a AngleAxis or a Quaternion
654   // both will work when calling Get( Quaternion);
655
656   Quaternion quaternionValue;
657   rotation.Get( quaternionValue );
658
659   actor.RotateBy( quaternionValue );
660 }
661
662 /**
663  * Apply a relative scale to an actor.
664  * @example
665  *    // Double actor width and height ( keep depth the same )
666  *    // using an array
667  *    actor.scaleBy( [2,2,1] );
668  *
669  *
670  * @for Actor
671  * @method scaleBy
672  * @param {object} JavaScript array
673  */
674 void ActorApi::ScaleBy( const v8::FunctionCallbackInfo<v8::Value>& args )
675 {
676   v8::Isolate* isolate = args.GetIsolate();
677   v8::HandleScope handleScope( isolate );
678   Actor actor = GetActor( isolate, args );
679
680   Vector3 vector;
681   int argCount( args.Length() );
682   if( argCount == 1 )
683   {
684     bool found(false);
685     vector = V8Utils::GetVector3Parameter( PARAMETER_0, found, isolate, args );
686     if( !found )
687     {
688       DALI_SCRIPT_EXCEPTION( isolate, "Vector3 move parameter missing" );
689       return;
690     }
691   }
692   else
693   {
694     DALI_SCRIPT_EXCEPTION( isolate, "Vector3 parameter missing" );
695     return;
696   }
697   actor.ScaleBy( vector );
698 }
699
700 } // namespace V8Plugin
701
702 } // namespace Dali