a266fadb9724803ede1d7705b04a9a433b42a481
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / animated-vector-image-visual.cpp
1 /*
2  * Copyright (c) 2018 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/visuals/animated-vector-image/animated-vector-image-visual.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/stage-devel.h>
24 #include <dali/integration-api/debug.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
28 #include <dali-toolkit/public-api/visuals/visual-properties.h>
29 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
30 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
31 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
32 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
33 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
34 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
35 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
36
37 namespace Dali
38 {
39
40 namespace Toolkit
41 {
42
43 namespace Internal
44 {
45
46 namespace
47 {
48
49 const Dali::Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f );
50 constexpr auto LOOP_FOREVER = -1;
51
52 } // unnamed namespace
53
54 AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties )
55 {
56   AnimatedVectorImageVisualPtr visual( new AnimatedVectorImageVisual( factoryCache, shaderFactory, imageUrl ) );
57   visual->SetProperties( properties );
58
59   return visual;
60 }
61
62 AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
63 {
64   AnimatedVectorImageVisualPtr visual( new AnimatedVectorImageVisual( factoryCache, shaderFactory, imageUrl ) );
65
66   return visual;
67 }
68
69 AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl )
70 : Visual::Base( factoryCache ),
71   mImageVisualShaderFactory( shaderFactory ),
72   mUrl( imageUrl ),
73   mVisualSize(),
74   mPlayRange( 0.0f, 1.0f ),
75   mPlacementActor(),
76   mVectorRasterizeThread(),
77   mLoopCount( LOOP_FOREVER ),
78   mActionStatus( DevelAnimatedVectorImageVisual::Action::STOP )
79 {
80   // the rasterized image is with pre-multiplied alpha format
81   mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
82 }
83
84 AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
85 {
86 }
87
88 void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize )
89 {
90   naturalSize = mVisualSize;
91 }
92
93 void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const
94 {
95   map.Clear();
96   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::ANIMATED_VECTOR_IMAGE );
97   if( mUrl.IsValid() )
98   {
99     map.Insert( Toolkit::ImageVisual::Property::URL, mUrl.GetUrl() );
100   }
101   map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast< int >( mLoopCount ) );
102   map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, static_cast< Vector2 >( mPlayRange ) );
103 }
104
105 void AnimatedVectorImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
106 {
107   // Do nothing
108 }
109
110 void AnimatedVectorImageVisual::DoSetProperties( const Property::Map& propertyMap )
111 {
112   // url already passed in from constructor
113   for( Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter )
114   {
115     KeyValuePair keyValue = propertyMap.GetKeyValue( iter );
116     if( keyValue.first.type == Property::Key::INDEX )
117     {
118       DoSetProperty( keyValue.first.indexKey, keyValue.second );
119     }
120     else
121     {
122        if( keyValue.first == LOOP_COUNT_NAME )
123        {
124           DoSetProperty( Toolkit::DevelImageVisual::Property::LOOP_COUNT, keyValue.second );
125        }
126        else if( keyValue.first == PLAY_RANGE_NAME )
127        {
128           DoSetProperty( Toolkit::DevelImageVisual::Property::PLAY_RANGE, keyValue.second );
129        }
130     }
131   }
132 }
133
134 void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Property::Value& value )
135 {
136   switch(index)
137   {
138     case Toolkit::DevelImageVisual::Property::LOOP_COUNT:
139     {
140       int32_t loopCount;
141       if( value.Get( loopCount ) )
142       {
143         mLoopCount = loopCount;
144         if( mVectorRasterizeThread )
145         {
146           mVectorRasterizeThread->SetLoopCount( loopCount );
147         }
148       }
149       break;
150     }
151     case Toolkit::DevelImageVisual::Property::PLAY_RANGE:
152     {
153       Vector2 range;
154       if( value.Get( range ) )
155       {
156         // Make sure the range specified is between 0.0 and 1.0
157         if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
158         {
159           Vector2 orderedRange( range );
160           // If the range is not in order swap values
161           if( range.x > range.y )
162           {
163             orderedRange = Vector2( range.y, range.x );
164           }
165
166           mPlayRange = orderedRange;
167
168           if( mVectorRasterizeThread )
169           {
170             mVectorRasterizeThread->SetPlayRange( mPlayRange );
171           }
172         }
173       }
174       break;
175     }
176   }
177 }
178
179 void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor )
180 {
181   Shader shader;
182
183   if( mImpl->mCustomShader )
184   {
185     shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource() : mImpl->mCustomShader->mVertexShader,
186                           mImpl->mCustomShader->mFragmentShader.empty() ? mImageVisualShaderFactory.GetFragmentShaderSource() : mImpl->mCustomShader->mFragmentShader,
187                           mImpl->mCustomShader->mHints );
188
189     shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
190   }
191   else
192   {
193     shader = mImageVisualShaderFactory.GetShader( mFactoryCache, false, true );
194   }
195
196   Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
197
198   mImpl->mRenderer = Renderer::New( geometry, shader );
199
200   TextureSet textureSet = TextureSet::New();
201   mImpl->mRenderer.SetTextures( textureSet );
202
203   // Register transform properties
204   mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
205
206   // Defer the rasterisation task until we get given a size (by Size Negotiation algorithm)
207
208   // Hold the weak handle of the placement actor and delay the adding of renderer until the rasterization is finished.
209   mPlacementActor = actor;
210
211   // This visual needs it's size set before it can be rasterized hence set ResourceReady once on stage
212   ResourceReady( Toolkit::Visual::ResourceStatus::READY );
213 }
214
215 void AnimatedVectorImageVisual::DoSetOffStage( Actor& actor )
216 {
217   if( mVectorRasterizeThread )
218   {
219     mVectorRasterizeThread->PauseAnimation();
220     DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
221     mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
222   }
223
224   if( mImpl->mRenderer )
225   {
226     actor.RemoveRenderer( mImpl->mRenderer );
227     mImpl->mRenderer.Reset();
228   }
229
230   mPlacementActor.Reset();
231
232   // Reset the visual size to zero so that when adding the actor back to stage the rasterization is forced
233   mVisualSize = Vector2::ZERO;
234 }
235
236 void AnimatedVectorImageVisual::OnSetTransform()
237 {
238   Vector2 visualSize = mImpl->mTransform.GetVisualSize( mImpl->mControlSize );
239
240   if( IsOnStage() )
241   {
242     if( visualSize != mVisualSize )
243     {
244       mVisualSize = visualSize;
245
246       if( !mVectorRasterizeThread )
247       {
248         uint32_t width = static_cast< uint32_t >( visualSize.width );
249         uint32_t height = static_cast< uint32_t >( visualSize.height );
250
251         mVectorRasterizeThread = std::unique_ptr< VectorRasterizeThread >( new VectorRasterizeThread( mUrl.GetUrl(), mImpl->mRenderer, width, height ) );
252
253         mVectorRasterizeThread->SetResourceReadyCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnResourceReady ) ) );
254         mVectorRasterizeThread->SetLoopCount( mLoopCount );
255         mVectorRasterizeThread->SetPlayRange( mPlayRange );
256
257         mVectorRasterizeThread->Start();
258
259         if( mActionStatus == DevelAnimatedVectorImageVisual::Action::PLAY )
260         {
261           mVectorRasterizeThread->StartAnimation();
262           DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY );
263         }
264         else
265         {
266           // Render one frame
267           mVectorRasterizeThread->RenderFrame();
268         }
269       }
270       else
271       {
272         uint32_t width = static_cast< uint32_t >( visualSize.width );
273         uint32_t height = static_cast< uint32_t >( visualSize.height );
274
275         mVectorRasterizeThread->SetSize( width, height );
276       }
277     }
278   }
279 }
280
281 void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, const Property::Value& attributes )
282 {
283   if( actionId == mActionStatus )
284   {
285     return;
286   }
287
288   // Check if action is valid for this visual type and perform action if possible
289   switch( actionId )
290   {
291     case DevelAnimatedVectorImageVisual::Action::PLAY:
292     {
293       if( IsOnStage())
294       {
295         if( mVectorRasterizeThread )
296         {
297           mVectorRasterizeThread->StartAnimation();
298           DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY );   //TODO: Should manage this globally
299         }
300       }
301       mActionStatus = DevelAnimatedVectorImageVisual::Action::PLAY;
302       break;
303     }
304     case DevelAnimatedVectorImageVisual::Action::PAUSE:
305     {
306       if( mVectorRasterizeThread )
307       {
308         mVectorRasterizeThread->PauseAnimation();
309         DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
310       }
311       mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
312       break;
313     }
314     case DevelAnimatedVectorImageVisual::Action::RESUME:
315     {
316       if( mVectorRasterizeThread )
317       {
318         mVectorRasterizeThread->ResumeAnimation();
319         DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY );
320       }
321       mActionStatus = DevelAnimatedVectorImageVisual::Action::RESUME;
322       break;
323     }
324     case DevelAnimatedVectorImageVisual::Action::STOP:
325     {
326       if( mVectorRasterizeThread )
327       {
328         mVectorRasterizeThread->StopAnimation();
329         DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
330       }
331       mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP;
332       break;
333     }
334   }
335 }
336
337 void AnimatedVectorImageVisual::OnResourceReady()
338 {
339   // If weak handle is holding a placement actor, it is the time to add the renderer to actor.
340   Actor actor = mPlacementActor.GetHandle();
341   if( actor )
342   {
343     actor.AddRenderer( mImpl->mRenderer );
344     // reset the weak handle so that the renderer only get added to actor once
345     mPlacementActor.Reset();
346
347     Stage::GetCurrent().KeepRendering( 0.0f );
348   }
349 }
350
351 } // namespace Internal
352
353 } // namespace Toolkit
354
355 } // namespace Dali