8469d7f1e106577ac07db496c233e7c9768f25d1
[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 );
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       else if( V8Utils::IsStringPrimitiveOrObject( v8Value) ) // Take string as value for properties that internally convert the string to an enum
679       {
680         daliPropertyValue = Dali::Property::Value( V8Utils::GetStringValue( isolate, v8Value) );
681       }
682       break;
683     }
684     case Dali::Property::STRING:
685     {
686       if( V8Utils::IsStringPrimitiveOrObject( v8Value) )
687       {
688         daliPropertyValue = Dali::Property::Value( V8Utils::GetStringValue( isolate, v8Value) );
689       }
690
691
692       break;
693     }
694     case Dali::Property::VECTOR2:
695     {
696       if( array.GetType() == Dali::Property::VECTOR2 )
697       {
698           daliPropertyValue = array;
699       }
700       break;
701     }
702     case Dali::Property::VECTOR3:
703     {
704       if( array.GetType() == Dali::Property::VECTOR3)
705       {
706         daliPropertyValue = array;
707       }
708       break;
709     }
710     case Dali::Property::VECTOR4:
711     {
712
713       if( array.GetType() == Dali::Property::VECTOR4)
714       {
715         daliPropertyValue = array;
716       }
717       break;
718     }
719     case Dali::Property::RECTANGLE:
720     {
721       if( array.GetType() == Dali::Property::VECTOR4)
722       {
723         Vector4 vec4( array.Get<Vector4>());
724         daliPropertyValue = Property::Value(Rect<int>( vec4.x,vec4.y, vec4.z, vec4.w ));
725       }
726       break;
727     }
728     case Dali::Property::ROTATION:
729     {
730       if( array.GetType() == Dali::Property::VECTOR4)
731       {
732         // v4 treated as axis angle
733         Dali::Vector4 v = array.Get<Dali::Vector4>();
734         daliPropertyValue = Dali::AngleAxis(Dali::Degree(v[0]), Dali::Vector3(v[1], v[2], v[3]));
735       }
736       else if(array.GetType() == Dali::Property::VECTOR3)
737       {
738         // v3 treated as euler in degrees
739         Dali::Vector3 v = array.Get<Dali::Vector3>();
740         daliPropertyValue = Dali::Quaternion( Radian(Degree(v[0])), Radian(Degree(v[1])), Radian(Degree(v[2])) );
741       }
742       break;
743     }
744     case Dali::Property::MATRIX:
745     {
746       Dali::Matrix mat = array.Get<Dali::Matrix>();
747       daliPropertyValue = mat;
748       break;
749     }
750     case Dali::Property::MATRIX3:
751     {
752       Dali::Matrix3 mat = array.Get<Dali::Matrix3>();
753       daliPropertyValue = mat;
754       break;
755     }
756     case Dali::Property::ARRAY:
757     {
758       daliPropertyValue = ArrayFromV8Array( isolate, v8Value );
759       break;
760     }
761     case Dali::Property::MAP:
762     {
763       if( v8Value->IsObject() )
764       {
765         v8::Local<v8::Object> object = v8::Handle<v8::Object>::Cast(v8Value);
766         Dali::Property::Map propertyMap = V8Utils::GetPropertyMapFromObject(isolate, object);
767         daliPropertyValue = Dali::Property::Value( propertyMap );
768       }
769       else if( V8Utils::IsStringPrimitiveOrObject( v8Value) )
770       {
771         // There are special cases where a property with property map type can accept a string value,
772         // so we do the additional check here.
773         daliPropertyValue = Dali::Property::Value( V8Utils::GetStringValue( isolate, v8Value) );
774       }
775
776       break;
777     }
778     case Dali::Property::NONE:
779     default:
780     {
781       break;
782     }
783   } // switch type
784
785   return daliPropertyValue;
786 }
787
788 void PropertyValueWrapper::NewRotation( const v8::FunctionCallbackInfo< v8::Value >& args)
789 {
790   v8::Isolate* isolate = args.GetIsolate();
791   v8::HandleScope handleScope( isolate);
792
793   if(!args.IsConstructCall())
794   {
795     DALI_SCRIPT_EXCEPTION( isolate, "Rotation constructor called without 'new'");
796     return;
797   }
798   v8::Local<v8::Object > object;
799
800   float v[4] = {0.f,0.f,0.f,0.f};
801
802   bool foundAllArguments(false);
803   V8Utils::ReadFloatArguments( foundAllArguments, v, 4, args, 0.f );
804
805   int length = args.Length();
806
807   // if length = 4 create AngleAxis, else create Quaternion
808
809   if( length > 3 )
810   {
811     const Dali::AngleAxis axis(  Degree( v[0] ), Vector3(v[1], v[2], v[3]) );
812     object = WrapDaliProperty( isolate, Dali::Property::Value( axis ) );
813   }
814   else if( length > 2 )
815   {
816     object = WrapDaliProperty( isolate, Dali::Quaternion( Degree(v[0]), Degree(v[1]), Degree(v[2]) ) );
817   }
818   else
819   {
820     const Dali::Quaternion quaternion( Dali::Quaternion( Dali::ANGLE_0, Dali::Vector3::YAXIS));
821     object = WrapDaliProperty( isolate, quaternion );
822   }
823
824   args.GetReturnValue().Set( object );
825 }
826
827 //
828 void PropertyValueWrapper::NewMatrix( const v8::FunctionCallbackInfo< v8::Value >& args )
829 {
830   v8::Isolate* isolate = args.GetIsolate();
831   v8::HandleScope handleScope( isolate);
832
833   if(!args.IsConstructCall())
834   {
835     DALI_SCRIPT_EXCEPTION( isolate, "Rotation constructor called without 'new'");
836     return;
837   }
838   v8::Local<v8::Object > object;
839
840   // we're constructing either a 4x4 Dali::Matrix or a 3x3 Dali::Matrix
841   // we're expecting an array of floats
842   // 4x4 = m00, m01, m02, m03,  m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33
843   // 3x3 or m00, m01, m02, m10, m11, m12,m20, m21, m22, m30, m31, m32,
844   bool foundAllArguments( false );
845
846   if( args.Length() == 16 )
847   {
848     float v[16];
849     V8Utils::ReadFloatArguments( foundAllArguments, v, 16, args, 0.f );
850     if(! foundAllArguments )
851     {
852       DALI_SCRIPT_EXCEPTION( isolate, "invalid Matrix parameters");
853       return;
854     }
855     Dali::Matrix matrix( v[0] );
856     object = WrapDaliProperty( isolate ,  Dali::Property::Value( matrix ) );
857   }
858   else if ( args.Length() == 9 )
859   {
860     float v[9];
861     V8Utils::ReadFloatArguments( foundAllArguments, v, 9, args, 0.f );
862     if(! foundAllArguments )
863     {
864       DALI_SCRIPT_EXCEPTION( isolate, "invalid Matrix parameters");
865       return;
866     }
867     Dali::Matrix3 matrix( v[0], v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8] );
868     object = WrapDaliProperty( isolate ,  Dali::Property::Value( matrix ) );
869   }
870   args.GetReturnValue().Set( object );
871
872
873 }
874
875 v8::Handle<v8::ObjectTemplate> PropertyValueWrapper::MakeDaliPropertyTemplate( v8::Isolate* isolate )
876 {
877   v8::EscapableHandleScope handleScope( isolate );
878
879   v8::Local<v8::ObjectTemplate> objTemplate = v8::ObjectTemplate::New();
880
881   objTemplate->SetInternalFieldCount( BaseWrappedObject::FIELD_COUNT );
882
883   // property handle intercepts property getters and setters
884   objTemplate->SetNamedPropertyHandler( PropertyGet, PropertySet);
885
886   return handleScope.Escape( objTemplate );
887
888 }
889
890 v8::Handle<v8::Object> PropertyValueWrapper::WrapDaliProperty(v8::Isolate* isolate, const Dali::Property::Value &value)
891 {
892   v8::EscapableHandleScope handleScope( isolate );
893
894   // Simple Dali properties (ints, strings, bools etc) are stored as JavaScript primitives (v8::Boolean ...)
895   // more complex properties (Vectors, Rectangles...) are wrapped by a JavaScript object
896   if( IsPrimitive( value ))
897   {
898     return handleScope.Escape( CreateJavaScriptPrimitive( isolate, value) );
899   }
900
901   // This will wrap a Dali structure (Vector, Rect, Matrix etc) inside a JavaScript object.
902
903   v8::Local<v8::ObjectTemplate> objectTemplate;
904
905   if(PropertyValueWrapper::mTemplatePrimitive.IsEmpty() )
906   {
907     objectTemplate = MakeDaliPropertyTemplate( isolate );
908     PropertyValueWrapper::mTemplatePrimitive.Reset( isolate, objectTemplate);
909   }
910   else
911   {
912     // get the object template
913     objectTemplate = v8::Local<v8::ObjectTemplate>::New( isolate, PropertyValueWrapper::mTemplatePrimitive );
914   }
915
916   v8::Local<v8::Object> localObject = objectTemplate->NewInstance();
917
918   PropertyValueWrapper* pointer =  new PropertyValueWrapper( value, Dali::V8Plugin::DaliWrapper::Get().GetDaliGarbageCollector() );
919
920    // assign the JavaScript object to the wrapper.
921   // This also stores Dali object, in an internal field inside the JavaScript object.
922   pointer->SetJavascriptObject( isolate, localObject );
923
924   return handleScope.Escape( localObject );
925
926 }
927
928 // Utility function that extracts the C++ map pointer from a wrapper
929 // object.
930
931 PropertyValueWrapper*  PropertyValueWrapper::Unwrap( v8::Isolate* isolate, v8::Handle< v8::Object> obj)
932 {
933   v8::HandleScope handleScope( isolate );
934
935   v8::Local<v8::External> field = v8::Local<v8::External>::Cast( obj->GetInternalField(0) );
936   void* ptr = field->Value();
937   return static_cast< PropertyValueWrapper *>(ptr);
938 }
939
940 void PropertyValueWrapper::PropertyGet( v8::Local<v8::String> propertyName,
941                                         const v8::PropertyCallbackInfo<v8::Value>& info)
942 {
943   v8::Isolate* isolate = info.GetIsolate();
944   v8::HandleScope handleScope( isolate );
945
946   std::string name = V8Utils::v8StringToStdString( propertyName );
947
948   // unwrap the object
949   PropertyValueWrapper* propWrapper = Unwrap( isolate, info.This() );
950
951   v8::Local<v8::Value> value = GetV8ValueFrom( isolate, propWrapper->mValue, name );
952
953   info.GetReturnValue().Set( value );
954 }
955
956 void PropertyValueWrapper::PropertySet( v8::Local<v8::String> propertyName,
957                   v8::Local<v8::Value> javaScriptValue,
958                   const v8::PropertyCallbackInfo<v8::Value>& info)
959 {
960   v8::Isolate* isolate = info.GetIsolate();
961   v8::HandleScope handleScope( isolate );
962
963   std::string name =  V8Utils::v8StringToStdString( propertyName );
964
965   PropertyValueWrapper* propWrapper = Unwrap( isolate, info.This() );
966
967   SetFromV8Value( isolate, propWrapper->mValue, name, javaScriptValue );
968
969 }
970
971
972 } // namespace V8Plugin
973
974 } // namespace Dali