Reserved Visual properties on renderer creation
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / border / border-visual.cpp
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "border-visual.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/rendering/renderer-devel.h>
23 #include <dali/integration-api/debug.h>
24
25 // INTERNAL INCLUDES
26 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
27 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
28 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
29 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
30 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
31 #include <dali-toolkit/public-api/visuals/border-visual-properties.h>
32 #include <dali-toolkit/public-api/visuals/visual-properties.h>
33
34 namespace Dali
35 {
36 namespace Toolkit
37 {
38 namespace Internal
39 {
40 namespace
41 {
42 const int CUSTOM_PROPERTY_COUNT(7); // 5 transform properties + color,size
43
44 const char* const POSITION_ATTRIBUTE_NAME("aPosition");
45 const char* const DRIFT_ATTRIBUTE_NAME("aDrift");
46 const char* const INDEX_NAME("indices");
47 } // namespace
48
49 BorderVisualPtr BorderVisual::New(VisualFactoryCache& factoryCache, const Property::Map& properties)
50 {
51   BorderVisualPtr borderVisualPtr(new BorderVisual(factoryCache));
52   borderVisualPtr->SetProperties(properties);
53   borderVisualPtr->Initialize();
54   return borderVisualPtr;
55 }
56
57 BorderVisual::BorderVisual(VisualFactoryCache& factoryCache)
58 : Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::BORDER),
59   mBorderColor(Color::TRANSPARENT),
60   mBorderSize(0.f),
61   mBorderColorIndex(Property::INVALID_INDEX),
62   mBorderSizeIndex(Property::INVALID_INDEX),
63   mAntiAliasing(false)
64 {
65 }
66
67 BorderVisual::~BorderVisual()
68 {
69 }
70
71 void BorderVisual::DoSetProperties(const Property::Map& propertyMap)
72 {
73   for(Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter)
74   {
75     KeyValuePair keyValue = propertyMap.GetKeyValue(iter);
76     if(keyValue.first.type == Property::Key::INDEX)
77     {
78       DoSetProperty(keyValue.first.indexKey, keyValue.second);
79     }
80     else
81     {
82       if(keyValue.first == COLOR_NAME)
83       {
84         DoSetProperty(Toolkit::BorderVisual::Property::COLOR, keyValue.second);
85       }
86       else if(keyValue.first == SIZE_NAME)
87       {
88         DoSetProperty(Toolkit::BorderVisual::Property::SIZE, keyValue.second);
89       }
90       else if(keyValue.first == ANTI_ALIASING)
91       {
92         DoSetProperty(Toolkit::BorderVisual::Property::ANTI_ALIASING, keyValue.second);
93       }
94     }
95   }
96 }
97
98 void BorderVisual::DoSetProperty(Dali::Property::Index        index,
99                                  const Dali::Property::Value& value)
100 {
101   switch(index)
102   {
103     case Toolkit::BorderVisual::Property::COLOR:
104     {
105       if(!value.Get(mBorderColor))
106       {
107         DALI_LOG_ERROR("BorderVisual: borderColor property has incorrect type\n");
108       }
109       break;
110     }
111     case Toolkit::BorderVisual::Property::SIZE:
112     {
113       if(!value.Get(mBorderSize))
114       {
115         DALI_LOG_ERROR("BorderVisual: borderSize property has incorrect type\n");
116       }
117       break;
118     }
119     case Toolkit::BorderVisual::Property::ANTI_ALIASING:
120     {
121       if(!value.Get(mAntiAliasing))
122       {
123         DALI_LOG_ERROR("BorderVisual: antiAliasing property has incorrect type\n");
124       }
125       break;
126     }
127   }
128 }
129
130 void BorderVisual::DoSetOnScene(Actor& actor)
131 {
132   mBorderColorIndex = mImpl->mRenderer.RegisterProperty(Toolkit::BorderVisual::Property::COLOR, COLOR_NAME, mBorderColor);
133   if(mBorderColor.a < 1.f || mAntiAliasing)
134   {
135     mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
136   }
137   mBorderSizeIndex = mImpl->mRenderer.RegisterProperty(Toolkit::BorderVisual::Property::SIZE, SIZE_NAME, mBorderSize);
138
139   actor.AddRenderer(mImpl->mRenderer);
140
141   // Border Visual Generated and ready to display
142   ResourceReady(Toolkit::Visual::ResourceStatus::READY);
143 }
144
145 void BorderVisual::DoCreatePropertyMap(Property::Map& map) const
146 {
147   map.Clear();
148   map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::BORDER);
149   map.Insert(Toolkit::BorderVisual::Property::COLOR, mBorderColor);
150   map.Insert(Toolkit::BorderVisual::Property::SIZE, mBorderSize);
151   map.Insert(Toolkit::BorderVisual::Property::ANTI_ALIASING, mAntiAliasing);
152 }
153
154 void BorderVisual::DoCreateInstancePropertyMap(Property::Map& map) const
155 {
156   // Do nothing
157 }
158
159 void BorderVisual::OnSetTransform()
160 {
161   if(mImpl->mRenderer)
162   {
163     mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
164   }
165 }
166
167 void BorderVisual::OnInitialize()
168 {
169   Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::BORDER_GEOMETRY);
170   if(!geometry)
171   {
172     geometry = CreateBorderGeometry();
173     mFactoryCache.SaveGeometry(VisualFactoryCache::BORDER_GEOMETRY, geometry);
174   }
175
176   Shader shader    = GetBorderShader();
177   mImpl->mRenderer = Renderer::New(geometry, shader);
178   mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
179
180   //Register transform properties
181   mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
182 }
183
184 Shader BorderVisual::GetBorderShader()
185 {
186   Shader shader;
187   if(mAntiAliasing)
188   {
189     shader = mFactoryCache.GetShader(VisualFactoryCache::BORDER_SHADER_ANTI_ALIASING);
190     if(!shader)
191     {
192       shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_BORDER_VISUAL_ANTI_ALIASING_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_BORDER_VISUAL_ANTI_ALIASING_SHADER_FRAG.data());
193       mFactoryCache.SaveShader(VisualFactoryCache::BORDER_SHADER_ANTI_ALIASING, shader);
194     }
195   }
196   else
197   {
198     shader = mFactoryCache.GetShader(VisualFactoryCache::BORDER_SHADER);
199     if(!shader)
200     {
201       shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_BORDER_VISUAL_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_BORDER_VISUAL_SHADER_FRAG.data());
202       mFactoryCache.SaveShader(VisualFactoryCache::BORDER_SHADER, shader);
203     }
204   }
205
206   return shader;
207 }
208
209 /**
210  * Vertices and triangles of the border geometry:
211  *
212  * vertex position = aPosition*uSize.xy + aDrift*uBorderSize;
213  *
214  * 0--1--2--3
215  * |\ | /| /|
216  * | \|/ |/ |
217  * 4--5--6--7
218  * |\ |  |\ |
219  * | \|  | \|
220  * 8--9--10-11
221  * | /| /|\ |
222  * |/ |/ | \|
223  * 12-13-14-15
224  */
225 Geometry BorderVisual::CreateBorderGeometry()
226 {
227   const float halfWidth  = 0.5f;
228   const float halfHeight = 0.5f;
229   struct BorderVertex
230   {
231     Vector2 position;
232     Vector2 drift;
233   };
234   BorderVertex borderVertexData[16] =
235     {
236       {Vector2(-halfWidth, -halfHeight), Vector2(0.f, 0.f)},
237       {Vector2(-halfWidth, -halfHeight), Vector2(1.f, 0.f)},
238       {Vector2(halfWidth, -halfHeight), Vector2(-1.f, 0.f)},
239       {Vector2(halfWidth, -halfHeight), Vector2(0.f, 0.f)},
240
241       {Vector2(-halfWidth, -halfHeight), Vector2(0.f, 1.f)},
242       {Vector2(-halfWidth, -halfHeight), Vector2(1.f, 1.f)},
243       {Vector2(halfWidth, -halfHeight), Vector2(-1.f, 1.f)},
244       {Vector2(halfWidth, -halfHeight), Vector2(0.f, 1.f)},
245
246       {Vector2(-halfWidth, halfHeight), Vector2(0.f, -1.f)},
247       {Vector2(-halfWidth, halfHeight), Vector2(1.f, -1.f)},
248       {Vector2(halfWidth, halfHeight), Vector2(-1.f, -1.f)},
249       {Vector2(halfWidth, halfHeight), Vector2(0.f, -1.f)},
250
251       {Vector2(-halfWidth, halfHeight), Vector2(0.f, 0.f)},
252       {Vector2(-halfWidth, halfHeight), Vector2(1.f, 0.f)},
253       {Vector2(halfWidth, halfHeight), Vector2(-1.f, 0.f)},
254       {Vector2(halfWidth, halfHeight), Vector2(0.f, 0.f)},
255     };
256
257   Property::Map borderVertexFormat;
258   borderVertexFormat[POSITION_ATTRIBUTE_NAME] = Property::VECTOR2;
259   borderVertexFormat[DRIFT_ATTRIBUTE_NAME]    = Property::VECTOR2;
260   VertexBuffer borderVertices                 = VertexBuffer::New(borderVertexFormat);
261   borderVertices.SetData(borderVertexData, 16);
262
263   // Create indices
264   unsigned short indexData[24] = {1, 5, 2, 6, 3, 7, 7, 6, 11, 10, 15, 14, 14, 10, 13, 9, 12, 8, 8, 9, 4, 5, 0, 1};
265
266   // Create the geometry object
267   Geometry geometry = Geometry::New();
268   geometry.AddVertexBuffer(borderVertices);
269   geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
270   geometry.SetType(Geometry::TRIANGLE_STRIP);
271
272   return geometry;
273 }
274
275 } // namespace Internal
276
277 } // namespace Toolkit
278
279 } // namespace Dali