Remove/move experimental features
[platform/core/uifw/dali-core.git] / dali / devel-api / scripting / scripting.cpp
1 /*
2  * Copyright (c) 2016 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/devel-api/scripting/scripting.h>
20
21 // INTERNAL INCLUDES
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/common/property-helper.h>
28 #include <dali/internal/event/images/resource-image-impl.h>
29 #include <dali/internal/event/images/frame-buffer-image-impl.h>
30 #include <dali/internal/event/images/buffer-image-impl.h>
31
32 namespace Dali
33 {
34
35 namespace Scripting
36 {
37
38 namespace
39 {
40
41 const StringEnum PIXEL_FORMAT_TABLE[] =
42 {
43   { "A8",                                           Pixel::A8                                           },
44   { "L8",                                           Pixel::L8                                           },
45   { "LA88",                                         Pixel::LA88                                         },
46   { "RGB565",                                       Pixel::RGB565                                       },
47   { "BGR565",                                       Pixel::BGR565                                       },
48   { "RGBA4444",                                     Pixel::RGBA4444                                     },
49   { "BGRA4444",                                     Pixel::BGRA4444                                     },
50   { "RGBA5551",                                     Pixel::RGBA5551                                     },
51   { "BGRA5551",                                     Pixel::BGRA5551                                     },
52   { "RGB888",                                       Pixel::RGB888                                       },
53   { "RGB8888",                                      Pixel::RGB8888                                      },
54   { "BGR8888",                                      Pixel::BGR8888                                      },
55   { "RGBA8888",                                     Pixel::RGBA8888                                     },
56   { "BGRA8888",                                     Pixel::BGRA8888                                     },
57   { "COMPRESSED_R11_EAC",                           Pixel::COMPRESSED_R11_EAC                           },
58   { "COMPRESSED_SIGNED_R11_EAC",                    Pixel::COMPRESSED_SIGNED_R11_EAC                    },
59   { "COMPRESSED_SIGNED_RG11_EAC",                   Pixel::COMPRESSED_SIGNED_RG11_EAC                   },
60   { "COMPRESSED_RG11_EAC",                          Pixel::COMPRESSED_RG11_EAC                          },
61   { "COMPRESSED_RGB8_ETC2",                         Pixel::COMPRESSED_RGB8_ETC2                         },
62   { "COMPRESSED_SRGB8_ETC2",                        Pixel::COMPRESSED_SRGB8_ETC2                        },
63   { "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2",     Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2     },
64   { "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2",    Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2    },
65   { "COMPRESSED_RGBA8_ETC2_EAC",                    Pixel::COMPRESSED_RGBA8_ETC2_EAC                    },
66   { "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC",             Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC             },
67   { "COMPRESSED_RGB8_ETC1",                         Pixel::COMPRESSED_RGB8_ETC1                         },
68   { "COMPRESSED_RGB_PVRTC_4BPPV1",                  Pixel::COMPRESSED_RGB_PVRTC_4BPPV1                  },
69 };
70 const unsigned int PIXEL_FORMAT_TABLE_COUNT = sizeof( PIXEL_FORMAT_TABLE ) / sizeof( PIXEL_FORMAT_TABLE[0] );
71
72 const StringEnum IMAGE_FITTING_MODE_TABLE[] =
73 {
74   { "SHRINK_TO_FIT", FittingMode::SHRINK_TO_FIT },
75   { "SCALE_TO_FILL", FittingMode::SCALE_TO_FILL },
76   { "FIT_WIDTH",     FittingMode::FIT_WIDTH    },
77   { "FIT_HEIGHT",    FittingMode::FIT_HEIGHT   },
78 };
79 const unsigned int IMAGE_FITTING_MODE_TABLE_COUNT = sizeof( IMAGE_FITTING_MODE_TABLE ) / sizeof( IMAGE_FITTING_MODE_TABLE[0] );
80
81 const StringEnum IMAGE_SAMPLING_MODE_TABLE[] =
82 {
83   { "BOX",              SamplingMode::BOX            },
84   { "NEAREST",          SamplingMode::NEAREST        },
85   { "LINEAR",           SamplingMode::LINEAR         },
86   { "BOX_THEN_NEAREST", SamplingMode::BOX_THEN_NEAREST },
87   { "BOX_THEN_LINEAR",  SamplingMode::BOX_THEN_LINEAR  },
88   { "NO_FILTER",        SamplingMode::NO_FILTER       },
89   { "DONT_CARE",        SamplingMode::DONT_CARE       },
90 };
91 const unsigned int IMAGE_SAMPLING_MODE_TABLE_COUNT = sizeof( IMAGE_SAMPLING_MODE_TABLE ) / sizeof( IMAGE_SAMPLING_MODE_TABLE[0] );
92
93 const char* ImageTypeName[] = { "ResourceImage", "FrameBufferImage", "BufferImage" };
94 enum ImageType                { RESOURCE_IMAGE,  FRAME_BUFFER_IMAGE, BUFFER_IMAGE };
95 const unsigned int imageTypeCount = sizeof( ImageTypeName ) / sizeof( const char* );
96
97 } // unnamed namespace
98
99 bool EnumStringToInteger( const char * const value, const StringEnum* const enumTable, unsigned int tableCount, int& integerEnum )
100 {
101   int ret = 0;
102
103   bool found = false;
104   bool done = false;
105
106   if( value && enumTable && tableCount )
107   {
108     const char* pValue = value;
109
110     while(!done)
111     {
112       size_t size = 0;
113
114       const StringEnum* table = enumTable;
115
116       for ( unsigned int i = 0; i < tableCount; ++i )
117       {
118         if( Internal::CompareTokens( pValue, table->string, size ) )
119         {
120           found = true;
121           ret |= table->value;
122           break;
123         }
124         table++;
125       }
126
127       done = true;
128
129       if(found)
130       {
131         // allow comma separated or'd value
132         if( *(pValue+size) == ',' )
133         {
134           pValue += size + 1;
135           done = false;
136         }
137       }
138
139     }
140
141     integerEnum = ret;
142   }
143
144   if ( !found )
145   {
146     DALI_LOG_ERROR( "Unknown enumeration string %s\n", value );
147   }
148   return found;
149 }
150
151 unsigned int FindEnumIndex( const char* value, const StringEnum* table, unsigned int tableCount )
152 {
153   unsigned int index = 0;
154   bool found = false;
155   for ( unsigned int i = 0; i < tableCount; ++i, ++index )
156   {
157     size_t sizeIgnored = 0;
158     if( Internal::CompareTokens( value, table->string, sizeIgnored ) )
159     {
160       found = true;
161       break;
162     }
163     ++table;
164   }
165   if ( !found )
166   {
167     DALI_LOG_ERROR( "Unknown enumeration string %s\n", value );
168   }
169   return index;
170 }
171
172
173 Image NewImage( const Property::Value& property )
174 {
175   Image ret;
176
177   std::string filename;
178   Internal::ImageAttributes attributes = Internal::ImageAttributes::New();
179
180   const Property::Map* map = property.GetMap();
181   ImageType imageType = RESOURCE_IMAGE; // default to resource image
182   if( map )
183   {
184     // first check the type as it determines, which other parameters are needed
185     const Property::Value* value = map->Find( "type" );
186     if( value )
187     {
188       std::string type;
189       value->Get( type );
190       for( unsigned int i = 0; i < imageTypeCount; ++i )
191       {
192         if( 0 == type.compare( ImageTypeName[ i ] ) )
193         {
194           imageType = static_cast<ImageType>( i );
195           break;
196         }
197       }
198     }
199
200     // filename is only needed for resource images
201     if( RESOURCE_IMAGE == imageType )
202     {
203       const Property::Value* value = map->Find( "filename" );
204       if( value )
205       {
206         value->Get( filename );
207       }
208       // if empty file, no need to go further
209       if( filename.size() == 0 )
210       {
211         DALI_LOG_ERROR( "No filename\n" );
212         return Image();
213       }
214     }
215
216     // Width and height can be set individually. Dali derives the unspecified
217     // dimension from the aspect ratio of the raw image.
218     int width = 0, height = 0;
219
220     value = map->Find( "width" );
221     if( value )
222     {
223       // handle floats and integer the same for json script
224       if( value->GetType() == Property::FLOAT )
225       {
226         width = static_cast<unsigned int>( value->Get<float>() );
227       }
228       else
229       {
230         value->Get( width );
231       }
232     }
233     value = map->Find( "height" );
234     if( value )
235     {
236       if( value->GetType() == Property::FLOAT )
237       {
238         height = static_cast<int>( value->Get<float>() );
239       }
240       else
241       {
242         value->Get( height );
243       }
244     }
245     attributes.SetSize( width, height );
246
247     Pixel::Format pixelFormat = Pixel::RGBA8888;
248     value = map->Find( "pixelFormat" );
249     if( value )
250     {
251       std::string format;
252       value->Get( format );
253       GetEnumeration< Pixel::Format >( format.c_str(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT, pixelFormat );
254     }
255
256     value = map->Find( "fittingMode" );
257     if( value )
258     {
259       std::string fitting;
260       value->Get( fitting );
261       FittingMode::Type mode;
262       if( GetEnumeration< FittingMode::Type >( fitting.c_str(), IMAGE_FITTING_MODE_TABLE, IMAGE_FITTING_MODE_TABLE_COUNT, mode ) )
263       {
264         attributes.SetScalingMode( mode );
265       }
266     }
267
268     value = map->Find( "samplingMode" );
269     if( value )
270     {
271       std::string sampling;
272       value->Get( sampling );
273       SamplingMode::Type mode;
274       if( GetEnumeration< SamplingMode::Type >( sampling.c_str(), IMAGE_SAMPLING_MODE_TABLE, IMAGE_SAMPLING_MODE_TABLE_COUNT, mode ) )
275       {
276         attributes.SetFilterMode( mode );
277       }
278     }
279
280     value = map->Find( "orientation" );
281     if( value )
282     {
283       bool b = value->Get<bool>();
284       attributes.SetOrientationCorrection( b );
285     }
286
287     switch( imageType )
288     {
289       case RESOURCE_IMAGE :
290       {
291         ret = ResourceImage::New( filename, ImageDimensions( attributes.GetSize().x, attributes.GetSize().y ),
292                                   attributes.GetScalingMode(), attributes.GetFilterMode(), attributes.GetOrientationCorrection() );
293         break;
294       }
295       case BUFFER_IMAGE :
296       {
297         ret = BufferImage::New( attributes.GetWidth(),
298                                 attributes.GetHeight(),
299                                 pixelFormat );
300         break;
301       }
302       case FRAME_BUFFER_IMAGE :
303       {
304         ret = FrameBufferImage::New( attributes.GetWidth(),
305                                      attributes.GetHeight(),
306                                      pixelFormat );
307         break;
308       }
309     }
310   }
311
312   return ret;
313
314 } // Image NewImage( Property::Value map )
315
316
317 Actor NewActor( const Property::Map& map )
318 {
319   BaseHandle handle;
320
321   // First find type and create Actor
322   Property::Value* typeValue = map.Find( "type" );
323   if ( typeValue )
324   {
325     TypeInfo type = TypeRegistry::Get().GetTypeInfo( typeValue->Get< std::string >() );
326     if ( type )
327     {
328       handle = type.CreateInstance();
329     }
330   }
331
332   if ( !handle )
333   {
334     DALI_LOG_ERROR( "Actor type not provided\n" );
335     return Actor();
336   }
337
338   Actor actor( Actor::DownCast( handle ) );
339
340   if ( actor )
341   {
342     // Now set the properties, or create children
343     for ( unsigned int i = 0, mapCount = map.Count(); i < mapCount; ++i )
344     {
345       const StringValuePair& pair( map.GetPair( i ) );
346       const std::string& key( pair.first );
347       if ( key == "type" )
348       {
349         continue;
350       }
351
352       const Property::Value& value( pair.second );
353
354       if ( key == "actors" )
355       {
356         // Create children
357         Property::Array actorArray = value.Get< Property::Array >();
358         for ( Property::Array::SizeType i = 0; i < actorArray.Size(); ++i)
359         {
360           actor.Add( NewActor( actorArray[i].Get< Property::Map >() ) );
361         }
362       }
363       else
364       {
365         Property::Index index( actor.GetPropertyIndex( key ) );
366
367         if ( index != Property::INVALID_INDEX )
368         {
369           actor.SetProperty( index, value );
370         }
371       }
372     }
373   }
374
375   return actor;
376 }
377
378 void CreatePropertyMap( Actor actor, Property::Map& map )
379 {
380   map.Clear();
381
382   if ( actor )
383   {
384     map[ "type" ] = actor.GetTypeName();
385
386     // Default properties
387     Property::IndexContainer indices;
388     actor.GetPropertyIndices( indices );
389     const Property::IndexContainer::ConstIterator endIter = indices.End();
390
391     for ( Property::IndexContainer::Iterator iter = indices.Begin(); iter != endIter; ++iter )
392     {
393       map[ actor.GetPropertyName( *iter ) ] = actor.GetProperty( *iter );
394     }
395
396     // Children
397     unsigned int childCount( actor.GetChildCount() );
398     if ( childCount )
399     {
400       Property::Array childArray;
401       for ( unsigned int child = 0; child < childCount; ++child )
402       {
403         Property::Map childMap;
404         CreatePropertyMap( actor.GetChildAt( child ), childMap );
405         childArray.PushBack( childMap );
406       }
407       map[ "actors" ] = childArray;
408     }
409   }
410 }
411
412 void CreatePropertyMap( Image image, Property::Map& map )
413 {
414   map.Clear();
415
416   if ( image )
417   {
418     std::string imageType( "ResourceImage" );
419
420     // Get Type - cannot use TypeRegistry as Image is not an Object and thus, not registered
421     BufferImage bufferImage = BufferImage::DownCast( image );
422     if ( bufferImage )
423     {
424       imageType = "BufferImage";
425       map[ "pixelFormat" ] = GetEnumerationName< Pixel::Format >( bufferImage.GetPixelFormat(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT );
426     }
427     else if ( FrameBufferImage::DownCast( image ) )
428     {
429       imageType = "FrameBufferImage";
430     }
431
432     map[ "type" ] = imageType;
433
434     ResourceImage resourceImage = ResourceImage::DownCast( image );
435     if( resourceImage )
436     {
437       map[ "filename" ] = resourceImage.GetUrl();
438     }
439
440     int width( image.GetWidth() );
441     int height( image.GetHeight() );
442
443     if ( width && height )
444     {
445       map[ "width" ] = width;
446       map[ "height" ] = height;
447     }
448   }
449 }
450
451 void NewAnimation( const Property::Map& map, Dali::AnimationData& outputAnimationData )
452 {
453   // Note: Builder cannot currently pass generic Property::Maps "{" that are nested, so currently we can only have one AnimateTo per animation.
454   Dali::AnimationData::AnimationDataElement* element = new Dali::AnimationData::AnimationDataElement();
455   element->alphaFunction = AlphaFunction::LINEAR;
456   element->timePeriodDelay = 0.0f;
457   element->timePeriodDuration = 1.0f;
458
459   // Now set the properties, or create children
460   for( unsigned int i = 0, animationMapCount = map.Count(); i < animationMapCount; ++i )
461   {
462     const StringValuePair& pair( map.GetPair( i ) );
463     const std::string& key( pair.first );
464     const Property::Value& value( pair.second );
465
466     if( key == "actor" )
467     {
468       element->actor = value.Get< std::string >();
469     }
470     else if( key == "property" )
471     {
472       element->property = value.Get< std::string >();
473     }
474     else if( key == "value" )
475     {
476       element->value = value;
477     }
478     else if( key == "alphaFunction" )
479     {
480       std::string alphaFunctionValue = value.Get< std::string >();
481
482       if( alphaFunctionValue == "LINEAR" )
483       {
484         element->alphaFunction = AlphaFunction::LINEAR;
485       }
486       else if( alphaFunctionValue == "REVERSE" )
487       {
488         element->alphaFunction = AlphaFunction::REVERSE;
489       }
490       else if( alphaFunctionValue == "EASE_IN_SQUARE" )
491       {
492         element->alphaFunction = AlphaFunction::EASE_IN_SQUARE;
493       }
494       else if( alphaFunctionValue == "EASE_OUT_SQUARE" )
495       {
496         element->alphaFunction = AlphaFunction::EASE_OUT_SQUARE;
497       }
498       else if( alphaFunctionValue == "EASE_IN" )
499       {
500         element->alphaFunction = AlphaFunction::EASE_IN;
501       }
502       else if( alphaFunctionValue == "EASE_OUT" )
503       {
504         element->alphaFunction = AlphaFunction::EASE_OUT;
505       }
506       else if( alphaFunctionValue == "EASE_IN_OUT" )
507       {
508         element->alphaFunction = AlphaFunction::EASE_IN_OUT;
509       }
510       else if( alphaFunctionValue == "EASE_IN_SINE" )
511       {
512         element->alphaFunction = AlphaFunction::EASE_IN_SINE;
513       }
514       else if( alphaFunctionValue == "EASE_OUT_SINE" )
515       {
516         element->alphaFunction = AlphaFunction::EASE_OUT_SINE;
517       }
518       else if( alphaFunctionValue == "EASE_IN_OUT_SINE" )
519       {
520         element->alphaFunction = AlphaFunction::EASE_IN_OUT_SINE;
521       }
522       else if( alphaFunctionValue == "BOUNCE" )
523       {
524         element->alphaFunction = AlphaFunction::BOUNCE;
525       }
526       else if( alphaFunctionValue == "SIN" )
527       {
528         element->alphaFunction = AlphaFunction::SIN;
529       }
530       else if( alphaFunctionValue == "EASE_OUT_BACK" )
531       {
532         element->alphaFunction = AlphaFunction::EASE_OUT_BACK;
533       }
534     }
535     else if( key == "timePeriod" )
536     {
537       Property::Map timeMap = value.Get< Property::Map >();
538       for( unsigned int i = 0; i < timeMap.Count(); ++i )
539       {
540         const StringValuePair& pair( timeMap.GetPair( i ) );
541         if( pair.first == "delay" )
542         {
543           element->timePeriodDelay = pair.second.Get< float >();
544         }
545         else if( pair.first == "duration" )
546         {
547           element->timePeriodDuration = pair.second.Get< float >();
548         }
549       }
550     }
551   }
552
553   outputAnimationData.Add( element );
554 }
555
556 } // namespace scripting
557
558 } // namespace Dali
559
560
561
562