Refactoring VisualActions
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / color / color-visual.cpp
index 2146e50..73b0931 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * 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.
 #include "color-visual.h"
 
 // EXTERNAL INCLUDES
+#include <dali/devel-api/rendering/renderer-devel.h>
 #include <dali/integration-api/debug.h>
 
 //INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
+#include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
+#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
-#include <dali-toolkit/internal/visuals/visual-data-impl.h>
+#include <dali-toolkit/public-api/visuals/color-visual-properties.h>
+#include <dali-toolkit/public-api/visuals/visual-properties.h>
 
 namespace Dali
 {
-
 namespace Toolkit
 {
-
 namespace Internal
 {
-
 namespace
 {
-const char * const COLOR_NAME("mixColor");
-
-const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
-  attribute mediump vec2 aPosition;\n
-  uniform mediump mat4 uMvpMatrix;\n
-  uniform mediump vec3 uSize;\n
-  \n
-  void main()\n
-  {\n
-    mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
-    vertexPosition.xyz *= uSize;\n
-    gl_Position = uMvpMatrix * vertexPosition;\n
-  }\n
-);
-
-const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
-  uniform lowp vec4 uColor;\n
-  uniform lowp vec4 mixColor;\n
-  \n
-  void main()\n
-  {\n
-    gl_FragColor = mixColor*uColor;\n
-  }\n
-);
+VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[6] =
+{
+  VisualFactoryCache::COLOR_SHADER,
+  VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER,
+  VisualFactoryCache::COLOR_SHADER_BORDERLINE,
+  VisualFactoryCache::COLOR_SHADER_ROUNDED_BORDERLINE,
+  VisualFactoryCache::COLOR_SHADER_BLUR_EDGE,
+  VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER_BLUR_EDGE,
+};
+
+// enum of required list when we select shader
+enum ColorVisualRequireFlag
+{
+  DEFAULT        = 0,
+  ROUNDED_CORNER = 1 << 0,
+  BORDERLINE     = 1 << 1,
+  BLUR           = 1 << 2,
+};
+} // unnamed namespace
+ColorVisualPtr ColorVisual::New(VisualFactoryCache& factoryCache, const Property::Map& properties)
+{
+  ColorVisualPtr colorVisualPtr(new ColorVisual(factoryCache));
+  colorVisualPtr->SetProperties(properties);
+  colorVisualPtr->Initialize();
+  return colorVisualPtr;
 }
 
-ColorVisual::ColorVisual( VisualFactoryCache& factoryCache )
-: Visual( factoryCache ),
-  mMixColorIndex( Property::INVALID_INDEX )
+ColorVisual::ColorVisual(VisualFactoryCache& factoryCache)
+: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR),
+  mBlurRadius(0.0f),
+  mBlurRadiusIndex(Property::INVALID_INDEX),
+  mAlwaysUsingBlurRadius(false)
 {
 }
 
@@ -74,83 +79,198 @@ ColorVisual::~ColorVisual()
 {
 }
 
-void ColorVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap )
+void ColorVisual::DoSetProperties(const Property::Map& propertyMap)
 {
-  Property::Value* color = propertyMap.Find( COLOR_NAME );
-  if( !( color && color->Get(mMixColor) ) )
+  // By virtue of DoSetProperties being called last, this will override
+  // anything set by Toolkit::Visual::Property::MIX_COLOR
+  Property::Value* colorValue = propertyMap.Find(Toolkit::ColorVisual::Property::MIX_COLOR, MIX_COLOR);
+  if(colorValue)
   {
-    DALI_LOG_ERROR( "Fail to provide a color to the ColorVisual object" );
+    Vector4 color;
+    if(colorValue->Get(color))
+    {
+      Property::Type type = colorValue->GetType();
+      if(type == Property::VECTOR4)
+      {
+        SetMixColor(color);
+      }
+      else if(type == Property::VECTOR3)
+      {
+        Vector3 color3(color);
+        SetMixColor(color3);
+      }
+    }
+    else
+    {
+      DALI_LOG_ERROR("ColorVisual: mixColor property has incorrect type\n");
+    }
   }
-}
-
-void ColorVisual::SetSize( const Vector2& size )
-{
-  Visual::SetSize( size );
 
-  // ToDo: renderer responds to the size change
+  Property::Value* blurRadiusValue = propertyMap.Find(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME);
+  if(blurRadiusValue)
+  {
+    if(!blurRadiusValue->Get(mBlurRadius))
+    {
+      DALI_LOG_ERROR("ColorVisual:DoSetProperties:: BLUR_RADIUS property has incorrect type: %d\n", blurRadiusValue->GetType());
+    }
+  }
 }
 
-void ColorVisual::SetClipRect( const Rect<int>& clipRect )
+void ColorVisual::DoSetOnScene(Actor& actor)
 {
-  Visual::SetClipRect( clipRect );
+  actor.AddRenderer(mImpl->mRenderer);
 
-  //ToDo: renderer responds to the clipRect change
+  // Color Visual generated and ready to display
+  ResourceReady(Toolkit::Visual::ResourceStatus::READY);
 }
 
-void ColorVisual::SetOffset( const Vector2& offset )
+void ColorVisual::DoSetOffScene(Actor& actor)
 {
-  //ToDo: renderer applies the offset
+  actor.RemoveRenderer(mImpl->mRenderer);
 }
 
