Remove UNSIGNED_INTEGER property type (removed from core)
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / object / property-value-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 // CLASS HEADER
18 #include "property-value-wrapper.h"
19
20 // EXTERNAL INCLUDES
21 #include <dali/integration-api/debug.h>
22 #include <dali/public-api/object/property-array.h>
23
24 // INTERNAL INCLUDES
25 #include <v8-utils.h>
26 #include <dali-wrapper.h>
27
28 namespace Dali
29 {
30
31 namespace V8Plugin
32 {
33
34 namespace
35 {
36
37 struct WrapTypeInfo
38 {
39   Dali::Property::Type propertyType;
40   BaseWrappedObject::Type wrappedType;
41 };
42 /**
43  * lookup table to convert between dali property types and wrapped types
44  * Wrapped types includes actors / timers / render tasks, hence we can't just
45  * use the dali property types to encode what a wrapped pointer contains
46  */
47 const WrapTypeInfo WrapTypeInfoLookup[]=
48 {
49   { Dali::Property::VECTOR2,    BaseWrappedObject::VECTOR2 },
50   { Dali::Property::VECTOR3,    BaseWrappedObject::VECTOR3 },
51   { Dali::Property::VECTOR4,    BaseWrappedObject::VECTOR4 },
52   { Dali::Property::RECTANGLE,  BaseWrappedObject::RECTANGLE  },
53   { Dali::Property::ROTATION,   BaseWrappedObject::ROTATION   },
54   { Dali::Property::MATRIX,     BaseWrappedObject::MATRIX     },
55   { Dali::Property::MATRIX3,    BaseWrappedObject::MATRIX3    },
56
57
58 };
59 const unsigned int WrapTypeLookupCount = sizeof( WrapTypeInfoLookup ) / sizeof( WrapTypeInfo );
60
61 BaseWrappedObject::Type GetWrappedType( Dali::Property::Type type )
62 {
63   for( unsigned int i = 0; i < WrapTypeLookupCount; ++i)
64   {
65     if( WrapTypeInfoLookup[ i ].propertyType == type )
66     {
67       return WrapTypeInfoLookup[ i ].wrappedType;
68     }
69   }
70   DALI_LOG_ERROR("GetWrappedType failed \n");
71   return BaseWrappedObject::UNKNOWN;
72 }
73
74 // Templates for setting members on propertys, like, x,y,z on a vector
75 template <typename T, typename S>
76 void SetX( Dali::Property::Value &value, S& v)
77 {
78   // to set a property value, we need to read into a temporary
79   // then assign it back.
80   // E.g.   Vector2 temp = value.Get<Vector2>();
81   //        temp.x = 10;
82   //        value = temp;
83   T tmp( value.Get<T>() );
84   tmp.x = v;
85   value = tmp;
86 }
87
88 template <typename T, typename S>
89 void SetY( Dali::Property::Value &value, S& v)
90 {
91   T tmp = value.Get<T>();
92   tmp.y = v;
93   value = tmp;
94 }
95
96 template <typename T, typename S>
97 void SetZ( Dali::Property::Value &value, S& v)
98 {
99   T tmp = value.Get<T>();
100   tmp.z = v;
101   value = tmp;
102 }
103
104 template <typename T, typename S>
105 void SetW( Dali::Property::Value &value, S& v)
106 {
107   T tmp = value.Get<T>();
108   tmp.w = v;
109   value = tmp;
110 }
111 template <typename T, typename S>
112 void SetWidth( Dali::Property::Value &value, S& v)
113 {
114   T tmp = value.Get<T>();
115   tmp.width = v;
116   value = tmp;
117 }
118
119 template <typename T, typename S>
120 void SetHeight( Dali::Property::Value &value, S& v)
121 {
122   T tmp = value.Get<T>();
123   tmp.height = v;
124   value = tmp;
125 }
126
127 v8::Handle< v8::Value > GetV8ValueFrom( v8::Isolate* isolate,
128                                         const Dali::Property::Value& value,
129                                         const std::string& field)
130 {
131   v8::EscapableHandleScope handleScope( isolate );
132   v8::Local<v8::Value> ret;
133
134   Dali::Property::Type type = value.GetType();
135   std::string objectType="Unknown type";
136
137   // simple property values are handled by the actor wrapper so we just handle property values with sub fields
138   switch(type)
139   {
140     case Dali::Property::VECTOR2:
141     {
142       objectType = "Vector2";
143
144       if( field == "x" || field == "width" )
145       {
146         Dali::Vector2 v2 = value.Get<Dali::Vector2>();
147         ret = v8::Number::New( isolate, v2.x);
148       }
149       else if(field == "y" || field == "height")
150       {
151         Dali::Vector2 v2 = value.Get<Dali::Vector2>();
152         ret = v8::Number::New( isolate, v2.y);
153       }
154
155       break;
156     }
157     case Dali::Property::VECTOR3:
158     {
159       objectType = "Vector3";
160
161       if(field == "x" || field == "width" || field == "r")
162       {
163         Dali::Vector3 v3 = value.Get<Dali::Vector3>();
164         ret = v8::Number::New( isolate, v3.x);
165       }
166       else if(field == "y" || field == "height" || field == "g")
167       {
168         Dali::Vector3 v3 = value.Get<Dali::Vector3>();
169         ret = v8::Number::New( isolate, v3.y);
170       }
171       else if(field == "z" || field == "depth" || field == "b")
172       {
173         Dali::Vector3 v3 = value.Get<Dali::Vector3>();
174         ret = v8::Number::New( isolate, v3.z);
175       }
176       break;
177     }
178     case Dali::Property::VECTOR4:
179     {
180       objectType = "vector4";
181
182       if(field == "x" || field == "s" || field == "r")
183       {
184         Dali::Vector4 v4 = value.Get<Dali::Vector4>();
185         ret = v8::Number::New( isolate, v4.x);
186       }
187       else if(field == "y" || field == "g" || field == "t")
188       {
189         Dali::Vector4 v4 = value.Get<Dali::Vector4>();
190         ret = v8::Number::New( isolate, v4.y);
191       }
192       else if(field == "z" || field == "r" || field == "b")
193       {
194         Dali::Vector4 v4 = value.Get<Dali::Vector4>();
195         ret = v8::Number::New( isolate, v4.z);
196       }
197       else if(field == "w" || field == "a" || field == "q")
198       {
199         Dali::Vector4 v4 = value.Get<Dali::Vector4>();
200         ret = v8::Number::New( isolate, v4.w);
201       }
202
203       break;
204     }
205     case Dali::Property::ROTATION:
206     {
207       objectType = "rotation";
208
209       if(field == "roll")
210       {
211         Dali::Vector4 v4 = value.Get<Dali::Quaternion>().EulerAngles();
212         ret = v8::Number::New( isolate, v4.z);
213       }
214       else if(field == "pitch")
215       {
216         Dali::Vector4 v4 = value.Get<Dali::Quaternion>().EulerAngles();
217         ret = v8::Number::New( isolate, v4.x);
218       }
219       else if(field == "yaw")
220       {
221         Dali::Vector4 v4 = value.Get<Dali::Quaternion>().EulerAngles();
222         ret = v8::Number::New( isolate, v4.y);
223       }
224
225        else if(field == "axis")
226       {
227         Dali::Vector3 axis;
228         Radian angle;
229         value.Get<Dali::Quaternion>().ToAxisAngle(axis, angle);
230         ret = PropertyValueWrapper::WrapDaliProperty( isolate , Dali::Property::Value( axis ) );
231       }
232       else if(field == "angle")
233       {
234         Dali::Vector3 axis;
235         Radian angle;
236         value.Get<Dali::Quaternion>().ToAxisAngle(axis, angle);
237         ret = PropertyValueWrapper::WrapDaliProperty( isolate , Dali::Property::Value( angle ) );
238       }
239       break;
240     }
241     case Dali::Property::RECTANGLE:
242     {
243       objectType = "rectangle";
244
245       if(field == "x")
246       {
247         Dali::Rect<int> r = value.Get<Dali::Rect<int> >();
248         ret = v8::Number::New( isolate, r.x);
249       }
250       else if(field == "y")
251       {
252         Dali::Rect<int> r = value.Get<Dali::Rect<int> >();
253         ret = v8::Number::New( isolate, r.y);
254       }
255       else if(field == "width")
256       {
257         Dali::Rect<int> r = value.Get<Dali::Rect<int> >();
258         ret = v8::Number::New( isolate, r.width);
259       }
260       else if(field == "height")
261       {
262         Dali::Rect<int> r = value.Get<Dali::Rect<int> >();
263         ret = v8::Number::New( isolate, r.height);
264       }
265       break;
266     }
267
268     default:
269     {
270       // will trigger a type error as ret.IsEmpty() == true
271       break;
272     }
273
274   } // switch type
275
276   if ( ret.IsEmpty() )
277   {
278     DALI_SCRIPT_EXCEPTION( isolate, "Cannot get property with field " + objectType+ ":" + field );
279   }
280   return handleScope.Escape(ret);
281 }
282
283
284 /*
285  * Setting a field on a property,  e.g.  Position.x = 5 or Rect.Width = 100
286  * The only property field that supports a struct is  rotation.axis
287  */
288 void SetFromV8Value(v8::Isolate* isolate,
289                      Dali::Property::Value& value,
290                      const std::string& field,
291                      v8::Local<v8::Value> v8Value )
292 {
293   v8::EscapableHandleScope handleScope( isolate );
294
295   Dali::Property::Type type = value.GetType();
296
297   float asFloat = 0.f;
298   int asInt = 0;
299
300   // all are numbers at the moment
301   if( v8Value->IsNumber() )
302   {
303     asFloat = static_cast<float>(v8Value->NumberValue());
304     asInt   = static_cast<int>(asFloat);
305   }
306   else
307   {
308     // if the v8 value isn't a number, then then only Dali object we support is a Vector3 part of a rotation
309     if( ! (type == Dali::Property::ROTATION && field == "axis") )
310     {
311       DALI_SCRIPT_EXCEPTION(isolate,std::string("Cannot set property with field (value is not a number):") + field);
312       return;
313     }
314   }
315
316   // simple property values are handled by the actor wrapper so we just handle property values with sub fields
317   switch(type)
318   {
319     case Dali::Property::VECTOR2:
320     {
321       if(field == "x" || field == "width")
322       {
323         SetX<Dali::Vector2>(value, asFloat);
324       }
325       else if(field == "y" || field == "height")
326       {
327         SetY<Dali::Vector2>(value, asFloat);
328       }
329       else
330       {
331         DALI_SCRIPT_EXCEPTION(isolate, std::string("Cannot set property with field (unknown type):") + field);
332         return;
333       }
334       break;
335     }
336     case Dali::Property::VECTOR3:
337     {
338       if(field == "x" || field == "width" || field == "r")
339       {
340         SetX<Dali::Vector3>(value, asFloat);
341       }
342       else if(field == "y" || field == "height" || field == "g")
343       {
344         SetY<Dali::Vector3>(value, asFloat);
345       }
346       else if(field == "z" || field == "depth" || field == "b")
347       {
348         SetZ<Dali::Vector3>(value, asFloat);
349       }
350       else
351       {
352         DALI_SCRIPT_EXCEPTION(isolate, std::string("Cannot set property with field (unknown type):") + field);
353         return;
354       }
355       break;
356     }
357     case Dali::Property::VECTOR4:
358     {
359       if(field == "x" || field == "s" || field == "r")
360       {
361         SetX<Dali::Vector4>(value, asFloat);
362       }
363       else if(field == "y" || field == "g" || field == "t")
364       {
365         SetY<Dali::Vector4>(value, asFloat);
366       }
367       else if(field == "z" || field == "r" || field == "b")
368       {
369         SetZ<Dali::Vector4>(value, asFloat);
370       }
371       else if(field == "w" || field == "a" || field == "q")
372       {
373         SetW<Dali::Vector4>(value, asFloat);
374       }
375       else
376       {
377         DALI_SCRIPT_EXCEPTION( isolate, std::string("Cannot set property with field (unknown type):") + field);
378         return;
379       }
380       break;
381     }
382     case Dali::Property::ROTATION:
383     {
384       if(field == "roll")
385       {
386         Dali::Vector4 v4 = value.Get<Dali::Quaternion>().EulerAngles();
387         v4.z = asFloat;
388         value = Dali::Quaternion( Radian(Degree(v4.x)), Radian(Degree(v4.y)), Radian(Degree(v4.z)) );
389       }
390       else if(field == "pitch")
391       {
392         Dali::Vector4 v4 = value.Get<Dali::Quaternion>().EulerAngles();
393         v4.x = asFloat;
394         value = Dali::Quaternion( Radian(Degree(v4.x)), Radian(Degree(v4.y)), Radian(Degree(v4.z)) );
395       }
396       else if(field == "yaw")
397       {
398         Dali::Vector4 v4 = value.Get<Dali::Quaternion>().EulerAngles();
399         v4.y = asFloat;
400         value = Dali::Quaternion( Radian(Degree(v4.x)), Radian(Degree(v4.y)), Radian(Degree(v4.z)) );
401       }
402       else if(field == "axis")
403       {
404         Dali::Vector3 axis;
405         Radian angle;
406         value.Get<Dali::Quaternion>().ToAxisAngle(axis, angle);
407
408         if( v8Value->IsObject() )
409         {
410           v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast( v8Value );
411
412           PropertyValueWrapper* wrapper = PropertyValueWrapper::Unwrap( isolate, object );
413           Dali::Property::Value v3 = wrapper->GetValue();
414
415           if(v3.GetType() == Dali::Property::VECTOR3)
416           {
417             value = Dali::Quaternion(angle, v3.Get<Dali::Vector3>());
418           }
419           else
420           {
421             DALI_SCRIPT_EXCEPTION( isolate, "Axis expects a Vector3:");
422             return;
423           }
424
425         }
426       }
427       else if(field == "angle")
428       {
429         Dali::Vector3 axis;
430         Radian angle;
431         value.Get<Dali::Quaternion>().ToAxisAngle( axis, angle );
432         value = Dali::Quaternion( Degree( asFloat ), axis );
433       }
434       else
435       {
436         DALI_SCRIPT_EXCEPTION(  isolate, std::string("Cannot set property with field (unknown type):") + field);
437         return;
438       }
439       break;
440     }
441     case Dali::Property::RECTANGLE:
442     {
443       if(field == "x")
444       {
445         SetX<Dali::Rect<int> >(value, asInt);
446       }
447       else if(field == "y")
448       {
449         SetY<Dali::Rect<int> >(value, asInt);
450       }
451       else if(field == "width")
452       {
453         SetWidth<Dali::Rect<int> >(value, asInt);
454       }
455       else if(field == "height")
456       {
457         SetHeight<Dali::Rect<int> >(value, asInt);
458       }
459       else
460       {
461         DALI_SCRIPT_EXCEPTION( isolate, std::string("Cannot set property with field (unknown type):") + field);
462         return;
463       }
464       break;
465     }
466     default:
467     {
468       DALI_SCRIPT_EXCEPTION( isolate, std::string("Cannot set property with field (unknown type):") + field);
469       return;
470       break;
471     }
472
473   } // switch type
474
475 } // SetFromV8Value
476
477
478 bool IsPrimitive( const Dali::Property::Value &value )
479 {
480   switch( value.GetType() )
481   {
482     case Dali::Property::BOOLEAN:
483     case Dali::Property::INTEGER:
484     case Dali::Property::STRING:
485     case Dali::Property::FLOAT:
486     {
487       return true;
488     }
489     default:
490     {
491       return false;
492     }
493   }
494 }
495 v8::Local<v8::Object> CreateJavaScriptPrimitive( v8::Isolate* isolate, const Dali::Property::Value &value )
496 {
497   v8::EscapableHandleScope handleScope( isolate );
498
499   v8::Local<v8::Value> v8Value;
500
501   switch( value.GetType() )
502    {
503      case Dali::Property::FLOAT:
504      {
505        v8Value = v8::Number::New( isolate, value.Get<float>()  );
506        break;
507      }
508      case Dali::Property::BOOLEAN:
509      {
510        v8Value = v8::Boolean::New(  isolate, value.Get<bool>());
511        break;
512      }
513      case Dali::Property::INTEGER:
514      {
515        v8Value = v8::Integer::New( isolate, value.Get<int>());
516        break;
517      }
518      case Dali::Property::STRING:
519      {
520        std::string string = value.Get< std::string >();
521        v8Value = v8::String::NewFromUtf8( isolate,  string.c_str());
522        break;
523      }
524      default:
525      {
526        DALI_LOG_ERROR("Primitive mismatch \n");
527        break;
528      }
529    }
530  v8::Local<v8::Object> ret = v8Value->ToObject();
531
532  return handleScope.Escape( ret );
533 }
534
535
536 } // un-named namespace
537
538
539
540 Dali::Property::Value PropertyValueWrapper::VectorOrMatrixFromV8Array( v8::Isolate* isolate, const v8::Local<v8::Value>& v8Value)
541 {
542   v8::EscapableHandleScope handleScope( isolate );
543
544   Dali::Property::Value ret;
545
546   if( !v8Value->IsArray() )
547   {
548     return ret;
549   }
550   v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast( v8Value );//v8::Array::Cast(  *v8Value);
551   uint32_t len = array->Length();
552   float out[16] = {0.f, 0.f, 0.f, 0.f,0.f, 0.f, 0.f, 0.f,0.f, 0.f, 0.f, 0.f,0.f, 0.f, 0.f, 0.f};
553   const unsigned int size = sizeof(out) / sizeof(float);
554   for( uint32_t i=0; i < (len > size? size:len); ++i)
555   {
556     v8::Handle<v8::Value> entry = array->Get( i);// v8::Integer::New( isolate, i));
557     if( V8Utils::IsNumberPrimitiveOrObject( entry ) )
558     {
559       out[i] = V8Utils::GetNumberValue( isolate, entry );
560       //printf("entry is a number %d , entry is a int %f \n",(int)i , out[i]  );
561     }
562   }
563   if(16 == len )
564   {
565     ret = Dali::Matrix( out[0] );
566   }
567   else if ( 9 == len )
568   {
569     ret = Dali::Matrix3( out[0],out[1],out[2],out[3],out[4],out[5],out[6],out[7],out[8] );
570   }
571   else if(4 == len)
572   {
573     ret = Dali::Vector4(out[0], out[1], out[2], out[3]);
574   }
575   else if(3 == len)
576   {
577     ret = Dali::Vector3(out[0], out[1], out[2]);
578   }
579   else if(2 == len)
580   {
581     ret = Dali::Vector2(out[0], out[1]);
582   }
583   else if(1 == len)
584   {
585     ret = out[0];
586   }
587
588   return ret;
589 }
590
591 Dali::Property::Value PropertyValueWrapper::ArrayFromV8Array( v8::Isolate* isolate, const v8::Local<v8::Value>& v8Value)
592 {
593   v8::EscapableHandleScope handleScope( isolate );
594
595   if( !v8Value->IsArray() )
596   {
597     return Dali::Property::Value();
598   }
599
600   //Cast v8::Value to v8::Array
601   v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast( v8Value );
602   uint32_t elementCount = v8Array->Length();
603   Dali::Property::Array data;
604   data.Reserve( elementCount );
605   bool bFound(false);
606   for( uint32_t i(0); i<elementCount; ++i )
607   {
608     //Get Property::Value for each element in the array
609     data.PushBack( V8Utils::GetPropertyValueFromObject( bFound, isolate, v8Array->Get(i) ) );
610   }
611
612   //return the Property::Value
613   return Dali::Property::Value( data );
614 }
615
616 v8::Persistent<v8::ObjectTemplate> PropertyValueWrapper::mTemplatePrimitive;
617
618
619 PropertyValueWrapper::~PropertyValueWrapper()
620 {
621
622 }
623
624 PropertyValueWrapper::PropertyValueWrapper( const Dali::Property::Value& value, GarbageCollectorInterface& gc )
625   : BaseWrappedObject(  GetWrappedType( value.GetType() ), gc ),
626     mValue(value)
627 {
628 }
629
630 Dali::Property::Value PropertyValueWrapper::ExtractPropertyValue( v8::Isolate* isolate, v8::Local< v8::Value> v8Value, Dali::Property::Type type)
631 {
632   v8::HandleScope handleScope( isolate);
633
634   Dali::Property::Value daliPropertyValue;
635
636   // check if it's a dali object (vector, rect etc)
637   if( v8Value->IsObject() )
638   {
639     v8::Local<v8::Object> object = v8::Handle<v8::Object>::Cast(v8Value);
640     if( object->InternalFieldCount() == BaseWrappedObject::FIELD_COUNT )
641     {
642       if( BaseWrappedObject::IsWrappedType( isolate, object, GetWrappedType(type) ) )
643       {
644         PropertyValueWrapper* propertyWrapper = Unwrap( isolate, object );
645         return propertyWrapper->GetValue();
646       }
647     }
648   }
649
650   // check if it's a javascript Array
651   Dali::Property::Value array = VectorOrMatrixFromV8Array( isolate, v8Value );
652
653   switch(type)
654   {
655     case Dali::Property::BOOLEAN:
656     {
657       if( V8Utils::IsBooleanPrimitiveOrObject( v8Value ) )
658       {
659         daliPropertyValue = Dali::Property::Value( V8Utils::GetBooleanValue( isolate, v8Value));
660       }
661       break;
662     }
663     case Dali::Property::FLOAT:
664     {
665       if( V8Utils::IsNumberPrimitiveOrObject( v8Value )  )
666       {
667         daliPropertyValue = Dali::Property::Value( V8Utils::GetNumberValue( isolate, v8Value) );
668       }
669
670       break;
671     }
672     case Dali::Property::INTEGER: // todo is it wise to distinguish int from float in javascript?!
673     {
674       if( v8Value->IsInt32() )
675       {
676         daliPropertyValue = Dali::Property::Value(  v8Value->Int32Value()  ) ;//static_cast<int>( V8Utils::GetNumberValue( isolate, v8Value) ));
677       }
678       break;
679     }
680     case Dali::Property::STRING:
681     {
682       if( V8Utils::IsStringPrimitiveOrObject( v8Value) )
683       {
684         daliPropertyValue = Dali::Property::Value( V8Utils::GetStringValue( isolate, v8Value) );
685       }
686
687
688       break;
689     }
690     case Dali::Property::VECTOR2:
691     {
692       if( array.GetType() == Dali::Property::VECTOR2 )
693       {
694           daliPropertyValue = array;
695       }
696       break;
697     }
698     case Dali::Property::VECTOR3:
699     {
700       if( array.GetType() == Dali::Property::VECTOR3)
701       {
702         daliPropertyValue = array;
703       }
704       break;
705     }
706     case Dali::Property::VECTOR4:
707     {
708
709       if( array.GetType() == Dali::Property::VECTOR4)
710       {
711         daliPropertyValue = array;
712       }
713       break;
714     }
715     case Dali::Property::RECTANGLE:
716     {
717       if( array.GetType() == Dali::Property::VECTOR4)
718       {
719         Vector4 vec4( array.Get<Vector4>());
720         daliPropertyValue = Property::Value(Rect<int>( vec4.x,vec4.y, vec4.z, vec4.w ));
721       }
722       break;
723     }
724     case Dali::Property::ROTATION:
725     {
726       if( array.GetType() == Dali::Property::VECTOR4)
727       {
728         // v4 treated as axis angle
729         Dali::Vector4 v = array.Get<Dali::Vector4>();
730         daliPropertyValue = Dali::AngleAxis(Dali::Degree(v[0]), Dali::Vector3(v[1], v[2], v[3]));
731       }
732       else if(array.GetType() == Dali::Property::VECTOR3)
733       {
734         // v3 treated as euler in degrees
735         Dali::Vector3 v = array.Get<Dali::Vector3>();
736         daliPropertyValue = Dali::Quaternion( Radian(Degree(v[0])), Radian(Degree(v[1])), Radian(Degree(v[2])) );
737       }
738       break;
739     }
740     case Dali::Property::MATRIX:
741     {
742       Dali::Matrix mat = array.Get<Dali::Matrix>();
743       daliPropertyValue = mat;
744       break;
745     }
746     case Dali::Property::MATRIX3:
747     {
748       Dali::Matrix3 mat = array.Get<Dali::Matrix3>();
749       daliPropertyValue = mat;
750       break;
751     }
752     case Dali::Property::ARRAY:
753     {
754       daliPropertyValue = ArrayFromV8Array( isolate, v8Value );
755       break;
756     }
757     case Dali::Property::NONE:
758     default:
759     {
760       break;
761     }
762    } // switch type
763
764    return daliPropertyValue;
765 }
766
767 void PropertyValueWrapper::NewRotation( const v8::FunctionCallbackInfo< v8::Value >& args)
768 {
769   v8::Isolate* isolate = args.GetIsolate();
770   v8::HandleScope handleScope( isolate);
771
772   if(!args.IsConstructCall())
773   {
774     DALI_SCRIPT_EXCEPTION( isolate, "Rotation constructor called without 'new'");
775     return;
776   }
777   v8::Local<v8::Object > object;
778
779   float v[4] = {0.f,0.f,0.f,0.f};
780
781   bool foundAllArguments(false);
782   V8Utils::ReadFloatArguments( foundAllArguments, v, 4, args, 0.f );
783
784   int length = args.Length();
785
786   // if length = 4 create AngleAxis, else create Quaternion
787
788   if( length > 3 )
789   {
790     const Dali::AngleAxis axis(  Degree( v[0] ), Vector3(v[1], v[2], v[3]) );
791     object = WrapDaliProperty( isolate, Dali::Property::Value( axis ) );
792   }
793   else if( length > 2 )
794   {
795     object = WrapDaliProperty( isolate, Dali::Quaternion( Degree(v[0]), Degree(v[1]), Degree(v[2]) ) );
796   }
797   else
798   {
799     const Dali::Quaternion quaternion( Dali::Quaternion( Dali::ANGLE_0, Dali::Vector3::YAXIS));
800     object = WrapDaliProperty( isolate, quaternion );
801   }
802
803   args.GetReturnValue().Set( object );
804 }
805
806 //
807 void PropertyValueWrapper::NewMatrix( const v8::FunctionCallbackInfo< v8::Value >& args )
808 {
809   v8::Isolate* isolate = args.GetIsolate();
810   v8::HandleScope handleScope( isolate);
811
812   if(!args.IsConstructCall())
813   {
814     DALI_SCRIPT_EXCEPTION( isolate, "Rotation constructor called without 'new'");
815     return;
816   }
817   v8::Local<v8::Object > object;
818
819   // we're constructing either a 4x4 Dali::Matrix or a 3x3 Dali::Matrix
820   // we're expecting an array of floats
821   // 4x4 = m00, m01, m02, m03,  m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33
822   // 3x3 or m00, m01, m02, m10, m11, m12,m20, m21, m22, m30, m31, m32,
823   bool foundAllArguments( false );
824
825   if( args.Length() == 16 )
826   {
827     float v[16];
828     V8Utils::ReadFloatArguments( foundAllArguments, v, 16, args, 0.f );
829     if(! foundAllArguments )
830     {
831       DALI_SCRIPT_EXCEPTION( isolate, "invalid Matrix parameters");
832       return;
833     }
834     Dali::Matrix matrix( v[0] );
835     object = WrapDaliProperty( isolate ,  Dali::Property::Value( matrix ) );
836   }
837   else if ( args.Length() == 9 )
838   {
839     float v[9];
840     V8Utils::ReadFloatArguments( foundAllArguments, v, 9, args, 0.f );
841     if(! foundAllArguments )
842     {
843       DALI_SCRIPT_EXCEPTION( isolate, "invalid Matrix parameters");
844       return;
845     }
846     Dali::Matrix3 matrix( v[0], v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8] );
847     object = WrapDaliProperty( isolate ,  Dali::Property::Value( matrix ) );
848   }
849   args.GetReturnValue().Set( object );
850
851
852 }
853
854 v8::Handle<v8::ObjectTemplate> PropertyValueWrapper::MakeDaliPropertyTemplate( v8::Isolate* isolate )
855 {
856   v8::EscapableHandleScope handleScope( isolate );
857
858   v8::Local<v8::ObjectTemplate> objTemplate = v8::ObjectTemplate::New();
859
860   objTemplate->SetInternalFieldCount( BaseWrappedObject::FIELD_COUNT );
861
862   // property handle intercepts property getters and setters
863   objTemplate->SetNamedPropertyHandler( PropertyGet, PropertySet);
864
865   return handleScope.Escape( objTemplate );
866
867 }
868
869 v8::Handle<v8::Object> PropertyValueWrapper::WrapDaliProperty(v8::Isolate* isolate, const Dali::Property::Value &value)
870 {
871   v8::EscapableHandleScope handleScope( isolate );
872
873   // Simple Dali properties (ints, strings, bools etc) are stored as JavaScript primitives (v8::Boolean ...)
874   // more complex properties (Vectors, Rectangles...) are wrapped by a JavaScript object
875   if( IsPrimitive( value ))
876   {
877     return handleScope.Escape( CreateJavaScriptPrimitive( isolate, value) );
878   }
879
880   // This will wrap a Dali structure (Vector, Rect, Matrix etc) inside a JavaScript object.
881
882   v8::Local<v8::ObjectTemplate> objectTemplate;
883
884   if(PropertyValueWrapper::mTemplatePrimitive.IsEmpty() )
885   {
886     objectTemplate = MakeDaliPropertyTemplate( isolate );
887     PropertyValueWrapper::mTemplatePrimitive.Reset( isolate, objectTemplate);
888   }
889   else
890   {
891     // get the object template
892     objectTemplate = v8::Local<v8::ObjectTemplate>::New( isolate, PropertyValueWrapper::mTemplatePrimitive );
893   }
894
895   v8::Local<v8::Object> localObject = objectTemplate->NewInstance();
896
897   PropertyValueWrapper* pointer =  new PropertyValueWrapper( value, Dali::V8Plugin::DaliWrapper::Get().GetDaliGarbageCollector() );
898
899    // assign the JavaScript object to the wrapper.
900   // This also stores Dali object, in an internal field inside the JavaScript object.
901   pointer->SetJavascriptObject( isolate, localObject );
902
903   return handleScope.Escape( localObject );
904
905 }
906
907 // Utility function that extracts the C++ map pointer from a wrapper
908 // object.
909
910 PropertyValueWrapper*  PropertyValueWrapper::Unwrap( v8::Isolate* isolate, v8::Handle< v8::Object> obj)
911 {
912   v8::HandleScope handleScope( isolate );
913
914   v8::Local<v8::External> field = v8::Local<v8::External>::Cast( obj->GetInternalField(0) );
915   void* ptr = field->Value();
916   return static_cast< PropertyValueWrapper *>(ptr);
917 }
918
919 void PropertyValueWrapper::PropertyGet( v8::Local<v8::String> propertyName,
920                                         const v8::PropertyCallbackInfo<v8::Value>& info)
921 {
922   v8::Isolate* isolate = info.GetIsolate();
923   v8::HandleScope handleScope( isolate );
924
925   std::string name = V8Utils::v8StringToStdString( propertyName );
926
927   // unwrap the object
928   PropertyValueWrapper* propWrapper = Unwrap( isolate, info.This() );
929
930   v8::Local<v8::Value> value = GetV8ValueFrom( isolate, propWrapper->mValue, name );
931
932   info.GetReturnValue().Set( value );
933 }
934
935 void PropertyValueWrapper::PropertySet( v8::Local<v8::String> propertyName,
936                   v8::Local<v8::Value> javaScriptValue,
937                   const v8::PropertyCallbackInfo<v8::Value>& info)
938 {
939   v8::Isolate* isolate = info.GetIsolate();
940   v8::HandleScope handleScope( isolate );
941
942   std::string name =  V8Utils::v8StringToStdString( propertyName );
943
944   PropertyValueWrapper* propWrapper = Unwrap( isolate, info.This() );
945
946   SetFromV8Value( isolate, propWrapper->mValue, name, javaScriptValue );
947
948 }
949
950
951 } // namespace V8Plugin
952
953 } // namespace Dali