/* * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "beat-control-impl.h" #include #include #include using namespace Dali; // Needed for macros using namespace Dali::Toolkit; namespace Demo { namespace Internal { namespace { const int BOUNCE_ANIMATION_RUNNING(0x0001); const int FADE_ANIMATION_RUNNING(0x0002); const int X_ANIMATION_RUNNING(0x0004); const int Y_ANIMATION_RUNNING(0x0008); Dali::BaseHandle Create() { return Demo::BeatControl::New(); } DALI_TYPE_REGISTRATION_BEGIN(BeatControl, Dali::Toolkit::Control, Create); DALI_PROPERTY_REGISTRATION(Demo, BeatControl, "bounceTransition", STRING, BOUNCE_TRANSITION); DALI_PROPERTY_REGISTRATION(Demo, BeatControl, "leftTransition", STRING, LEFT_TRANSITION); DALI_PROPERTY_REGISTRATION(Demo, BeatControl, "upTransition", STRING, UP_TRANSITION); DALI_PROPERTY_REGISTRATION(Demo, BeatControl, "fadeTransition", STRING, FADE_TRANSITION); DALI_PROPERTY_REGISTRATION(Demo, BeatControl, "beatVisual", MAP, BEAT_VISUAL); DALI_TYPE_REGISTRATION_END(); Toolkit::TransitionData ConvertPropertyToTransition(const Property::Value& value) { Toolkit::TransitionData transitionData; const Property::Array* array = value.GetArray(); if(array) { transitionData = Toolkit::TransitionData::New(*array); } else { const Property::Map* map = value.GetMap(); if(map) { transitionData = Toolkit::TransitionData::New(*map); } } return transitionData; } } // anonymous namespace Internal::BeatControl::BeatControl() : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)), mTransformSize(1.0f, 1.0f), mTransformOrigin(Align::CENTER), mTransformAnchorPoint(Align::CENTER), mAnimationPlaying(0) { } Internal::BeatControl::~BeatControl() { } Demo::BeatControl Internal::BeatControl::New() { IntrusivePtr impl = new Internal::BeatControl(); Demo::BeatControl handle = Demo::BeatControl(*impl); impl->Initialize(); return handle; } void BeatControl::StartBounceAnimation() { if(mAnimation) { mAnimation.Stop(); mAnimation.FinishedSignal().Disconnect(this, &BeatControl::OnBounceAnimationFinished); OnBounceAnimationFinished(mAnimation); } mAnimation = DevelControl::CreateTransition(*this, mBounceTransition); mAnimation.FinishedSignal().Connect(this, &BeatControl::OnBounceAnimationFinished); mAnimation.Play(); mAnimationPlaying |= BOUNCE_ANIMATION_RUNNING; } void BeatControl::StartXAnimation() { if(mXAnimation) { mXAnimation.Stop(); mXAnimation.FinishedSignal().Disconnect(this, &BeatControl::OnXAnimationFinished); OnXAnimationFinished(mXAnimation); } mXAnimation = DevelControl::CreateTransition(*this, mLeftTransition); mXAnimation.FinishedSignal().Connect(this, &BeatControl::OnXAnimationFinished); mXAnimation.Play(); mAnimationPlaying |= X_ANIMATION_RUNNING; } void BeatControl::StartYAnimation() { if(mYAnimation) { mYAnimation.Stop(); mYAnimation.FinishedSignal().Disconnect(this, &BeatControl::OnYAnimationFinished); OnYAnimationFinished(mYAnimation); } mYAnimation = DevelControl::CreateTransition(*this, mUpTransition); mYAnimation.FinishedSignal().Connect(this, &BeatControl::OnYAnimationFinished); mYAnimation.Play(); mAnimationPlaying |= Y_ANIMATION_RUNNING; } void BeatControl::StartFadeAnimation() { if(mFadeAnimation) { mFadeAnimation.Stop(); mFadeAnimation.FinishedSignal().Disconnect(this, &BeatControl::OnFadeAnimationFinished); OnFadeAnimationFinished(mFadeAnimation); } mFadeAnimation = DevelControl::CreateTransition(*this, mFadeTransition); mFadeAnimation.FinishedSignal().Connect(this, &BeatControl::OnFadeAnimationFinished); mFadeAnimation.Play(); mAnimationPlaying |= FADE_ANIMATION_RUNNING; } void BeatControl::OnBounceAnimationFinished(Animation& src) { mAnimationPlaying &= ~BOUNCE_ANIMATION_RUNNING; } void BeatControl::OnXAnimationFinished(Animation& src) { mAnimationPlaying &= ~X_ANIMATION_RUNNING; } void BeatControl::OnYAnimationFinished(Animation& src) { mAnimationPlaying &= ~Y_ANIMATION_RUNNING; } void BeatControl::OnFadeAnimationFinished(Animation& src) { mAnimationPlaying &= ~FADE_ANIMATION_RUNNING; } void BeatControl::OnInitialize() { Actor self = Self(); } void BeatControl::OnSceneConnection(int depth) { Control::OnSceneConnection(depth); } void BeatControl::OnSceneDisconnection() { Control::OnSceneDisconnection(); } void BeatControl::OnSizeSet(const Vector3& targetSize) { Control::OnSizeSet(targetSize); RelayoutVisuals(Vector2(targetSize)); } void BeatControl::OnRelayout(const Vector2& targetSize, RelayoutContainer& container) { RelayoutVisuals(targetSize); } void BeatControl::RelayoutVisuals(const Vector2& targetSize) { if(mVisual) { if((mAnimationPlaying & (X_ANIMATION_RUNNING | Y_ANIMATION_RUNNING)) == 0) { Vector2 size(targetSize); Property::Map transformMap; // Make the visual half the size of the control, but leave // origin and anchor point at center, position is relative, but Zer0 transformMap[Visual::Transform::Property::SIZE] = mTransformSize; transformMap[Visual::Transform::Property::ORIGIN] = mTransformOrigin; transformMap[Visual::Transform::Property::ANCHOR_POINT] = mTransformAnchorPoint; mVisual.SetTransformAndSize(transformMap, size); } } } Vector3 BeatControl::GetNaturalSize() { if(mVisual) { Vector2 naturalSize; mVisual.GetNaturalSize(naturalSize); return Vector3(naturalSize); } return Vector3::ZERO; } void BeatControl::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) { // Chain up. Control::OnStyleChange(styleManager, change); } /////////////////////////////////////////////////////////// // // Properties // void BeatControl::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value) { Demo::BeatControl beatControl = Demo::BeatControl::DownCast(Dali::BaseHandle(object)); if(beatControl) { BeatControl& impl = GetImpl(beatControl); Actor self = impl.Self(); switch(index) { case Demo::BeatControl::Property::BEAT_VISUAL: { bool sizeAndPositionOnly = false; // Determine if a transform.size property exists in the map, and // save it. const Property::Map* map = value.GetMap(); if(map) { Property::Value* transformValue = map->Find(Visual::Property::TRANSFORM, "transform"); if(transformValue) { Property::Map* transformMap = transformValue->GetMap(); if(transformMap) { // We'll increment this whenever SIZE, ORIGIN or ANCHOR_POINT's are modified as we won't need to create a new visual if only these properties are used // If there are more properties in the transform map, then we need to create a new visual unsigned int sizeAndPositionPropertyCount = 0; Property::Value* sizeValue = transformMap->Find(Visual::Transform::Property::SIZE, "size"); if(sizeValue) { sizeValue->Get(impl.mTransformSize); ++sizeAndPositionPropertyCount; } Property::Value* originValue = transformMap->Find(Visual::Transform::Property::ORIGIN, "origin"); if(originValue) { int intValue = 0; if(originValue->Get(intValue)) { impl.mTransformOrigin = static_cast(intValue); ++sizeAndPositionPropertyCount; } } Property::Value* anchorPointValue = transformMap->Find(Visual::Transform::Property::ANCHOR_POINT, "anchorPoint"); if(anchorPointValue) { int intValue = 0; if(anchorPointValue->Get(intValue)) { impl.mTransformAnchorPoint = static_cast(intValue); ++sizeAndPositionPropertyCount; } } // If the only properties that the application is overriding are the size and the position properties, then we do not need to create another visual. if(map->Count() == 1 && transformMap->Count() == sizeAndPositionPropertyCount) { sizeAndPositionOnly = true; } } } if(!sizeAndPositionOnly) { // Only register a visual if there is more than just a size setting impl.mVisual = Toolkit::VisualFactory::Get().CreateVisual(*map); DevelControl::RegisterVisual(impl, Demo::BeatControl::Property::BEAT_VISUAL, impl.mVisual); // We have registered a new visual: must trigger size negotiation // in order to call SetTransformAndSize on the visual with the right size: impl.RelayoutRequest(); } } break; } case Demo::BeatControl::Property::BOUNCE_TRANSITION: { impl.mBounceTransition = ConvertPropertyToTransition(value); break; } case Demo::BeatControl::Property::LEFT_TRANSITION: { impl.mLeftTransition = ConvertPropertyToTransition(value); break; } case Demo::BeatControl::Property::UP_TRANSITION: { impl.mUpTransition = ConvertPropertyToTransition(value); break; } case Demo::BeatControl::Property::FADE_TRANSITION: { impl.mFadeTransition = ConvertPropertyToTransition(value); break; } } } } Property::Value BeatControl::GetProperty(BaseObject* object, Property::Index propertyIndex) { Property::Value value; Demo::BeatControl beatControl = Demo::BeatControl::DownCast(Dali::BaseHandle(object)); if(beatControl) { BeatControl& impl = GetImpl(beatControl); switch(propertyIndex) { case Demo::BeatControl::Property::BEAT_VISUAL: { if(impl.mVisual) { Property::Map map; impl.mVisual.CreatePropertyMap(map); value = map; } break; } case Demo::BeatControl::Property::BOUNCE_TRANSITION: case Demo::BeatControl::Property::LEFT_TRANSITION: case Demo::BeatControl::Property::UP_TRANSITION: case Demo::BeatControl::Property::FADE_TRANSITION: default: break; } } return value; } } // namespace Internal } // namespace Demo