1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_particle_bridge.h"
16
17 #include "frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
18
19 namespace OHOS::Ace::NG {
20 constexpr int32_t DISTURBANCE_FIELD_SIZE = 10;
21 constexpr int32_t STEP_0 = 0;
22 constexpr int32_t STEP_1 = 1;
23 constexpr int32_t STEP_2 = 2;
24 constexpr int32_t STEP_3 = 3;
25 constexpr int32_t STEP_4 = 4;
26 constexpr int32_t STEP_5 = 5;
27 constexpr int32_t STEP_6 = 6;
28 constexpr int32_t STEP_7 = 7;
29 constexpr int32_t STEP_8 = 8;
30 constexpr int32_t STEP_9 = 9;
31 constexpr double DEFAULT_CENTER_VALUE = 0.5;
32 constexpr int32_t DEFAULT_ANNULUS_UNIT = static_cast<int32_t>(DimensionUnit::PERCENT);
33 constexpr double DEFAULT_START_ANGLE_VALUE = 0.0;
34 constexpr double DEFAULT_END_ANGLE_VALUE = 360.0;
35
36 namespace {
ParseAnnulusRegionCenter(EcmaVM * vm,panda::Local<panda::FunctionRef> emitterPropertyObj,ArkEmitterPropertyOptions & emitterProperty)37 void ParseAnnulusRegionCenter(EcmaVM* vm, panda::Local<panda::FunctionRef> emitterPropertyObj,
38 ArkEmitterPropertyOptions& emitterProperty)
39 {
40 //parse annulusRegion center
41 auto isSetCenter = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isSetCenter"));
42 int32_t hasCenterValue = 0;
43 ArkTSUtils::ParseJsInteger(vm, isSetCenter, hasCenterValue);
44 emitterProperty.isSetCenter = hasCenterValue;
45 if (hasCenterValue == 1) {
46 auto centerXValueJs = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "centerXValue"));
47 auto centerXUnitJs = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "centerXUnit"));
48 double centerXValue = DEFAULT_CENTER_VALUE;
49 int32_t centerXUnit = DEFAULT_ANNULUS_UNIT;
50 ArkTSUtils::ParseJsDouble(vm, centerXValueJs, centerXValue);
51 ArkTSUtils::ParseJsInteger(vm, centerXUnitJs, centerXUnit);
52 ArkUIDimensionType centerX;
53 centerX.value = centerXValue;
54 centerX.units = centerXUnit;
55 emitterProperty.centerX = centerX;
56
57 auto centerYValueJs = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "centerYValue"));
58 auto centerYUnitJs = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "centerYUnit"));
59 double centerYValue = DEFAULT_CENTER_VALUE;
60 int32_t centerYUnit = DEFAULT_ANNULUS_UNIT;
61 ArkTSUtils::ParseJsDouble(vm, centerYValueJs, centerYValue);
62 ArkTSUtils::ParseJsInteger(vm, centerYUnitJs, centerYUnit);
63 ArkUIDimensionType centerY;
64 centerY.value = centerYValue;
65 centerY.units = centerYUnit;
66 emitterProperty.centerY = centerY;
67 }
68 }
69
ParseAnnulusRegionRadius(EcmaVM * vm,panda::Local<panda::FunctionRef> emitterPropertyObj,ArkEmitterPropertyOptions & emitterProperty)70 void ParseAnnulusRegionRadius(EcmaVM* vm, panda::Local<panda::FunctionRef> emitterPropertyObj,
71 ArkEmitterPropertyOptions& emitterProperty)
72 {
73 //parse annulusRegion radius
74 auto isSetInnerRadius = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isSetInnerRadius"));
75 int32_t hasInnerRadiusValue = 0;
76 ArkTSUtils::ParseJsInteger(vm, isSetInnerRadius, hasInnerRadiusValue);
77 emitterProperty.isSetInnerRadius = hasInnerRadiusValue;
78 if (hasInnerRadiusValue == 1) {
79 auto innerRadiusValueJs = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "innerRadiusValue"));
80 auto innerRadiusXUnitJs = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "innerRadiusUnit"));
81 double innerRadiusValue = 0.0;
82 int32_t innerRadiusXUnit = 0;
83 ArkTSUtils::ParseJsDouble(vm, innerRadiusValueJs, innerRadiusValue);
84 ArkTSUtils::ParseJsInteger(vm, innerRadiusXUnitJs, innerRadiusXUnit);
85 ArkUIDimensionType innerRadius;
86 innerRadius.value = innerRadiusValue;
87 innerRadius.units = innerRadiusXUnit;
88 emitterProperty.innerRadius = innerRadius;
89 }
90
91 auto isSetOuterRadius = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isSetOuterRadius"));
92 int32_t hasOuterRadiusValue = 0;
93 ArkTSUtils::ParseJsInteger(vm, isSetOuterRadius, hasOuterRadiusValue);
94 emitterProperty.isSetOuterRadius = hasOuterRadiusValue;
95 if (hasOuterRadiusValue == 1) {
96 auto outerRadiusValueJs = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "outerRadiusValue"));
97 auto outerRadiusXUnitJs = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "outerRadiusUnit"));
98 double outerRadiusValue = 0.0;
99 int32_t outerRadiusXUnit = 0;
100 ArkTSUtils::ParseJsDouble(vm, outerRadiusValueJs, outerRadiusValue);
101 ArkTSUtils::ParseJsInteger(vm, outerRadiusXUnitJs, outerRadiusXUnit);
102 ArkUIDimensionType outerRadius;
103 outerRadius.value = outerRadiusValue;
104 outerRadius.units = outerRadiusXUnit;
105 emitterProperty.outerRadius = outerRadius;
106 }
107 }
108
ParseAnnulusRegionAngle(EcmaVM * vm,panda::Local<panda::FunctionRef> emitterPropertyObj,ArkEmitterPropertyOptions & emitterProperty)109 void ParseAnnulusRegionAngle(EcmaVM* vm, panda::Local<panda::FunctionRef> emitterPropertyObj,
110 ArkEmitterPropertyOptions& emitterProperty)
111 {
112 //parse annulusRegion angle
113 auto isSetStartAngle = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isSetStartAngle"));
114 int32_t hasStartAngleValue = 0;
115 ArkTSUtils::ParseJsInteger(vm, isSetStartAngle, hasStartAngleValue);
116 emitterProperty.isSetStartAngle = hasStartAngleValue;
117 if (hasStartAngleValue == 1) {
118 auto startAngle = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "startAngle"));
119 double startAngleValue = DEFAULT_START_ANGLE_VALUE;
120 ArkTSUtils::ParseJsDouble(vm, startAngle, startAngleValue);
121 emitterProperty.startAngle = startAngleValue;
122 }
123
124 auto isSetEndAngle = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isSetEndAngle"));
125 int32_t hasEndAngleValue = 0;
126 ArkTSUtils::ParseJsInteger(vm, isSetEndAngle, hasEndAngleValue);
127 emitterProperty.isSetEndAngle = hasEndAngleValue;
128 if (hasEndAngleValue == 1) {
129 auto endAngle = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "endAngle"));
130 double endAngleValue = DEFAULT_END_ANGLE_VALUE;
131 ArkTSUtils::ParseJsDouble(vm, endAngle, endAngleValue);
132 emitterProperty.endAngle = endAngleValue;
133 }
134 }
135
ParseEmitterAnnulusRegion(EcmaVM * vm,panda::Local<panda::FunctionRef> emitterPropertyObj,ArkEmitterPropertyOptions & emitterProperty)136 void ParseEmitterAnnulusRegion(EcmaVM* vm, panda::Local<panda::FunctionRef> emitterPropertyObj,
137 ArkEmitterPropertyOptions& emitterProperty)
138 {
139 //parse annulusRegion
140 auto isSetAnnulusRegion = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isSetAnnulusRegion"));
141 int32_t hasAnnulusRegionValue = 0;
142 ArkTSUtils::ParseJsInteger(vm, isSetAnnulusRegion, hasAnnulusRegionValue);
143 emitterProperty.isSetAnnulusRegion = hasAnnulusRegionValue;
144 if (hasAnnulusRegionValue == 1) {
145 ParseAnnulusRegionCenter(vm, emitterPropertyObj, emitterProperty);
146 ParseAnnulusRegionRadius(vm, emitterPropertyObj, emitterProperty);
147 ParseAnnulusRegionAngle(vm, emitterPropertyObj, emitterProperty);
148 }
149 }
150
ParseEmitterPositionAndSize(EcmaVM * vm,panda::Local<panda::FunctionRef> emitterPropertyObj,ArkEmitterPropertyOptions & emitterProperty)151 void ParseEmitterPositionAndSize(EcmaVM* vm, panda::Local<panda::FunctionRef> emitterPropertyObj,
152 ArkEmitterPropertyOptions& emitterProperty)
153 {
154 //parse position
155 auto isSetPosition = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isSetPosition"));
156 int32_t hasPositionValue = 0;
157 ArkTSUtils::ParseJsInteger(vm, isSetPosition, hasPositionValue);
158 emitterProperty.isSetPosition = hasPositionValue;
159 if (hasPositionValue == 1) {
160 auto positionX = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "positionX"));
161 double positionXValue = 0.0;
162 ArkTSUtils::ParseJsDouble(vm, positionX, positionXValue);
163 emitterProperty.positionX = positionXValue;
164 auto positionY = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "positionY"));
165 double positionYValue = 0.0;
166 ArkTSUtils::ParseJsDouble(vm, positionY, positionYValue);
167 emitterProperty.positionY = positionYValue;
168 }
169
170 //parse size
171 auto isSetSize = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isSetSize"));
172 int32_t hasSizeValue = 0;
173 ArkTSUtils::ParseJsInteger(vm, isSetSize, hasSizeValue);
174 emitterProperty.isSetSize = hasSizeValue;
175 if (hasSizeValue == 1) {
176 auto sizeWidth = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "sizeWidth"));
177 double sizeWidthValue = 0.0;
178 ArkTSUtils::ParseJsDouble(vm, sizeWidth, sizeWidthValue);
179 emitterProperty.sizeWidth = sizeWidthValue;
180 auto sizeHeight = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "sizeHeight"));
181 double sizeHeightValue = 0.0;
182 ArkTSUtils::ParseJsDouble(vm, sizeHeight, sizeHeightValue);
183 emitterProperty.sizeHeight = sizeHeightValue;
184 }
185 }
186 }
187
SetDisturbanceField(ArkUIRuntimeCallInfo * runtimeCallInfo)188 ArkUINativeModuleValue ParticleBridge::SetDisturbanceField(ArkUIRuntimeCallInfo* runtimeCallInfo)
189 {
190 EcmaVM* vm = runtimeCallInfo->GetVM();
191 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
192 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
193 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
194 Local<JSValueRef> jsValueRef = runtimeCallInfo->GetCallArgRef(1);
195 if (!jsValueRef->IsArray(vm)) {
196 return panda::JSValueRef::Undefined(vm);
197 }
198 auto array = panda::Local<panda::ArrayRef>(jsValueRef);
199 auto length = array->Length(vm);
200 std::vector<ArkUIInt32orFloat32> dataVector;
201 dataVector.resize(length);
202 for (uint32_t index = 0; index < length / DISTURBANCE_FIELD_SIZE; index++) {
203 Local<JSValueRef> strength = panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_0);
204 int32_t strengthValue = 0;
205 ArkTSUtils::ParseJsInteger(vm, strength, strengthValue);
206 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_0].f32 = static_cast<float>(strengthValue);
207 Local<JSValueRef> shape = panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_1);
208 int32_t shapeValue = 0;
209 ArkTSUtils::ParseJsInteger(vm, shape, shapeValue);
210 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_1].i32 = static_cast<int32_t>(shapeValue);
211 Local<JSValueRef> sizeWidth = panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_2);
212 int32_t sizeWidthValue = 0;
213 ArkTSUtils::ParseJsInteger(vm, sizeWidth, sizeWidthValue);
214 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_2].i32 = sizeWidthValue;
215 Local<JSValueRef> sizeHeight = panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_3);
216 int32_t sizeHeightValue = 0;
217 ArkTSUtils::ParseJsInteger(vm, sizeHeight, sizeHeightValue);
218 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_3].i32 = sizeHeightValue;
219 Local<JSValueRef> positionX = panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_4);
220 int32_t positionXValue = 0;
221 ArkTSUtils::ParseJsInteger(vm, positionX, positionXValue);
222 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_4].i32 = positionXValue;
223 Local<JSValueRef> positionY = panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_5);
224 int32_t positionYValue = 0;
225 ArkTSUtils::ParseJsInteger(vm, positionY, positionYValue);
226 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_5].i32 = positionYValue;
227 Local<JSValueRef> feather = panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_6);
228 int32_t featherValue = 0;
229 ArkTSUtils::ParseJsInteger(vm, feather, featherValue);
230 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_6].i32 = featherValue;
231 Local<JSValueRef> noiseScale = panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_7);
232 double noiseScaleValue = 1.0;
233 ArkTSUtils::ParseJsDouble(vm, noiseScale, noiseScaleValue);
234 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_7].f32 = static_cast<float>(noiseScaleValue);
235 Local<JSValueRef> noiseFrequency =
236 panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_8);
237 double noiseFrequencyValue = 1.0;
238 ArkTSUtils::ParseJsDouble(vm, noiseFrequency, noiseFrequencyValue);
239 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_8].f32 = static_cast<float>(noiseScaleValue);
240 Local<JSValueRef> noiseAmplitude =
241 panda::ArrayRef::GetValueAt(vm, array, index * DISTURBANCE_FIELD_SIZE + STEP_9);
242 double noiseAmplitudeValue = 1.0;
243 ArkTSUtils::ParseJsDouble(vm, noiseAmplitude, noiseAmplitudeValue);
244 dataVector[index * DISTURBANCE_FIELD_SIZE + STEP_9].f32 = static_cast<float>(noiseAmplitudeValue);
245 }
246 ArkUIInt32orFloat32* dataArray = dataVector.data();
247 GetArkUINodeModifiers()->getParticleModifier()->SetDisturbanceField(
248 nativeNode, dataArray, static_cast<ArkUI_Int32>(dataVector.size()));
249 return panda::JSValueRef::Undefined(vm);
250 }
251
ResetDisturbanceField(ArkUIRuntimeCallInfo * runtimeCallInfo)252 ArkUINativeModuleValue ParticleBridge::ResetDisturbanceField(ArkUIRuntimeCallInfo* runtimeCallInfo)
253 {
254 EcmaVM* vm = runtimeCallInfo->GetVM();
255 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
256 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
257 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
258 GetArkUINodeModifiers()->getParticleModifier()->ResetDisturbanceField(nativeNode);
259 return panda::JSValueRef::Undefined(vm);
260 }
261
SetEmitter(ArkUIRuntimeCallInfo * runtimeCallInfo)262 ArkUINativeModuleValue ParticleBridge::SetEmitter(ArkUIRuntimeCallInfo* runtimeCallInfo)
263 {
264 EcmaVM* vm = runtimeCallInfo->GetVM();
265 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
266 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
267 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
268 Local<JSValueRef> jsValueRef = runtimeCallInfo->GetCallArgRef(1);
269 if (!jsValueRef->IsArray(vm)) {
270 return panda::JSValueRef::Undefined(vm);
271 }
272 auto array = panda::Local<panda::ArrayRef>(jsValueRef);
273 auto length = array->Length(vm);
274 std::vector<ArkEmitterPropertyOptions> dataVector;
275 dataVector.resize(length);
276
277 for (uint32_t i = 0; i < length; i++) {
278 ArkEmitterPropertyOptions emitterProperty;
279 Local<JSValueRef> emitterPropertyValue = panda::ArrayRef::GetValueAt(vm, array, i);
280 if (emitterPropertyValue->IsObject(vm)) {
281 auto emitterPropertyObj = emitterPropertyValue->ToObject(vm);
282
283 //parse index
284 auto index = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "index"));
285 int32_t indexValue = 0;
286 ArkTSUtils::ParseJsInteger(vm, index, indexValue);
287 emitterProperty.index = indexValue;
288
289 //parse emitRate
290 auto isSetEmitRate = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isSetEmitRate"));
291 int32_t hasEmitRateValue = 0;
292 ArkTSUtils::ParseJsInteger(vm, isSetEmitRate, hasEmitRateValue);
293 emitterProperty.isSetEmitRate = hasEmitRateValue;
294 if (hasEmitRateValue == 1) {
295 auto emitRate = emitterPropertyObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "emitRate"));
296 int32_t emitRateValue = 0;
297 ArkTSUtils::ParseJsInteger(vm, emitRate, emitRateValue);
298 emitterProperty.emitRate = emitRateValue;
299 }
300 ParseEmitterPositionAndSize(vm, emitterPropertyObj, emitterProperty);
301 ParseEmitterAnnulusRegion(vm, emitterPropertyObj, emitterProperty);
302 }
303 dataVector.emplace_back(emitterProperty);
304 }
305 GetArkUINodeModifiers()->getParticleModifier()->SetEmitter(
306 nativeNode, dataVector.data(), static_cast<ArkUI_Int32>(dataVector.size()));
307 return panda::JSValueRef::Undefined(vm);
308 }
309
ResetEmitter(ArkUIRuntimeCallInfo * runtimeCallInfo)310 ArkUINativeModuleValue ParticleBridge::ResetEmitter(ArkUIRuntimeCallInfo* runtimeCallInfo)
311 {
312 EcmaVM* vm = runtimeCallInfo->GetVM();
313 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
314 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
315 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
316 GetArkUINodeModifiers()->getParticleModifier()->ResetEmitter(nativeNode);
317 return panda::JSValueRef::Undefined(vm);
318 }
319 } // namespace OHOS::Ace::NG