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