2 * Copyright (c) 2023 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 "rive-animation-view-impl.h"
22 #include <dali/devel-api/adaptor-framework/window-devel.h>
23 #include <dali/devel-api/common/stage.h>
24 #include <dali/devel-api/rendering/renderer-devel.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali-toolkit/devel-api/controls/control-devel.h>
31 #include <dali-extension/devel-api/rive-animation-view/rive-animation-view.h>
42 Geometry CreateQuadGeometry()
44 const float halfWidth = 0.5f;
45 const float halfHeight = 0.5f;
50 QuadVertex quadVertexData[4] =
52 {Vector2(-halfWidth, -halfHeight)},
53 {Vector2(-halfWidth, halfHeight)},
54 {Vector2(halfWidth, -halfHeight)},
55 {Vector2(halfWidth, halfHeight)}};
57 Property::Map quadVertexFormat;
58 quadVertexFormat["aPosition"] = Property::VECTOR2;
59 VertexBuffer quadVertices = VertexBuffer::New(quadVertexFormat);
60 quadVertices.SetData(quadVertexData, 4);
62 // Create the geometry object
63 Geometry geometry = Geometry::New();
64 geometry.AddVertexBuffer(quadVertices);
65 geometry.SetType(Geometry::TRIANGLE_STRIP);
72 return Extension::RiveAnimationView::New();
75 // Setup properties, signals and actions using the type-registry.
76 DALI_TYPE_REGISTRATION_BEGIN(Extension::RiveAnimationView, Toolkit::Control, Create);
77 DALI_PROPERTY_REGISTRATION(Extension, RiveAnimationView, "url", STRING, URL)
78 DALI_PROPERTY_REGISTRATION(Extension, RiveAnimationView, "playState", INTEGER, PLAY_STATE)
79 DALI_TYPE_REGISTRATION_END()
81 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
82 attribute mediump vec2 aPosition;\n
83 uniform highp mat4 uMvpMatrix;\n
84 uniform highp vec3 uSize;\n
85 varying mediump vec2 vTexCoord;\n
89 gl_Position = uMvpMatrix * vec4(aPosition * uSize.xy, 0.0, 1.0);\n
90 vTexCoord = aPosition + vec2(0.5);\n
94 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
95 varying mediump vec2 vTexCoord;\n
96 uniform sampler2D sTexture;\n
97 uniform lowp vec4 uColor;\n
101 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
105 #if defined(DEBUG_ENABLED)
106 Debug::Filter* gRiveAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RIVE_ANIMATION");
109 } // unnamed namespace
111 RiveAnimationView::RiveAnimationView()
112 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
113 mRiveAnimationTask(new RiveAnimationTask())
117 RiveAnimationView::~RiveAnimationView()
121 auto& riveAnimationManager = RiveAnimationManager::GetInstance();
122 riveAnimationManager.RemoveObserver(*this);
126 riveAnimationManager.UnregisterEventCallback(mEventCallback);
127 mEventCallback = nullptr;
130 // Finalize animation task and disconnect the signal in the main thread
131 mRiveAnimationTask->UploadCompletedSignal().Disconnect(this, &RiveAnimationView::OnUploadCompleted);
132 mRiveAnimationTask->Finalize();
136 Extension::RiveAnimationView RiveAnimationView::New()
138 RiveAnimationView* impl = new RiveAnimationView();
140 Dali::Extension::RiveAnimationView handle = Dali::Extension::RiveAnimationView(*impl);
142 // Second-phase init of the implementation
143 // This can only be done after the CustomActor connection has been made...
149 void RiveAnimationView::OnSceneConnection(int depth)
151 Control::OnSceneConnection(depth);
159 mRiveAnimationTask->SetRenderer(mRenderer);
160 Actor actor = Self();
162 // Add property notification for scaling & size
163 mScaleNotification = actor.AddPropertyNotification(Actor::Property::WORLD_SCALE, StepCondition(0.1f, 1.0f));
164 mScaleNotification.NotifySignal().Connect(this, &RiveAnimationView::OnScaleNotification);
166 mSizeNotification = actor.AddPropertyNotification(Actor::Property::SIZE, StepCondition(3.0f));
167 mSizeNotification.NotifySignal().Connect(this, &RiveAnimationView::OnSizeNotification);
169 DevelActor::VisibilityChangedSignal(actor).Connect(this, &RiveAnimationView::OnControlVisibilityChanged);
171 Window window = DevelWindow::Get(actor);
174 DevelWindow::VisibilityChangedSignal(window).Connect(this, &RiveAnimationView::OnWindowVisibilityChanged);
178 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::OnSceneConnection [%p]\n", this);
182 void RiveAnimationView::OnSceneDisconnection()
184 Control::OnSceneDisconnection();
189 Actor actor = Self();
193 actor.RemoveRenderer(mRenderer);
194 mRendererAdded = false;
197 // Remove property notification
198 actor.RemovePropertyNotification(mScaleNotification);
199 actor.RemovePropertyNotification(mSizeNotification);
201 DevelActor::VisibilityChangedSignal(actor).Disconnect(this, &RiveAnimationView::OnControlVisibilityChanged);
203 Window window = DevelWindow::Get(actor);
206 DevelWindow::VisibilityChangedSignal(window).Disconnect(this, &RiveAnimationView::OnWindowVisibilityChanged);
209 // Reset the visual size to zero so that when adding the actor back to stage the rasterization is forced
210 mSize = Vector2::ZERO;
211 mScale = Vector2::ONE;
213 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::OnSceneDisconnection [%p]\n", this);
216 void RiveAnimationView::OnInitialize()
219 Self().SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::IMAGE);
220 Self().SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
223 Vector3 RiveAnimationView::GetNaturalSize()
227 if(mSize != Vector2::ZERO)
233 uint32_t width, height;
234 mRiveAnimationTask->GetDefaultSize(width, height);
235 naturalSize.x = width;
236 naturalSize.y = height;
239 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::GetNaturalSize: w = %f, h = %f [%p]\n", naturalSize.width, naturalSize.height, this);
244 void RiveAnimationView::OnRelayout(const Vector2& size, RelayoutContainer& container)
246 Control::OnRelayout(size, container);
248 if(Self()[Actor::Property::CONNECTED_TO_SCENE] && size != mSize)
250 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::OnRelayout: width = %f, height = %f [%p]\n", size.width, size.height, this);
254 SetVectorImageSize();
256 if(mPlayState == Dali::Extension::RiveAnimationView::PlayState::PLAYING && mAnimationData.playState != Dali::Extension::RiveAnimationView::PlayState::PLAYING)
258 mAnimationData.playState = Dali::Extension::RiveAnimationView::PlayState::PLAYING;
259 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_PLAY_STATE;
266 ///////////////////////////////////////////////////////////
271 void RiveAnimationView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
273 Dali::Extension::RiveAnimationView riveAnimationView = Dali::Extension::RiveAnimationView::DownCast(Dali::BaseHandle(object));
275 if(riveAnimationView)
277 RiveAnimationView& impl = GetImplementation(riveAnimationView);
280 case Dali::Extension::RiveAnimationView::Property::URL:
293 Property::Value RiveAnimationView::GetProperty(BaseObject* object, Property::Index propertyIndex)
295 Property::Value value;
297 Dali::Extension::RiveAnimationView riveAnimationView = Dali::Extension::RiveAnimationView::DownCast(Dali::BaseHandle(object));
299 if(riveAnimationView)
301 RiveAnimationView& impl = GetImplementation(riveAnimationView);
302 switch(propertyIndex)
304 case Dali::Extension::RiveAnimationView::Property::URL:
315 void RiveAnimationView::PlayAnimation()
317 Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
319 if(Self()[Actor::Property::CONNECTED_TO_SCENE] && size != Vector3::ZERO)
321 if(mAnimationData.playState != Dali::Extension::RiveAnimationView::PlayState::PLAYING)
323 mAnimationData.playState = Dali::Extension::RiveAnimationView::PlayState::PLAYING;
324 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_PLAY_STATE;
327 mPlayState = Dali::Extension::RiveAnimationView::PlayState::PLAYING;
329 TriggerVectorRasterization();
332 void RiveAnimationView::StopAnimation()
334 if(mAnimationData.playState != Dali::Extension::RiveAnimationView::PlayState::STOPPED)
336 mAnimationData.playState = Dali::Extension::RiveAnimationView::PlayState::STOPPED;
337 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_PLAY_STATE;
339 mPlayState = Dali::Extension::RiveAnimationView::PlayState::STOPPED;
341 TriggerVectorRasterization();
344 void RiveAnimationView::PauseAnimation()
346 if(mAnimationData.playState == Dali::Extension::RiveAnimationView::PlayState::PLAYING)
348 mAnimationData.playState = Dali::Extension::RiveAnimationView::PlayState::PAUSED;
349 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_PLAY_STATE;
351 mPlayState = Dali::Extension::RiveAnimationView::PlayState::PAUSED;
353 TriggerVectorRasterization();
356 void RiveAnimationView::EnableAnimation(const std::string& animationName, bool enable)
358 mAnimationData.animations.push_back(std::pair<std::string, bool>(animationName, enable));
359 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_ENABLE_ANIMATION;
361 TriggerVectorRasterization();
364 void RiveAnimationView::SetAnimationElapsedTime(const std::string& animationName, float elapsed)
366 mAnimationData.elapsedTimes.push_back(std::pair<std::string, float>(animationName, elapsed));
367 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_ANIMATION_ELAPSED_TIME;
369 TriggerVectorRasterization();
372 void RiveAnimationView::SetShapeFillColor(const std::string& fillName, Vector4 color)
374 mAnimationData.fillColors.push_back(std::pair<std::string, Vector4>(fillName, color));
375 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_FILL_COLOR;
377 TriggerVectorRasterization();
380 void RiveAnimationView::SetShapeStrokeColor(const std::string& strokeName, Vector4 color)
382 mAnimationData.strokeColors.push_back(std::pair<std::string, Vector4>(strokeName, color));
383 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_STROKE_COLOR;
385 TriggerVectorRasterization();
388 void RiveAnimationView::SetNodeOpacity(const std::string& nodeName, float opacity)
390 mAnimationData.opacities.push_back(std::pair<std::string, float>(nodeName, opacity));
391 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_OPACITY;
393 TriggerVectorRasterization();
396 void RiveAnimationView::SetNodeScale(const std::string& nodeName, Vector2 scale)
398 mAnimationData.scales.push_back(std::pair<std::string, Vector2>(nodeName, scale));
399 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_SCALE;
401 TriggerVectorRasterization();
404 void RiveAnimationView::SetNodeRotation(const std::string& nodeName, Degree degree)
406 mAnimationData.rotations.push_back(std::pair<std::string, Degree>(nodeName, degree));
407 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_ROTATION;
409 TriggerVectorRasterization();
412 void RiveAnimationView::SetNodePosition(const std::string& nodeName, Vector2 position)
414 mAnimationData.positions.push_back(std::pair<std::string, Vector2>(nodeName, position));
415 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_POSITION;
417 TriggerVectorRasterization();
420 void RiveAnimationView::PointerMove(float x, float y)
422 mRiveAnimationTask->PointerMove(x, y);
425 void RiveAnimationView::PointerDown(float x, float y)
427 mRiveAnimationTask->PointerDown(x, y);
430 void RiveAnimationView::PointerUp(float x, float y)
432 mRiveAnimationTask->PointerUp(x, y);
435 bool RiveAnimationView::SetNumberState(const std::string& stateMachineName, const std::string& inputName, float value)
437 return mRiveAnimationTask->SetNumberState(stateMachineName, inputName, value);
440 bool RiveAnimationView::SetBooleanState(const std::string& stateMachineName, const std::string& inputName, bool value)
442 return mRiveAnimationTask->SetBooleanState(stateMachineName, inputName, value);
445 bool RiveAnimationView::FireState(const std::string& stateMachineName, const std::string& inputName)
447 return mRiveAnimationTask->FireState(stateMachineName, inputName);
450 Dali::Extension::RiveAnimationView::AnimationSignalType& RiveAnimationView::AnimationFinishedSignal()
452 return mFinishedSignal;
455 void RiveAnimationView::RiveAnimationManagerDestroyed()
457 mCoreShutdown = true;
460 void RiveAnimationView::SetUrl(const std::string& url)
464 if(!mRiveAnimationTask->Load(mUrl))
469 mRiveAnimationTask->UploadCompletedSignal().Connect(this, &RiveAnimationView::OnUploadCompleted);
470 mRiveAnimationTask->SetAnimationFinishedCallback(new EventThreadCallback(MakeCallback(this, &RiveAnimationView::OnAnimationFinished)));
472 auto& vectorAnimationManager = RiveAnimationManager::GetInstance();
473 vectorAnimationManager.AddObserver(*this);
475 Geometry geometry = CreateQuadGeometry();
476 Shader shader = Shader::New(VERTEX_SHADER, FRAGMENT_SHADER);
477 mRenderer = Renderer::New(geometry, shader);
479 TextureSet textureSet = TextureSet::New();
480 mRenderer.SetTextures(textureSet);
482 mRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true);
484 mRiveAnimationTask->SetRenderer(mRenderer);
486 TriggerVectorRasterization();
489 void RiveAnimationView::OnUploadCompleted()
493 Self().AddRenderer(mRenderer);
494 mRendererAdded = true;
496 //TODO: do something - resource ready
498 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::OnUploadCompleted: Renderer is added [%p]\n", this);
502 void RiveAnimationView::OnAnimationFinished()
504 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::OnAnimationFinished: action state = %d [%p]\n", mPlayState, this);
506 if(mPlayState != Dali::Extension::RiveAnimationView::PlayState::STOPPED)
508 mPlayState = Dali::Extension::RiveAnimationView::PlayState::STOPPED;
510 mAnimationData.playState = Dali::Extension::RiveAnimationView::PlayState::STOPPED;
512 Dali::Extension::RiveAnimationView handle(GetOwner());
513 mFinishedSignal.Emit(handle);
518 mRenderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED);
522 void RiveAnimationView::SendAnimationData()
524 if(mAnimationData.resendFlag)
526 mRiveAnimationTask->SetAnimationData(mAnimationData);
527 ClearAnimationsData();
531 if(mAnimationData.playState == Dali::Extension::RiveAnimationView::PlayState::PLAYING)
533 mRenderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY);
537 mRenderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED);
541 mAnimationData.resendFlag = 0;
545 void RiveAnimationView::ClearAnimationsData()
547 mAnimationData.animations.clear();
548 mAnimationData.elapsedTimes.clear();
549 mAnimationData.fillColors.clear();
550 mAnimationData.strokeColors.clear();
551 mAnimationData.opacities.clear();
552 mAnimationData.scales.clear();
553 mAnimationData.rotations.clear();
554 mAnimationData.positions.clear();
557 void RiveAnimationView::SetVectorImageSize()
559 uint32_t width = static_cast<uint32_t>(mSize.width * mScale.width);
560 uint32_t height = static_cast<uint32_t>(mSize.height * mScale.height);
562 mAnimationData.width = width;
563 mAnimationData.height = height;
564 mAnimationData.resendFlag |= RiveAnimationTask::RESEND_SIZE;
567 void RiveAnimationView::TriggerVectorRasterization()
569 if(!mEventCallback && !mCoreShutdown)
571 mEventCallback = MakeCallback(this, &RiveAnimationView::OnProcessEvents);
572 auto& riveAnimationManager = RiveAnimationManager::GetInstance();
573 riveAnimationManager.RegisterEventCallback(mEventCallback);
574 Stage::GetCurrent().KeepRendering(0.0f); // Trigger event processing
578 void RiveAnimationView::OnScaleNotification(PropertyNotification& source)
580 Vector3 scale = Self().GetProperty<Vector3>(Actor::Property::WORLD_SCALE);
582 if(scale.width >= 1.0f || scale.height >= 1.0f)
584 mScale.width = scale.width;
585 mScale.height = scale.height;
587 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::OnScaleNotification: scale = %f, %f [%p]\n", mScale.width, mScale.height, this);
589 SetVectorImageSize();
592 Stage::GetCurrent().KeepRendering(0.0f); // Trigger event processing
596 void RiveAnimationView::OnSizeNotification(PropertyNotification& source)
598 Vector3 size = Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
599 mSize.width = size.width;
600 mSize.height = size.height;
602 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::OnSizeNotification: size = %f, %f [%p]\n", mSize.width, mSize.height, this);
604 SetVectorImageSize();
607 Stage::GetCurrent().KeepRendering(0.0f); // Trigger event processing
610 void RiveAnimationView::OnControlVisibilityChanged(Actor actor, bool visible, DevelActor::VisibilityChange::Type type)
615 TriggerVectorRasterization();
617 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::OnControlVisibilityChanged: invisibile. Pause animation [%p]\n", this);
621 void RiveAnimationView::OnWindowVisibilityChanged(Window window, bool visible)
626 TriggerVectorRasterization();
628 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationView::OnWindowVisibilityChanged: invisibile. Pause animation [%p]\n", this);
632 void RiveAnimationView::OnProcessEvents()
636 mEventCallback = nullptr; // The callback will be deleted in the RiveAnimationManager
639 } // namespace Internal
640 } // namespace Extension