2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
18 #include <dali/public-api/scripting/scripting.h>
21 #include <dali/public-api/actors/actor.h>
22 #include <dali/public-api/images/image.h>
23 #include <dali/public-api/images/image-attributes.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/internal/event/images/image-impl.h>
26 #include <dali/internal/event/images/frame-buffer-image-impl.h>
27 #include <dali/internal/event/images/bitmap-image-impl.h>
28 #include <dali/internal/event/effects/shader-effect-impl.h>
39 // Helpers for converting strings to the enumerations and vice versa
41 template< typename T >
44 const std::string string;
48 const StringEnum< ColorMode > COLOR_MODE_TABLE[] =
50 { "USE_OWN_COLOR", USE_OWN_COLOR },
51 { "USE_PARENT_COLOR", USE_PARENT_COLOR },
52 { "USE_OWN_MULTIPLY_PARENT_COLOR", USE_OWN_MULTIPLY_PARENT_COLOR },
53 { "USE_OWN_MULTIPLY_PARENT_ALPHA", USE_OWN_MULTIPLY_PARENT_ALPHA },
55 const unsigned int COLOR_MODE_TABLE_COUNT = sizeof( COLOR_MODE_TABLE ) / sizeof( COLOR_MODE_TABLE[0] );
57 const StringEnum< PositionInheritanceMode > POSITION_INHERITANCE_MODE_TABLE[] =
59 { "INHERIT_PARENT_POSITION", INHERIT_PARENT_POSITION },
60 { "USE_PARENT_POSITION", USE_PARENT_POSITION },
61 { "USE_PARENT_POSITION_PLUS_LOCAL_POSITION", USE_PARENT_POSITION_PLUS_LOCAL_POSITION },
62 { "DONT_INHERIT_POSITION", DONT_INHERIT_POSITION },
64 const unsigned int POSITION_INHERITANCE_MODE_TABLE_COUNT = sizeof( POSITION_INHERITANCE_MODE_TABLE ) / sizeof( POSITION_INHERITANCE_MODE_TABLE[0] );
66 const StringEnum< DrawMode::Type > DRAW_MODE_TABLE[] =
68 { "NORMAL", DrawMode::NORMAL },
69 { "OVERLAY", DrawMode::OVERLAY },
70 { "STENCIL", DrawMode::STENCIL },
72 const unsigned int DRAW_MODE_TABLE_COUNT = sizeof( DRAW_MODE_TABLE ) / sizeof( DRAW_MODE_TABLE[0] );
74 const StringEnum< Vector3 > ANCHOR_CONSTANT_TABLE[] =
76 { "BACK_TOP_LEFT", ParentOrigin::BACK_TOP_LEFT },
77 { "BACK_TOP_CENTER", ParentOrigin::BACK_TOP_CENTER },
78 { "BACK_TOP_RIGHT", ParentOrigin::BACK_TOP_RIGHT },
79 { "BACK_CENTER_LEFT", ParentOrigin::BACK_CENTER_LEFT },
80 { "BACK_CENTER", ParentOrigin::BACK_CENTER },
81 { "BACK_CENTER_RIGHT", ParentOrigin::BACK_CENTER_RIGHT },
82 { "BACK_BOTTOM_LEFT", ParentOrigin::BACK_BOTTOM_LEFT },
83 { "BACK_BOTTOM_CENTER", ParentOrigin::BACK_BOTTOM_CENTER },
84 { "BACK_BOTTOM_RIGHT", ParentOrigin::BACK_BOTTOM_RIGHT },
85 { "TOP_LEFT", ParentOrigin::TOP_LEFT },
86 { "TOP_CENTER", ParentOrigin::TOP_CENTER },
87 { "TOP_RIGHT", ParentOrigin::TOP_RIGHT },
88 { "CENTER_LEFT", ParentOrigin::CENTER_LEFT },
89 { "CENTER", ParentOrigin::CENTER },
90 { "CENTER_RIGHT", ParentOrigin::CENTER_RIGHT },
91 { "BOTTOM_LEFT", ParentOrigin::BOTTOM_LEFT },
92 { "BOTTOM_CENTER", ParentOrigin::BOTTOM_CENTER },
93 { "BOTTOM_RIGHT", ParentOrigin::BOTTOM_RIGHT },
94 { "FRONT_TOP_LEFT", ParentOrigin::FRONT_TOP_LEFT },
95 { "FRONT_TOP_CENTER", ParentOrigin::FRONT_TOP_CENTER },
96 { "FRONT_TOP_RIGHT", ParentOrigin::FRONT_TOP_RIGHT },
97 { "FRONT_CENTER_LEFT", ParentOrigin::FRONT_CENTER_LEFT },
98 { "FRONT_CENTER", ParentOrigin::FRONT_CENTER },
99 { "FRONT_CENTER_RIGHT", ParentOrigin::FRONT_CENTER_RIGHT },
100 { "FRONT_BOTTOM_LEFT", ParentOrigin::FRONT_BOTTOM_LEFT },
101 { "FRONT_BOTTOM_CENTER", ParentOrigin::FRONT_BOTTOM_CENTER },
102 { "FRONT_BOTTOM_RIGHT", ParentOrigin::FRONT_BOTTOM_RIGHT },
104 const unsigned int ANCHOR_CONSTANT_TABLE_COUNT = sizeof( ANCHOR_CONSTANT_TABLE ) / sizeof( ANCHOR_CONSTANT_TABLE[0] );
106 const StringEnum< Image::LoadPolicy > IMAGE_LOAD_POLICY_TABLE[] =
108 { "IMMEDIATE", Image::Immediate },
109 { "ON_DEMAND", Image::OnDemand },
111 const unsigned int IMAGE_LOAD_POLICY_TABLE_COUNT = sizeof( IMAGE_LOAD_POLICY_TABLE ) / sizeof( IMAGE_LOAD_POLICY_TABLE[0] );
113 const StringEnum< Image::ReleasePolicy > IMAGE_RELEASE_POLICY_TABLE[] =
115 { "UNUSED", Image::Unused },
116 { "NEVER", Image::Never },
118 const unsigned int IMAGE_RELEASE_POLICY_TABLE_COUNT = sizeof( IMAGE_RELEASE_POLICY_TABLE ) / sizeof( IMAGE_RELEASE_POLICY_TABLE[0] );
120 const StringEnum< Pixel::Format > PIXEL_FORMAT_TABLE[] =
124 { "LA88", Pixel::LA88 },
125 { "RGB565", Pixel::RGB565 },
126 { "BGR565", Pixel::BGR565 },
127 { "RGBA4444", Pixel::RGBA4444 },
128 { "BGRA4444", Pixel::BGRA4444 },
129 { "RGBA5551", Pixel::RGBA5551 },
130 { "BGRA5551", Pixel::BGRA5551 },
131 { "RGB888", Pixel::RGB888 },
132 { "RGB8888", Pixel::RGB8888 },
133 { "BGR8888", Pixel::BGR8888 },
134 { "RGBA8888", Pixel::RGBA8888 },
135 { "BGRA8888", Pixel::BGRA8888 },
136 { "COMPRESSED_R11_EAC", Pixel::COMPRESSED_R11_EAC },
137 { "COMPRESSED_SIGNED_R11_EAC", Pixel::COMPRESSED_SIGNED_R11_EAC },
138 { "COMPRESSED_RG11_EAC", Pixel::COMPRESSED_RG11_EAC },
139 { "COMPRESSED_SIGNED_RG11_EAC", Pixel::COMPRESSED_SIGNED_RG11_EAC },
140 { "COMPRESSED_RGB8_ETC2", Pixel::COMPRESSED_RGB8_ETC2 },
141 { "COMPRESSED_SRGB8_ETC2", Pixel::COMPRESSED_SRGB8_ETC2 },
142 { "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 },
143 { "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 },
144 { "COMPRESSED_RGBA8_ETC2_EAC", Pixel::COMPRESSED_RGBA8_ETC2_EAC },
145 { "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC },
146 { "COMPRESSED_RGB8_ETC1", Pixel::COMPRESSED_RGB8_ETC1 },
147 { "COMPRESSED_RGB_PVRTC_4BPPV1", Pixel::COMPRESSED_RGB_PVRTC_4BPPV1 },
149 const unsigned int PIXEL_FORMAT_TABLE_COUNT = sizeof( PIXEL_FORMAT_TABLE ) / sizeof( PIXEL_FORMAT_TABLE[0] );
151 const StringEnum< ImageAttributes::ScalingMode > IMAGE_SCALING_MODE_TABLE[] =
153 { "SHRINK_TO_FIT", ImageAttributes::ShrinkToFit },
154 { "SCALE_TO_FILL", ImageAttributes::ScaleToFill },
155 { "FIT_WIDTH", ImageAttributes::FitWidth },
156 { "FIT_HEIGHT", ImageAttributes::FitHeight },
158 const unsigned int IMAGE_SCALING_MODE_TABLE_COUNT = sizeof( IMAGE_SCALING_MODE_TABLE ) / sizeof( IMAGE_SCALING_MODE_TABLE[0] );
160 template< typename T >
161 T GetEnumeration( const std::string& value, const StringEnum< T >* table, const unsigned int tableCount )
166 for ( unsigned int i = 0; ( i < tableCount ) && ( !set ); ++i )
168 set = SetIfEqual(value, table->string, v, table->value );
174 DALI_ASSERT_ALWAYS( !"Unknown enumeration string" );
180 template< typename T >
181 const std::string& GetEnumerationName( const T& value, const StringEnum< T >* table, const unsigned int tableCount )
183 for ( unsigned int i = 0; i < tableCount; ++i )
185 if ( value == table[i].value )
187 return table[i].string;
192 return String::EMPTY;
195 } // unnamed namespace
197 bool CompareEnums(const std::string& a, const std::string& b)
199 std::string::const_iterator ia = a.begin();
200 std::string::const_iterator ib = b.begin();
202 while( (ia != a.end()) && (ib != b.end()) )
207 if(ca == '-' || ca == '_')
213 if(cb == '-' || cb == '_')
219 if( 'A' <= ca && ca <= 'Z')
221 ca = ca + ('a' - 'A');
224 if( 'A' <= cb && cb <= 'Z')
226 cb = cb + ('a' - 'A');
238 if( (ia == a.end() && ib == b.end() ) )
250 ColorMode GetColorMode( const std::string& value )
252 return GetEnumeration< ColorMode >( value, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
256 const std::string& GetColorMode( ColorMode value )
258 return GetEnumerationName< ColorMode >( value, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
261 PositionInheritanceMode GetPositionInheritanceMode( const std::string& value )
263 return GetEnumeration< PositionInheritanceMode >( value, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
267 const std::string& GetPositionInheritanceMode( PositionInheritanceMode value )
269 return GetEnumerationName< PositionInheritanceMode >( value, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
273 DrawMode::Type GetDrawMode( const std::string& value )
275 return GetEnumeration< DrawMode::Type >( value, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
279 const std::string& GetDrawMode( DrawMode::Type value )
281 return GetEnumerationName< DrawMode::Type >( value, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
285 Vector3 GetAnchorConstant( const std::string& value )
287 return GetEnumeration< Vector3 >( value, ANCHOR_CONSTANT_TABLE, ANCHOR_CONSTANT_TABLE_COUNT );
291 Image NewImage( const Property::Value& map )
295 std::string filename;
296 Image::LoadPolicy loadPolicy = Dali::Internal::ImageLoadPolicyDefault;
297 Image::ReleasePolicy releasePolicy = Dali::Internal::ImageReleasePolicyDefault;
298 ImageAttributes attributes = ImageAttributes::New();
300 if( Property::MAP == map.GetType() )
302 std::string field = "filename";
303 if( map.HasKey(field) )
305 DALI_ASSERT_ALWAYS(map.GetValue(field).GetType() == Property::STRING && "Image filename property is not a string" );
306 filename = map.GetValue(field).Get<std::string>();
309 field = "load-policy";
310 if( map.HasKey(field) )
312 DALI_ASSERT_ALWAYS(map.GetValue(field).GetType() == Property::STRING && "Image load-policy property is not a string" );
313 std::string v(map.GetValue(field).Get<std::string>());
314 loadPolicy = GetEnumeration< Image::LoadPolicy >( v, IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT );
317 field = "release-policy";
318 if( map.HasKey(field) )
320 DALI_ASSERT_ALWAYS(map.GetValue(field).GetType() == Property::STRING && "Image release-policy property is not a string" );
321 std::string v(map.GetValue(field).Get<std::string>());
322 releasePolicy = GetEnumeration< Image::ReleasePolicy >( v, IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT );
325 if( map.HasKey("width") && map.HasKey("height") )
327 Property::Value &value = map.GetValue("width");
328 unsigned int w = 0, h = 0;
329 // handle floats and integer the same for json script
330 if( value.GetType() == Property::FLOAT)
332 w = static_cast<unsigned int>( value.Get<float>() );
336 DALI_ASSERT_ALWAYS(value.GetType() == Property::INTEGER && "Image width property is not a number" );
337 w = value.Get<int>();
340 value = map.GetValue("height");
341 if( value.GetType() == Property::FLOAT)
343 h = static_cast<unsigned int>( value.Get<float>() );
347 DALI_ASSERT_ALWAYS(value.GetType() == Property::INTEGER && "Image width property is not a number" );
348 h = value.Get<int>();
351 attributes.SetSize( w, h );
354 field = "pixel-format";
355 if( map.HasKey(field) )
357 DALI_ASSERT_ALWAYS(map.GetValue(field).GetType() == Property::STRING && "Image release-policy property is not a string" );
358 std::string s(map.GetValue(field).Get<std::string>());
359 attributes.SetPixelFormat( GetEnumeration< Pixel::Format >( s, PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT ));
362 field = "scaling-mode";
363 if( map.HasKey(field) )
365 DALI_ASSERT_ALWAYS(map.GetValue(field).GetType() == Property::STRING && "Image release-policy property is not a string" );
366 std::string s(map.GetValue(field).Get<std::string>());
367 attributes.SetScalingMode( GetEnumeration< ImageAttributes::ScalingMode >( s, IMAGE_SCALING_MODE_TABLE, IMAGE_SCALING_MODE_TABLE_COUNT ) );
371 if( map.HasKey(field) )
373 DALI_ASSERT_ALWAYS(map.GetValue(field).GetType() == Property::VECTOR4 && "Image release-policy property is not a string" );
374 Vector4 v(map.GetValue(field).Get<Vector4>());
375 attributes.SetCrop( Rect<float>(v.x, v.y, v.z, v.w) );
378 if( map.HasKey("type") )
380 DALI_ASSERT_ALWAYS( map.GetValue("type").GetType() == Property::STRING );
381 std::string s(map.GetValue("type").Get<std::string>());
382 if("FrameBufferImage" == s)
384 ret = new Internal::FrameBufferImage(attributes.GetWidth(),
385 attributes.GetHeight(),
386 attributes.GetPixelFormat(),
389 else if("BitmapImage" == s)
391 ret = new Internal::BitmapImage(attributes.GetWidth(),
392 attributes.GetHeight(),
393 attributes.GetPixelFormat(),
397 else if("Image" == s)
399 ret = Image::New(filename, attributes, loadPolicy, releasePolicy);
403 DALI_ASSERT_ALWAYS( !"Unknown image type" );
408 ret = Image::New(filename, attributes, loadPolicy, releasePolicy);
414 } // Image NewImage( Property::Value map )
417 ShaderEffect NewShaderEffect( const Property::Value& map )
419 Internal::ShaderEffectPtr ret;
421 if( map.GetType() == Property::MAP )
423 ret = Internal::ShaderEffect::New(Dali::ShaderEffect::HINT_NONE); // hint can be reset if in map
425 if( map.HasKey("program") )
427 Property::Index index = ret->GetPropertyIndex("program");
428 DALI_ASSERT_DEBUG( map.GetValue("program").GetType() == Property::MAP );
429 ret->SetProperty(index, map.GetValue("program"));
432 for(int i = 0; i < map.GetSize(); ++i)
434 const std::string& key = map.GetKey(i);
437 Property::Index index = ret->GetPropertyIndex( key );
439 if( Property::INVALID_INDEX != index )
441 ret->SetProperty(index, map.GetItem(i));
445 // if its not a property then register it as a uniform (making a custom property)
447 if(map.GetItem(i).GetType() == Property::INTEGER)
449 // valid uniforms are floats, vec3's etc so we recast if the user accidentally
450 // set as integer. Note the map could have come from json script.
451 Property::Value asFloat( static_cast<float>( map.GetItem(i).Get<int>() ) );
452 ret->SetUniform( key, asFloat, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
456 ret->SetUniform( key, map.GetItem(i), Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
463 return Dali::ShaderEffect(ret.Get());
467 Actor NewActor( const Property::Map& map )
471 const Property::Map::const_iterator endIter = map.end();
473 // First find type and create Actor
474 Property::Map::const_iterator typeIter = map.begin();
475 for (; typeIter != endIter; ++typeIter )
477 if ( typeIter->first == "type" )
479 TypeInfo type = TypeRegistry::Get().GetTypeInfo( typeIter->second.Get< std::string >() );
482 handle = type.CreateInstance();
490 DALI_LOG_ERROR( "Actor type not provided, returning empty handle" );
494 Actor actor( Actor::DownCast( handle ) );
498 // Now set the properties, or create children
499 for ( Property::Map::const_iterator iter = map.begin(); iter != endIter; ++iter )
501 if ( iter == typeIter )
506 if ( iter->first == "actors" )
510 Property::Array actorArray = iter->second.Get< Property::Array >();
511 for ( Property::Array::iterator arrayIter = actorArray.begin(), arrayEndIter = actorArray.end(); arrayIter != arrayEndIter; ++arrayIter )
513 actor.Add( NewActor( arrayIter->Get< Property::Map >() ) );
516 else if ( iter->first == "signals" )
518 DALI_LOG_ERROR( "signals not supported" );
520 else if( iter->first == "parent-origin" )
522 // Parent Origin can be a string constant as well as a Vector3
524 const Property::Type type( iter->second.GetType() );
525 if ( type == Property::VECTOR3 )
527 actor.SetParentOrigin( iter->second.Get< Vector3 >() );
529 else if( type == Property::STRING )
531 actor.SetParentOrigin( GetAnchorConstant( iter->second.Get< std::string >() ) );
534 else if( iter->first == "anchor-point" )
536 // Anchor Point can be a string constant as well as a Vector3
538 const Property::Type type( iter->second.GetType() );
539 if ( type == Property::VECTOR3 )
541 actor.SetAnchorPoint( iter->second.Get< Vector3 >() );
543 else if( type == Property::STRING )
545 actor.SetAnchorPoint( GetAnchorConstant( iter->second.Get< std::string >() ) );
550 Property::Index index( actor.GetPropertyIndex( iter->first ) );
552 if ( index != Property::INVALID_INDEX )
554 actor.SetProperty( index, iter->second );
563 void CreatePropertyMap( Actor actor, Property::Map& map )
569 map.push_back( Property::StringValuePair( "type", actor.GetTypeName() ) );
571 // Default properties
572 Property::IndexContainer indices;
573 actor.GetPropertyIndices( indices );
574 const Property::IndexContainer::const_iterator endIter = indices.end();
575 for ( Property::IndexContainer::iterator iter = indices.begin(); iter != endIter; ++iter )
577 map.push_back( Property::StringValuePair( actor.GetPropertyName( *iter ), actor.GetProperty( *iter ) ) );
581 unsigned int childCount( actor.GetChildCount() );
584 Property::Array childArray;
585 for ( unsigned int child = 0; child < childCount; ++child )
587 Property::Map childMap;
588 CreatePropertyMap( actor.GetChildAt( child ), childMap );
589 childArray.push_back( childMap );
591 map.push_back( Property::StringValuePair( "actors", childArray ) );
596 void CreatePropertyMap( Image image, Property::Map& map )
602 std::string imageType( "Image" );
604 // Get Type - cannot use TypeRegistry as Image is not a ProxyObject and thus, not registered
605 if ( BitmapImage::DownCast( image ) )
607 imageType = "BitmapImage";
609 else if ( FrameBufferImage::DownCast( image ) )
611 imageType = "FrameBufferImage";
614 map.push_back( Property::StringValuePair( "type", imageType ) );
615 map.push_back( Property::StringValuePair( "filename", image.GetFilename() ) );
616 map.push_back( Property::StringValuePair( "load-policy", GetEnumerationName< Image::LoadPolicy >( image.GetLoadPolicy(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT ) ) );
617 map.push_back( Property::StringValuePair( "release-policy", GetEnumerationName< Image::ReleasePolicy >( image.GetReleasePolicy(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT ) ) );
619 ImageAttributes attributes( image.GetAttributes() );
620 map.push_back( Property::StringValuePair( "pixel-format", GetEnumerationName< Pixel::Format >( attributes.GetPixelFormat(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT ) ) );
621 map.push_back( Property::StringValuePair( "scaling-mode", GetEnumerationName< ImageAttributes::ScalingMode >( attributes.GetScalingMode(), IMAGE_SCALING_MODE_TABLE, IMAGE_SCALING_MODE_TABLE_COUNT ) ) );
623 Rect< float > crop( attributes.GetCrop() );
624 map.push_back( Property::StringValuePair( "crop", Vector4( crop.x, crop.y, crop.width, crop.height ) ) );
626 int width( image.GetWidth() );
627 int height( image.GetHeight() );
629 if ( width && height )
631 map.push_back( Property::StringValuePair( "width", width ) );
632 map.push_back( Property::StringValuePair( "height", height ) );
637 } // namespace scripting