+
+Property::Index Visual::Base::GetPropertyIndex( Property::Key key )
+{
+ Property::Index index = DevelHandle::GetPropertyIndex( mImpl->mRenderer, key );
+
+ if( index == Property::INVALID_INDEX )
+ {
+ // Is it a shader property?
+ Shader shader = mImpl->mRenderer.GetShader();
+ index = DevelHandle::GetPropertyIndex( shader, key );
+ if( index != Property::INVALID_INDEX )
+ {
+ // Yes - we should register it in the Renderer so it can be set / animated
+ // independently, as shaders are shared across multiple renderers.
+ std::string keyName;
+ Property::Index keyIndex( Property::INVALID_KEY );
+ if( key.type == Property::Key::INDEX )
+ {
+ keyName = shader.GetPropertyName( index );
+ keyIndex = key.indexKey;
+ }
+ else
+ {
+ keyName = key.stringKey;
+ // Leave keyIndex as INVALID_KEY - it can still be registered against the string key.
+ }
+ Property::Value value = shader.GetProperty( index );
+ index = DevelHandle::RegisterProperty( mImpl->mRenderer, keyIndex, keyName, value );
+ }
+ }
+ return index;
+}
+
+void Visual::Base::SetupTransition(
+ Dali::Animation& transition,
+ Internal::TransitionData::Animator& animator,
+ Property::Index index )
+{
+ if( index != Property::INVALID_INDEX )
+ {
+ if( mImpl->mRenderer )
+ {
+ if( animator.animate == false )
+ {
+ mImpl->mRenderer.SetProperty( index, animator.targetValue );
+ }
+ else
+ {
+ if( animator.initialValue.GetType() != Property::NONE )
+ {
+ mImpl->mRenderer.SetProperty( index, animator.initialValue );
+ }
+
+ if( ! transition )
+ {
+ transition = Dali::Animation::New( 0.1f );
+ }
+
+ transition.AnimateTo( Property( mImpl->mRenderer, index ),
+ animator.targetValue,
+ animator.alphaFunction,
+ TimePeriod( animator.timePeriodDelay,
+ animator.timePeriodDuration ) );
+ }
+ }
+ }
+}
+
+void Visual::Base::AnimateProperty(
+ Dali::Animation& transition,
+ Internal::TransitionData::Animator& animator )
+{
+#if defined(DEBUG_ENABLED)
+ {
+ std::ostringstream oss;
+ oss << "Visual::Base::AnimateProperty(Visual:" << mImpl->mName << " Property:" << animator.propertyKey << " Target: " << animator.targetValue << std::endl;
+ DALI_LOG_INFO( gVisualBaseLogFilter, Debug::General, oss.str().c_str() );
+ }
+#endif
+
+ Property::Index index = Property::INVALID_INDEX;
+
+ bool isMixColor = false;
+ bool isMixColorOpaque = true;
+
+ // Get the property index
+ if( animator.propertyKey == Toolkit::DevelVisual::Property::MIX_COLOR ||
+ animator.propertyKey == MIX_COLOR )
+ {
+ isMixColor = true;
+ index = mImpl->mMixColorIndex;
+
+ Vector4 initialColor;
+ if( animator.initialValue.Get(initialColor) ) // if there is an initial color, test it
+ {
+ isMixColorOpaque = initialColor.a >= 1.0f;
+ }
+ else
+ {
+ isMixColorOpaque = mImpl->mMixColor.a >= 1.0f; // otherwise, test the current color
+ }
+ }
+ else if( mImpl->mRenderer )
+ {
+ index = GetPropertyIndex( animator.propertyKey );
+ }
+
+ // Set target value into data store
+ if( animator.targetValue.GetType() != Property::NONE )
+ {
+ if( isMixColor )
+ {
+ animator.targetValue.Get( mImpl->mMixColor );
+ }
+ else
+ {
+ // Note: there may be several of these calls if more than one
+ // transform property is animated.
+ Property::Map map;
+ if( animator.propertyKey.type == Property::Key::INDEX )
+ {
+ map.Add( animator.propertyKey.indexKey, animator.targetValue );
+ }
+ else
+ {
+ map.Add( animator.propertyKey.stringKey, animator.targetValue );
+ }
+
+ mImpl->mTransform.UpdatePropertyMap( map );
+ }
+ }
+
+ if( index != Property::INVALID_INDEX )
+ {
+ SetupTransition( transition, animator, index );
+
+ // For mix color, ensure the blend mode is on if the initial or final values are not opaque,
+ // and that it is turned off after the animation ends if the final value is opaque
+ if( isMixColor && (!isMixColorOpaque || mImpl->mMixColor.a < 1.0f) )
+ {
+ mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
+
+ if( animator.animate == true && mImpl->mMixColor.a >= 1.0f )
+ {
+ // When it becomes opaque, set the blend mode back to automatically
+ if( ! mImpl->mBlendSlotDelegate )
+ {
+ mImpl->mBlendSlotDelegate = new SlotDelegate<Visual::Base>(this);
+ }
+ transition.FinishedSignal().Connect( *(mImpl->mBlendSlotDelegate),
+ &Visual::Base::OnMixColorFinished );
+ }
+ }
+ }
+}
+
+void Visual::Base::OnMixColorFinished( Animation& animation )
+{
+ if( mImpl->mRenderer )
+ {
+ DALI_LOG_INFO( gVisualBaseLogFilter, Debug::General, "Visual::Base::OnMixColorFinished()\n");
+ mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE,
+ ( mImpl->mMixColor.a < 1.0 ) ? BlendMode::ON : BlendMode::AUTO );
+ }
+ delete mImpl->mBlendSlotDelegate;
+ mImpl->mBlendSlotDelegate = NULL;
+}
+