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 "BloomJS.h"
16
17 #include "BaseObjectJS.h"
18
19 template<napi_value (BloomConfiguration::*F)(NapiApi::FunctionContext<>&)>
Method(napi_env env,napi_callback_info info)20 napi_value BloomConfiguration::Method(napi_env env, napi_callback_info info)
21 {
22 NapiApi::FunctionContext fc(env, info);
23 if (fc && fc.This()) {
24 BloomConfiguration* impl = nullptr;
25 napi_unwrap(fc.GetEnv(), fc.This().ToNapiValue(), (void**)&impl);
26 if (impl) {
27 return (impl->*F)(fc);
28 }
29 }
30 return fc.GetUndefined();
31 }
32
33 template<napi_value (BloomConfiguration::*F)(NapiApi::FunctionContext<>&)>
Getter(napi_env env,napi_callback_info info)34 napi_value BloomConfiguration::Getter(napi_env env, napi_callback_info info)
35 {
36 NapiApi::FunctionContext fc(env, info);
37 if (fc && fc.This()) {
38 BloomConfiguration* impl = nullptr;
39 napi_unwrap(fc.GetEnv(), fc.This().ToNapiValue(), (void**)&impl);
40 if (impl) {
41 return (impl->*F)(fc);
42 }
43 }
44 return fc.GetUndefined();
45 }
46 template<typename Type, void (BloomConfiguration::*F)(NapiApi::FunctionContext<Type>&)>
Setter(napi_env env,napi_callback_info info)47 inline napi_value BloomConfiguration::Setter(napi_env env, napi_callback_info info)
48 {
49 NapiApi::FunctionContext<Type> fc(env, info);
50 if (fc && fc.This()) {
51 BloomConfiguration* impl = nullptr;
52 napi_unwrap(fc.GetEnv(), fc.This().ToNapiValue(), (void**)&impl);
53 if (impl) {
54 (impl->*F)(fc);
55 }
56 }
57 return fc.GetUndefined();
58 };
59
BloomConfiguration()60 BloomConfiguration::BloomConfiguration() {}
61
Detach()62 void BloomConfiguration::Detach()
63 {
64 if (bloom_ || postproc_) {
65 SCENE_NS::IBloom::WeakPtr tmpb = bloom_;
66 SCENE_NS::IPostProcess::WeakPtr tmpp = postproc_;
67 if (bloom_) {
68 bloom_.reset(); // release it.
69 //* can verify if the object actually died by trying to lock it.
70 if (!tmpb.lock()) {
71 LOG_V("bloom instance destroyed");
72 }
73 }
74 if (postproc_) {
75 postproc_.reset(); // release it.
76 if (!tmpp.lock()) {
77 LOG_V("postprocess instance destroyed");
78 }
79 }
80 }
81 }
~BloomConfiguration()82 BloomConfiguration::~BloomConfiguration()
83 {
84 if (bloom_ || postproc_) {
85 Detach();
86 }
87 }
SetFrom(NapiApi::Object obj)88 void BloomConfiguration::SetFrom(NapiApi::Object obj)
89 {
90 type_ = (Type)obj.Get<uint32_t>("type").valueOrDefault((uint32_t)Type::NORMAL);
91 quality_ = (Quality)obj.Get<uint32_t>("quality").valueOrDefault((uint32_t)Quality::NORMAL);
92 thresholdHard_ = obj.Get<float>("thresholdHard").valueOrDefault(1.0);
93 thresholdSoft_ = obj.Get<float>("thresholdSoft").valueOrDefault(2.0); // 2.0: param
94 scatter_ = obj.Get<float>("scatter").valueOrDefault(1.0);
95 scaleFactor_ = obj.Get<float>("scaleFactor").valueOrDefault(1.0);
96 amountCoefficient_ = obj.Get<float>("amountCoefficient").valueOrDefault(0.25f);
97 }
SetTo(NapiApi::Object obj)98 void BloomConfiguration::SetTo(NapiApi::Object obj)
99 {
100 NapiApi::Env env(obj.GetEnv());
101 obj.Set("type", env.GetNumber((uint32_t)type_));
102 obj.Set("quality", env.GetNumber((uint32_t)quality_));
103 obj.Set("thresholdHard", env.GetNumber(thresholdHard_));
104 obj.Set("thresholdSoft", env.GetNumber(thresholdSoft_));
105 obj.Set("scatter", env.GetNumber(scatter_));
106 obj.Set("scaleFactor", env.GetNumber(scaleFactor_));
107 obj.Set("amountCoefficient", env.GetNumber(amountCoefficient_));
108 }
109
SetFrom(SCENE_NS::IBloom::Ptr bloom)110 void BloomConfiguration::SetFrom(SCENE_NS::IBloom::Ptr bloom)
111 {
112 ExecSyncTask([bloom, this]() {
113 type_ = SetType(bloom->Type()->GetValue());
114 quality_ = SetQuality(bloom->Quality()->GetValue());
115 thresholdHard_ = bloom->ThresholdHard()->GetValue();
116 thresholdSoft_ = bloom->ThresholdSoft()->GetValue();
117 scatter_ = bloom->Scatter()->GetValue();
118 scaleFactor_ = bloom->ScaleFactor()->GetValue();
119 amountCoefficient_ = bloom->AmountCoefficient()->GetValue();
120 return META_NS::IAny::Ptr {};
121 });
122 }
123
SetTo(SCENE_NS::IBloom::Ptr bloom)124 void BloomConfiguration::SetTo(SCENE_NS::IBloom::Ptr bloom)
125 {
126 ExecSyncTask([bloom, this]() {
127 bloom->Enabled()->SetValue(true);
128 bloom->Type()->SetValue(GetType(type_));
129 bloom->Quality()->SetValue(GetQuality(quality_));
130 bloom->ThresholdHard()->SetValue(thresholdHard_);
131 bloom->ThresholdSoft()->SetValue(thresholdSoft_);
132 bloom->Scatter()->SetValue(scatter_);
133 bloom->ScaleFactor()->SetValue(scaleFactor_);
134 bloom->AmountCoefficient()->SetValue(amountCoefficient_);
135 if (postproc_) {
136 postproc_->Bloom()->SetValue(bloom);
137 }
138 return META_NS::IAny::Ptr {};
139 });
140 }
141
Unwrap(NapiApi::Object obj)142 BloomConfiguration* BloomConfiguration::Unwrap(NapiApi::Object obj)
143 {
144 BloomConfiguration* settings = nullptr;
145 napi_unwrap(obj.GetEnv(), obj.ToNapiValue(), (void**)&settings);
146 return settings;
147 }
148
Dispose(NapiApi::FunctionContext<> & ctx)149 napi_value BloomConfiguration::Dispose(NapiApi::FunctionContext<>& ctx)
150 {
151 Detach();
152 return ctx.GetUndefined();
153 }
154
Wrap(NapiApi::Object obj)155 NapiApi::StrongRef BloomConfiguration::Wrap(NapiApi::Object obj)
156 {
157 // wrap it..
158 auto DTOR = [](napi_env env, void* nativeObject, void* finalize) {
159 BloomConfiguration* ptr = static_cast<BloomConfiguration*>(nativeObject);
160 delete ptr;
161 };
162
163 napi_wrap(obj.GetEnv(), obj.ToNapiValue(), this, DTOR, nullptr, nullptr);
164
165 // clang-format off
166 napi_property_descriptor descs[] = {
167 { "type", nullptr, nullptr, Getter<&BloomConfiguration::GetType>,
168 Setter<uint32_t, &BloomConfiguration::SetType>, nullptr, napi_default_jsproperty, this },
169 { "quality", nullptr, nullptr, Getter<&BloomConfiguration::GetQuality>,
170 Setter<uint32_t, &BloomConfiguration::SetQuality>, nullptr, napi_default_jsproperty, this },
171 { "amountCoefficient", nullptr, nullptr, Getter<&BloomConfiguration::GetAmount>,
172 Setter<float, &BloomConfiguration::SetAmount>, nullptr, napi_default_jsproperty, this },
173 { "thresholdSoft", nullptr, nullptr, Getter<&BloomConfiguration::GetThresholdSoft>,
174 Setter<float, &BloomConfiguration::SetThresholdSoft>, nullptr, napi_default_jsproperty, this },
175 { "thresholdHard", nullptr, nullptr, Getter<&BloomConfiguration::GetThresholdHard>,
176 Setter<float, &BloomConfiguration::SetThresholdHard>, nullptr, napi_default_jsproperty, this },
177 { "scatter", nullptr, nullptr, Getter<&BloomConfiguration::GetScatter>,
178 Setter<float, &BloomConfiguration::SetScatter>, nullptr, napi_default_jsproperty, this },
179 { "scaleFactor", nullptr, nullptr, Getter<&BloomConfiguration::GetScaleFactor>,
180 Setter<float, &BloomConfiguration::SetScaleFactor>, nullptr, napi_default_jsproperty, this },
181 { "destroy", nullptr, Method<&BloomConfiguration::Dispose>,
182 nullptr, nullptr, nullptr, napi_default_jsproperty, this }
183 };
184 // clang-format on
185 napi_define_properties(obj.GetEnv(), obj.ToNapiValue(), BASE_NS::countof(descs), descs);
186
187 SetTo(obj);
188 return NapiApi::StrongRef(obj);
189 }
190
GetType(NapiApi::FunctionContext<> & ctx)191 napi_value BloomConfiguration::GetType(NapiApi::FunctionContext<>& ctx)
192 {
193 SCENE_NS::BloomType type = GetType(type_);
194 if (bloom_) {
195 type = bloom_->Type()->GetValue();
196 }
197 uint32_t tp = (uint32_t)SetType(type);
198 return ctx.GetNumber(tp);
199 }
GetQuality(NapiApi::FunctionContext<> & ctx)200 napi_value BloomConfiguration::GetQuality(NapiApi::FunctionContext<>& ctx)
201 {
202 SCENE_NS::EffectQualityType type = GetQuality(quality_);
203 if (bloom_) {
204 type = bloom_->Quality()->GetValue();
205 }
206 uint32_t tp = (uint32_t)SetQuality(type);
207 return ctx.GetNumber(tp);
208 }
209
GetScatter(NapiApi::FunctionContext<> & ctx)210 napi_value BloomConfiguration::GetScatter(NapiApi::FunctionContext<>& ctx)
211 {
212 float amount = scatter_;
213 if (bloom_) {
214 ExecSyncTask([bl = bloom_, &amount]() {
215 amount = bl->Scatter()->GetValue();
216 return META_NS::IAny::Ptr {};
217 });
218 }
219 return ctx.GetNumber(amount);
220 }
221
GetScaleFactor(NapiApi::FunctionContext<> & ctx)222 napi_value BloomConfiguration::GetScaleFactor(NapiApi::FunctionContext<>& ctx)
223 {
224 float amount = scaleFactor_;
225 if (bloom_) {
226 ExecSyncTask([bl = bloom_, &amount]() {
227 amount = bl->ScaleFactor()->GetValue();
228 return META_NS::IAny::Ptr {};
229 });
230 }
231 return ctx.GetNumber(amount);
232 }
233
GetThresholdHard(NapiApi::FunctionContext<> & ctx)234 napi_value BloomConfiguration::GetThresholdHard(NapiApi::FunctionContext<>& ctx)
235 {
236 float amount = thresholdHard_;
237 if (bloom_) {
238 amount = bloom_->ThresholdHard()->GetValue();
239 }
240 return ctx.GetNumber(amount);
241 }
242
GetThresholdSoft(NapiApi::FunctionContext<> & ctx)243 napi_value BloomConfiguration::GetThresholdSoft(NapiApi::FunctionContext<>& ctx)
244 {
245 float amount = thresholdSoft_;
246 if (bloom_) {
247 amount = bloom_->ThresholdSoft()->GetValue();
248 }
249 return ctx.GetNumber(amount);
250 }
251
GetAmount(NapiApi::FunctionContext<> & ctx)252 napi_value BloomConfiguration::GetAmount(NapiApi::FunctionContext<>& ctx)
253 {
254 float amount = amountCoefficient_;
255 if (bloom_) {
256 amount = bloom_->AmountCoefficient()->GetValue();
257 }
258 return ctx.GetNumber(amount);
259 }
SetType(NapiApi::FunctionContext<uint32_t> & ctx)260 void BloomConfiguration::SetType(NapiApi::FunctionContext<uint32_t>& ctx)
261 {
262 type_ = (BloomConfiguration::Type)ctx.Arg<0>().valueOrDefault();
263 if (bloom_) {
264 bloom_->Type()->SetValue(GetType(type_));
265 if (postproc_) {
266 postproc_->Bloom()->SetValue(bloom_);
267 }
268 }
269 }
SetQuality(NapiApi::FunctionContext<uint32_t> & ctx)270 void BloomConfiguration::SetQuality(NapiApi::FunctionContext<uint32_t>& ctx)
271 {
272 quality_ = (BloomConfiguration::Quality)ctx.Arg<0>().valueOrDefault();
273 if (bloom_) {
274 bloom_->Quality()->SetValue(GetQuality(quality_));
275 if (postproc_) {
276 postproc_->Bloom()->SetValue(bloom_);
277 }
278 }
279 }
SetThresholdHard(NapiApi::FunctionContext<float> & ctx)280 void BloomConfiguration::SetThresholdHard(NapiApi::FunctionContext<float>& ctx)
281 {
282 thresholdHard_ = ctx.Arg<0>();
283 if (bloom_) {
284 bloom_->ThresholdHard()->SetValue(thresholdHard_);
285 if (postproc_) {
286 postproc_->Bloom()->SetValue(bloom_);
287 }
288 }
289 }
SetScatter(NapiApi::FunctionContext<float> & ctx)290 void BloomConfiguration::SetScatter(NapiApi::FunctionContext<float>& ctx)
291 {
292 scatter_= ctx.Arg<0>();
293 if (bloom_) {
294 bloom_->Scatter()->SetValue(scatter_);
295 if (postproc_) {
296 postproc_->Bloom()->SetValue(bloom_);
297 }
298 }
299 }
SetScaleFactor(NapiApi::FunctionContext<float> & ctx)300 void BloomConfiguration::SetScaleFactor(NapiApi::FunctionContext<float>& ctx)
301 {
302 scaleFactor_ = ctx.Arg<0>();
303 scaleFactor_ = (scaleFactor_ < 1e-6) ? 1e-6 : scaleFactor_;
304 if (bloom_) {
305 bloom_->ScaleFactor()->SetValue(scaleFactor_);
306 if (postproc_) {
307 postproc_->Bloom()->SetValue(bloom_);
308 }
309 }
310 }
SetThresholdSoft(NapiApi::FunctionContext<float> & ctx)311 void BloomConfiguration::SetThresholdSoft(NapiApi::FunctionContext<float>& ctx)
312 {
313 thresholdSoft_ = ctx.Arg<0>();
314 if (bloom_) {
315 bloom_->ThresholdSoft()->SetValue(thresholdSoft_);
316 if (postproc_) {
317 postproc_->Bloom()->SetValue(bloom_);
318 }
319 }
320 }
SetAmount(NapiApi::FunctionContext<float> & ctx)321 void BloomConfiguration::SetAmount(NapiApi::FunctionContext<float>& ctx)
322 {
323 amountCoefficient_ = ctx.Arg<0>();
324 if (bloom_) {
325 bloom_->AmountCoefficient()->SetValue(amountCoefficient_);
326 if (postproc_) {
327 postproc_->Bloom()->SetValue(bloom_);
328 }
329 }
330 }
GetPostProc()331 SCENE_NS::IPostProcess::Ptr BloomConfiguration::GetPostProc()
332 {
333 return postproc_;
334 }
335
SetPostProc(SCENE_NS::IPostProcess::Ptr postproc)336 void BloomConfiguration::SetPostProc(SCENE_NS::IPostProcess::Ptr postproc)
337 {
338 if (!postproc) {
339 // detaching.
340 Detach();
341 return;
342 }
343 if ((postproc_) && (postproc != postproc_)) {
344 LOG_F("Invalid state");
345 return;
346 }
347 postproc_ = postproc;
348 auto bloom = postproc_->Bloom()->GetValue();
349 if ((bloom_) && (bloom != bloom_)) {
350 LOG_F("Invalid state");
351 bloom = nullptr;
352 } else {
353 if (!bloom) {
354 bloom = META_NS::GetObjectRegistry().Create<SCENE_NS::IBloom>(SCENE_NS::ClassId::Bloom);
355 }
356 bloom_ = bloom;
357 }
358 if (!bloom_) {
359 postproc_ = nullptr;
360 } else {
361 SetTo(bloom_);
362 }
363 }
364
GetQuality(BloomConfiguration::Quality bloomQualityType)365 SCENE_NS::EffectQualityType BloomConfiguration::GetQuality(BloomConfiguration::Quality bloomQualityType)
366 {
367 switch (bloomQualityType) {
368 case Quality::LOW:
369 return SCENE_NS::EffectQualityType::LOW;
370 case Quality::HIGH:
371 return SCENE_NS::EffectQualityType::HIGH;
372 case Quality::NORMAL:
373 default:
374 return SCENE_NS::EffectQualityType::NORMAL;
375 };
376 return SCENE_NS::EffectQualityType::NORMAL;
377 }
SetQuality(SCENE_NS::EffectQualityType bloomQualityType)378 BloomConfiguration::Quality BloomConfiguration::SetQuality(SCENE_NS::EffectQualityType bloomQualityType)
379 {
380 switch (bloomQualityType) {
381 case SCENE_NS::EffectQualityType::LOW:
382 return BloomConfiguration::Quality::LOW;
383 case SCENE_NS::EffectQualityType::HIGH:
384 return BloomConfiguration::Quality::HIGH;
385 case SCENE_NS::EffectQualityType::NORMAL:
386 default:
387 return BloomConfiguration::Quality::NORMAL;
388 };
389 return BloomConfiguration::Quality::NORMAL;
390 }
391
GetType(BloomConfiguration::Type bloomType)392 SCENE_NS::BloomType BloomConfiguration::GetType(BloomConfiguration::Type bloomType)
393 {
394 switch (bloomType) {
395 case Type::HORIZONTAL:
396 return SCENE_NS::BloomType::HORIZONTAL;
397 case Type::VERTICAL:
398 return SCENE_NS::BloomType::VERTICAL;
399 case Type::BILATERAL:
400 return SCENE_NS::BloomType::BILATERAL;
401 case Type::NORMAL:
402 default:
403 return SCENE_NS::BloomType::NORMAL;
404 };
405 return SCENE_NS::BloomType::NORMAL;
406 }
SetType(SCENE_NS::BloomType bloomTypeIn)407 BloomConfiguration::Type BloomConfiguration::SetType(SCENE_NS::BloomType bloomTypeIn)
408 {
409 switch (bloomTypeIn) {
410 case SCENE_NS::BloomType::HORIZONTAL:
411 return BloomConfiguration::Type::HORIZONTAL;
412 case SCENE_NS::BloomType::VERTICAL:
413 return BloomConfiguration::Type::VERTICAL;
414 case SCENE_NS::BloomType::BILATERAL:
415 return BloomConfiguration::Type::NORMAL;
416 case SCENE_NS::BloomType::NORMAL:
417 default:
418 return BloomConfiguration::Type::NORMAL;
419 };
420 return BloomConfiguration::Type::NORMAL;
421 }
422