2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/devel-api/scripting/scripting.h>
22 #include <dali/public-api/actors/actor.h>
23 #include <dali/public-api/images/resource-image.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/public-api/object/property-array.h>
26 #include <dali/internal/common/image-attributes.h>
27 #include <dali/internal/event/images/resource-image-impl.h>
28 #include <dali/internal/event/images/frame-buffer-image-impl.h>
29 #include <dali/internal/event/images/buffer-image-impl.h>
30 #include <dali/internal/event/effects/shader-effect-impl.h>
41 // Tables used here for converting strings to the enumerations and vice versa
43 const StringEnum< ColorMode > COLOR_MODE_TABLE[] =
45 { "USE_OWN_COLOR", USE_OWN_COLOR },
46 { "USE_PARENT_COLOR", USE_PARENT_COLOR },
47 { "USE_OWN_MULTIPLY_PARENT_COLOR", USE_OWN_MULTIPLY_PARENT_COLOR },
48 { "USE_OWN_MULTIPLY_PARENT_ALPHA", USE_OWN_MULTIPLY_PARENT_ALPHA },
50 const unsigned int COLOR_MODE_TABLE_COUNT = sizeof( COLOR_MODE_TABLE ) / sizeof( COLOR_MODE_TABLE[0] );
52 const StringEnum< PositionInheritanceMode > POSITION_INHERITANCE_MODE_TABLE[] =
54 { "INHERIT_PARENT_POSITION", INHERIT_PARENT_POSITION },
55 { "USE_PARENT_POSITION", USE_PARENT_POSITION },
56 { "USE_PARENT_POSITION_PLUS_LOCAL_POSITION", USE_PARENT_POSITION_PLUS_LOCAL_POSITION },
57 { "DONT_INHERIT_POSITION", DONT_INHERIT_POSITION },
59 const unsigned int POSITION_INHERITANCE_MODE_TABLE_COUNT = sizeof( POSITION_INHERITANCE_MODE_TABLE ) / sizeof( POSITION_INHERITANCE_MODE_TABLE[0] );
61 const StringEnum< DrawMode::Type > DRAW_MODE_TABLE[] =
63 { "NORMAL", DrawMode::NORMAL },
64 { "OVERLAY", DrawMode::OVERLAY },
65 { "STENCIL", DrawMode::STENCIL },
67 const unsigned int DRAW_MODE_TABLE_COUNT = sizeof( DRAW_MODE_TABLE ) / sizeof( DRAW_MODE_TABLE[0] );
69 const StringEnum< Vector3 > ANCHOR_CONSTANT_TABLE[] =
71 { "TOP_LEFT", ParentOrigin::TOP_LEFT },
72 { "TOP_CENTER", ParentOrigin::TOP_CENTER },
73 { "TOP_RIGHT", ParentOrigin::TOP_RIGHT },
74 { "CENTER_LEFT", ParentOrigin::CENTER_LEFT },
75 { "CENTER", ParentOrigin::CENTER },
76 { "CENTER_RIGHT", ParentOrigin::CENTER_RIGHT },
77 { "BOTTOM_LEFT", ParentOrigin::BOTTOM_LEFT },
78 { "BOTTOM_CENTER", ParentOrigin::BOTTOM_CENTER },
79 { "BOTTOM_RIGHT", ParentOrigin::BOTTOM_RIGHT },
81 const unsigned int ANCHOR_CONSTANT_TABLE_COUNT = sizeof( ANCHOR_CONSTANT_TABLE ) / sizeof( ANCHOR_CONSTANT_TABLE[0] );
83 const StringEnum< ResourceImage::LoadPolicy > IMAGE_LOAD_POLICY_TABLE[] =
85 { "IMMEDIATE", ResourceImage::IMMEDIATE },
86 { "ON_DEMAND", ResourceImage::ON_DEMAND },
88 const unsigned int IMAGE_LOAD_POLICY_TABLE_COUNT = sizeof( IMAGE_LOAD_POLICY_TABLE ) / sizeof( IMAGE_LOAD_POLICY_TABLE[0] );
90 const StringEnum< Image::ReleasePolicy > IMAGE_RELEASE_POLICY_TABLE[] =
92 { "UNUSED", Image::UNUSED },
93 { "NEVER", Image::NEVER },
95 const unsigned int IMAGE_RELEASE_POLICY_TABLE_COUNT = sizeof( IMAGE_RELEASE_POLICY_TABLE ) / sizeof( IMAGE_RELEASE_POLICY_TABLE[0] );
97 const StringEnum< Pixel::Format > PIXEL_FORMAT_TABLE[] =
101 { "LA88", Pixel::LA88 },
102 { "RGB565", Pixel::RGB565 },
103 { "BGR565", Pixel::BGR565 },
104 { "RGBA4444", Pixel::RGBA4444 },
105 { "BGRA4444", Pixel::BGRA4444 },
106 { "RGBA5551", Pixel::RGBA5551 },
107 { "BGRA5551", Pixel::BGRA5551 },
108 { "RGB888", Pixel::RGB888 },
109 { "RGB8888", Pixel::RGB8888 },
110 { "BGR8888", Pixel::BGR8888 },
111 { "RGBA8888", Pixel::RGBA8888 },
112 { "BGRA8888", Pixel::BGRA8888 },
113 { "COMPRESSED_R11_EAC", Pixel::COMPRESSED_R11_EAC },
114 { "COMPRESSED_SIGNED_R11_EAC", Pixel::COMPRESSED_SIGNED_R11_EAC },
115 { "COMPRESSED_SIGNED_RG11_EAC", Pixel::COMPRESSED_SIGNED_RG11_EAC },
116 { "COMPRESSED_RG11_EAC", Pixel::COMPRESSED_RG11_EAC },
117 { "COMPRESSED_RGB8_ETC2", Pixel::COMPRESSED_RGB8_ETC2 },
118 { "COMPRESSED_SRGB8_ETC2", Pixel::COMPRESSED_SRGB8_ETC2 },
119 { "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 },
120 { "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 },
121 { "COMPRESSED_RGBA8_ETC2_EAC", Pixel::COMPRESSED_RGBA8_ETC2_EAC },
122 { "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC },
123 { "COMPRESSED_RGB8_ETC1", Pixel::COMPRESSED_RGB8_ETC1 },
124 { "COMPRESSED_RGB_PVRTC_4BPPV1", Pixel::COMPRESSED_RGB_PVRTC_4BPPV1 },
126 const unsigned int PIXEL_FORMAT_TABLE_COUNT = sizeof( PIXEL_FORMAT_TABLE ) / sizeof( PIXEL_FORMAT_TABLE[0] );
128 const StringEnum< FittingMode::Type > IMAGE_FITTING_MODE_TABLE[] =
130 { "SHRINK_TO_FIT", FittingMode::SHRINK_TO_FIT },
131 { "SCALE_TO_FILL", FittingMode::SCALE_TO_FILL },
132 { "FIT_WIDTH", FittingMode::FIT_WIDTH },
133 { "FIT_HEIGHT", FittingMode::FIT_HEIGHT },
135 const unsigned int IMAGE_FITTING_MODE_TABLE_COUNT = sizeof( IMAGE_FITTING_MODE_TABLE ) / sizeof( IMAGE_FITTING_MODE_TABLE[0] );
137 const StringEnum< SamplingMode::Type > IMAGE_SAMPLING_MODE_TABLE[] =
139 { "BOX", SamplingMode::BOX },
140 { "NEAREST", SamplingMode::NEAREST },
141 { "LINEAR", SamplingMode::LINEAR },
142 { "BOX_THEN_NEAREST", SamplingMode::BOX_THEN_NEAREST },
143 { "BOX_THEN_LINEAR", SamplingMode::BOX_THEN_LINEAR },
144 { "NO_FILTER", SamplingMode::NO_FILTER },
145 { "DONT_CARE", SamplingMode::DONT_CARE },
147 const unsigned int IMAGE_SAMPLING_MODE_TABLE_COUNT = sizeof( IMAGE_SAMPLING_MODE_TABLE ) / sizeof( IMAGE_SAMPLING_MODE_TABLE[0] );
149 } // unnamed namespace
151 bool CompareEnums( const char * a, const char * b )
153 while( ( *a != '\0' ) && ( *b != '\0' ) )
158 if( ( ( ca == '-' ) || ( ca == '_') ) &&
159 ( ( cb == '-' ) || ( cb == '_') ) )
166 if( ( 'A' <= ca ) && ( ca <= 'Z') )
168 ca = ca + ( 'a' - 'A' );
171 if( ( 'A' <= cb ) && ( cb <= 'Z') )
173 cb = cb + ( 'a' - 'A' );
185 if( ( *a == '\0' ) && ( *b == '\0' ) )
194 ColorMode GetColorMode( const std::string& value )
196 return GetEnumeration< ColorMode >( value.c_str(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
200 std::string GetColorMode( ColorMode value )
202 return GetEnumerationName< ColorMode >( value, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
205 PositionInheritanceMode GetPositionInheritanceMode( const std::string& value )
207 return GetEnumeration< PositionInheritanceMode >( value.c_str(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
211 std::string GetPositionInheritanceMode( PositionInheritanceMode value )
213 return GetEnumerationName< PositionInheritanceMode >( value, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
217 DrawMode::Type GetDrawMode( const std::string& value )
219 return GetEnumeration< DrawMode::Type >( value.c_str(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
223 std::string GetDrawMode( DrawMode::Type value )
225 return GetEnumerationName< DrawMode::Type >( value, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
229 Vector3 GetAnchorConstant( const std::string& value )
231 return GetEnumeration< Vector3 >( value.c_str(), ANCHOR_CONSTANT_TABLE, ANCHOR_CONSTANT_TABLE_COUNT );
235 Image NewImage( const Property::Value& map )
239 std::string filename;
240 ResourceImage::LoadPolicy loadPolicy = Dali::Internal::IMAGE_LOAD_POLICY_DEFAULT;
241 Image::ReleasePolicy releasePolicy = Dali::Internal::IMAGE_RELEASE_POLICY_DEFAULT;
242 Internal::ImageAttributes attributes = Internal::ImageAttributes::New();
244 if( Property::MAP == map.GetType() )
246 std::string field = "filename";
247 if( map.HasKey(field) )
249 DALI_ASSERT_ALWAYS(map.GetValue(field).GetType() == Property::STRING && "Image filename property is not a string" );
250 filename = map.GetValue(field).Get<std::string>();
253 field = "load-policy";
254 if( map.HasKey(field) )
256 DALI_ASSERT_ALWAYS(map.GetValue(field).GetType() == Property::STRING && "Image load-policy property is not a string" );
257 std::string v(map.GetValue(field).Get<std::string>());
258 loadPolicy = GetEnumeration< ResourceImage::LoadPolicy >( v.c_str(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT );
261 field = "release-policy";
262 if( map.HasKey(field) )
264 DALI_ASSERT_ALWAYS(map.GetValue(field).GetType() == Property::STRING && "Image release-policy property is not a string" );
265 std::string v(map.GetValue(field).Get<std::string>());
266 releasePolicy = GetEnumeration< Image::ReleasePolicy >( v.c_str(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT );
269 // Width and height can be set individually. Dali derives the unspecified
270 // dimension from the aspect ratio of the raw image.
271 unsigned int width = 0, height = 0;
274 if( map.HasKey( field ) )
276 Property::Value &value = map.GetValue( field );
278 // handle floats and integer the same for json script
279 if( value.GetType() == Property::FLOAT )
281 width = static_cast<unsigned int>( value.Get<float>() );
285 DALI_ASSERT_ALWAYS( value.GetType() == Property::INTEGER && "Image width property is not a number" );
286 width = value.Get<int>();
291 if( map.HasKey( field ) )
293 Property::Value &value = map.GetValue( field );
294 if( value.GetType() == Property::FLOAT )
296 height = static_cast<unsigned int>( value.Get<float>() );
300 DALI_ASSERT_ALWAYS( value.GetType() == Property::INTEGER && "Image width property is not a number" );
301 height = value.Get<int>();
305 attributes.SetSize( width, height );
307 field = "pixel-format";
308 Pixel::Format pixelFormat = Pixel::RGBA8888;
309 if( map.HasKey(field) )
311 DALI_ASSERT_ALWAYS( map.GetValue(field).GetType() == Property::STRING && "Image release-policy property is not a string" );
312 std::string s( map.GetValue(field).Get<std::string>() );
313 pixelFormat = GetEnumeration< Pixel::Format >( s.c_str(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT );
316 field = "fitting-mode";
317 if( map.HasKey( field ) )
319 Property::Value& value = map.GetValue( field );
320 DALI_ASSERT_ALWAYS( value.GetType() == Property::STRING && "Image fitting-mode property is not a string" );
321 std::string s( value.Get<std::string>() );
322 attributes.SetScalingMode( GetEnumeration< FittingMode::Type >( s.c_str(), IMAGE_FITTING_MODE_TABLE, IMAGE_FITTING_MODE_TABLE_COUNT ) );
325 field = "sampling-mode";
326 if( map.HasKey( field ) )
328 Property::Value& value = map.GetValue( field );
329 DALI_ASSERT_ALWAYS( value.GetType() == Property::STRING && "Image sampling-mode property is not a string" );
330 std::string s( value.Get<std::string>() );
331 attributes.SetFilterMode( GetEnumeration< SamplingMode::Type >( s.c_str(), IMAGE_SAMPLING_MODE_TABLE, IMAGE_SAMPLING_MODE_TABLE_COUNT ) );
334 field = "orientation";
335 if( map.HasKey( field ) )
337 Property::Value& value = map.GetValue( field );
338 DALI_ASSERT_ALWAYS( value.GetType() == Property::BOOLEAN && "Image orientation property is not a boolean" );
339 bool b = value.Get<bool>();
340 attributes.SetOrientationCorrection( b );
343 if( map.HasKey("type") )
345 DALI_ASSERT_ALWAYS( map.GetValue("type").GetType() == Property::STRING );
346 std::string s(map.GetValue("type").Get<std::string>());
347 if("FrameBufferImage" == s)
349 ret = FrameBufferImage::New(attributes.GetWidth(),
350 attributes.GetHeight(),
354 else if("BufferImage" == s)
356 ret = BufferImage::New(attributes.GetWidth(),
357 attributes.GetHeight(),
361 else if("ResourceImage" == s)
363 ret = ResourceImage::New( filename, loadPolicy, releasePolicy, ImageDimensions( attributes.GetSize().x, attributes.GetSize().y ), attributes.GetScalingMode(), attributes.GetFilterMode(), attributes.GetOrientationCorrection() );
367 DALI_ASSERT_ALWAYS( !"Unknown image type" );
372 ret = ResourceImage::New( filename, loadPolicy, releasePolicy, ImageDimensions( attributes.GetSize().x, attributes.GetSize().y ), attributes.GetScalingMode(), attributes.GetFilterMode(), attributes.GetOrientationCorrection() );
378 } // Image NewImage( Property::Value map )
381 ShaderEffect NewShaderEffect( const Property::Value& map )
383 Internal::ShaderEffectPtr ret;
385 if( map.GetType() == Property::MAP )
387 ret = Internal::ShaderEffect::New(Dali::ShaderEffect::HINT_NONE); // hint can be reset if in map
389 if( map.HasKey("program") )
391 Property::Index index = ret->GetPropertyIndex("program");
392 DALI_ASSERT_DEBUG( map.GetValue("program").GetType() == Property::MAP );
393 ret->SetProperty(index, map.GetValue("program"));
396 for(int i = 0; i < map.GetSize(); ++i)
398 const std::string& key = map.GetKey(i);
401 Property::Index index = ret->GetPropertyIndex( key );
403 if( Property::INVALID_INDEX != index )
405 ret->SetProperty(index, map.GetItem(i));
409 // if its not a property then register it as a uniform (making a custom property)
411 if(map.GetItem(i).GetType() == Property::INTEGER)
413 // valid uniforms are floats, vec3's etc so we recast if the user accidentally
414 // set as integer. Note the map could have come from json script.
415 Property::Value asFloat( static_cast<float>( map.GetItem(i).Get<int>() ) );
416 ret->SetUniform( key, asFloat, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
420 ret->SetUniform( key, map.GetItem(i), Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
427 return Dali::ShaderEffect(ret.Get());
431 Actor NewActor( const Property::Map& map )
435 // First find type and create Actor
436 Property::Value* typeValue = map.Find( "type" );
439 TypeInfo type = TypeRegistry::Get().GetTypeInfo( typeValue->Get< std::string >() );
442 handle = type.CreateInstance();
448 DALI_LOG_ERROR( "Actor type not provided, returning empty handle" );
452 Actor actor( Actor::DownCast( handle ) );
456 // Now set the properties, or create children
457 for ( unsigned int i = 0, mapCount = map.Count(); i < mapCount; ++i )
459 const StringValuePair& pair( map.GetPair( i ) );
460 const std::string& key( pair.first );
466 const Property::Value& value( pair.second );
468 if ( key == "actors" )
472 Property::Array actorArray = value.Get< Property::Array >();
473 for ( size_t i = 0; i < actorArray.Size(); ++i)
475 actor.Add( NewActor( actorArray[i].Get< Property::Map >() ) );
478 else if ( key == "signals" )
480 DALI_LOG_ERROR( "signals not supported" );
482 else if( key == "parent-origin" )
484 // Parent Origin can be a string constant as well as a Vector3
486 const Property::Type type( value.GetType() );
487 if ( type == Property::VECTOR3 )
489 actor.SetParentOrigin( value.Get< Vector3 >() );
491 else if( type == Property::STRING )
493 actor.SetParentOrigin( GetAnchorConstant( value.Get< std::string >() ) );
496 else if( key == "anchor-point" )
498 // Anchor Point can be a string constant as well as a Vector3
500 const Property::Type type( value.GetType() );
501 if ( type == Property::VECTOR3 )
503 actor.SetAnchorPoint( value.Get< Vector3 >() );
505 else if( type == Property::STRING )
507 actor.SetAnchorPoint( GetAnchorConstant( value.Get< std::string >() ) );
512 Property::Index index( actor.GetPropertyIndex( key ) );
514 if ( index != Property::INVALID_INDEX )
516 actor.SetProperty( index, value );
525 void CreatePropertyMap( Actor actor, Property::Map& map )
531 map[ "type" ] = actor.GetTypeName();
533 // Default properties
534 Property::IndexContainer indices;
535 actor.GetPropertyIndices( indices );
536 const Property::IndexContainer::ConstIterator endIter = indices.End();
538 for ( Property::IndexContainer::Iterator iter = indices.Begin(); iter != endIter; ++iter )
540 map[ actor.GetPropertyName( *iter ) ] = actor.GetProperty( *iter );
544 unsigned int childCount( actor.GetChildCount() );
547 Property::Array childArray;
548 for ( unsigned int child = 0; child < childCount; ++child )
550 Property::Map childMap;
551 CreatePropertyMap( actor.GetChildAt( child ), childMap );
552 childArray.PushBack( childMap );
554 map[ "actors" ] = childArray;
559 void CreatePropertyMap( Image image, Property::Map& map )
565 std::string imageType( "ResourceImage" );
567 // Get Type - cannot use TypeRegistry as Image is not an Object and thus, not registered
568 BufferImage bufferImage = BufferImage::DownCast( image );
571 imageType = "BufferImage";
572 map[ "pixel-format" ] = GetEnumerationName< Pixel::Format >( bufferImage.GetPixelFormat(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT );
574 else if ( FrameBufferImage::DownCast( image ) )
576 imageType = "FrameBufferImage";
579 map[ "type" ] = imageType;
580 map[ "release-policy" ] = GetEnumerationName< Image::ReleasePolicy >( image.GetReleasePolicy(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT );
582 ResourceImage resourceImage = ResourceImage::DownCast( image );
585 map[ "filename" ] = resourceImage.GetUrl();
586 map[ "load-policy" ] = GetEnumerationName< ResourceImage::LoadPolicy >( resourceImage.GetLoadPolicy(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT );
589 int width( image.GetWidth() );
590 int height( image.GetHeight() );
592 if ( width && height )
594 map[ "width" ] = width;
595 map[ "height" ] = height;
601 DALI_IMPORT_API bool SetRotation( const Property::Value& value, Quaternion& quaternion )
604 Property::Type type = value.GetType();
605 if( Property::VECTOR3 == type )
609 quaternion.SetEuler( Radian(Degree(v3.x)), Radian(Degree(v3.y)), Radian(Degree(v3.z)) );
612 else if( Property::VECTOR4 == type )
616 quaternion = Quaternion(v4);
619 else if( Property::ROTATION == type )
621 value.Get(quaternion);
628 } // namespace scripting