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