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