Merge "Added PropertyValue Array as a class" into tizen
[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::UNSIGNED_INTEGER:
485     case Dali::Property::STRING:
486     case Dali::Property::FLOAT:
487     {
488       return true;
489     }
490     default:
491     {
492       return false;
493     }
494   }
495 }
496 v8::Local<v8::Object> CreateJavaScriptPrimitive( v8::Isolate* isolate, const Dali::Property::Value &value )
497 {
498   v8::EscapableHandleScope handleScope( isolate );
499
500   v8::Local<v8::Value> v8Value;
501
502   switch( value.GetType() )
503    {
504      case Dali::Property::FLOAT:
505      {
506        v8Value = v8::Number::New( isolate, value.Get<float>()  );
507        break;
508      }
509      case Dali::Property::BOOLEAN:
510      {
511        v8Value = v8::Boolean::New(  isolate, value.Get<bool>());
512        break;
513      }
514      case Dali::Property::INTEGER:
515      {
516        v8Value = v8::Integer::New( isolate, value.Get<int>());
517        break;
518      }
519      case Dali::Property::UNSIGNED_INTEGER:
520      {
521        v8Value = v8::Integer::New( isolate, value.Get<unsigned int>());
522        break;
523      }
524      case Dali::Property::STRING:
525      {
526        std::string string = value.Get< std::string >();
527        v8Value = v8::String::NewFromUtf8( isolate,  string.c_str());
528        break;
529      }
530      default:
531      {
532        DALI_LOG_ERROR("Primitive mismatch \n");
533        break;
534      }
535    }
536  v8::Local<v8::Object> ret = v8Value->ToObject();
537
538  return handleScope.Escape( ret );
539 }
540
541
542 } // un-named namespace
543
544
545
546 Dali::Property::Value PropertyValueWrapper::VectorOrMatrixFromV8Array( v8::Isolate* isolate, const v8::Local<v8::Value>& v8Value)
547 {
548   v8::EscapableHandleScope handleScope( isolate );
549
550   Dali::Property::Value ret;
551
552   if( !v8Value->IsArray() )
553   {
554     return ret;
555   }
556   v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast( v8Value );//v8::Array::Cast(  *v8Value);
557   uint32_t len = array->Length();
558   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};
559   const unsigned int size = sizeof(out) / sizeof(float);
560   for( uint32_t i=0; i < (len > size? size:len); ++i)
561   {
562     v8::Handle<v8::Value> entry = array->Get( i);// v8::Integer::New( isolate, i));
563     if( V8Utils::IsNumberPrimitiveOrObject( entry ) )
564     {
565       out[i] = V8Utils::GetNumberValue( isolate, entry );
566       //printf("entry is a number %d , entry is a int %f \n",(int)i , out[i]  );
567     }
568   }
569   if(16 == len )
570   {
571     ret = Dali::Matrix( out[0] );
572   }
573   else if ( 9 == len )
574   {
575     ret = Dali::Matrix3( out[0],out[1],out[2],out[3],out[4],out[5],out[6],out[7],out[8] );
576   }
577   else if(4 == len)
578   {
579     ret = Dali::Vector4(out[0], out[1], out[2], out[3]);
580   }
581   else if(3 == len)
582   {
583     ret = Dali::Vector3(out[0], out[1], out[2]);
584   }
585   else if(2 == len)
586   {
587     ret = Dali::Vector2(out[0], out[1]);
588   }
589   else if(1 == len)
590   {
591     ret = out[0];
592   }
593
594   return ret;
595 }
596
597 Dali::Property::Value PropertyValueWrapper::ArrayFromV8Array( v8::Isolate* isolate, const v8::Local<v8::Value>& v8Value)
598 {
599   v8::EscapableHandleScope handleScope( isolate );
600
601   if( !v8Value->IsArray() )
602   {
603     return Dali::Property::Value();
604   }
605
606   //Cast v8::Value to v8::Array
607   v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast( v8Value );
608   uint32_t elementCount = v8Array->Length();
609   Dali::Property::Array data;
610   data.Reserve( elementCount );
611   bool bFound(false);
612   for( uint32_t i(0); i<elementCount; ++i )
613   {
614     //Get Property::Value for each element in the array
615     data.PushBack( V8Utils::GetPropertyValueFromObject( bFound, isolate, v8Array->Get(i) ) );
616   }
617
618   //return the Property::Value
619   return Dali::Property::Value( data );
620 }
621
622 v8::Persistent<v8::ObjectTemplate> PropertyValueWrapper::mTemplatePrimitive;
623
624
625 PropertyValueWrapper::~PropertyValueWrapper()
626 {
627
628 }
629
630 PropertyValueWrapper::PropertyValueWrapper( const Dali::Property::Value& value, GarbageCollectorInterface& gc )
631   : BaseWrappedObject(  GetWrappedType( value.GetType() ), gc ),
632     mValue(value)
633 {
634 }
635
636 Dali::Property::Value PropertyValueWrapper::ExtractPropertyValue( v8::Isolate* isolate, v8::Local< v8::Value> v8Value, Dali::Property::Type type)
637 {
638   v8::HandleScope handleScope( isolate);
639
640   Dali::Property::Value daliPropertyValue;
641
642   // check if it's a dali object (vector, rect etc)
643   if( v8Value->IsObject() )
644   {
645     v8::Local<v8::Object> object = v8::Handle<v8::Object>::Cast(v8Value);
646     if( object->InternalFieldCount() == BaseWrappedObject::FIELD_COUNT )
647     {
648       if( BaseWrappedObject::IsWrappedType( isolate, object, GetWrappedType(type) ) )
649       {
650         PropertyValueWrapper* propertyWrapper = Unwrap( isolate, object );
651         return propertyWrapper->GetValue();
652       }
653     }
654   }
655
656   // check if it's a javascript Array
657   Dali::Property::Value array = VectorOrMatrixFromV8Array( isolate, v8Value );
658
659   switch(type)
660   {
661     case Dali::Property::BOOLEAN:
662     {
663       if( V8Utils::IsBooleanPrimitiveOrObject( v8Value ) )
664       {
665         daliPropertyValue = Dali::Property::Value( V8Utils::GetBooleanValue( isolate, v8Value));
666       }
667       break;
668     }
669     case Dali::Property::FLOAT:
670     {
671       if( V8Utils::IsNumberPrimitiveOrObject( v8Value )  )
672       {
673         daliPropertyValue = Dali::Property::Value( V8Utils::GetNumberValue( isolate, v8Value) );
674       }
675
676       break;
677     }
678     case Dali::Property::INTEGER: // todo is it wise to distinguish int from float in javascript?!
679     {
680       if( v8Value->IsInt32() )
681       {
682         daliPropertyValue = Dali::Property::Value(  v8Value->Int32Value()  ) ;//static_cast<int>( V8Utils::GetNumberValue( isolate, v8Value) ));
683       }
684       break;
685     }
686     case Dali::Property::UNSIGNED_INTEGER:
687     {
688       if( v8Value->IsUint32() )
689       {
690         daliPropertyValue = Dali::Property::Value(  v8Value->Uint32Value() );//static_cast<unsigned int>( V8Utils::GetNumberValue( isolate, v8Value) ));
691       }
692       break;
693     }
694     case Dali::Property::STRING:
695     {
696       if( V8Utils::IsStringPrimitiveOrObject( v8Value) )
697       {
698         daliPropertyValue = Dali::Property::Value( V8Utils::GetStringValue( isolate, v8Value) );
699       }
700
701
702       break;
703     }
704     case Dali::Property::VECTOR2:
705     {
706       if( array.GetType() == Dali::Property::VECTOR2 )
707       {
708           daliPropertyValue = array;
709       }
710       break;
711     }
712     case Dali::Property::VECTOR3:
713     {
714       if( array.GetType() == Dali::Property::VECTOR3)
715       {
716         daliPropertyValue = array;
717       }
718       break;
719     }
720     case Dali::Property::VECTOR4:
721     {
722
723       if( array.GetType() == Dali::Property::VECTOR4)
724       {
725         daliPropertyValue = array;
726       }
727       break;
728     }
729     case Dali::Property::RECTANGLE:
730     {
731       if( array.GetType() == Dali::Property::VECTOR4)
732       {
733         Vector4 vec4( array.Get<Vector4>());
734         daliPropertyValue = Property::Value(Rect<int>( vec4.x,vec4.y, vec4.z, vec4.w ));
735       }
736       break;
737     }
738     case Dali::Property::ROTATION:
739     {
740       if( array.GetType() == Dali::Property::VECTOR4)
741       {
742         // v4 treated as axis angle
743         Dali::Vector4 v = array.Get<Dali::Vector4>();
744         daliPropertyValue = Dali::AngleAxis(Dali::Degree(v[0]), Dali::Vector3(v[1], v[2], v[3]));
745       }
746       else if(array.GetType() == Dali::Property::VECTOR3)
747       {
748         // v3 treated as euler in degrees
749         Dali::Vector3 v = array.Get<Dali::Vector3>();
750         daliPropertyValue = Dali::Quaternion( Radian(Degree(v[0])), Radian(Degree(v[1])), Radian(Degree(v[2])) );
751       }
752       break;
753     }
754     case Dali::Property::MATRIX:
755     {
756       Dali::Matrix mat = array.Get<Dali::Matrix>();
757       daliPropertyValue = mat;
758       break;
759     }
760     case Dali::Property::MATRIX3:
761     {
762       Dali::Matrix3 mat = array.Get<Dali::Matrix3>();
763       daliPropertyValue = mat;
764       break;
765     }
766     case Dali::Property::ARRAY:
767     {
768       daliPropertyValue = ArrayFromV8Array( isolate, v8Value );
769       break;
770     }
771     case Dali::Property::NONE:
772     case Dali::Property::TYPE_COUNT:
773     default:
774     {
775       break;
776     }
777    } // switch type
778
779    return daliPropertyValue;
780 }
781
782 void PropertyValueWrapper::NewRotation( const v8::FunctionCallbackInfo< v8::Value >& args)
783 {
784   v8::Isolate* isolate = args.GetIsolate();
785   v8::HandleScope handleScope( isolate);
786
787   if(!args.IsConstructCall())
788   {
789     DALI_SCRIPT_EXCEPTION( isolate, "Rotation constructor called without 'new'");
790     return;
791   }
792   v8::Local<v8::Object > object;
793
794   float v[4] = {0.f,0.f,0.f,0.f};
795
796   bool foundAllArguments(false);
797   V8Utils::ReadFloatArguments( foundAllArguments, v, 4, args, 0.f );
798
799   int length = args.Length();
800
801   // if length = 4 create AngleAxis, else create Quaternion
802
803   if( length > 3 )
804   {
805     const Dali::AngleAxis axis(  Degree( v[0] ), Vector3(v[1], v[2], v[3]) );
806     object = WrapDaliProperty( isolate, Dali::Property::Value( axis ) );
807   }
808   else if( length > 2 )
809   {
810     object = WrapDaliProperty( isolate, Dali::Quaternion( Degree(v[0]), Degree(v[1]), Degree(v[2]) ) );
811   }
812   else
813   {
814     const Dali::Quaternion quaternion( Dali::Quaternion( Dali::ANGLE_0, Dali::Vector3::YAXIS));
815     object = WrapDaliProperty( isolate, quaternion );
816   }
817
818   args.GetReturnValue().Set( object );
819 }
820
821 //
822 void PropertyValueWrapper::NewMatrix( const v8::FunctionCallbackInfo< v8::Value >& args )
823 {
824   v8::Isolate* isolate = args.GetIsolate();
825   v8::HandleScope handleScope( isolate);
826
827   if(!args.IsConstructCall())
828   {
829     DALI_SCRIPT_EXCEPTION( isolate, "Rotation constructor called without 'new'");
830     return;
831   }
832   v8::Local<v8::Object > object;
833
834   // we're constructing either a 4x4 Dali::Matrix or a 3x3 Dali::Matrix
835   // we're expecting an array of floats
836   // 4x4 = m00, m01, m02, m03,  m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33
837   // 3x3 or m00, m01, m02, m10, m11, m12,m20, m21, m22, m30, m31, m32,
838   bool foundAllArguments( false );
839
840   if( args.Length() == 16 )
841   {
842     float v[16];
843     V8Utils::ReadFloatArguments( foundAllArguments, v, 16, args, 0.f );
844     if(! foundAllArguments )
845     {
846       DALI_SCRIPT_EXCEPTION( isolate, "invalid Matrix parameters");
847       return;
848     }
849     Dali::Matrix matrix( v[0] );
850     object = WrapDaliProperty( isolate ,  Dali::Property::Value( matrix ) );
851   }
852   else if ( args.Length() == 9 )
853   {
854     float v[9];
855     V8Utils::ReadFloatArguments( foundAllArguments, v, 9, args, 0.f );
856     if(! foundAllArguments )
857     {
858       DALI_SCRIPT_EXCEPTION( isolate, "invalid Matrix parameters");
859       return;
860     }
861     Dali::Matrix3 matrix( v[0], v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8] );
862     object = WrapDaliProperty( isolate ,  Dali::Property::Value( matrix ) );
863   }
864   args.GetReturnValue().Set( object );
865
866
867 }
868
869 v8::Handle<v8::ObjectTemplate> PropertyValueWrapper::MakeDaliPropertyTemplate( v8::Isolate* isolate )
870 {
871   v8::EscapableHandleScope handleScope( isolate );
872
873   v8::Local<v8::ObjectTemplate> objTemplate = v8::ObjectTemplate::New();
874
875   objTemplate->SetInternalFieldCount( BaseWrappedObject::FIELD_COUNT );
876
877   // property handle intercepts property getters and setters
878   objTemplate->SetNamedPropertyHandler( PropertyGet, PropertySet);
879
880   return handleScope.Escape( objTemplate );
881
882 }
883
884 v8::Handle<v8::Object> PropertyValueWrapper::WrapDaliProperty(v8::Isolate* isolate, const Dali::Property::Value &value)
885 {
886   v8::EscapableHandleScope handleScope( isolate );
887
888   // Simple Dali properties (ints, strings, bools etc) are stored as JavaScript primitives (v8::Boolean ...)
889   // more complex properties (Vectors, Rectangles...) are wrapped by a JavaScript object
890   if( IsPrimitive( value ))
891   {
892     return handleScope.Escape( CreateJavaScriptPrimitive( isolate, value) );
893   }
894
895   // This will wrap a Dali structure (Vector, Rect, Matrix etc) inside a JavaScript object.
896
897   v8::Local<v8::ObjectTemplate> objectTemplate;
898
899   if(PropertyValueWrapper::mTemplatePrimitive.IsEmpty() )
900   {
901     objectTemplate = MakeDaliPropertyTemplate( isolate );
902     PropertyValueWrapper::mTemplatePrimitive.Reset( isolate, objectTemplate);
903   }
904   else
905   {
906     // get the object template
907     objectTemplate = v8::Local<v8::ObjectTemplate>::New( isolate, PropertyValueWrapper::mTemplatePrimitive );
908   }
909
910   v8::Local<v8::Object> localObject = objectTemplate->NewInstance();
911
912   PropertyValueWrapper* pointer =  new PropertyValueWrapper( value, Dali::V8Plugin::DaliWrapper::Get().GetDaliGarbageCollector() );
913
914    // assign the JavaScript object to the wrapper.
915   // This also stores Dali object, in an internal field inside the JavaScript object.
916   pointer->SetJavascriptObject( isolate, localObject );
917
918   return handleScope.Escape( localObject );
919
920 }
921
922 // Utility function that extracts the C++ map pointer from a wrapper
923 // object.
924
925 PropertyValueWrapper*  PropertyValueWrapper::Unwrap( v8::Isolate* isolate, v8::Handle< v8::Object> obj)
926 {
927   v8::HandleScope handleScope( isolate );
928
929   v8::Local<v8::External> field = v8::Local<v8::External>::Cast( obj->GetInternalField(0) );
930   void* ptr = field->Value();
931   return static_cast< PropertyValueWrapper *>(ptr);
932 }
933
934 void PropertyValueWrapper::PropertyGet( v8::Local<v8::String> propertyName,
935                                         const v8::PropertyCallbackInfo<v8::Value>& info)
936 {
937   v8::Isolate* isolate = info.GetIsolate();
938   v8::HandleScope handleScope( isolate );
939
940   std::string name = V8Utils::v8StringToStdString( propertyName );
941
942   // unwrap the object
943   PropertyValueWrapper* propWrapper = Unwrap( isolate, info.This() );
944
945   v8::Local<v8::Value> value = GetV8ValueFrom( isolate, propWrapper->mValue, name );
946
947   info.GetReturnValue().Set( value );
948 }
949
950 void PropertyValueWrapper::PropertySet( v8::Local<v8::String> propertyName,
951                   v8::Local<v8::Value> javaScriptValue,
952                   const v8::PropertyCallbackInfo<v8::Value>& info)
953 {
954   v8::Isolate* isolate = info.GetIsolate();
955   v8::HandleScope handleScope( isolate );
956
957   std::string name =  V8Utils::v8StringToStdString( propertyName );
958
959   PropertyValueWrapper* propWrapper = Unwrap( isolate, info.This() );
960
961   SetFromV8Value( isolate, propWrapper->mValue, name, javaScriptValue );
962
963 }
964
965
966 } // namespace V8Plugin
967
968 } // namespace Dali