[dali_2.3.29] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / update / common / property-condition-step-functions.cpp
1 /*
2  * Copyright (c) 2024 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 #include <dali/internal/update/common/property-condition-step-functions.h>
19 #include <dali/public-api/common/dali-common.h>
20 #include <dali/public-api/math/quaternion.h>
21 #include <dali/public-api/math/vector2.h>
22 #include <dali/public-api/math/vector3.h>
23 #include <dali/public-api/math/vector4.h>
24 #include <dali/public-api/object/property-input.h>
25
26 namespace Dali
27 {
28 namespace Internal
29 {
30 namespace SceneGraph
31 {
32 namespace
33 {
34 const int32_t ARGINDEX_REF_VALUE    = 0;
35 const int32_t ARGINDEX_STEP_SIZE    = 1;
36 const int32_t ARGINDEX_CURRENT_STEP = 2;
37 const int32_t ARGINDEX_FIRST_VALUE  = 3;
38 const int32_t ARGINDEX_SECOND_VALUE = 4;
39 const int32_t ARGINDEX_THIRD_VALUE  = 5;
40
41 inline float AngleDifference(float a1, float a2, const float angleRangeHalf)
42 {
43   float diff = fabs(a1 - a2);
44   return diff < angleRangeHalf ? diff : angleRangeHalf * 2.0f - diff;
45 }
46
47 } // namespace
48
49 ConditionFunction Step::GetFunction(Property::Type valueType)
50 {
51   ConditionFunction function = nullptr;
52
53   switch(valueType)
54   {
55     case Property::INTEGER:
56     {
57       function = EvalInteger;
58       break;
59     }
60     case Property::FLOAT:
61     {
62       function = EvalFloat;
63       break;
64     }
65     case Property::VECTOR2:
66     {
67       function = EvalVector2;
68       break;
69     }
70     case Property::VECTOR3:
71     {
72       function = EvalVector3;
73       break;
74     }
75     case Property::VECTOR4:
76     {
77       function = EvalVector4;
78       break;
79     }
80     default:
81     {
82       function = EvalDefault;
83       break;
84     }
85   } // end switch
86
87   return function;
88 }
89
90 ConditionFunction Step::GetCompareFunction(Property::Type valueType)
91 {
92   ConditionFunction function = nullptr;
93   if(valueType == Property::VECTOR3)
94   {
95     function = EvalAndCompareVector3;
96   }
97   else if(valueType == Property::ROTATION)
98   {
99     function = EvalAndCompareQuaternion;
100   }
101   else
102   {
103     function = GetFunction(valueType);
104   }
105
106   return function;
107 }
108
109 bool Step::Evaluate(const float propertyValue, PropertyNotification::RawArgumentContainer& arg)
110 {
111   const float   refValue    = arg[ARGINDEX_REF_VALUE];
112   const float   step        = arg[ARGINDEX_STEP_SIZE];
113   const int32_t currentStep = static_cast<int32_t>(arg[ARGINDEX_CURRENT_STEP]);
114   const float   distance    = (propertyValue - refValue);
115   // step is actual 1.0f / step so can multiply instead of dividing
116   const int32_t newStep = static_cast<int32_t>(floorf(distance * step));
117
118   if(newStep != currentStep)
119   {
120     // in new section
121     arg[ARGINDEX_CURRENT_STEP] = static_cast<float>(newStep);
122     return true;
123   }
124   return false;
125 }
126
127 bool Step::EvalInteger(const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg)
128 {
129   const float propertyValue = static_cast<float>(value.GetInteger());
130   return Evaluate(propertyValue, arg);
131 }
132
133 bool Step::EvalFloat(const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg)
134 {
135   const float propertyValue = value.GetFloat();
136   return Evaluate(propertyValue, arg);
137 }
138
139 bool Step::EvalVector2(const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg)
140 {
141   const float propertyValue = value.GetVector2().Length();
142   return Evaluate(propertyValue, arg);
143 }
144
145 bool Step::EvalVector3(const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg)
146 {
147   float propertyValue = value.GetVector3().Length();
148   return Evaluate(propertyValue, arg);
149 }
150
151 bool Step::EvalAndCompareVector3(const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg)
152 {
153   float propertyValue = value.GetVector3().Length();
154   bool  result        = Evaluate(propertyValue, arg);
155   if(result == false)
156   {
157     const float step = 1.0f / arg[ARGINDEX_STEP_SIZE];
158     if((fabsf(arg[ARGINDEX_FIRST_VALUE] - value.GetVector3().x) > step) || (fabsf(arg[ARGINDEX_SECOND_VALUE] - value.GetVector3().y) > step) || (fabsf(arg[ARGINDEX_THIRD_VALUE] - value.GetVector3().z) > step))
159     {
160       result = true;
161     }
162   }
163   arg[ARGINDEX_FIRST_VALUE]  = value.GetVector3().x;
164   arg[ARGINDEX_SECOND_VALUE] = value.GetVector3().y;
165   arg[ARGINDEX_THIRD_VALUE]  = value.GetVector3().z;
166   return result;
167 }
168
169 bool Step::EvalVector4(const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg)
170 {
171   const float propertyValue = value.GetVector4().Length();
172   return Evaluate(propertyValue, arg);
173 }
174
175 bool Step::EvalAndCompareQuaternion(const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg)
176 {
177   // TODO : Make some meaningfule calculation here
178
179   Quaternion propertyValue = value.GetQuaternion();
180
181   Vector4     v          = propertyValue.EulerAngles();
182   const float checkValue = v.LengthSquared();
183   bool        result     = Evaluate(checkValue, arg);
184
185   if(result == false)
186   {
187     const float step = 1.0f / arg[ARGINDEX_STEP_SIZE];
188     if((AngleDifference(arg[ARGINDEX_FIRST_VALUE], v.x, Dali::Math::PI) > step) ||
189        (AngleDifference(arg[ARGINDEX_SECOND_VALUE], v.y, Dali::Math::PI_2) > step) ||
190        (AngleDifference(arg[ARGINDEX_THIRD_VALUE], v.z, Dali::Math::PI) > step))
191     {
192       result = true;
193     }
194   }
195   arg[ARGINDEX_FIRST_VALUE]  = v.x;
196   arg[ARGINDEX_SECOND_VALUE] = v.y;
197   arg[ARGINDEX_THIRD_VALUE]  = v.z;
198   return result;
199 }
200
201 bool Step::EvalDefault(const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg)
202 {
203   return false;
204 }
205
206 } // namespace SceneGraph
207
208 } // namespace Internal
209
210 } // namespace Dali