-void ColorVisual::DoSetOnStage( Actor& actor )
+void ColorVisual::DoCreatePropertyMap(Property::Map& map) const
 {
-  InitializeRenderer();
+  map.Clear();
+  map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+  map.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, mImpl->mMixColor);
+
+  if(mImpl->mRenderer && mBlurRadiusIndex != Property::INVALID_INDEX)
+  {
+    // Update values from Renderer
+    float blurRadius = mImpl->mRenderer.GetProperty<float>(mBlurRadiusIndex);
+    map.Insert(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, blurRadius);
+  }
+  else
+  {
+    map.Insert(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, mBlurRadius);
+  }
 }
 
-void ColorVisual::DoCreatePropertyMap( Property::Map& map ) const
+void ColorVisual::DoCreateInstancePropertyMap(Property::Map& map) const
 {
-  map.Clear();
-  map.Insert( RENDERER_TYPE, COLOR_RENDERER );
-  map.Insert( COLOR_NAME, mMixColor );
+  // Do nothing
 }
 
-void ColorVisual::InitializeRenderer()
+void ColorVisual::OnSetTransform()
 {
-  Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
-  if( !geometry )
+  if(mImpl->mRenderer)
   {
-    geometry =  VisualFactoryCache::CreateQuadGeometry();
-    mFactoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry );
+    mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
   }
+}
 
-  Shader shader = mFactoryCache.GetShader( VisualFactoryCache::COLOR_SHADER );
-  if( !shader )
+void ColorVisual::UpdateShader()
+{
+  if(mImpl->mRenderer)
   {
-    shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
-    mFactoryCache.SaveShader( VisualFactoryCache::COLOR_SHADER, shader );
+    Shader shader = GenerateShader();
+    mImpl->mRenderer.SetShader(shader);
   }
+}
 
-  mImpl->mRenderer = Renderer::New( geometry, shader );
+void ColorVisual::OnInitialize()
+{
+  Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
 
-  mMixColorIndex = mImpl->mRenderer.RegisterProperty( COLOR_NAME, mMixColor );
-  if( mMixColor.a < 1.f )
+  Shader shader = GenerateShader();
+
+  mImpl->mRenderer = Renderer::New(geometry, shader);
+
+  // ColorVisual has it's own index key for mix color - use this instead
+  // of using the new base index to avoid changing existing applications
+  // String keys will get to this property.
+  mImpl->mMixColorIndex = mImpl->mRenderer.RegisterProperty(Toolkit::ColorVisual::Property::MIX_COLOR, MIX_COLOR, Vector3(mImpl->mMixColor));
+
+  if(!EqualsZero(mBlurRadius))
   {
-    mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
+    mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
+    mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
   }
+
+  // Register transform properties
+  mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
 }
 
-void ColorVisual::SetColor(const Vector4& color)
+Shader ColorVisual::GenerateShader() const
 {
-  mMixColor = color;
+  Shader shader;
+  VisualFactoryCache::ShaderType shaderType;
 
-  if( mImpl->mRenderer )
+  bool roundedCorner = IsRoundedCornerRequired();
+  bool borderline    = IsBorderlineRequired();
+  bool blur          = !EqualsZero(mBlurRadius) || mAlwaysUsingBlurRadius;
+  int shaderTypeFlag = ColorVisualRequireFlag::DEFAULT;
+
+  if(roundedCorner)
+  {
+    shaderTypeFlag |= ColorVisualRequireFlag::ROUNDED_CORNER;
+  }
+  if(blur)
   {
-    (mImpl->mRenderer).SetProperty( mMixColorIndex, color );
-    if( color.a < 1.f )
+    // If we use blur, just ignore borderline
+    borderline = false;
+    shaderTypeFlag |= ColorVisualRequireFlag::BLUR;
+  }
+  if(borderline)
+  {
+    shaderTypeFlag |= ColorVisualRequireFlag::BORDERLINE;
+  }
+
+  shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
+  shader = mFactoryCache.GetShader(shaderType);
+  if(!shader)
+  {
+    std::string vertexShaderPrefixList;
+    std::string fragmentShaderPrefixList;
+    if(roundedCorner)
+    {
+      vertexShaderPrefixList   += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+      fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+    }
+    if(blur)
+    {
+      vertexShaderPrefixList   += "#define IS_REQUIRED_BLUR 1\n";
+      fragmentShaderPrefixList += "#define IS_REQUIRED_BLUR 1\n";
+    }
+    if(borderline)
     {
-      mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
+      vertexShaderPrefixList   += "#define IS_REQUIRED_BORDERLINE 1\n";
+      fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
     }
+    shader = Shader::New(Dali::Shader::GetVertexShaderPrefix()   + vertexShaderPrefixList   + SHADER_COLOR_VISUAL_SHADER_VERT.data(),
+                         Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_COLOR_VISUAL_SHADER_FRAG.data());
+    mFactoryCache.SaveShader(shaderType, shader);
+  }
+
+  return shader;
+}
+
+Dali::Property ColorVisual::OnGetPropertyObject(Dali::Property::Key key)
+{
+  if(!mImpl->mRenderer)
+  {
+    Handle handle;
+    return Dali::Property(handle, Property::INVALID_INDEX);
   }
+
+  if((key.type == Property::Key::INDEX && key.indexKey == DevelColorVisual::Property::BLUR_RADIUS) || (key.type == Property::Key::STRING && key.stringKey == BLUR_RADIUS_NAME))
+  {
+    mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
+
+    // Blur is animated now. we always have to use blur feature.
+    mAlwaysUsingBlurRadius = true;
+
+    mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+
+    // Change shader
+    UpdateShader();
+
+    return Dali::Property(mImpl->mRenderer, mBlurRadiusIndex);
+  }
+
+  Handle handle;
+  return Dali::Property(handle, Property::INVALID_INDEX);
 }
 
 } // namespace Internal