9b81f4115dd2a0badc150293f397098f6ba3bbc6
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / actors / actor-wrapper.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-wrapper.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/object/type-registry.h>
23 #include <dali-toolkit/public-api/controls/control.h>
24
25 // INTERNAL INCLUDES
26 #include <actors/layer-api.h>
27 #include <actors/actor-api.h>
28 #include <actors/image-actor-api.h>
29 #include <actors/camera-actor-api.h>
30 #include <v8-utils.h>
31 #include <dali-wrapper.h>
32
33 namespace Dali
34 {
35
36 namespace V8Plugin
37 {
38
39 v8::Persistent<v8::ObjectTemplate> ActorWrapper::mActorTemplate;
40 v8::Persistent<v8::ObjectTemplate> ActorWrapper::mImageActorTemplate;
41 v8::Persistent<v8::ObjectTemplate> ActorWrapper::mCameraActorTemplate;
42 v8::Persistent<v8::ObjectTemplate> ActorWrapper::mLayerActorTemplate;
43
44 namespace
45 {
46
47
48 /**
49  * pointer to a persistent template handle
50  */
51 struct ActorTemplate
52 {
53   v8::Persistent<v8::ObjectTemplate>* actorTemplate;
54 };
55
56 /**
57  * array of templates for each type of actor
58  */
59 const ActorTemplate ActorTemplateLookup[]=
60 {
61     { &ActorWrapper::mActorTemplate },        // ACTOR
62     { &ActorWrapper::mImageActorTemplate },   // IMAGE_ACTOR
63     { &ActorWrapper::mLayerActorTemplate },   // LAYER_ACTOR
64     { &ActorWrapper::mCameraActorTemplate}    // CAMERA_ACTOR
65 };
66
67 /**
68  * Bitmask of API's that an actor can support
69  */
70 enum ActorApiBitMask
71 {
72   ACTOR_API              = 1 << 0,
73   IMAGE_ACTOR_API        = 1 << 1,
74   LAYER_API              = 1 << 2,
75   CAMERA_ACTOR_API       = 1 << 3,
76 };
77
78 /**
79  * structure used for the ActorApiLookup.
80  */
81 struct ActorApiStruct
82 {
83   const char* actorName;
84   ActorWrapper::ActorType actorType;
85   Actor (*constructor)( const v8::FunctionCallbackInfo< v8::Value >& args);
86   int supportApis;
87 };
88
89 /**
90  * Lookup table to match a actor type with a constructor and supported API's.
91  * HandleWrapper::ActorType is used to index this table
92  */
93 const ActorApiStruct ActorApiLookup[]=
94 {
95   {"Actor",      ActorWrapper::ACTOR,        ActorApi::New,       ACTOR_API },
96   {"ImageActor", ActorWrapper::IMAGE_ACTOR,  ImageActorApi::New,  ACTOR_API | IMAGE_ACTOR_API   },
97   {"Layer",      ActorWrapper::LAYER_ACTOR,  LayerApi::New,       ACTOR_API | LAYER_API                                },
98   {"CameraActor",ActorWrapper::CAMERA_ACTOR, CameraActorApi::New, ACTOR_API | CAMERA_ACTOR_API                         },
99 };
100
101 const unsigned int ActorApiLookupCount = sizeof(ActorApiLookup)/sizeof(ActorApiLookup[0]);
102
103
104
105 /**
106  * Creates an actor given a type name
107  * Uses the type registry to create an actor of the correct type
108  */
109 Actor CreateActor( const v8::FunctionCallbackInfo< v8::Value >& args,
110                         const std::string& typeName )
111 {
112   Actor actor;
113
114   ActorWrapper::ActorType actorType = ActorWrapper::GetActorType( typeName );
115
116   // if we don't currently support the actor type, then use type registry to create it
117   if( actorType == ActorWrapper::UNKNOWN_ACTOR )
118   {
119       DALI_SCRIPT_EXCEPTION( args.GetIsolate(), "Unknown actor type" );
120       return Actor();
121   }
122   else
123   {
124     // run the constructor for this type of actor so it can pull out
125     // custom parameters, e.g. new ImageActor( MyImage );
126     actor = (ActorApiLookup[actorType].constructor)( args );
127   }
128   return actor;
129 }
130
131
132
133 /**
134  * given an actor type return what api's it supports
135  */
136 int GetActorSupportedApis( ActorWrapper::ActorType type )
137 {
138   return ActorApiLookup[ type].supportApis;
139 }
140
141 /**
142  * Used for the ActorFunctionTable to map function names to functions
143  * with for a specific API
144  */
145 struct ActorFunctions
146 {
147   const char* name;               ///< function name
148   void (*function)( const v8::FunctionCallbackInfo< v8::Value >& args);
149   ActorApiBitMask api;
150 };
151
152 /**
153  * Contains a list of all functions that can be called an
154  * actor / image-actor / layer / camera-actor
155  */
156 const ActorFunctions ActorFunctionTable[]=
157 {
158     /**************************************
159     * Actor API (in order of actor.h)
160     * Any properties that have accessor functions are ignored to avoid duplication
161     **************************************/
162     // ignore. GetName()  use Actor.name
163     // ignore. SetName()  use Actor.name
164     { "GetId",             ActorApi::GetId,            ACTOR_API },
165     { "IsRoot",            ActorApi::IsRoot,           ACTOR_API },
166     { "OnStage",           ActorApi::OnStage,          ACTOR_API },
167     { "IsLayer",           ActorApi::IsLayer,          ACTOR_API },
168     { "GetLayer",          ActorApi::GetLayer,         ACTOR_API },
169     { "Add",               ActorApi::AddActor,         ACTOR_API },
170     { "Remove",            ActorApi::RemoveActor,      ACTOR_API },
171     { "IsEqualTo" ,        ActorApi::IsEqualTo,        ACTOR_API },
172     { "Unparent",          ActorApi::Unparent,         ACTOR_API },
173     { "GetChildCount",     ActorApi::GetChildCount,    ACTOR_API },
174     { "GetChildAt"   ,     ActorApi::GetChildAt,       ACTOR_API },
175     { "FindChildByName",   ActorApi::FindChildByName,  ACTOR_API },
176     { "FindChildById",     ActorApi::FindChildById,    ACTOR_API },
177     { "GetParent" ,        ActorApi::GetParent,        ACTOR_API },
178     { "GetActorType" ,     ActorApi::GetActorType,     ACTOR_API }, // custom for javascript
179
180     // ignore. SetParentOrigin() use Actor.parentOrigin
181     // ignore. GetCurrentParentOrigin()  use Actor.parentOrigin
182     // ignore. SetAnchorPoint()  use Actor.anchorPoint
183     // ignore. GetCurrentAnchorPoint()  use Actor.anchorPoint
184     // ignore. SetSize() use Actor.size
185     // ignore. GetCurrentSize() use Actor.size
186     { "GetNaturalSize",   ActorApi::GetNaturalSize,    ACTOR_API },
187     { "GetWidthForHeight",ActorApi::GetWidthForHeight, ACTOR_API },
188     { "GetHeightForWidth",ActorApi::GetHeightForWidth, ACTOR_API },
189     // ignore. SetPosition(....) use Actor.position
190     // ignore. SetX, SetY, SetZ,  use Actor.position.x, Actor.position.y, Actor.position.z
191     { "TranslateBy",         ActorApi::TranslateBy,              ACTOR_API },
192     // ignore GetCurrentPosition(). use Actor.position
193     // ignore GetCurrentWorldPosition() use Actor.worldPosition
194     // ignore SetPositionInheritanceMode() use Actor.positionInheritance
195     // ignore GetPositionInheritanceMode()  use Actor.positionInheritance
196     // ignore SetOrientation() use Actor.orientation
197     { "RotateBy",         ActorApi::RotateBy,          ACTOR_API },
198     // ignore GetCurrentOrientation() use Actor.orientation
199     // ignore SetInheritOrientation() use Actor.inheritOrientation
200     // ignore IsOrientationInherited() use Actor.inheritOrientation
201     // ignore GetCurrentWorldOrientation() use Actor.worldOrientation
202     // ignore SetScale() use Actor.scale
203     { "ScaleBy",         ActorApi::ScaleBy,            ACTOR_API },
204     // ignore GetCurrentScale() use Actor.scale
205     // ignore GetCurrentWorldScale() use Actor.worldScale
206     // ignore SetInheritScale() use Actor.inheritScale
207     // ignore IsScaleInherited() use Actor.inheritScale
208     // ignore GetCurrentWorldMatrix() use Actor.worldMatrix
209     // ignore SetVisible() use Actor.visible
210     // ignore IsVisible() use Actor.visible
211     // ignore SetOpacity() use Actor.opacity
212     // ignore GetCurrentOpacity() use Actor.opacity
213     // ignore SetColor() use Actor.color
214     // ignore GetCurrentColor() use Actor.color
215     // ignore SetColorMode() use Actor.colorMode
216     // ignore GetColorMode() use Actor.colorMode
217     // ignore GetCurrentWorldColor() use Actor.worldColor
218     // ignore SetInheritShaderEffect() use Actor.inheritShaderEffect
219     // ignore GetInheritShaderEffect() use Actor.inheritShaderEffect
220     // ignore SetDrawMode() use Actor.drawMode
221     // ignore GetDrawMode() use Actor.drawMode
222     // ignore SetSensitive() use Actor.sensitve
223     // ignore IsSensitive() use Actor.sensitive
224     { "ScreenToLocal"       , ActorApi::ScreenToLocal,         ACTOR_API},
225     // ignore SetLeaveRequired() use Actor.leaveRequired
226     // ignore GetLeaveRequired() use Actor.leaveRequired
227     { "SetKeyboardFocusable", ActorApi::SetKeyboardFocusable,  ACTOR_API }, //-- should this be a property???
228     { "IsKeyboardFocusable" , ActorApi::IsKeyboardFocusable,   ACTOR_API }, //-- should this be a property???
229
230     /**************************************
231      * Layer  API (in order of layer.h)
232      **************************************/
233     { "GetDepth",           LayerApi::GetDepth,                 LAYER_API  },
234     { "Raise",              LayerApi::Raise,                    LAYER_API  },
235     { "Lower",              LayerApi::Lower,                    LAYER_API  },
236     { "RaiseAbove",         LayerApi::RaiseAbove,               LAYER_API  },
237     { "RaiseBelow",         LayerApi::LowerBelow,               LAYER_API  },
238     { "RaiseToTop",         LayerApi::RaiseToTop,               LAYER_API  },
239     { "LowerToBottom",      LayerApi::ToBottom,                 LAYER_API  },
240     { "MoveAbove",          LayerApi::MoveAbove,                LAYER_API  },
241     { "MoveBelow",          LayerApi::MoveBelow,                LAYER_API  },
242     // ignore SetClipping, use layer.clippingEnable
243     // ignore IsClipping, use layer.clippingEnable
244     // ignore SetClippingBox, use layer.clippingBox
245     { "SetDepthTestDisabled", LayerApi::SetDepthTestDisabled,   LAYER_API },
246     { "IsDepthTestDisabled",  LayerApi::IsDepthTestDisabled,    LAYER_API },
247     // @todo SetSortFunction
248
249     /**************************************
250      * Image Actor API (in order of image-actor.h)
251      **************************************/
252
253     { "SetImage",           ImageActorApi::SetImage,              IMAGE_ACTOR_API },
254     { "GetImage",           ImageActorApi::GetImage,              IMAGE_ACTOR_API },
255     // ignore SetPixelArea, use imageActor.pixelArea
256     // ignore GetPixelArea, use imageActor.pixelArea
257     // ignore SetStyle, use imageActor.style
258     // ignore GetStyle, use imageActor.style
259     // ignore SetNinePatchBorder use imageActor.border
260     // ignore GetNinePatchBorder use imageActor.border
261     { "SetSortModifier",    ImageActorApi::SetSortModifier,   IMAGE_ACTOR_API  },
262     { "GetSortModifier",    ImageActorApi::GetSortModifier,   IMAGE_ACTOR_API  },
263     { "SetBlendMode",       ImageActorApi::SetBlendMode,      IMAGE_ACTOR_API  },
264     { "GetBlendMode",       ImageActorApi::GetBlendMode,      IMAGE_ACTOR_API  },
265     { "SetBlendFunc",       ImageActorApi::SetBlendFunc,      IMAGE_ACTOR_API  },
266     { "GetBlendFunc",       ImageActorApi::GetBlendFunc,      IMAGE_ACTOR_API  },
267     { "SetShaderEffect",    ImageActorApi::SetShaderEffect,   IMAGE_ACTOR_API  },
268     { "GetShaderEffect",    ImageActorApi::GetShaderEffect,   IMAGE_ACTOR_API  },
269     { "RemoveShaderEffect", ImageActorApi::RemoveShaderEffect,IMAGE_ACTOR_API  },
270     // ignore SetFadeIn use imageActor.fadeIn
271     // ignore GetFadeIn use imageActor.fadeIn
272     // ignore SetFadeInDuration use imageActor.fadeInDuration
273     // ignore GetFadeInDuration use imageActor.fadeInDuration
274     //{ "GetCurrentImageSize", ImageActorApi::GetCurrentImageSize,  IMAGE_ACTOR_API },
275
276     /**************************************
277      * Mesh Actor API (in order of mesh-actor.h)
278      **************************************/
279     // @todo a version of MeshActor::New( mesh )
280     // @todo a version of MeshActor::New( AnimatableMesh )
281     // @todo SetMaterial
282     // @todo GetMaterial
283     // @todo BindBonesToMesh
284
285     /**************************************
286      * Camera Actor API (in order of camera.h)
287      **************************************/
288     // ignore SetType use camera.type
289     // ignore GetType use camera.type
290     // ignore SetProjectionMode use camera.projectionMode
291     // ignore GetProjectionMode use camera.projectionMode
292     // ignore SetFieldOfView use camera.fieldOfView
293     // ignore GetFieldOfView use camera.fieldOfView
294     // ignore SetAspectRatio use camera.aspectRatio
295     // ignore GetAspectRatio use camera.aspectRatio
296     // ignore SetNearClippingPlane use camera.nearPlaneDistance
297     // ignore GetNearClippingPlane use camera.nearPlaneDistance
298     // ignore SetFarClippingPlane use camera.farPlaneDistance
299     // ignore GetFarClippingPlane use camera.farPlaneDistance
300     // ignore GetTargetPosition use camera.targetPosition
301     // ignore SetInvertYAxis use camera.invertYAxis
302     // ignore GetInvertYAxis use camera.invertYAxis
303     { "SetPerspectiveProjection",   CameraActorApi::SetPerspectiveProjection,   CAMERA_ACTOR_API },
304     { "SetOrthographicProjection",  CameraActorApi::SetOrthographicProjection,  CAMERA_ACTOR_API },
305
306 };
307
308 const unsigned int ActorFunctionTableCount = sizeof(ActorFunctionTable)/sizeof(ActorFunctionTable[0]);
309 } //un-named space
310
311
312 ActorWrapper::ActorWrapper( Actor actor,
313               GarbageCollectorInterface& gc )
314 : HandleWrapper( BaseWrappedObject::ACTOR , actor, gc ),
315   mActor( actor )
316
317 {
318 }
319
320 v8::Handle<v8::Object> ActorWrapper::WrapActor(v8::Isolate* isolate, Actor actor )
321 {
322   v8::EscapableHandleScope handleScope( isolate );
323
324   // Check whether the actor is a Control
325   ActorWrapper::ActorType type = Toolkit::Control::DownCast(actor) ? ACTOR : GetActorType( actor.GetTypeName() );
326   v8::Local<v8::Object> object = WrapActor( isolate, actor, type );
327
328   return handleScope.Escape( object );
329 }
330
331 Actor ActorWrapper::GetActor()
332 {
333   return mActor;
334 }
335
336 v8::Handle<v8::Object> ActorWrapper::WrapActor( v8::Isolate* isolate, Actor actor, ActorType actorType )
337 {
338   v8::EscapableHandleScope handleScope( isolate );
339   v8::Local<v8::ObjectTemplate> objectTemplate;
340
341   objectTemplate = GetActorTemplate( isolate, actorType );
342
343   // create an instance of the template
344   v8::Local<v8::Object> localObject = objectTemplate->NewInstance();
345
346   // create teh actor object
347   ActorWrapper* pointer = new ActorWrapper( actor, Dali::V8Plugin::DaliWrapper::Get().GetDaliGarbageCollector() );
348
349   // assign the JavaScript object to the wrapper.
350   // This also stores Dali object, in an internal field inside the JavaScript object.
351   pointer->SetJavascriptObject( isolate, localObject );
352
353   return handleScope.Escape( localObject );
354 }
355
356 v8::Local<v8::ObjectTemplate> ActorWrapper::GetActorTemplate( v8::Isolate* isolate, ActorWrapper::ActorType type )
357 {
358   v8::EscapableHandleScope handleScope( isolate );
359   v8::Local<v8::ObjectTemplate> objectTemplate;
360
361   if( ActorTemplateLookup[type].actorTemplate->IsEmpty() )
362   {
363     objectTemplate = MakeDaliActorTemplate( isolate, type );
364     ActorTemplateLookup[type].actorTemplate->Reset( isolate, objectTemplate );
365   }
366   else
367   {
368     // get the object template
369     objectTemplate = v8::Local<v8::ObjectTemplate>::New( isolate, *ActorTemplateLookup[type].actorTemplate );
370   }
371
372   return handleScope.Escape( objectTemplate );
373 }
374
375 v8::Handle<v8::ObjectTemplate> ActorWrapper::MakeDaliActorTemplate( v8::Isolate* isolate, ActorType actorType )
376 {
377   v8::EscapableHandleScope handleScope( isolate );
378
379   v8::Local<v8::ObjectTemplate> objTemplate = v8::ObjectTemplate::New();
380
381   objTemplate->SetInternalFieldCount( BaseWrappedObject::FIELD_COUNT );
382
383   // find out what API's this actor supports
384   int supportApis = GetActorSupportedApis( actorType );
385
386   // add our function properties
387   for( unsigned int i = 0; i < ActorFunctionTableCount; ++i )
388   {
389     const ActorFunctions property =  ActorFunctionTable[i];
390
391     // check to see if the actor supports a certain type of API
392     // e.g. ImageActor will support ACTOR_API, RENDERABLE_API and IMAGE_ACTOR_API
393     if( supportApis &  property.api )
394     {
395       std::string funcName = V8Utils::GetJavaScriptFunctionName( property.name);
396
397       objTemplate->Set( v8::String::NewFromUtf8(   isolate, funcName.c_str() ),
398                       v8::FunctionTemplate::New( isolate, property.function ) );
399     }
400   }
401
402   // property handle intercepts property getters and setters and signals
403   HandleWrapper::AddInterceptsToTemplate( isolate, objTemplate );
404
405
406   return handleScope.Escape( objTemplate );
407 }
408
409 void ActorWrapper::NewActor( const v8::FunctionCallbackInfo< v8::Value >& args)
410 {
411   v8::Isolate* isolate = args.GetIsolate();
412   v8::HandleScope handleScope( isolate );
413
414   if( !args.IsConstructCall() )
415   {
416     DALI_SCRIPT_EXCEPTION( isolate, "constructor called without 'new" );
417     return;
418   }
419
420   // find out the callee function name...e.g. ImageActor, MeshActor
421   v8::Local<v8::Function> callee = args.Callee();
422   v8::Local<v8::Value> v8String = callee->GetName();
423   std::string typeName = V8Utils::v8StringToStdString( v8String );
424
425   // create a new actor based on type, using the type registry.
426   Actor actor = CreateActor( args, typeName );
427
428   v8::Local<v8::Object> localObject = WrapActor( isolate, actor );
429
430   args.GetReturnValue().Set( localObject );
431 }
432
433 void ActorWrapper::NewControl( const v8::FunctionCallbackInfo< v8::Value >& args)
434 {
435   v8::Isolate* isolate = args.GetIsolate();
436   v8::HandleScope handleScope( isolate );
437
438   if( !args.IsConstructCall() )
439   {
440     DALI_SCRIPT_EXCEPTION( isolate, "constructor called without 'new" );
441     return;
442   }
443
444   bool found( false );
445   std::string controlName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate,  args );
446
447   if( !found )
448   {
449     DALI_SCRIPT_EXCEPTION( isolate, "missing control name" );
450     return;
451   }
452   Actor control;
453   Dali::TypeInfo typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( controlName );
454   if( typeInfo ) // handle, check if it has a value
455   {
456     Dali::BaseHandle handle = typeInfo.CreateInstance();
457     if( handle )
458     {
459       control = Actor::DownCast( handle );
460     }
461   }
462
463   v8::Local<v8::Object> localObject = WrapActor( isolate, control, ACTOR );
464
465   args.GetReturnValue().Set( localObject );
466 }
467
468
469 /**
470  * given an actor type name, e.g. ImageActor returns the type, e.g. ActorWrapper::IMAGE_ACTOR
471  */
472 ActorWrapper::ActorType ActorWrapper::GetActorType( const std::string& name )
473 {
474   for( unsigned int i = 0 ; i < ActorApiLookupCount ; i++ )
475   {
476     if( ActorApiLookup[i].actorName == name )
477     {
478       return ActorApiLookup[i].actorType;
479     }
480   }
481   return ActorWrapper::UNKNOWN_ACTOR;
482 }
483
484
485
486 } // namespace V8Plugin
487
488 } // namespace Dali