2 * Copyright (c) 2021 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 "visual-base-impl.h"
22 #include <dali-toolkit/public-api/dali-toolkit-common.h>
23 #include <dali/devel-api/rendering/renderer-devel.h>
24 #include <dali/devel-api/scripting/enum-helper.h>
25 #include <dali/integration-api/debug.h>
28 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
29 #include <dali-toolkit/internal/helpers/property-helper.h>
30 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
31 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
32 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
33 #include <dali-toolkit/public-api/visuals/primitive-visual-properties.h>
34 #include <dali-toolkit/public-api/visuals/visual-properties.h>
38 #if defined(DEBUG_ENABLED)
39 Debug::Filter* gVisualBaseLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VISUAL_BASE");
42 const char* const PRE_MULTIPLIED_ALPHA_PROPERTY("preMultipliedAlpha");
54 DALI_ENUM_TO_STRING_TABLE_BEGIN(VISUAL_FITTING_MODE)
55 DALI_ENUM_TO_STRING_WITH_SCOPE(Visual::FittingMode, FIT_KEEP_ASPECT_RATIO)
56 DALI_ENUM_TO_STRING_WITH_SCOPE(Visual::FittingMode, FILL)
57 DALI_ENUM_TO_STRING_WITH_SCOPE(Visual::FittingMode, OVER_FIT_KEEP_ASPECT_RATIO)
58 DALI_ENUM_TO_STRING_WITH_SCOPE(Visual::FittingMode, CENTER)
59 DALI_ENUM_TO_STRING_WITH_SCOPE(Visual::FittingMode, FIT_WIDTH)
60 DALI_ENUM_TO_STRING_WITH_SCOPE(Visual::FittingMode, FIT_HEIGHT)
61 DALI_ENUM_TO_STRING_TABLE_END(VISUAL_FITTING_MODE)
65 Visual::Base::Base(VisualFactoryCache& factoryCache, FittingMode fittingMode, Toolkit::Visual::Type type)
66 : mImpl(new Impl(fittingMode, type)),
67 mFactoryCache(factoryCache)
76 void Visual::Base::Initialize()
78 // The Renderer should be created inside derived class here.
85 if(IsRoundedCornerRequired())
87 mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius);
88 mImpl->mRenderer.RegisterProperty(CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy);
90 mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
92 if(IsBorderlineRequired())
94 mImpl->mBorderlineWidthIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth);
95 mImpl->mBorderlineColorIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor);
96 mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset);
98 mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
103 void Visual::Base::SetCustomShader(const Property::Map& shaderMap)
105 if(mImpl->mCustomShader)
107 mImpl->mCustomShader->SetPropertyMap(shaderMap);
111 mImpl->mCustomShader = new Impl::CustomShader(shaderMap);
114 // Let derived class know
118 void Visual::Base::SetProperties(const Property::Map& propertyMap)
120 for(size_t i = 0; i < propertyMap.Count(); ++i)
122 const KeyValuePair& pair = propertyMap.GetKeyValue(i);
123 const Property::Key& key = pair.first;
124 const Property::Value& value = pair.second;
126 Property::Key matchKey = key;
127 if(matchKey.type == Property::Key::STRING)
129 if(matchKey == CUSTOM_SHADER)
131 matchKey = Property::Key(Toolkit::Visual::Property::SHADER);
133 else if(matchKey == TRANSFORM)
135 matchKey = Property::Key(Toolkit::Visual::Property::TRANSFORM);
137 else if(matchKey == PREMULTIPLIED_ALPHA)
139 matchKey = Property::Key(Toolkit::Visual::Property::PREMULTIPLIED_ALPHA);
141 else if(matchKey == MIX_COLOR)
143 matchKey = Property::Key(Toolkit::Visual::Property::MIX_COLOR);
145 else if(matchKey == OPACITY)
147 matchKey = Property::Key(Toolkit::Visual::Property::OPACITY);
149 else if(matchKey == VISUAL_FITTING_MODE)
151 matchKey = Property::Key(Toolkit::DevelVisual::Property::VISUAL_FITTING_MODE);
153 else if(matchKey == BORDERLINE_WIDTH)
155 matchKey = Property::Key(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH);
157 else if(matchKey == BORDERLINE_COLOR)
159 matchKey = Property::Key(Toolkit::DevelVisual::Property::BORDERLINE_COLOR);
161 else if(matchKey == BORDERLINE_OFFSET)
163 matchKey = Property::Key(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET);
165 else if(matchKey == CORNER_RADIUS)
167 matchKey = Property::Key(Toolkit::DevelVisual::Property::CORNER_RADIUS);
169 else if(matchKey == CORNER_RADIUS_POLICY)
171 matchKey = Property::Key(Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY);
175 switch(matchKey.indexKey)
177 case Toolkit::Visual::Property::SHADER:
179 Property::Map shaderMap;
180 if(value.Get(shaderMap))
182 SetCustomShader(shaderMap);
187 case Toolkit::Visual::Property::TRANSFORM:
192 mImpl->mTransform.SetPropertyMap(map);
197 case Toolkit::Visual::Property::PREMULTIPLIED_ALPHA:
199 bool premultipliedAlpha = false;
200 if(value.Get(premultipliedAlpha))
202 EnablePreMultipliedAlpha(premultipliedAlpha);
207 case Toolkit::Visual::Property::MIX_COLOR:
210 if(value.Get(mixColor))
212 if(value.GetType() == Property::VECTOR4)
214 SetMixColor(mixColor);
218 Vector3 mixColor3(mixColor);
219 SetMixColor(mixColor3);
224 case Toolkit::Visual::Property::OPACITY:
227 if(value.Get(opacity))
229 mImpl->mMixColor.a = opacity;
230 SetMixColor(mImpl->mMixColor);
234 case Toolkit::DevelVisual::Property::VISUAL_FITTING_MODE:
236 Scripting::GetEnumerationProperty<Visual::FittingMode>(
237 value, VISUAL_FITTING_MODE_TABLE, VISUAL_FITTING_MODE_TABLE_COUNT, mImpl->mFittingMode);
240 case Toolkit::DevelVisual::Property::BORDERLINE_WIDTH:
245 mImpl->mBorderlineWidth = width;
249 case Toolkit::DevelVisual::Property::BORDERLINE_COLOR:
254 mImpl->mBorderlineColor = color;
258 case Toolkit::DevelVisual::Property::BORDERLINE_OFFSET:
261 if(value.Get(offset))
263 mImpl->mBorderlineOffset = offset;
267 case Toolkit::DevelVisual::Property::CORNER_RADIUS:
269 if(value.GetType() == Property::VECTOR4)
271 // If CORNER_RADIUS Property is Vector4,
272 // Each values mean the radius of
273 // (top-left, top-right, bottom-right, bottom-left)
275 if(value.Get(radius))
277 mImpl->mCornerRadius = radius;
282 // If CORNER_RADIUS Property is float,
283 // Every corner radius have same value
285 if(value.Get(radius))
287 mImpl->mCornerRadius = Vector4(radius, radius, radius, radius);
292 case Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY:
295 if(value.Get(policy))
299 case Toolkit::Visual::Transform::Policy::RELATIVE:
300 case Toolkit::Visual::Transform::Policy::ABSOLUTE:
302 mImpl->mCornerRadiusPolicy = policy;
307 DALI_LOG_ERROR("Unsupported policy: %d\n", policy);
317 DoSetProperties(propertyMap);
320 void Visual::Base::SetTransformAndSize(const Property::Map& transform, Size controlSize)
322 mImpl->mControlSize = controlSize;
323 mImpl->mTransform.UpdatePropertyMap(transform);
325 #if defined(DEBUG_ENABLED)
326 std::ostringstream oss;
328 DALI_LOG_INFO(gVisualBaseLogFilter, Debug::General, "Visual::Base::SetTransformAndSize(%s) - [\e[1;32mtransform: %s controlSize: (%3.1f, %3.1f)]\e[0m\n", GetName().c_str(), oss.str().c_str(), controlSize.x, controlSize.y);
334 void Visual::Base::SetName(const std::string& name)
339 const std::string& Visual::Base::GetName() const
344 float Visual::Base::GetHeightForWidth(float width)
346 float aspectCorrectedHeight = 0.f;
348 GetNaturalSize(naturalSize);
349 if(naturalSize.width)
351 aspectCorrectedHeight = naturalSize.height * width / naturalSize.width;
353 return aspectCorrectedHeight;
356 float Visual::Base::GetWidthForHeight(float height)
358 float aspectCorrectedWidth = 0.f;
360 GetNaturalSize(naturalSize);
361 if(naturalSize.height > 0.0f)
363 aspectCorrectedWidth = naturalSize.width * height / naturalSize.height;
365 return aspectCorrectedWidth;
368 void Visual::Base::GetNaturalSize(Vector2& naturalSize)
370 naturalSize = Vector2::ZERO;
373 void Visual::Base::DoAction(const Property::Index actionId, const Property::Value attributes)
375 OnDoAction(actionId, attributes);
378 void Visual::Base::SetDepthIndex(int index)
380 mImpl->mDepthIndex = index;
383 mImpl->mRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, mImpl->mDepthIndex);
387 int Visual::Base::GetDepthIndex() const
389 return mImpl->mDepthIndex;
392 void Visual::Base::SetOnScene(Actor& actor)
396 // To display the actor correctly, renderer should not be added to actor until all required resources are ready.
397 // Thus the calling of actor.AddRenderer() should happen inside derived class as base class does not know the exact timing.
402 mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, IsPreMultipliedAlphaEnabled());
403 mImpl->mRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, mImpl->mDepthIndex);
406 mImpl->mFlags |= Impl::IS_ON_SCENE;
410 void Visual::Base::SetOffScene(Actor& actor)
414 DoSetOffScene(actor);
415 mImpl->mFlags &= ~Impl::IS_ON_SCENE;
419 void Visual::Base::CreatePropertyMap(Property::Map& map) const
423 // Update values from Renderer
424 mImpl->mMixColor = mImpl->mRenderer.GetProperty<Vector3>(mImpl->mMixColorIndex);
425 mImpl->mMixColor.a = mImpl->mRenderer.GetProperty<float>(DevelRenderer::Property::OPACITY);
426 if(mImpl->mTransform.mOffsetIndex != Property::INVALID_INDEX)
428 mImpl->mTransform.mOffset = mImpl->mRenderer.GetProperty<Vector2>(mImpl->mTransform.mOffsetIndex);
430 if(mImpl->mTransform.mSizeIndex != Property::INVALID_INDEX)
432 mImpl->mTransform.mSize = mImpl->mRenderer.GetProperty<Vector2>(mImpl->mTransform.mSizeIndex);
434 if(mImpl->mCornerRadiusIndex != Property::INVALID_INDEX)
436 mImpl->mCornerRadius = mImpl->mRenderer.GetProperty<Vector4>(mImpl->mCornerRadiusIndex);
438 if(mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX)
440 mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty<float>(mImpl->mBorderlineWidthIndex);
442 if(mImpl->mBorderlineColorIndex != Property::INVALID_INDEX)
444 mImpl->mBorderlineColor = mImpl->mRenderer.GetProperty<Vector4>(mImpl->mBorderlineColorIndex);
446 if(mImpl->mBorderlineOffsetIndex != Property::INVALID_INDEX)
448 mImpl->mBorderlineOffset = mImpl->mRenderer.GetProperty<float>(mImpl->mBorderlineOffsetIndex);
452 DoCreatePropertyMap(map);
454 if(mImpl->mCustomShader)
456 mImpl->mCustomShader->CreatePropertyMap(map);
459 Property::Map transform;
460 mImpl->mTransform.GetPropertyMap(transform);
461 map.Insert(Toolkit::Visual::Property::TRANSFORM, transform);
463 bool premultipliedAlpha(IsPreMultipliedAlphaEnabled());
464 map.Insert(Toolkit::Visual::Property::PREMULTIPLIED_ALPHA, premultipliedAlpha);
466 // Note, Color and Primitive will also insert their own mix color into the map
467 // which is ok, because they have a different key value range.
468 map.Insert(Toolkit::Visual::Property::MIX_COLOR, mImpl->mMixColor); // vec4
469 map.Insert(Toolkit::Visual::Property::OPACITY, mImpl->mMixColor.a);
471 auto fittingModeString = Scripting::GetLinearEnumerationName<FittingMode>(
472 mImpl->mFittingMode, VISUAL_FITTING_MODE_TABLE, VISUAL_FITTING_MODE_TABLE_COUNT);
473 map.Insert(Toolkit::DevelVisual::Property::VISUAL_FITTING_MODE, fittingModeString);
475 map.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, mImpl->mBorderlineWidth);
476 map.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, mImpl->mBorderlineColor);
477 map.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, mImpl->mBorderlineOffset);
479 map.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, mImpl->mCornerRadius);
480 map.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY, static_cast<int>(mImpl->mCornerRadiusPolicy));
483 void Visual::Base::CreateInstancePropertyMap(Property::Map& map) const
485 DoCreateInstancePropertyMap(map);
487 if(mImpl->mCustomShader)
489 mImpl->mCustomShader->CreatePropertyMap(map);
493 void Visual::Base::EnablePreMultipliedAlpha(bool preMultiplied)
497 mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
501 mImpl->mFlags &= ~Impl::IS_PREMULTIPLIED_ALPHA;
506 mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, preMultiplied);
507 mImpl->mRenderer.RegisterProperty(PRE_MULTIPLIED_ALPHA_PROPERTY, static_cast<float>(preMultiplied));
511 bool Visual::Base::IsPreMultipliedAlphaEnabled() const
513 return mImpl->mFlags & Impl::IS_PREMULTIPLIED_ALPHA;
516 void Visual::Base::DoSetOffScene(Actor& actor)
518 actor.RemoveRenderer(mImpl->mRenderer);
521 bool Visual::Base::IsOnScene() const
523 return mImpl->mFlags & Impl::IS_ON_SCENE;
526 bool Visual::Base::IsRoundedCornerRequired() const
528 if(mImpl->mRenderer && mImpl->mCornerRadiusIndex != Property::INVALID_INDEX)
530 // Update values from Renderer
531 mImpl->mCornerRadius = mImpl->mRenderer.GetProperty<Vector4>(mImpl->mCornerRadiusIndex);
533 return !(mImpl->mCornerRadius == Vector4::ZERO) || mImpl->mNeedCornerRadius;
536 bool Visual::Base::IsBorderlineRequired() const
538 if(mImpl->mRenderer && mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX)
540 // Update values from Renderer
541 mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty<float>(mImpl->mBorderlineWidthIndex);
543 return !EqualsZero(mImpl->mBorderlineWidth) || mImpl->mNeedBorderline;
546 void Visual::Base::OnDoAction(const Property::Index actionId, const Property::Value& attributes)
548 // May be overriden by derived class
551 void Visual::Base::RegisterMixColor()
553 // Only register if not already registered.
554 // (Color and Primitive visuals will register their own and save to this index)
555 if(mImpl->mMixColorIndex == Property::INVALID_INDEX)
557 mImpl->mMixColorIndex = mImpl->mRenderer.RegisterProperty(
558 Toolkit::Visual::Property::MIX_COLOR,
560 Vector3(mImpl->mMixColor));
563 mImpl->mRenderer.SetProperty(DevelRenderer::Property::OPACITY, mImpl->mMixColor.a);
565 float preMultipliedAlpha = 0.0f;
566 if(IsPreMultipliedAlphaEnabled())
568 preMultipliedAlpha = 1.0f;
570 mImpl->mRenderer.RegisterProperty(PRE_MULTIPLIED_ALPHA_PROPERTY, preMultipliedAlpha);
573 void Visual::Base::SetMixColor(const Vector4& color)
575 mImpl->mMixColor = color;
579 mImpl->mRenderer.SetProperty(mImpl->mMixColorIndex, Vector3(color));
580 mImpl->mRenderer.SetProperty(DevelRenderer::Property::OPACITY, color.a);
584 void Visual::Base::SetMixColor(const Vector3& color)
586 mImpl->mMixColor.r = color.r;
587 mImpl->mMixColor.g = color.g;
588 mImpl->mMixColor.b = color.b;
592 mImpl->mRenderer.SetProperty(mImpl->mMixColorIndex, color);
596 void Visual::Base::AddEventObserver(Visual::EventObserver& observer)
598 mImpl->mEventObserver = &observer;
601 void Visual::Base::RemoveEventObserver(Visual::EventObserver& observer)
603 mImpl->mEventObserver = NULL;
606 void Visual::Base::ResourceReady(Toolkit::Visual::ResourceStatus resourceStatus)
608 if(mImpl->mResourceStatus != resourceStatus)
610 mImpl->mResourceStatus = resourceStatus;
612 if(mImpl->mEventObserver)
614 // observer is currently a control impl
615 mImpl->mEventObserver->ResourceReady(*this);
620 bool Visual::Base::IsResourceReady() const
622 return (mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::READY);
625 bool Visual::Base::IsSynchronousLoadingRequired() const
627 return (mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING);
630 Toolkit::Visual::Type Visual::Base::GetType() const
635 Toolkit::Visual::ResourceStatus Visual::Base::GetResourceStatus() const
637 return mImpl->mResourceStatus;
640 Visual::FittingMode Visual::Base::GetFittingMode() const
642 return mImpl->mFittingMode;
645 Visual::Base& Visual::Base::GetVisualObject()
650 Renderer Visual::Base::GetRenderer()
652 return mImpl->mRenderer;
655 Property::Index Visual::Base::GetPropertyIndex(Property::Key key)
657 Property::Index index = mImpl->mRenderer.GetPropertyIndex(key);
659 if(index == Property::INVALID_INDEX)
661 // Is it a shader property?
662 Shader shader = mImpl->mRenderer.GetShader();
663 index = shader.GetPropertyIndex(key);
664 if(index != Property::INVALID_INDEX)
666 // Yes - we should register it in the Renderer so it can be set / animated
667 // independently, as shaders are shared across multiple renderers.
669 Property::Index keyIndex(Property::INVALID_KEY);
670 if(key.type == Property::Key::INDEX)
672 keyName = shader.GetPropertyName(index);
673 keyIndex = key.indexKey;
677 keyName = key.stringKey;
678 // Leave keyIndex as INVALID_KEY - it can still be registered against the string key.
680 Property::Value value = shader.GetProperty(index);
681 index = mImpl->mRenderer.RegisterProperty(keyIndex, keyName, value);
687 void Visual::Base::SetupTransition(
688 Dali::Animation& transition,
689 Internal::TransitionData::Animator& animator,
690 Property::Index index,
691 Property::Value& initialValue,
692 Property::Value& targetValue)
694 if(index != Property::INVALID_INDEX)
698 if(animator.animate == false)
700 mImpl->mRenderer.SetProperty(index, targetValue);
704 if(animator.initialValue.GetType() != Property::NONE)
706 mImpl->mRenderer.SetProperty(index, initialValue);
711 transition = Dali::Animation::New(0.1f);
714 transition.AnimateTo(Property(mImpl->mRenderer, index),
716 animator.alphaFunction,
717 TimePeriod(animator.timePeriodDelay,
718 animator.timePeriodDuration));
724 void Visual::Base::AnimateProperty(
725 Dali::Animation& transition,
726 Internal::TransitionData::Animator& animator)
728 #if defined(DEBUG_ENABLED)
730 std::ostringstream oss;
731 oss << "Visual::Base::AnimateProperty(Visual:" << mImpl->mName << " Property:" << animator.propertyKey << " Target: " << animator.targetValue << std::endl;
732 DALI_LOG_INFO(gVisualBaseLogFilter, Debug::General, oss.str().c_str());
736 if(animator.propertyKey == Toolkit::Visual::Property::MIX_COLOR ||
737 animator.propertyKey == MIX_COLOR ||
738 (mImpl->mType == Toolkit::Visual::COLOR &&
739 animator.propertyKey == ColorVisual::Property::MIX_COLOR) ||
740 (mImpl->mType == Toolkit::Visual::PRIMITIVE &&
741 animator.propertyKey == PrimitiveVisual::Property::MIX_COLOR))
743 AnimateMixColorProperty(transition, animator);
745 else if(animator.propertyKey == Toolkit::Visual::Property::OPACITY ||
746 animator.propertyKey == OPACITY)
748 AnimateOpacityProperty(transition, animator);
750 else if(mImpl->mRenderer)
752 AnimateRendererProperty(transition, animator);
756 void Visual::Base::AnimateOpacityProperty(
757 Dali::Animation& transition,
758 Internal::TransitionData::Animator& animator)
761 if(animator.targetValue.Get(targetOpacity))
763 mImpl->mMixColor.a = targetOpacity;
766 SetupTransition(transition, animator, DevelRenderer::Property::OPACITY, animator.initialValue, animator.targetValue);
769 void Visual::Base::AnimateRendererProperty(
770 Dali::Animation& transition,
771 Internal::TransitionData::Animator& animator)
773 Property::Index index = GetPropertyIndex(animator.propertyKey);
774 if(index != Property::INVALID_INDEX)
776 if(animator.targetValue.GetType() != Property::NONE)
778 // Try writing target value into transform property map
779 // if it's not a valid key, then it won't alter mTransform
781 if(animator.propertyKey.type == Property::Key::INDEX)
783 map.Add(animator.propertyKey.indexKey, animator.targetValue);
787 map.Add(animator.propertyKey.stringKey, animator.targetValue);
790 mImpl->mTransform.UpdatePropertyMap(map);
793 SetupTransition(transition, animator, index, animator.initialValue, animator.targetValue);
797 void Visual::Base::AnimateMixColorProperty(
798 Dali::Animation& transition,
799 Internal::TransitionData::Animator& animator)
801 Property::Index index = mImpl->mMixColorIndex;
802 bool animateOpacity = false;
804 Property::Value initialOpacity;
805 Property::Value targetOpacity;
806 Property::Value initialMixColor;
807 Property::Value targetMixColor;
809 if(index != Property::INVALID_INDEX)
811 Vector4 initialColor;
812 if(animator.initialValue.Get(initialColor))
814 if(animator.initialValue.GetType() == Property::VECTOR4)
816 // if there is an initial color specifying alpha, test it
817 initialOpacity = initialColor.a;
819 initialMixColor = Vector3(initialColor);
822 // Set target value into data store
823 if(animator.targetValue.GetType() != Property::NONE)
826 animator.targetValue.Get(mixColor);
827 if(animator.targetValue.GetType() == Property::VECTOR4)
829 mImpl->mMixColor.a = mixColor.a;
830 targetOpacity = mixColor.a;
831 animateOpacity = true;
834 mImpl->mMixColor.r = mixColor.r;
835 mImpl->mMixColor.g = mixColor.g;
836 mImpl->mMixColor.b = mixColor.b;
837 targetMixColor = Vector3(mixColor);
840 SetupTransition(transition, animator, index, initialMixColor, targetMixColor);
843 SetupTransition(transition, animator, DevelRenderer::Property::OPACITY, initialOpacity, targetOpacity);
848 Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key)
850 if(!mImpl->mRenderer)
853 return Dali::Property(handle, Property::INVALID_INDEX);
856 // Mix color or opacity cases
857 if(key.type == Property::Key::INDEX)
859 if(key.indexKey == Toolkit::Visual::Property::MIX_COLOR || (mImpl->mType == Toolkit::Visual::COLOR && key.indexKey == ColorVisual::Property::MIX_COLOR) || (mImpl->mType == Toolkit::Visual::PRIMITIVE && key.indexKey == PrimitiveVisual::Property::MIX_COLOR))
861 return Dali::Property(mImpl->mRenderer, mImpl->mMixColorIndex);
863 else if(key.indexKey == Toolkit::Visual::Property::OPACITY)
865 return Dali::Property(mImpl->mRenderer, DevelRenderer::Property::OPACITY);
867 else if(key.indexKey == Toolkit::Visual::Transform::Property::OFFSET)
869 return Dali::Property(mImpl->mRenderer, OFFSET);
871 else if(key.indexKey == Toolkit::Visual::Transform::Property::SIZE)
873 return Dali::Property(mImpl->mRenderer, SIZE);
878 if(key.stringKey == MIX_COLOR)
880 return Dali::Property(mImpl->mRenderer, mImpl->mMixColorIndex);
882 else if(key.stringKey == OPACITY)
884 return Dali::Property(mImpl->mRenderer, DevelRenderer::Property::OPACITY);
886 else if(key.stringKey == OFFSET)
888 return Dali::Property(mImpl->mRenderer, OFFSET);
890 else if(key.stringKey == SIZE)
892 return Dali::Property(mImpl->mRenderer, SIZE);
897 Property::Index index = GetPropertyIndex(key);
898 if(index == Property::INVALID_INDEX)
900 if((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_WIDTH) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_WIDTH) ||
901 (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_COLOR) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_COLOR) ||
902 (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_OFFSET) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_OFFSET))
904 mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
906 // Register borderline properties
907 mImpl->mBorderlineWidthIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth);
908 mImpl->mBorderlineColorIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor);
909 mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset);
910 mImpl->mNeedBorderline = true;
912 index = mImpl->mRenderer.GetPropertyIndex(key);
917 else if((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::CORNER_RADIUS) || (key.type == Property::Key::STRING && key.stringKey == CORNER_RADIUS))
919 // Register CORNER_RADIUS property
920 mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius);
921 mImpl->mRenderer.RegisterProperty(CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy);
923 mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
925 index = mImpl->mCornerRadiusIndex;
926 mImpl->mNeedCornerRadius = true;
933 // We can't find the property in the base class.
934 // Request to child class
935 return OnGetPropertyObject(key);
939 return Dali::Property(mImpl->mRenderer, index);
942 } // namespace Internal
944 } // namespace Toolkit