Fixed crash while wrapping a Control as an actor in JavaScript plugin
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / builder-impl.cpp
1 /*
2  * Copyright (c) 2014 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
18 // CLASS HEADER
19 #include <dali-toolkit/internal/builder/builder-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <sys/stat.h>
23 #include <sstream>
24 #include <dali/public-api/render-tasks/render-task-list.h>
25 #include <dali/public-api/object/type-info.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/public-api/object/property-array.h>
28 #include <dali/public-api/actors/layer.h>
29 #include <dali/public-api/actors/image-actor.h>
30 #include <dali/public-api/actors/camera-actor.h>
31 #include <dali/devel-api/scripting/scripting.h>
32 #include <dali/public-api/signals/functor-delegate.h>
33 #include <dali/integration-api/debug.h>
34
35 // INTERNAL INCLUDES
36 #include <dali-toolkit/public-api/controls/control.h>
37 #include <dali-toolkit/devel-api/builder/json-parser.h>
38
39 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
40 #include <dali-toolkit/internal/builder/builder-filesystem.h>
41 #include <dali-toolkit/internal/builder/builder-declarations.h>
42 #include <dali-toolkit/internal/builder/replacement.h>
43
44 namespace Dali
45 {
46
47 namespace Toolkit
48 {
49
50 namespace Internal
51 {
52 class Replacement;
53
54 extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot, Builder* const builder );
55 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
56 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value, const Replacement& replacements );
57 extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value );
58 extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value, const Replacement& replacements );
59 extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder);
60 extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder);
61 extern Actor SetupActor( const TreeNode& node, Actor& actor, const Replacement& constant );
62
63 #if defined(DEBUG_ENABLED)
64 Integration::Log::Filter* gFilterScript  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_SCRIPT");
65 #endif
66
67 namespace
68 {
69
70 #define TOKEN_STRING(x) #x
71
72 const std::string KEYNAME_STYLES    = "styles";
73 const std::string KEYNAME_TYPE      = "type";
74 const std::string KEYNAME_ACTORS    = "actors";
75 const std::string KEYNAME_SIGNALS   = "signals";
76 const std::string KEYNAME_NAME      = "name";
77 const std::string KEYNAME_TEMPLATES = "templates";
78 const std::string KEYNAME_INCLUDES  = "includes";
79
80 typedef std::vector<const TreeNode*> TreeNodeList;
81
82 template <typename T>
83 std::string ToString(const T& value)
84 {
85   std::stringstream ss;
86   ss << value;
87   return ss.str();
88 }
89
90 template <>
91 std::string ToString(const Rect<int>& value)
92 {
93   std::stringstream ss;
94   ss << value.x << "," << value.y << "," << value.width << "," << value.height;
95   return ss.str();
96 }
97
98 #if defined(DEBUG_ENABLED)
99
100 std::string PropertyValueToString( const Property::Value& value )
101 {
102   std::string ret;
103
104   switch( value.GetType() )
105   {
106     case Property::NONE:
107     {
108       ret = "NONE";
109       break;
110     }            ///< No type
111     case Property::BOOLEAN:
112     {
113       ret = value.Get<bool>() ? "True" : "False";
114       break;
115     }
116     case Property::FLOAT:
117     {
118
119       ret = ToString( value.Get<float>() );
120       break;
121     }
122     case Property::INTEGER:
123     {
124       ret = ToString( value.Get<int>() );
125       break;
126     }
127     case Property::UNSIGNED_INTEGER:
128     {
129       ret = ToString( value.Get<unsigned int>() );
130       break;
131     }
132     case Property::VECTOR2:
133     {
134       ret = ToString( value.Get<Vector2>() );
135       break;
136     }
137     case Property::VECTOR3:
138     {
139       ret = ToString( value.Get<Vector3>() );
140       break;
141     }
142     case Property::VECTOR4:
143     {
144       ret = ToString( value.Get<Vector4>() );
145       break;
146     }
147     case Property::MATRIX3:
148     {
149       ret = ToString( value.Get<Matrix3>() );
150       break;
151     }
152     case Property::MATRIX:
153     {
154       ret = ToString( value.Get<Matrix>() );
155       break;
156     }
157     case Property::RECTANGLE:
158     {
159       ret = ToString( value.Get< Rect<int> >() );
160       break;
161     }
162     case Property::ROTATION:
163     {
164       break;
165     }
166     case Property::STRING:
167     {
168       ret = value.Get<std::string>();
169       break;
170     }
171     case Property::ARRAY:
172     {
173       ret = std::string("Array Size=") + ToString( value.Get<Property::Array>().Size() );
174       break;
175     }
176     case Property::MAP:
177     {
178       ret = std::string("Map Size=") + ToString( value.Get<Property::Map>().Count() );
179       break;
180     }
181   }
182
183   return ret;
184 }
185 #endif // DEBUG_ENABLED
186
187 /*
188  * Recursively collects all stylesin a node (An array of style names).
189  *
190  * stylesCollection The set of styles from the json file (a json object of named styles)
191  * style The style array to begin the collection from
192  * styleList The style list to add nodes to apply
193  */
194 void CollectAllStyles( const TreeNode& stylesCollection, const TreeNode& style, TreeNodeList& styleList )
195 {
196   // style is an array of style names
197   if( TreeNode::ARRAY == style.GetType() )
198   {
199     for(TreeNode::ConstIterator iter = style.CBegin(); iter != style.CEnd(); ++iter)
200     {
201       if( OptionalString styleName = IsString( (*iter).second ) )
202       {
203         if( OptionalChild node = IsChild( stylesCollection, *styleName) )
204         {
205           styleList.push_back( &(*node) );
206
207           if( OptionalChild subStyle = IsChild( *node, KEYNAME_STYLES ) )
208           {
209             CollectAllStyles( stylesCollection, *subStyle, styleList );
210           }
211         }
212       }
213     }
214   }
215 }
216
217
218 } // namespace anon
219
220 /*
221  * Sets the handle properties found in the tree node
222  */
223 void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replacement& constant )
224 {
225   if( handle )
226   {
227     for( TreeNode::ConstIterator iter = node.CBegin(); iter != node.CEnd(); ++iter )
228     {
229       const TreeNode::KeyNodePair& keyChild = *iter;
230
231       std::string key( keyChild.first );
232
233       // ignore special fields; type,actors,signals,styles
234       if(key == KEYNAME_TYPE || key == KEYNAME_ACTORS || key == KEYNAME_SIGNALS || key == KEYNAME_STYLES)
235       {
236         continue;
237       }
238
239       // special field 'image' usually contains an json object description
240       // although sometimes refers to a framebuffer
241       if( 0 == keyChild.second.Size() )
242       {
243         if(key == "image")
244         {
245           ImageActor imageActor = ImageActor::DownCast(handle);
246           if(imageActor)
247           {
248             if( OptionalString s = constant.IsString( keyChild.second ) )
249             {
250               FrameBufferImage fb = GetFrameBufferImage(*s, constant);
251               if(fb)
252               {
253                 imageActor.SetImage( fb );
254               }
255             }
256           }
257         }
258       }
259
260       // special field 'effect' references the shader effect instances
261       if(key == "effect")
262       {
263         ImageActor actor = ImageActor::DownCast(handle);
264         if( actor )
265         {
266           OptionalString str = constant.IsString( keyChild.second );
267           if( str )
268           {
269             ShaderEffect effect = GetShaderEffect( *str, constant );
270             actor.SetShaderEffect(effect);
271           }
272         }
273         else
274         {
275           DALI_SCRIPT_WARNING("Could not find or set shader effect\n");
276         }
277
278         continue;
279       }
280
281       Handle propertyObject( handle );
282
283       Dali::Property::Index index = propertyObject.GetPropertyIndex( key );
284
285       if( Property::INVALID_INDEX == index )
286       {
287         ImageActor actor = ImageActor::DownCast(handle);
288         if( actor )
289         {
290           if( ShaderEffect effect = actor.GetShaderEffect() )
291           {
292             index = effect.GetPropertyIndex( key );
293             if(index != Property::INVALID_INDEX)
294             {
295               propertyObject = effect;
296             }
297           }
298         }
299       }
300
301       if( Property::INVALID_INDEX != index )
302       {
303         Property::Type type = propertyObject.GetPropertyType(index);
304
305         Property::Value value;
306         if( !SetPropertyFromNode( keyChild.second, type, value, constant ) )
307         {
308           // verbose as this might not be a problem
309           // eg parent-origin can be a string which is picked up later
310           DALI_SCRIPT_VERBOSE("Could not convert property:%s\n", key.c_str());
311         }
312         else
313         {
314           DALI_SCRIPT_VERBOSE("SetProperty '%s' Index=:%d Value Type=%d Value '%s'\n", key.c_str(), index, value.GetType(), PropertyValueToString(value).c_str() );
315
316           propertyObject.SetProperty( index, value );
317         }
318       }
319       else
320       {
321         DALI_SCRIPT_VERBOSE("SetProperty INVALID '%s' Index=:%d\n", key.c_str(), index);
322       }
323
324     } // for property nodes
325   }
326   else
327   {
328     DALI_SCRIPT_WARNING("Style applied to empty handle\n");
329   }
330 }
331
332 // Set properties from node on handle.
333 void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node,
334                                Dali::Handle& handle, const Replacement& constant )
335 {
336   if( Actor actor = Actor::DownCast(handle) )
337   {
338     SetProperties( node, actor, constant );
339
340     if( actor )
341     {
342       SetupActor( node, actor, constant );
343
344       // add signals
345       SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, this );
346       SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, this );
347    }
348   }
349   else
350   {
351     SetProperties( node, handle, constant );
352   }
353 }
354
355 // Appling by style helper
356 // use FindChildByName() to apply properties referenced in KEYNAME_ACTORS in the node
357 void Builder::ApplyStylesByActor(  const TreeNode& root, const TreeNode& node,
358                                    Dali::Handle& handle, const Replacement& constant )
359 {
360   if( Dali::Actor actor = Dali::Actor::DownCast( handle ) )
361   {
362     if( const TreeNode* actors = node.GetChild( KEYNAME_ACTORS ) )
363     {
364       // in a style the actor subtree properties referenced by actor name
365       for( TreeConstIter iter = actors->CBegin(); iter != actors->CEnd(); ++iter )
366       {
367         Dali::Actor foundActor;
368
369         if( (*iter).first )
370         {
371           foundActor = actor.FindChildByName( (*iter).first );
372         }
373
374         if( !foundActor )
375         {
376           // debug log cannot find searched for actor
377 #if defined(DEBUG_ENABLED)
378           DALI_SCRIPT_VERBOSE("Cannot find actor in style application '%s'\n", (*iter).first);
379 #endif
380         }
381         else
382         {
383 #if defined(DEBUG_ENABLED)
384           DALI_SCRIPT_VERBOSE("Styles applied to actor '%s'\n", (*iter).first);
385 #endif
386           ApplyProperties( root, (*iter).second, foundActor, constant );
387         }
388       }
389     }
390   }
391 }
392
393
394 void Builder::ApplyAllStyleProperties( const TreeNode& root, const TreeNode& node,
395                                        Dali::Handle& handle, const Replacement& constant )
396 {
397   OptionalChild styles = IsChild(root, KEYNAME_STYLES);
398   OptionalChild style  = IsChild(node, KEYNAME_STYLES);
399
400   if( styles && style )
401   {
402     TreeNodeList additionalStyles;
403
404     CollectAllStyles( *styles, *style, additionalStyles );
405
406 #if defined(DEBUG_ENABLED)
407     for(TreeNode::ConstIterator iter = (*style).CBegin(); iter != (*style).CEnd(); ++iter)
408     {
409       if( OptionalString styleName = IsString( (*iter).second ) )
410       {
411         DALI_SCRIPT_VERBOSE("Style Applied '%s'\n", (*styleName).c_str());
412       }
413     }
414 #endif
415
416     // a style may have other styles, which has other styles etc so we apply in reverse by convention.
417     for(TreeNodeList::reverse_iterator iter = additionalStyles.rbegin(); iter != additionalStyles.rend(); ++iter)
418     {
419       ApplyProperties( root, *(*iter), handle, constant );
420
421       ApplyStylesByActor( root, *(*iter), handle, constant );
422     }
423   }
424
425   // applying given node last
426   ApplyProperties( root, node, handle, constant );
427
428   ApplyStylesByActor( root, node, handle, constant );
429
430 }
431
432
433 /*
434  * Create a dali type from a node.
435  * If parent given and an actor type was created then add it to the parent and
436  * recursively add nodes children.
437  */
438 BaseHandle Builder::DoCreate( const TreeNode& root, const TreeNode& node,
439                               Actor parent, const Replacement& replacements )
440 {
441   BaseHandle baseHandle;
442   TypeInfo typeInfo;
443   const TreeNode* templateNode = NULL;
444
445   if( OptionalString typeName = IsString(node, KEYNAME_TYPE) )
446   {
447     typeInfo = TypeRegistry::Get().GetTypeInfo( *typeName );
448
449     if( !typeInfo )
450     {
451       // a template name is also allowed inplace of the type name
452       OptionalChild templates = IsChild( root, KEYNAME_TEMPLATES);
453
454       if( templates )
455       {
456         if( OptionalChild isTemplate = IsChild( *templates, *typeName ) )
457         {
458           templateNode = &(*isTemplate);
459
460           if( OptionalString templateTypeName = IsString(*templateNode, KEYNAME_TYPE) )
461           {
462             typeInfo = TypeRegistry::Get().GetTypeInfo( *templateTypeName );
463           }
464         }
465       }
466     }
467   }
468
469   if(!typeInfo)
470   {
471     DALI_SCRIPT_WARNING("Cannot create Dali type from node '%s'\n", node.GetName());
472   }
473   else
474   {
475     baseHandle       = typeInfo.CreateInstance();
476     Handle handle    = Handle::DownCast(baseHandle);
477     Actor actor      = Actor::DownCast(handle);
478
479     if(handle)
480     {
481
482       DALI_SCRIPT_VERBOSE("Create:%s\n", typeInfo.GetName().c_str());
483
484 #if defined(DEBUG_ENABLED)
485       if(handle)
486       {
487         DALI_SCRIPT_VERBOSE("  Is Handle Object=%d\n", (long*)handle.GetObjectPtr());
488         DALI_SCRIPT_VERBOSE("  Is Handle Property Count=%d\n", handle.GetPropertyCount());
489       }
490
491       if(actor)
492       {
493         DALI_SCRIPT_VERBOSE("  Is Actor id=%d\n", actor.GetId());
494       }
495
496       Toolkit::Control control  = Toolkit::Control::DownCast(handle);
497       if(control)
498       {
499         DALI_SCRIPT_VERBOSE("  Is Control id=%d\n", actor.GetId());
500       }
501 #endif // DEBUG_ENABLED
502
503       if( templateNode )
504       {
505         ApplyProperties( root, *templateNode, handle, replacements );
506
507         if( OptionalChild actors = IsChild( *templateNode, KEYNAME_ACTORS ) )
508         {
509           for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter )
510           {
511             DoCreate( root, (*iter).second, actor, replacements );
512           }
513         }
514       }
515
516       if( actor )
517       {
518         // add children of all the styles
519         if( OptionalChild actors = IsChild( node, KEYNAME_ACTORS ) )
520         {
521           for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter )
522           {
523             DoCreate( root, (*iter).second, actor, replacements );
524           }
525         }
526
527         // apply style on top as they need the children to exist
528         ApplyAllStyleProperties( root, node, actor, replacements );
529
530         // then add to parent
531         if( parent )
532         {
533           parent.Add( actor );
534         }
535       }
536       else
537       {
538         ApplyProperties( root, node, handle, replacements );
539       }
540     }
541     else
542     {
543       DALI_SCRIPT_WARNING("Cannot create handle from type '%s'\n", typeInfo.GetName().c_str());
544     }
545   }
546
547   return baseHandle;
548 }
549
550 void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replacement& constant )
551 {
552   const Stage& stage = Stage::GetCurrent();
553   Layer root  = stage.GetRootLayer();
554
555   if( OptionalString s = constant.IsString( IsChild(node, "source-actor") ) )
556   {
557     Actor actor = root.FindChildByName(*s);
558     if(actor)
559     {
560       task.SetSourceActor( actor );
561     }
562     else
563     {
564       DALI_SCRIPT_WARNING("Cannot find source actor on stage for render task called '%s'\n", (*s).c_str() );
565     }
566   }
567
568   if( OptionalString s = constant.IsString( IsChild(node, "camera-actor") ) )
569   {
570     CameraActor actor = CameraActor::DownCast( root.FindChildByName(*s) );
571     if(actor)
572     {
573       task.SetCameraActor( actor );
574     }
575     else
576     {
577       DALI_SCRIPT_WARNING("Cannot find camera actor on stage for render task called '%s'\n", (*s).c_str() );
578     }
579   }
580
581   if( OptionalString s = constant.IsString( IsChild(node, "target-frame-buffer") ) )
582   {
583     FrameBufferImage fb = GetFrameBufferImage( *s, constant );
584     if(fb)
585     {
586       task.SetTargetFrameBuffer( fb );
587     }
588     else
589     {
590       DALI_SCRIPT_WARNING("Cannot find target frame buffer '%s'\n", (*s).c_str() );
591     }
592   }
593
594   if( OptionalString s = constant.IsString( IsChild(node, "screen-to-frame-buffer-function") ) )
595   {
596     if("DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION" == *s)
597     {
598       task.SetScreenToFrameBufferFunction( RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION );
599     }
600     else if("FULLSCREEN_FRAMEBUFFER_FUNCTION" == *s)
601     {
602       task.SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
603     }
604     else
605     {
606       DALI_SCRIPT_WARNING("todo");
607     }
608   }
609
610   // other setup is via the property system
611   SetProperties( node, task, constant ); // @ todo, remove 'source-actor', 'camera-actor'?
612
613 }
614
615 void Builder::CreateRenderTask( const std::string &name )
616 {
617   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
618
619   Replacement constant(mReplacementMap);
620
621   const Stage& stage = Stage::GetCurrent();
622
623   OptionalChild tasks = IsChild(*mParser.GetRoot(), "render-tasks");
624
625   if(tasks)
626   {
627     //
628     // Create the tasks from the current task as generally we want
629     // to setup task zero and onwards. Although this does overwrite
630     // the properties of the current task.
631     //
632     if( OptionalChild renderTask = IsChild(*tasks, name ) )
633     {
634       RenderTaskList list = stage.GetRenderTaskList();
635       unsigned int start = list.GetTaskCount();
636
637       RenderTask task;
638       if(0 == start)
639       {
640         // zero should have already been created by the stage so really
641         // this case should never happen
642         task = list.CreateTask();
643         start++;
644       }
645
646       TreeNode::ConstIterator iter = (*renderTask).CBegin();
647       task = list.GetTask( start - 1 );
648
649       SetupTask( task, (*iter).second, constant  );
650
651       ++iter;
652
653       for(; iter != (*renderTask).CEnd(); ++iter )
654       {
655         task = list.CreateTask();
656         SetupTask( task, (*iter).second, constant );
657       }
658     }
659   }
660 }
661
662 ShaderEffect Builder::GetShaderEffect( const std::string &name)
663 {
664   Replacement constant( mReplacementMap );
665   return GetShaderEffect( name, constant );
666 }
667
668 ShaderEffect Builder::GetShaderEffect( const std::string &name, const Replacement& constant )
669 {
670   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
671
672   ShaderEffect ret;
673
674   ShaderEffectLut::const_iterator iter( mShaderEffectLut.find( name ) );
675   if( iter != mShaderEffectLut.end() )
676   {
677     ret = iter->second;
678   }
679   else
680   {
681     if( OptionalChild effects = IsChild( *mParser.GetRoot(), "shader-effects") )
682     {
683       if( OptionalChild effect = IsChild( *effects, name ) )
684       {
685         Dali::Property::Value propertyMap(Property::MAP);
686         if( SetPropertyFromNode( *effect, Property::MAP, propertyMap, constant ) )
687         {
688           ret = Dali::Scripting::NewShaderEffect( propertyMap );
689           mShaderEffectLut[ name ] = ret;
690         }
691       }
692     }
693   }
694
695   return ret;
696 }
697
698 FrameBufferImage Builder::GetFrameBufferImage( const std::string &name )
699 {
700   Replacement constant( mReplacementMap );
701   return GetFrameBufferImage(name, constant);
702 }
703
704 FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Replacement& constant )
705 {
706   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
707
708   FrameBufferImage ret;
709
710   ImageLut::const_iterator iter( mFrameBufferImageLut.find( name ) );
711   if( iter != mFrameBufferImageLut.end() )
712   {
713     ret = iter->second;
714   }
715   else
716   {
717     if( OptionalChild images = IsChild( *mParser.GetRoot(), "frame-buffer-images") )
718     {
719       if( OptionalChild image = IsChild( *images, name ) )
720       {
721         Dali::Property::Value property(Property::MAP);
722         if( SetPropertyFromNode( *image, Property::MAP, property, constant ) )
723         {
724           Property::Map* map = property.GetMap();
725           (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") );
726           ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) );
727           mFrameBufferImageLut[ name ] = ret;
728         }
729       }
730     }
731   }
732
733   return ret;
734 }
735
736 Path Builder::GetPath( const std::string& name )
737 {
738   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
739
740   Path ret;
741
742   PathLut::const_iterator iter( mPathLut.find( name ) );
743   if( iter != mPathLut.end() )
744   {
745     ret = iter->second;
746   }
747   else
748   {
749     if( OptionalChild paths = IsChild( *mParser.GetRoot(), "paths") )
750     {
751       if( OptionalChild path = IsChild( *paths, name ) )
752       {
753         //points property
754         if( OptionalChild pointsProperty = IsChild( *path, "points") )
755         {
756           Dali::Property::Value points(Property::ARRAY);
757           if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
758           {
759             ret = Path::New();
760             ret.SetProperty( Path::Property::POINTS, points);
761
762             //control-points property
763             if( OptionalChild pointsProperty = IsChild( *path, "control-points") )
764             {
765               Dali::Property::Value points(Property::ARRAY);
766               if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
767               {
768                 ret.SetProperty( Path::Property::CONTROL_POINTS, points);
769               }
770             }
771             else
772             {
773               //Curvature
774               float curvature(0.25f);
775               if( OptionalFloat pointsProperty = IsFloat( *path, "curvature") )
776               {
777                 curvature = *pointsProperty;
778               }
779               ret.GenerateControlPoints(curvature);
780             }
781
782             //Add the new path to the hash table for paths
783             mPathLut[ name ] = ret;
784           }
785         }
786         else
787         {
788           //Interpolation points not specified
789           DALI_SCRIPT_WARNING("Interpolation points not specified for path '%s'\n", name.c_str() );
790         }
791       }
792
793     }
794   }
795
796   return ret;
797 }
798
799 PathConstrainer Builder::GetPathConstrainer( const std::string& name )
800 {
801   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
802
803   //Search the pathConstrainer in the LUT
804   size_t count( mPathConstrainerLut.size() );
805   for( size_t i(0); i!=count; ++i )
806   {
807     if( mPathConstrainerLut[i].name == name )
808     {
809       //PathConstrainer has already been created
810       return mPathConstrainerLut[i].pathConstrainer;
811     }
812   }
813
814   //Create a new PathConstrainer
815   PathConstrainer ret;
816   if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") )
817   {
818     if( OptionalChild pathConstrainer = IsChild( *constrainers, name ) )
819     {
820       OptionalString constrainerType(IsString(IsChild(*pathConstrainer, "type")));
821       if(!constrainerType)
822       {
823         DALI_SCRIPT_WARNING("Constrainer type not specified for constrainer '%s'\n", name.c_str() );
824       }
825       else if( *constrainerType == "PathConstrainer")
826       {
827         //points property
828         if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "points") )
829         {
830           Dali::Property::Value points(Property::ARRAY);
831           if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
832           {
833             ret = PathConstrainer::New();
834             ret.SetProperty( PathConstrainer::Property::POINTS, points);
835
836             //control-points property
837             if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "control-points") )
838             {
839               Dali::Property::Value points(Property::ARRAY);
840               if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
841               {
842                 ret.SetProperty( PathConstrainer::Property::CONTROL_POINTS, points);
843               }
844
845               //Forward vector
846               OptionalVector3 forward( IsVector3( IsChild(*pathConstrainer, "forward" ) ) );
847               if( forward )
848               {
849                 ret.SetProperty( PathConstrainer::Property::FORWARD, *forward);
850               }
851
852               //Add the new constrainer to the vector of PathConstrainer
853               PathConstrainerEntry entry = {name,ret};
854               mPathConstrainerLut.push_back( entry );
855             }
856             else
857             {
858               //Control points not specified
859               DALI_SCRIPT_WARNING("Control points not specified for pathConstrainer '%s'\n", name.c_str() );
860             }
861           }
862         }
863         else
864         {
865           //Interpolation points not specified
866           DALI_SCRIPT_WARNING("Interpolation points not specified for pathConstrainer '%s'\n", name.c_str() );
867         }
868       }
869       else
870       {
871         DALI_SCRIPT_WARNING("Constrainer '%s' is not a PathConstrainer\n", name.c_str() );
872       }
873     }
874   }
875
876   return ret;
877 }
878
879 bool Builder::IsPathConstrainer( const std::string& name )
880 {
881   size_t count( mPathConstrainerLut.size() );
882   for( size_t i(0); i!=count; ++i )
883   {
884     if( mPathConstrainerLut[i].name == name )
885     {
886       return true;
887     }
888   }
889
890   if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") )
891   {
892     if( OptionalChild constrainer = IsChild( *constrainers, name ) )
893     {
894       OptionalString constrainerType(IsString(IsChild(*constrainer, "type")));
895       if(!constrainerType)
896       {
897         return false;
898       }
899       else
900       {
901          return *constrainerType == "PathConstrainer";
902       }
903     }
904   }
905   return false;
906 }
907
908 Dali::LinearConstrainer Builder::GetLinearConstrainer( const std::string& name )
909 {
910   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
911
912   //Search the LinearConstrainer in the LUT
913   size_t count( mLinearConstrainerLut.size() );
914   for( size_t i(0); i!=count; ++i )
915   {
916     if( mLinearConstrainerLut[i].name == name )
917     {
918       //LinearConstrainer has already been created
919       return mLinearConstrainerLut[i].linearConstrainer;
920     }
921   }
922
923   //Create a new LinearConstrainer
924   LinearConstrainer ret;
925   if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") )
926   {
927     if( OptionalChild linearConstrainer = IsChild( *constrainers, name ) )
928     {
929       OptionalString constrainerType(IsString(IsChild(*linearConstrainer, "type")));
930       if(!constrainerType)
931       {
932         DALI_SCRIPT_WARNING("Constrainer type not specified for constrainer '%s'\n", name.c_str() );
933       }
934       else if( *constrainerType == "LinearConstrainer")
935       {
936         //points property
937         if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "value") )
938         {
939           Dali::Property::Value points(Property::ARRAY);
940           if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
941           {
942             ret = Dali::LinearConstrainer::New();
943             ret.SetProperty( LinearConstrainer::Property::VALUE, points);
944
945             //control-points property
946             if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "progress") )
947             {
948               Dali::Property::Value points(Property::ARRAY);
949               if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
950               {
951                 ret.SetProperty( LinearConstrainer::Property::PROGRESS, points);
952               }
953             }
954             //Add the new constrainer to vector of LinearConstrainer
955             LinearConstrainerEntry entry = {name,ret};
956             mLinearConstrainerLut.push_back( entry );
957           }
958         }
959         else
960         {
961           //Interpolation points not specified
962           DALI_SCRIPT_WARNING("Values not specified for LinearConstrainer '%s'\n", name.c_str() );
963         }
964       }
965       else
966       {
967         DALI_SCRIPT_WARNING("Constrainer '%s' is not a LinearConstrainer\n", name.c_str() );
968       }
969     }
970   }
971
972   return ret;
973 }
974
975 bool Builder::IsLinearConstrainer( const std::string& name )
976 {
977   //Search the LinearConstrainer in the LUT
978   size_t count( mLinearConstrainerLut.size() );
979   for( size_t i(0); i!=count; ++i )
980   {
981     if( mLinearConstrainerLut[i].name == name )
982     {
983       return true;
984     }
985   }
986
987   if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") )
988   {
989     if( OptionalChild constrainer = IsChild( *constrainers, name ) )
990     {
991       OptionalString constrainerType(IsString(IsChild(*constrainer, "type")));
992       if(!constrainerType)
993       {
994         return false;
995       }
996       else
997       {
998          return *constrainerType == "LinearConstrainer";
999       }
1000     }
1001   }
1002   return false;
1003 }
1004
1005 Toolkit::Builder::BuilderSignalType& Builder::QuitSignal()
1006 {
1007   return mQuitSignal;
1008 }
1009
1010 void Builder::EmitQuitSignal()
1011 {
1012   mQuitSignal.Emit();
1013 }
1014
1015 void Builder::AddActors( Actor toActor )
1016 {
1017   // 'stage' is the default/by convention section to add from
1018   AddActors( "stage", toActor );
1019 }
1020
1021 void Builder::AddActors( const std::string &sectionName, Actor toActor )
1022 {
1023   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1024
1025   Property::Map overrideMap;
1026   Replacement replacements(overrideMap, mReplacementMap);
1027
1028   OptionalChild add = IsChild(*mParser.GetRoot(), sectionName);
1029
1030   if( add )
1031   {
1032     for( TreeNode::ConstIterator iter = (*add).CBegin(); iter != (*add).CEnd(); ++iter )
1033     {
1034       // empty actor adds directly to the stage
1035       BaseHandle baseHandle = DoCreate( *mParser.GetRoot(), (*iter).second, Actor(), replacements );
1036       Actor actor = Actor::DownCast(baseHandle);
1037       if(actor)
1038       {
1039         toActor.Add( actor );
1040       }
1041     }
1042
1043     // if were adding the 'stage' section then also check for a render task called stage
1044     // to add automatically
1045     if( "stage" == sectionName )
1046     {
1047       if( OptionalChild renderTasks = IsChild(*mParser.GetRoot(), "render-tasks") )
1048       {
1049         if( OptionalChild tasks = IsChild(*renderTasks, "stage") )
1050         {
1051           CreateRenderTask( "stage" );
1052         }
1053       }
1054     }
1055   }
1056 }
1057
1058 Animation Builder::CreateAnimation( const std::string& animationName, const Replacement& replacement, Dali::Actor sourceActor )
1059 {
1060   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1061
1062   Animation anim;
1063
1064   if( OptionalChild animations = IsChild(*mParser.GetRoot(), "animations") )
1065   {
1066     if( OptionalChild animation = IsChild(*animations, animationName) )
1067     {
1068       anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor, this );
1069     }
1070     else
1071     {
1072       DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed\n", animationName.c_str() );
1073     }
1074   }
1075   else
1076   {
1077     DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed (no animation section)\n", animationName.c_str() );
1078   }
1079
1080   return anim;
1081 }
1082
1083 Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map, Dali::Actor sourceActor )
1084 {
1085   Replacement replacement(map, mReplacementMap);
1086   return CreateAnimation( animationName, replacement, sourceActor);
1087 }
1088
1089 Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map )
1090 {
1091   Replacement replacement(map, mReplacementMap);
1092   return CreateAnimation( animationName, replacement, Stage::GetCurrent().GetRootLayer() );
1093 }
1094
1095 Animation Builder::CreateAnimation( const std::string& animationName, Dali::Actor sourceActor )
1096 {
1097   Replacement replacement( mReplacementMap );
1098
1099   return CreateAnimation( animationName, replacement, sourceActor );
1100 }
1101
1102 Animation Builder::CreateAnimation( const std::string& animationName )
1103 {
1104   Replacement replacement( mReplacementMap );
1105
1106   return CreateAnimation( animationName, replacement, Dali::Stage::GetCurrent().GetRootLayer() );
1107 }
1108
1109 void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::UIFormat format )
1110 {
1111   // parser to get constants and includes only
1112   Dali::Toolkit::JsonParser parser = Dali::Toolkit::JsonParser::New();
1113
1114   if( !parser.Parse( data ) )
1115   {
1116     DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n",
1117                       parser.GetErrorLineNumber(),
1118                       parser.GetErrorColumn(),
1119                       parser.GetErrorDescription().c_str() );
1120
1121     DALI_ASSERT_ALWAYS(!"Cannot parse JSON");
1122
1123   }
1124   else
1125   {
1126     // load constant map (allows the user to override the constants in the json after loading)
1127     LoadConstants( *parser.GetRoot(), mReplacementMap );
1128
1129     // merge includes
1130     if( OptionalChild includes = IsChild(*parser.GetRoot(), KEYNAME_INCLUDES) )
1131     {
1132       Replacement replacer( mReplacementMap );
1133
1134       for(TreeNode::ConstIterator iter = (*includes).CBegin(); iter != (*includes).CEnd(); ++iter)
1135       {
1136         OptionalString filename = replacer.IsString( (*iter).second );
1137
1138         if( filename )
1139         {
1140 #if defined(DEBUG_ENABLED)
1141           DALI_SCRIPT_VERBOSE("Loading Include '%s'\n", (*filename).c_str());
1142 #endif
1143           LoadFromString( GetFileContents(*filename) );
1144         }
1145       }
1146     }
1147
1148     if( !mParser.Parse( data ) )
1149     {
1150       DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n",
1151                         mParser.GetErrorLineNumber(),
1152                         mParser.GetErrorColumn(),
1153                         mParser.GetErrorDescription().c_str() );
1154
1155       DALI_ASSERT_ALWAYS(!"Cannot parse JSON");
1156     }
1157   }
1158
1159   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON");
1160
1161 }
1162
1163 void Builder::AddConstants( const Property::Map& map )
1164 {
1165   mReplacementMap.Merge( map );
1166 }
1167
1168 void Builder::AddConstant( const std::string& key, const Property::Value& value )
1169 {
1170   mReplacementMap[key] = value;
1171 }
1172
1173 const Property::Map& Builder::GetConstants() const
1174 {
1175   return mReplacementMap;
1176 }
1177
1178 const Property::Value& Builder::GetConstant( const std::string& key ) const
1179 {
1180   Property::Value* match = mReplacementMap.Find( key );
1181   if( match )
1182   {
1183     return (*match);
1184   }
1185   else
1186   {
1187     static Property::Value invalid;
1188     return invalid;
1189   }
1190 }
1191
1192 void Builder::LoadConstants( const TreeNode& root, Property::Map& intoMap )
1193 {
1194   Replacement replacer(intoMap);
1195
1196   if( OptionalChild constants = IsChild(root, "constants") )
1197   {
1198     for(TreeNode::ConstIterator iter = (*constants).CBegin();
1199         iter != (*constants).CEnd(); ++iter)
1200     {
1201       Dali::Property::Value property;
1202       if( (*iter).second.GetName() )
1203       {
1204 #if defined(DEBUG_ENABLED)
1205         DALI_SCRIPT_VERBOSE("Constant set from json '%s'\n", (*iter).second.GetName());
1206 #endif
1207         if( SetPropertyFromNode( (*iter).second, property, replacer ) )
1208         {
1209           intoMap[ (*iter).second.GetName() ] = property;
1210         }
1211         else
1212         {
1213           DALI_SCRIPT_WARNING("Cannot convert property for constant %s\n",
1214                               (*iter).second.GetName() == NULL ? "no name?" : (*iter).second.GetName());
1215         }
1216       }
1217     }
1218   }
1219
1220 #if defined(DEBUG_ENABLED)
1221   Property::Value* iter = intoMap.Find( "CONFIG_SCRIPT_LOG_LEVEL" );
1222   if( iter && iter->GetType() == Property::STRING )
1223   {
1224     std::string logLevel( iter->Get< std::string >() );
1225     if( logLevel == "NoLogging" )
1226     {
1227       gFilterScript->SetLogLevel( Integration::Log::NoLogging );
1228     }
1229     else if( logLevel == "Concise" )
1230     {
1231       gFilterScript->SetLogLevel( Integration::Log::Concise );
1232     }
1233     else if( logLevel == "General" )
1234     {
1235       gFilterScript->SetLogLevel( Integration::Log::General );
1236     }
1237     else if( logLevel == "Verbose" )
1238     {
1239       gFilterScript->SetLogLevel( Integration::Log::Verbose );
1240     }
1241   }
1242 #endif
1243
1244 }
1245
1246 bool Builder::ApplyStyle( const std::string& styleName, Handle& handle )
1247 {
1248   Replacement replacer( mReplacementMap );
1249   return ApplyStyle( styleName, handle, replacer );
1250 }
1251
1252 bool Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement )
1253 {
1254   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1255
1256   OptionalChild styles = IsChild( *mParser.GetRoot(), KEYNAME_STYLES );
1257   OptionalChild style  = IsChild( *styles, styleName );
1258
1259   if( styles && style )
1260   {
1261     ApplyAllStyleProperties( *mParser.GetRoot(), *style, handle, replacement );
1262     return true;
1263   }
1264   else
1265   {
1266     return false;
1267   }
1268 }
1269
1270 BaseHandle Builder::Create( const std::string& templateName, const Property::Map& map )
1271 {
1272   Replacement replacement( map, mReplacementMap );
1273   return Create( templateName, replacement );
1274 }
1275
1276 BaseHandle Builder::Create( const std::string& templateName, const Replacement& constant )
1277 {
1278   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1279
1280   BaseHandle baseHandle;
1281
1282   OptionalChild templates = IsChild(*mParser.GetRoot(), KEYNAME_TEMPLATES);
1283
1284   if( !templates )
1285   {
1286     DALI_SCRIPT_WARNING("No template section found to CreateFromTemplate\n");
1287   }
1288   else
1289   {
1290     OptionalChild childTemplate = IsChild(*templates, templateName);
1291     if(!childTemplate)
1292     {
1293       DALI_SCRIPT_WARNING("Template '%s' does not exist in template section\n", templateName.c_str());
1294     }
1295     else
1296     {
1297       OptionalString type = constant.IsString( IsChild(*childTemplate, KEYNAME_TYPE) );
1298
1299       if(!type)
1300       {
1301         DALI_SCRIPT_WARNING("Cannot create template '%s' as template section is missing 'type'\n", templateName.c_str());
1302       }
1303       else
1304       {
1305         baseHandle = DoCreate( *mParser.GetRoot(), *childTemplate, Actor(), constant );
1306       }
1307     }
1308   }
1309
1310   return baseHandle;
1311 }
1312
1313 BaseHandle Builder::CreateFromJson( const std::string& json )
1314 {
1315   BaseHandle ret;
1316
1317   // merge in new template, hoping no one else has one named '@temp@'
1318   std::string newTemplate =
1319     std::string("{\"templates\":{\"@temp@\":") +                      \
1320     json +                                                            \
1321     std::string("}}");
1322
1323   if( mParser.Parse(newTemplate) )
1324   {
1325     Replacement replacement( mReplacementMap );
1326     ret = Create( "@temp@", replacement );
1327   }
1328
1329   return ret;
1330 }
1331
1332 bool Builder::ApplyFromJson(  Handle& handle, const std::string& json )
1333 {
1334   bool ret = false;
1335
1336   // merge new style, hoping no one else has one named '@temp@'
1337   std::string newStyle =
1338     std::string("{\"styles\":{\"@temp@\":") +                           \
1339     json +                                                              \
1340     std::string("}}");
1341
1342   if( mParser.Parse(newStyle) )
1343   {
1344     Replacement replacement( mReplacementMap );
1345     ret = ApplyStyle( "@temp@", handle, replacement );
1346   }
1347
1348   return ret;
1349 }
1350
1351
1352 BaseHandle Builder::Create( const std::string& templateName )
1353 {
1354   Replacement replacement( mReplacementMap );
1355   return Create( templateName, replacement );
1356 }
1357
1358 Builder::Builder()
1359 : mSlotDelegate( this )
1360 {
1361   mParser = Dali::Toolkit::JsonParser::New();
1362
1363   Property::Map defaultDirs;
1364   defaultDirs[ TOKEN_STRING(DALI_IMAGE_DIR) ]  = DALI_IMAGE_DIR;
1365   defaultDirs[ TOKEN_STRING(DALI_SOUND_DIR) ]  = DALI_SOUND_DIR;
1366   defaultDirs[ TOKEN_STRING(DALI_STYLE_DIR) ] = DALI_STYLE_DIR;
1367
1368   AddConstants( defaultDirs );
1369 }
1370
1371 Builder::~Builder()
1372 {
1373 }
1374
1375 } // namespace Internal
1376
1377 } // namespace Toolkit
1378
1379 } // namespace Dali