* Copyright (C) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SceneComponentImpl.h"
#include "ImageImpl.h"
#include "property_proxy/ImageProxy.h"
#include "property_proxy/PropertyProxy.h"
#include "Vec2Impl.h"
#include "property_proxy/Vec2Proxy.h"
#include "Vec3Impl.h"
#include "property_proxy/Vec3Proxy.h"
#include "Vec4Impl.h"
#include "property_proxy/Vec4Proxy.h"
namespace OHOS::Render3D::KITETS {
SceneComponentImpl::SceneComponentImpl(std::shared_ptr<SceneComponentETS> sceneComponentETS)
: sceneComponentETS_(sceneComponentETS)
{
WIDGET_LOGD("SceneComponentImpl ctor");
}
::taihe::string SceneComponentImpl::getName()
{
if (!sceneComponentETS_) {
WIDGET_LOGE("empty SceneComponentETS");
return "";
}
return ::taihe::string(sceneComponentETS_->GetName());
}
void SceneComponentImpl::setName(::taihe::string_view name)
{
if (!sceneComponentETS_) {
WIDGET_LOGE("empty SceneComponentETS");
return;
}
sceneComponentETS_->SetName(std::string(name));
}
int32_t SceneComponentImpl::getPropertySize()
{
if (!sceneComponentETS_) {
WIDGET_LOGE("empty SceneComponentETS");
return 0;
}
return sceneComponentETS_->GetPropertySize();
}
::taihe::array<::taihe::string> SceneComponentImpl::getPropertyKeys()
{
if (!sceneComponentETS_) {
WIDGET_LOGE("empty SceneComponentETS");
return {};
}
std::vector<std::string> propertyKeys = sceneComponentETS_->GetPropertyKeys();
std::vector<::taihe::string> keys;
keys.reserve(propertyKeys.size());
for (size_t i = 0; i < propertyKeys.size(); ++i) {
keys.emplace_back(::taihe::string(propertyKeys[i]));
}
return ::taihe::array_view<::taihe::string>(keys);
}
::taihe::optional<::SceneTH::ComponentPropertyType> SceneComponentImpl::getComponentProperty(::taihe::string_view key)
{
if (!sceneComponentETS_) {
WIDGET_LOGE("empty SceneComponentETS");
return std::nullopt;
}
std::shared_ptr<IPropertyProxy> propProxy = sceneComponentETS_->GetProperty(std::string(key));
if (!propProxy) {
return std::nullopt;
}
META_NS::IProperty::Ptr prop = propProxy->GetPropertyPtr();
if (!prop) {
return std::nullopt;
}
if (META_NS::IsCompatibleWith<BASE_NS::string>(prop)) {
auto proxy = static_pointer_cast<PropertyProxy<BASE_NS::string>>(propProxy);
::taihe::string result{proxy->GetValue().c_str()};
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_string(result));
}
if (META_NS::IsCompatibleWith<bool>(prop)) {
auto proxy = static_pointer_cast<PropertyProxy<bool>>(propProxy);
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_bool(proxy->GetValue()));
}
if (META_NS::IsCompatibleWith<int32_t>(prop)) {
auto proxy = static_pointer_cast<PropertyProxy<int32_t>>(propProxy);
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_i32(proxy->GetValue()));
}
if (META_NS::IsCompatibleWith<float>(prop)) {
auto proxy = static_pointer_cast<PropertyProxy<float>>(propProxy);
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_f64(proxy->GetValue()));
}
if (META_NS::IsCompatibleWith<BASE_NS::Math::Vec2>(prop)) {
auto proxy = static_pointer_cast<Vec2Proxy>(propProxy);
::SceneTypes::Vec2 result = ::taihe::make_holder<Vec2Impl, ::SceneTypes::Vec2>(proxy);
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_vec2(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::Math::Vec3>(prop)) {
auto proxy = static_pointer_cast<Vec3Proxy>(propProxy);
::SceneTypes::Vec3 result = ::taihe::make_holder<Vec3Impl, ::SceneTypes::Vec3>(proxy);
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_vec3(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::Math::Vec4>(prop)) {
auto proxy = static_pointer_cast<Vec4Proxy>(propProxy);
::SceneTypes::Vec4 result = ::taihe::make_holder<Vec4Impl, ::SceneTypes::Vec4>(proxy);
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_vec4(result));
}
if (META_NS::IsCompatibleWith<SCENE_NS::IImage::Ptr>(prop)) {
auto proxy = static_pointer_cast<ImageProxy>(propProxy);
std::shared_ptr<ImageETS> imageETS = std::make_shared<ImageETS>(proxy->GetValue());
::SceneResources::Image result = ::taihe::make_holder<ImageImpl, ::SceneResources::Image>(imageETS);
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_scene_resource(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::vector<BASE_NS::string>>(prop)) {
auto proxy = static_pointer_cast<ArrayPropertyProxy<BASE_NS::string>>(propProxy);
std::vector<::taihe::string> vec;
for (auto& s : proxy->GetValue()) {
vec.emplace_back(s.c_str());
}
::taihe::array<::taihe::string> result{vec};
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_string_arr(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::vector<bool>>(prop)) {
auto proxy = static_pointer_cast<ArrayPropertyProxy<bool>>(propProxy);
std::vector<int> vec;
for (auto& v : proxy->GetValue()) {
vec.emplace_back(v);
}
::taihe::array<bool> result{vec.data(), vec.size()};
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_bool_arr(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::vector<int32_t>>(prop)) {
auto proxy = static_pointer_cast<ArrayPropertyProxy<int32_t>>(propProxy);
std::vector<int32_t> vec;
for (auto& v : proxy->GetValue()) {
vec.emplace_back(v);
}
::taihe::array<int32_t> result{vec};
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_i32_arr(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::vector<float>>(prop)) {
auto proxy = static_pointer_cast<ArrayPropertyProxy<float>>(propProxy);
std::vector<double> vec;
for (auto& v : proxy->GetValue()) {
vec.emplace_back(v);
}
::taihe::array<double> result{vec};
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_f64_arr(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::vector<BASE_NS::Math::Vec2>>(prop)) {
auto proxy = static_pointer_cast<ArrayPropertyProxy<BASE_NS::Math::Vec2>>(propProxy);
std::vector<::SceneTypes::Vec2> vec;
for (auto& v : proxy->GetValue()) {
vec.push_back(::taihe::make_holder<Vec2Impl, ::SceneTypes::Vec2>(v));
}
::taihe::array<::SceneTypes::Vec2> result{vec};
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_vec2_arr(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::vector<BASE_NS::Math::Vec3>>(prop)) {
auto proxy = static_pointer_cast<ArrayPropertyProxy<BASE_NS::Math::Vec3>>(propProxy);
std::vector<::SceneTypes::Vec3> vec;
for (auto& v : proxy->GetValue()) {
vec.push_back(::taihe::make_holder<Vec3Impl, ::SceneTypes::Vec3>(v));
}
::taihe::array<::SceneTypes::Vec3> result{vec};
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_vec3_arr(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::vector<BASE_NS::Math::Vec4>>(prop)) {
auto proxy = static_pointer_cast<ArrayPropertyProxy<BASE_NS::Math::Vec4>>(propProxy);
std::vector<::SceneTypes::Vec4> vec;
for (auto& v : proxy->GetValue()) {
vec.push_back(::taihe::make_holder<Vec4Impl, ::SceneTypes::Vec4>(v));
}
::taihe::array<::SceneTypes::Vec4> result{vec};
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_vec4_arr(result));
}
if (META_NS::IsCompatibleWith<BASE_NS::vector<SCENE_NS::IImage::Ptr>>(prop)) {
auto proxy = static_pointer_cast<ArrayPropertyProxy<SCENE_NS::IImage::Ptr>>(propProxy);
std::vector<::SceneResources::SceneResource> vec;
for (auto& v : proxy->GetValue()) {
std::shared_ptr<ImageETS> imageETS = std::make_shared<ImageETS>(v);
auto imageTH = ::taihe::make_holder<ImageImpl, ::SceneResources::Image>(imageETS);
vec.push_back(static_cast<::SceneResources::SceneResource>(imageTH));
}
::taihe::array<::SceneResources::SceneResource> result{vec};
return ::taihe::optional<::SceneTH::ComponentPropertyType>(
std::in_place, ::SceneTH::ComponentPropertyType::make_t_scene_resource_arr(result));
}
auto any = META_NS::GetInternalAny(prop);
WIDGET_LOGE("Unsupported property type [%{public}s]", any ? any->GetTypeIdString().c_str() : "<Unknown>");
return std::nullopt;
}
void SceneComponentImpl::SetPropertyFromSceneResource(
const std::string& name, const ::SceneResources::SceneResource& sr)
{
taihe::optional<int64_t> srOp = sr->getImpl();
if (!srOp) {
WIDGET_LOGE("taihe optional does not hold impl");
return;
}
SceneResourceImpl* srImpl = reinterpret_cast<SceneResourceImpl*>(srOp.value());
if (!srImpl) {
WIDGET_LOGE("failed to set impl from taihe");
return;
}
auto srType = srImpl->getResourceType();
switch (srType.get_key()) {
case ::SceneResources::SceneResourceType::key_t::NODE:
break;
case ::SceneResources::SceneResourceType::key_t::ENVIRONMENT:
break;
case ::SceneResources::SceneResourceType::key_t::MATERIAL:
break;
case ::SceneResources::SceneResourceType::key_t::MESH:
break;
case ::SceneResources::SceneResourceType::key_t::ANIMATION:
break;
case ::SceneResources::SceneResourceType::key_t::SHADER:
break;
case ::SceneResources::SceneResourceType::key_t::IMAGE: {
std::shared_ptr<ImageETS> imgETS = static_cast<ImageImpl*>(srImpl)->getInternalImage();
sceneComponentETS_->SetProperty(name, imgETS->GetNativeImage());
break;
}
case ::SceneResources::SceneResourceType::key_t::MESH_RESOURCE:
break;
default:
WIDGET_LOGE("no match SceneResourceType");
break;
}
}
namespace {
std::optional<BASE_NS::vector<SCENE_NS::IImage::Ptr>> BuildImageArray(
const ::taihe::array<::SceneResources::SceneResource>& srArray)
{
BASE_NS::vector<SCENE_NS::IImage::Ptr> arr;
for (size_t i = 0; i < srArray.size(); ++i) {
taihe::optional<int64_t> srOp = srArray[i]->getImpl();
if (!srOp.has_value()) {
WIDGET_LOGE("array element at index %{public}zu does not hold impl", i);
arr.push_back(nullptr);
continue;
}
SceneResourceImpl* srImpl = reinterpret_cast<SceneResourceImpl*>(srOp.value());
if (!srImpl) {
WIDGET_LOGE("failed to set impl from taihe at index %{public}zu", i);
arr.push_back(nullptr);
continue;
}
auto currentType = srImpl->getResourceType();
if (currentType.get_key() != ::SceneResources::SceneResourceType::key_t::IMAGE) {
WIDGET_LOGE("array element at index %{public}zu is not IMAGE type", i);
return std::nullopt;
}
std::shared_ptr<ImageETS> imgETS = static_cast<ImageImpl*>(srImpl)->getInternalImage();
arr.push_back(imgETS->GetNativeImage());
}
return arr;
}
}
void SceneComponentImpl::SetArrayPropertyFromSceneResource(
const std::string& name, const ::taihe::array<::SceneResources::SceneResource>& srArray)
{
if (srArray.size() == 0) {
sceneComponentETS_->ClearArrayProperty(name);
return;
}
auto srType = srArray[0]->getResourceType();
if (srType.get_key() == ::SceneResources::SceneResourceType::key_t::IMAGE) {
auto arr = BuildImageArray(srArray);
if (arr.has_value()) {
sceneComponentETS_->SetArrayProperty(name, arr.value());
}
} else {
WIDGET_LOGE("SceneResourceType [%{public}d] is not supported yet", static_cast<int>(srType.get_key()));
}
}
void SceneComponentImpl::setComponentProperty(::taihe::string_view key, ::SceneTH::ComponentPropertyType const& value)
{
if (!sceneComponentETS_) {
WIDGET_LOGE("empty SceneComponentETS");
return;
}
const std::string name = std::string(key);
if (value.holds_t_string()) {
std::string strValue(value.get_t_string_ref());
sceneComponentETS_->SetProperty(name, BASE_NS::string(strValue.c_str()));
} else if (value.holds_t_bool()) {
sceneComponentETS_->SetProperty(name, value.get_t_bool_ref());
} else if (value.holds_t_i32()) {
sceneComponentETS_->SetProperty(name, value.get_t_i32_ref());
} else if (value.holds_t_f64()) {
sceneComponentETS_->SetProperty(name, static_cast<float>(value.get_t_f64_ref()));
} else if (value.holds_t_vec2()) {
::SceneTypes::Vec2 vec2 = value.get_t_vec2_ref();
sceneComponentETS_->SetProperty(name, BASE_NS::Math::Vec2(vec2->getX(), vec2->getY()));
} else if (value.holds_t_vec3()) {
::SceneTypes::Vec3 vec3 = value.get_t_vec3_ref();
sceneComponentETS_->SetProperty(name, BASE_NS::Math::Vec3(vec3->getX(), vec3->getY(), vec3->getZ()));
} else if (value.holds_t_vec4()) {
::SceneTypes::Vec4 vec4 = value.get_t_vec4_ref();
sceneComponentETS_->SetProperty(
name, BASE_NS::Math::Vec4(vec4->getX(), vec4->getY(), vec4->getZ(), vec4->getW()));
} else if (value.holds_t_scene_resource()) {
SetPropertyFromSceneResource(name, value.get_t_scene_resource_ref());
} else if (value.holds_t_string_arr()) {
BASE_NS::vector<BASE_NS::string> arr;
for (auto& v : value.get_t_string_arr_ref()) {
arr.emplace_back(v.c_str());
}
sceneComponentETS_->SetArrayProperty(name, arr);
} else if (value.holds_t_bool_arr()) {
BASE_NS::vector<bool> arr;
for (auto& v : value.get_t_bool_arr_ref()) {
arr.emplace_back(v);
}
sceneComponentETS_->SetArrayProperty(name, arr);
} else if (value.holds_t_i32_arr()) {
BASE_NS::vector<int> arr;
for (auto& v : value.get_t_i32_arr_ref()) {
arr.emplace_back(v);
}
sceneComponentETS_->SetArrayProperty(name, arr);
} else if (value.holds_t_f64_arr()) {
BASE_NS::vector<float> arr;
for (auto& v : value.get_t_f64_arr_ref()) {
arr.emplace_back(v);
}
sceneComponentETS_->SetArrayProperty(name, arr);
} else if (value.holds_t_vec2_arr()) {
BASE_NS::vector<BASE_NS::Math::Vec2> arr;
for (auto& v : value.get_t_vec2_arr_ref()) {
arr.emplace_back(v->getX(), v->getY());
}
sceneComponentETS_->SetArrayProperty(name, arr);
} else if (value.holds_t_vec3_arr()) {
BASE_NS::vector<BASE_NS::Math::Vec3> arr;
for (auto& v : value.get_t_vec3_arr_ref()) {
arr.emplace_back(v->getX(), v->getY(), v->getZ());
}
sceneComponentETS_->SetArrayProperty(name, arr);
} else if (value.holds_t_vec4_arr()) {
BASE_NS::vector<BASE_NS::Math::Vec4> arr;
for (auto& v : value.get_t_vec4_arr_ref()) {
arr.emplace_back(v->getX(), v->getY(), v->getZ(), v->getW());
}
sceneComponentETS_->SetArrayProperty(name, arr);
} else if (value.holds_t_scene_resource_arr()) {
SetArrayPropertyFromSceneResource(name, value.get_t_scene_resource_arr_ref());
}
}
}