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