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