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