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