Merge remote-tracking branch 'origin/tizen' into new_text
[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-constraint-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  * Move an actor relative to its existing position.
503  * @example
504  *
505  *    // using an array
506  *    actor.translateBy( [20,40,0] );
507  *
508  * @for Actor
509  * @method translateBy
510  * @param {object} an array of 3 numbers
511  */
512 void ActorApi::TranslateBy( const v8::FunctionCallbackInfo<v8::Value>& args )
513 {
514   v8::Isolate* isolate = args.GetIsolate();
515   v8::HandleScope handleScope( isolate );
516   Actor actor = GetActor( isolate, args );
517
518   //Get displacement vector
519   Vector3 vector;
520   int argCount( args.Length() );
521   if( argCount == 1 )
522   {
523     bool found(false);
524     vector = V8Utils::GetVector3Parameter( PARAMETER_0, found, isolate, args );
525     if( !found )
526     {
527       DALI_SCRIPT_EXCEPTION( isolate, "Vector3 move parameter missing" );
528       return;
529     }
530   }
531   else
532   {
533     DALI_SCRIPT_EXCEPTION( isolate, "Vector3 move parameter missing" );
534     return;
535   }
536   actor.TranslateBy( vector );
537
538 }
539
540
541 /**
542  * Apply a relative rotation to an actor.
543  * @example
544  *
545  *     var rotation =new dali.Rotation( pitch, roll, yaw );
546  *     actor.rotateBy( rotation );
547  *
548  * @for Actor
549  * @method rotateBy
550  * @param {object} dali rotation object
551  */
552 void ActorApi::RotateBy( const v8::FunctionCallbackInfo<v8::Value>& args )
553 {
554   v8::Isolate* isolate = args.GetIsolate();
555   v8::HandleScope handleScope( isolate );
556   Actor actor = GetActor( isolate, args );
557
558   bool found( false );
559   Property::Value rotation = V8Utils::GetPropertyValueParameter( PARAMETER_0, found, isolate, args );
560
561   if( rotation.GetType() != Property::ROTATION )
562   {
563     DALI_SCRIPT_EXCEPTION( isolate, "Rotation parameter missing" );
564     return;
565   }
566   // the rotation parameter has to be either a AngleAxis or a Quaternion
567   // both will work when calling Get( Quaternion);
568
569   Quaternion quaternionValue;
570   rotation.Get( quaternionValue );
571
572   actor.RotateBy( quaternionValue );
573 }
574
575 /**
576  * Apply a relative scale to an actor.
577  * @example
578  *    // Double actor width and height ( keep depth the same )
579  *    // using an array
580  *    actor.scaleBy( [2,2,1] );
581  *
582  *
583  * @for Actor
584  * @method scaleBy
585  * @param {object} JavaScript array
586  */
587 void ActorApi::ScaleBy( const v8::FunctionCallbackInfo<v8::Value>& args )
588 {
589   v8::Isolate* isolate = args.GetIsolate();
590   v8::HandleScope handleScope( isolate );
591   Actor actor = GetActor( isolate, args );
592
593   Vector3 vector;
594   int argCount( args.Length() );
595   if( argCount == 1 )
596   {
597     bool found(false);
598     vector = V8Utils::GetVector3Parameter( PARAMETER_0, found, isolate, args );
599     if( !found )
600     {
601       DALI_SCRIPT_EXCEPTION( isolate, "Vector3 move parameter missing" );
602       return;
603     }
604   }
605   else
606   {
607     DALI_SCRIPT_EXCEPTION( isolate, "Vector3 parameter missing" );
608     return;
609   }
610   actor.ScaleBy( vector );
611 }
612
613 void ActorApi::ApplyPathConstraint( const v8::FunctionCallbackInfo< v8::Value >& args )
614 {
615   v8::Isolate* isolate = args.GetIsolate();
616   v8::HandleScope handleScope( isolate );
617
618   //Get target actor
619   Actor targetActor = GetActor( isolate, args );
620
621   //Get PathConstraint
622   bool found(false);
623   Handle pathConstraintHandle =  V8Utils::GetHandleParameter(PARAMETER_0, found, isolate, args );
624   if( !found )
625   {
626     DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 0 (PathConstraint)" );
627     return;
628   }
629   PathConstraint pathConstraint = PathConstraint::DownCast(pathConstraintHandle);
630
631   //Get target property
632   std::string propertyName = V8Utils::GetStringParameter( PARAMETER_1, found, isolate, args );
633   if(!found)
634   {
635     DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 1 (Property name)" );
636     return;
637   }
638
639   // try both properties with dashes and without
640   Property::Index targetPropertyIndex = targetActor.GetPropertyIndex( propertyName );
641   if( targetPropertyIndex == Property::INVALID_INDEX )
642   {
643     std::string convertedName = V8Utils::JavaScriptNameToPropertyName( propertyName );
644     targetPropertyIndex = targetActor.GetPropertyIndex( convertedName );
645
646     if( targetPropertyIndex == Property::INVALID_INDEX )
647     {
648       DALI_SCRIPT_EXCEPTION( isolate, "Property not found" );
649     }
650   }
651
652   //Get source actor
653   Actor sourceActor = V8Utils::GetActorParameter( PARAMETER_2, found, isolate, args );
654   if( !found )
655   {
656     DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 2 (Actor)" );
657   }
658
659   // try both properties with dashes and without
660   propertyName = V8Utils::GetStringParameter( PARAMETER_3, found, isolate, args );
661   if(!found)
662   {
663     DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 3 (Property name)" );
664     return;
665   }
666
667   Property::Index sourcePropertyIndex = sourceActor.GetPropertyIndex( propertyName );
668   if( sourcePropertyIndex == Property::INVALID_INDEX )
669   {
670     std::string convertedName = V8Utils::JavaScriptNameToPropertyName( propertyName );
671     sourcePropertyIndex = sourceActor.GetPropertyIndex( convertedName );
672
673     if( sourcePropertyIndex == Property::INVALID_INDEX )
674     {
675       DALI_SCRIPT_EXCEPTION( isolate, "Property not found" );
676       return;
677     }
678   }
679
680   //Check if forward vector is specified
681   Vector3 forward( 0.0f,0.0f,0.0f);
682   if( args.Length() > 4 )
683   {
684     forward =  V8Utils::GetVector3Parameter( PARAMETER_4, found, isolate, args );
685     if( !found )
686     {
687       DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 4 (Vector3)" );
688       return;
689     }
690   }
691
692   pathConstraint.Apply( Dali::Property(sourceActor,sourcePropertyIndex),
693                         Dali::Property(targetActor,targetPropertyIndex),
694                         forward );
695
696 }
697
698 void ActorApi::RemovePathConstraint( const v8::FunctionCallbackInfo< v8::Value >& args )
699 {
700   v8::Isolate* isolate = args.GetIsolate();
701   v8::HandleScope handleScope( isolate );
702
703   //Get target actor
704   Actor actor = GetActor( isolate, args );
705
706   //Get PathConstraint
707   bool found(false);
708   Handle pathConstraintHandle =  V8Utils::GetHandleParameter(PARAMETER_0, found, isolate, args );
709   if( !found )
710   {
711     DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 0 (PathConstraint)" );
712     return;
713   }
714   PathConstraint pathConstraint = PathConstraint::DownCast(pathConstraintHandle);
715   pathConstraint.Remove(actor);
716 }
717
718 } // namespace V8Plugin
719
720 } // namespace Dali