* 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 "SceneETS.h"
#include <meta/api/make_callback.h>
#include <meta/interface/animation/intf_animation.h>
#include <meta/interface/intf_object_context.h>
#include <meta/interface/intf_task_queue.h>
#include <meta/interface/intf_task_queue_registry.h>
#include <meta/interface/property/construct_property.h>
#include <meta/interface/property/property_events.h>
#include <scene/ext/intf_render_resource.h>
#include <scene/ext/util.h>
#include <scene/interface/intf_light.h>
#include <scene/interface/intf_material.h>
#include <scene/interface/intf_mesh_resource.h>
#include <scene/interface/intf_node_import.h>
#include <scene/interface/intf_render_configuration.h>
#include <scene/interface/intf_render_context.h>
#include <scene/interface/intf_scene.h>
#include <scene/interface/resource/intf_render_resource_manager.h>
#include <core/image/intf_image_loader_manager.h>
#include <core/intf_engine.h>
#include <render/device/intf_gpu_resource_manager.h>
#include <render/intf_render_context.h>
#include "3d_widget_adapter_log.h"
#include "scene_adapter/scene_adapter.h"
#include <scene/ext/intf_ecs_context.h>
#include <scene/ext/intf_ecs_object.h>
#include <scene/ext/intf_ecs_object_access.h>
#include <3d/ecs/components/name_component.h>
#include <3d/ecs/components/node_component.h>
namespace {
void Fixnames(SCENE_NS::IScene::Ptr scene)
{
struct rr {
uint32_t id_ = 1;
BASE_NS::unordered_map<CORE_NS::Entity, BASE_NS::vector<CORE_NS::Entity>> tree;
BASE_NS::vector<CORE_NS::Entity> roots;
CORE3D_NS::INodeComponentManager* cm;
CORE3D_NS::INameComponentManager* nm;
explicit rr(SCENE_NS::IScene::Ptr scene)
{
CORE_NS::IEcs::Ptr ecs = scene->GetInternalScene()->GetEcsContext().GetNativeEcs();
cm = CORE_NS::GetManager<CORE3D_NS::INodeComponentManager>(*ecs);
nm = CORE_NS::GetManager<CORE3D_NS::INameComponentManager>(*ecs);
fix();
}
void scan()
{
const auto count = cm->GetComponentCount();
tree.reserve(cm->GetComponentCount());
for (auto i = 0; i < count; i++) {
auto enti = cm->GetEntity(i);
tree.insert({enti, {}});
auto parent = cm->Get(i).parent;
if (CORE_NS::EntityUtil::IsValid(parent)) {
tree[parent].push_back(enti);
} else {
roots.push_back(enti);
}
}
}
void recurse(CORE_NS::Entity id)
{
CORE3D_NS::NameComponent c = nm->Get(id);
if (c.name.empty()) {
c.name = "Unnamed Node ";
c.name += BASE_NS::to_string(id_++);
nm->Set(id, c);
}
for (auto c : tree[id]) {
recurse(c);
}
}
void fix()
{
scan();
for (auto i : roots) {
id_ = 1;
for (auto c : tree[i]) {
recurse(c);
}
}
}
} r(scene);
}
using IntfPtr = BASE_NS::shared_ptr<CORE_NS::IInterface>;
using IntfWeakPtr = BASE_NS::weak_ptr<CORE_NS::IInterface>;
}
namespace OHOS::Render3D {
SceneETS::SceneETS()
{
resources_ = RenderContextETS::GetInstance().GetResources();
}
SceneETS::SceneETS(SCENE_NS::IScene::Ptr scene, std::shared_ptr<OHOS::Render3D::ISceneAdapter> sceneAdapter)
: scene_(scene), sceneAdapter_(sceneAdapter)
{
if (!scene_ || !sceneAdapter_) {
WIDGET_LOGE("invalid scene or sceneAdapter");
return;
}
SCENE_NS::IEnvironment::Ptr environment;
if (auto rc = scene_->RenderConfiguration()->GetValue()) {
environment = rc->Environment()->GetValue();
}
if (environment) {
environmentETS_ = std::make_shared<EnvironmentETS>(environment, scene_, "DefaultEnv");
} else {
WIDGET_LOGE("no environment in scene");
}
resources_ = RenderContextETS::GetInstance().GetResources();
LoadRenderConfiguration(scene_);
}
SceneETS::~SceneETS()
{
Destroy();
}
void SceneETS::AddScene(META_NS::IObjectRegistry* obr, SCENE_NS::IScene::Ptr scene)
{
if (!obr) {
return;
}
auto params = interface_pointer_cast<META_NS::IMetadata>(obr->GetDefaultObjectContext());
if (!params) {
return;
}
auto duh = params->GetArrayProperty<IntfWeakPtr>("Scenes");
if (!duh) {
return;
}
duh->AddValue(interface_pointer_cast<CORE_NS::IInterface>(scene));
}
SCENE_NS::ISceneManager::Ptr SceneETS::CreateSceneManager(BASE_NS::string_view uri)
{
auto& objRegistry = META_NS::GetObjectRegistry();
auto objContext = interface_pointer_cast<META_NS::IMetadata>(objRegistry.GetDefaultObjectContext());
if (uri.ends_with(".scene2")) {
const auto renderContext = SCENE_NS::GetBuildArg<SCENE_NS::IRenderContext::Ptr>(objContext, "RenderContext");
if (!renderContext || !renderContext->GetRenderer()) {
WIDGET_LOGE("Unable to configure file resource manager for loading scene files: render context missing");
return {};
}
auto& fileManager = renderContext->GetRenderer()->GetEngine().GetFileManager();
fileManager.RegisterPath("project", ExtractPathToProject(uri), true);
}
return objRegistry.Create<SCENE_NS::ISceneManager>(SCENE_NS::ClassId::SceneManager, objContext);
}
BASE_NS::string_view SceneETS::ExtractPathToProject(BASE_NS::string_view uri)
{
const auto secondToLastSlashPos = uri.find_last_of('/', uri.find_last_of('/') - 1);
return uri.substr(0, secondToLastSlashPos);
}
bool SceneETS::Load(std::string uri, SceneLoadParams sceneLoadParams)
{
if (uri.empty()) {
uri = "scene://empty";
}
for (;;) {
auto t = uri.find_first_of('\\');
if (t == std::string::npos) {
break;
}
uri[t] = '/';
}
auto engineThreadTask = [this](SCENE_NS::IScene::Ptr scene) mutable {
if (!scene || !scene->RenderConfiguration()->GetValue()) {
return;
}
scene->GetInternalScene()->GetEcsContext().CreateUnnamedRootNode();
Fixnames(scene);
auto& obr = META_NS::GetObjectRegistry();
AddScene(&obr, scene);
scene_ = scene;
LoadRenderConfiguration(scene);
auto curenv = GetEnvironment();
if (!curenv) {
auto res = CreateEnvironment("DefaultEnv", "");
if (res) {
res.value->SetBackgroundType(
EnvironmentETS::EnvironmentBackgroundType::BACKGROUND_IMAGE);
SetEnvironment(res.value);
}
}
for (auto&& c : scene->GetCameras().GetResult()) {
c->RenderingPipeline()->SetValue(SCENE_NS::CameraPipeline::FORWARD);
c->ColorTargetCustomization()->SetValue({SCENE_NS::ColorFormat{BASE_NS::BASE_FORMAT_R16G16B16A16_SFLOAT}});
}
#ifdef __SCENE_ADAPTER__
auto sceneAdapter = std::make_shared<OHOS::Render3D::SceneAdapter>();
sceneAdapter->SetSceneObj(interface_pointer_cast<META_NS::IObject>(scene));
sceneAdapter_ = sceneAdapter;
#endif
};
auto sceneManager = CreateSceneManager(uri.c_str());
if (!sceneManager) {
CORE_LOG_E("Creating scene manager failed");
return false;
}
auto params = interface_pointer_cast<META_NS::IMetadata>(META_NS::GetObjectRegistry().GetDefaultObjectContext());
auto engineQ = META_NS::GetTaskQueueRegistry().GetTaskQueue(ENGINE_THREAD);
sceneManager->CreateScene(uri.c_str(), sceneLoadParams.offset)
.Then(BASE_NS::move(engineThreadTask), engineQ)
.Wait();
return true;
}
std::vector<std::shared_ptr<AnimationETS>> SceneETS::GetAnimations()
{
if (animations_) {
return animations_.value();
}
ExecSyncTask([this]() {
nativeAnimations_ = scene_->GetAnimations().GetResult();
return META_NS::IAny::Ptr{};
});
std::vector<std::shared_ptr<AnimationETS>> animationETSlist;
for (const auto& animationRef : nativeAnimations_) {
animationETSlist.emplace_back(std::make_shared<AnimationETS>(animationRef, scene_));
}
animations_ = std::move(animationETSlist);
return animations_.value();
}
std::shared_ptr<NodeETS> SceneETS::GetNodeByPath(const std::string& path)
{
std::shared_ptr<NodeETS> rootNode = GetRoot().value;
if (!rootNode) {
return nullptr;
}
std::string realPath = path;
const std::string rootName = rootNode->GetName();
if (realPath.empty() || (realPath == std::string_view("/")) || (realPath == rootName)) {
return rootNode;
}
size_t pos = 0;
if (realPath[0] != '/') {
pos = realPath.find('/', 0);
std::string_view step = realPath.substr(0, pos);
if (!step.empty() && (step != rootName)) {
return nullptr;
}
}
if (pos != std::string_view::npos) {
realPath = realPath.substr(pos + 1);
}
if (realPath.empty()) {
return rootNode;
}
return rootNode->GetNodeByPath(realPath);
}
std::shared_ptr<NodeETS> SceneETS::CloneNode(
std::shared_ptr<NodeETS> node, std::shared_ptr<NodeETS> parent, const std::string& name)
{
if (!scene_ || !node || !parent) {
CORE_LOG_E("empty scene/node/parent");
return nullptr;
}
if (SCENE_NS::INode::Ptr parentNode = parent->GetInternalNode()) {
if (SCENE_NS::INode::Ptr n = node->GetInternalNode()) {
auto clone = n->Clone(name.c_str(), parentNode).GetResult();
if (!clone) {
return nullptr;
}
return NodeETS::FromNative(clone);
}
}
return nullptr;
}
InvokeReturn<std::shared_ptr<NodeETS>> SceneETS::CreateNode(const std::string& path)
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<NodeETS>>(nullptr, "Invalid scene");
}
if (auto node = scene_->CreateNode(path.c_str(), SCENE_NS::ClassId::Node).GetResult()) {
auto nodePtr = std::make_shared<NodeETS>(NodeETS::NodeType::NODE, node);
nodePtr->Attached(true);
return InvokeReturn(nodePtr);
} else {
return InvokeReturn<std::shared_ptr<NodeETS>>(
nullptr, "Node creation failed. Is the given node path unique and valid?");
}
}
InvokeReturn<std::shared_ptr<NodeETS>> SceneETS::GetRoot()
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<NodeETS>>(nullptr, "Invalid scene");
}
auto rootNode = std::make_shared<NodeETS>(NodeETS::NodeType::NODE, scene_->GetRootNode().GetResult());
rootNode->Attached(true);
return InvokeReturn(rootNode);
}
InvokeReturn<std::shared_ptr<GeometryETS>> SceneETS::CreateGeometry(
const std::string& path, const std::shared_ptr<MeshResourceETS>& mr)
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<GeometryETS>>(nullptr, "Invalid scene");
}
auto meshNode = scene_->CreateNode(path.c_str(), SCENE_NS::ClassId::MeshNode).GetResult();
if (auto access = interface_pointer_cast<SCENE_NS::IMeshAccess>(meshNode)) {
const auto mesh = mr->CreateMesh(scene_);
access->SetMesh(mesh).GetResult();
auto nodeETS = GeometryETS::FromJS(meshNode, mr->GetName(), mr->GetUri());
nodeETS->Attached(true);
return InvokeReturn<std::shared_ptr<GeometryETS>>(nodeETS);
} else {
return InvokeReturn<std::shared_ptr<GeometryETS>>(
nullptr, "Geometry node creation failed. Is the given node path unique and valid?");
}
}
InvokeReturn<std::shared_ptr<CameraETS>> SceneETS::CreateCamera(const std::string& path, uint32_t pipeline, bool msaa)
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<CameraETS>>(nullptr, "Invalid scene");
}
const auto camera = scene_->CreateNode<SCENE_NS::ICamera>(path.c_str(), SCENE_NS::ClassId::CameraNode).GetResult();
if (!camera) {
return InvokeReturn<std::shared_ptr<CameraETS>>(nullptr, "Create camera error");
}
camera->SetActive(false);
camera->ColorTargetCustomization()->SetValue({SCENE_NS::ColorFormat{BASE_NS::BASE_FORMAT_R16G16B16A16_SFLOAT}});
camera->RenderingPipeline()->SetValue(SCENE_NS::CameraPipeline(pipeline));
auto cameraETS = std::make_shared<CameraETS>(camera);
cameraETS->Attached(true);
cameraETS->SetMSAA(msaa);
return InvokeReturn(cameraETS);
}
InvokeReturn<std::shared_ptr<LightETS>> SceneETS::CreateLight(
const std::string& name, const std::string& path, LightETS::LightType lightType)
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<LightETS>>(nullptr, "Invalid scene");
}
if (auto nativeLight = interface_pointer_cast<SCENE_NS::ILight>(
scene_->CreateNode(path.c_str(), SCENE_NS::ClassId::LightNode).GetResult())) {
return InvokeReturn(std::make_shared<LightETS>(nativeLight, lightType, name, path));
} else {
return InvokeReturn<std::shared_ptr<LightETS>>(nullptr, "Light creation failed");
}
}
InvokeReturn<std::shared_ptr<MaterialETS>> SceneETS::CreateMaterial(
const std::string& name, const std::string& uri, const MaterialETS::MaterialType& materialType)
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<MaterialETS>>(nullptr, "Invalid scene");
}
SCENE_NS::IMaterial::Ptr mat;
if (materialType == MaterialETS::MaterialType::OCCLUSION) {
mat = scene_->CreateObject<SCENE_NS::IMaterial>(SCENE_NS::ClassId::OcclusionMaterial).GetResult();
} else {
mat = scene_->CreateObject<SCENE_NS::IMaterial>(SCENE_NS::ClassId::Material).GetResult();
}
if (mat) {
if (materialType == MaterialETS::MaterialType::SHADER) {
META_NS::SetValue(mat->Type(), SCENE_NS::MaterialType::CUSTOM);
} else if (materialType == MaterialETS::MaterialType::UNLIT) {
META_NS::SetValue(mat->Type(), SCENE_NS::MaterialType::UNLIT);
} else if (materialType == MaterialETS::MaterialType::UNLIT_SHADOW_ALPHA) {
META_NS::SetValue(mat->Type(), SCENE_NS::MaterialType::UNLIT_SHADOW_ALPHA);
}
return InvokeReturn(std::make_shared<MaterialETS>(mat, name, uri));
} else {
return InvokeReturn<std::shared_ptr<MaterialETS>>(nullptr, "Material creation failed");
}
}
InvokeReturn<std::shared_ptr<EffectETS>> SceneETS::CreateEffect(BASE_NS::string_view effectId)
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<EffectETS>>(nullptr, "Invalid scene");
}
if (!BASE_NS::IsUidString(effectId)) {
return InvokeReturn<std::shared_ptr<EffectETS>>(nullptr, "Invalid effect id");
}
if (auto effectClassId = BASE_NS::StringToUid(effectId); effectClassId != BASE_NS::Uid{}) {
const auto effect =
interface_pointer_cast<SCENE_NS::IEffect>(META_NS::GetObjectRegistry().Create(SCENE_NS::ClassId::Effect));
if (!(effect && effect->InitializeEffect(scene_, effectClassId).GetResult())) {
return InvokeReturn<std::shared_ptr<EffectETS>>(nullptr, "Failed to instantiate Effect");
}
return InvokeReturn(std::make_shared<EffectETS>(effect));
}
return InvokeReturn<std::shared_ptr<EffectETS>>(nullptr, "Effect creation failed");
}
InvokeReturn<std::shared_ptr<EnvironmentETS>> SceneETS::CreateEnvironment(
const std::string& name, const std::string& uri)
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<EnvironmentETS>>(nullptr, "Invalid scene");
}
if (auto nativeEnv = interface_pointer_cast<SCENE_NS::IEnvironment>(
scene_->CreateObject(SCENE_NS::ClassId::Environment).GetResult())) {
return InvokeReturn(std::make_shared<EnvironmentETS>(nativeEnv, scene_, name, uri));
} else {
return InvokeReturn<std::shared_ptr<EnvironmentETS>>(nullptr, "Environment creation failed");
}
}
InvokeReturn<std::shared_ptr<EnvironmentETS>> SceneETS::GetEnvironment()
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<EnvironmentETS>>(nullptr, "Invalid scene");
}
SCENE_NS::IEnvironment::Ptr environment;
if (auto rc = scene_->RenderConfiguration()->GetValue()) {
environment = rc->Environment()->GetValue();
}
if (environment) {
if (environmentETS_ &&
environmentETS_->GetNativeObj() == interface_pointer_cast<META_NS::IObject>(environment)) {
return InvokeReturn(environmentETS_);
}
CORE_LOG_E("no environmentETS_, do not expect go here");
environmentETS_ = std::make_shared<EnvironmentETS>(environment, scene_);
return InvokeReturn(environmentETS_);
}
return InvokeReturn<std::shared_ptr<EnvironmentETS>>(nullptr, "no environment in rendercontext");
}
void SceneETS::SetEnvironment(const std::shared_ptr<EnvironmentETS> environmentETS)
{
if (!scene_) {
CORE_LOG_E("empty scene object");
return;
}
if (!environmentETS) {
CORE_LOG_E("empty environmentETS");
return;
}
if (environmentETS == environmentETS_) {
return;
}
environmentETS_ = environmentETS;
auto environment = interface_pointer_cast<SCENE_NS::IEnvironment>(environmentETS_->GetNativeObj());
if (auto rc = scene_->RenderConfiguration()->GetValue()) {
rc->Environment()->SetValue(environment);
}
}
bool SceneETS::RenderFrame(RenderParameters renderParam)
{
if (!scene_) {
CORE_LOG_E("empty scene object");
return false;
}
bool alwaysRender = renderParam.valid_ ? true : renderParam.alwaysRender_;
if (alwaysRender != currentAlwaysRender_) {
currentAlwaysRender_ = alwaysRender;
if (alwaysRender) {
scene_->SetRenderMode(SCENE_NS::RenderMode::ALWAYS);
} else {
scene_->SetRenderMode(SCENE_NS::RenderMode::IF_DIRTY);
}
}
if (auto sceneAdapter = std::static_pointer_cast<OHOS::Render3D::SceneAdapter>(sceneAdapter_)) {
sceneAdapter->SetNeedsRepaint(false);
sceneAdapter->RenderFrame(false);
return true;
} else {
return false;
}
}
std::shared_ptr<NodeETS> SceneETS::ImportNode(
const std::string& name, std::shared_ptr<NodeETS> node, std::shared_ptr<NodeETS> parent)
{
if (!scene_ || !node) {
CORE_LOG_E("empty scene/node object");
return nullptr;
}
SCENE_NS::INode::Ptr nodeObj = node->GetInternalNode();
SCENE_NS::INode::Ptr parentObj;
if (parent) {
parentObj = parent->GetInternalNode();
} else {
parentObj = scene_->GetRootNode().GetResult();
}
if (auto import = interface_cast<SCENE_NS::INodeImport>(parentObj)) {
auto importedNode = import->ImportChild(nodeObj).GetResult();
if (!name.empty()) {
if (auto named = interface_cast<META_NS::INamed>(importedNode)) {
named->Name()->SetValue(name.c_str());
}
}
ResetAnimations();
auto nodeETS = NodeETS::FromNative(importedNode);
nodeETS->Attached(true);
return nodeETS;
}
return nullptr;
}
std::shared_ptr<NodeETS> SceneETS::ImportScene(
const std::string& name, std::shared_ptr<SceneETS> scene, std::shared_ptr<NodeETS> parent)
{
if (!scene_ || !scene) {
CORE_LOG_E("empty scene/importedScene object");
return nullptr;
}
SCENE_NS::IScene::Ptr extScene = scene->GetNativeScene();
SCENE_NS::INode::Ptr parentObj;
if (parent) {
parentObj = parent->GetInternalNode();
} else {
parentObj = scene_->GetRootNode().GetResult();
}
if (auto import = interface_cast<SCENE_NS::INodeImport>(parentObj)) {
SCENE_NS::INodeImport::ImportOptions opts;
opts.nodeName = name.c_str();
opts.shareResources = false;
auto importedNode = import->ImportChildScene(extScene, opts).GetResult();
ResetAnimations();
auto nodeETS = NodeETS::FromNative(importedNode);
nodeETS->Attached(true);
return nodeETS;
}
return nullptr;
}
InvokeReturn<std::shared_ptr<SceneComponentETS>> SceneETS::CreateComponent(
std::shared_ptr<NodeETS> node, const std::string& name)
{
if (!scene_ || !node || name.empty()) {
return InvokeReturn<std::shared_ptr<SceneComponentETS>>(nullptr, "Invalid scene or input");
}
auto nodeObj = node->GetInternalNode();
if (auto comp = scene_->CreateComponent(nodeObj, name.c_str()).GetResult()) {
return InvokeReturn(std::make_shared<SceneComponentETS>(comp, name));
}
return InvokeReturn<std::shared_ptr<SceneComponentETS>>(nullptr, "CreateComponent failed");
}
void SceneETS::LoadRenderConfiguration(SCENE_NS::IScene::Ptr scene)
{
Scene::IRenderConfiguration::Ptr rsScenePtr = scene->RenderConfiguration()->GetValue();
if (rsScenePtr) {
auto rcETS = CreateRenderConfiguration(rsScenePtr);
renderConfigurationETS_ = rcETS.value;
} else {
WIDGET_LOGE("RenderConfigurationETS load failed");
}
}
InvokeReturn<std::shared_ptr<RenderConfigurationETS>> SceneETS::CreateRenderConfiguration(
SCENE_NS::IRenderConfiguration::Ptr& rc)
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<RenderConfigurationETS>>(nullptr, "Invalid scene");
}
return InvokeReturn(std::make_shared<RenderConfigurationETS>(rc, scene_));
}
InvokeReturn<std::shared_ptr<RenderConfigurationETS>> SceneETS::GetRenderConfiguration()
{
if (!scene_) {
return InvokeReturn<std::shared_ptr<RenderConfigurationETS>>(nullptr, "Invalid scene");
}
SCENE_NS::IRenderConfiguration::Ptr rc = scene_->RenderConfiguration()->GetValue();
if (rc) {
if (renderConfigurationETS_ &&
renderConfigurationETS_->GetNativeObj() == interface_pointer_cast<META_NS::IObject>(rc)) {
return InvokeReturn(renderConfigurationETS_);
}
CORE_LOG_E("no renderConfigurationETS_, do not expect go here");
renderConfigurationETS_ = std::make_shared<RenderConfigurationETS>(rc, scene_);
return InvokeReturn(renderConfigurationETS_);
}
return InvokeReturn<std::shared_ptr<RenderConfigurationETS>>(nullptr, "no rc in render context");
}
InvokeReturn<std::shared_ptr<SceneComponentETS>> SceneETS::GetComponent(
std::shared_ptr<NodeETS> node, const std::string& name)
{
if (!scene_ || !node || name.empty()) {
return InvokeReturn<std::shared_ptr<SceneComponentETS>>(nullptr, "Invalid scene or input");
}
auto nodeObj = node->GetInternalNode();
if (auto attach = interface_pointer_cast<META_NS::IAttach>(nodeObj)) {
if (auto cont = attach->GetAttachmentContainer(false)) {
if (auto comp = cont->FindByName<SCENE_NS::IComponent>(name.c_str())) {
return InvokeReturn(std::make_shared<SceneComponentETS>(comp, name));
}
}
}
return InvokeReturn<std::shared_ptr<SceneComponentETS>>(nullptr, "GetComponent failed");
}
void SceneETS::Destroy()
{
if (disposed_) {
return;
}
disposed_ = true;
#ifdef __SCENE_ADAPTER__
if (auto sceneAdapter = std::static_pointer_cast<OHOS::Render3D::SceneAdapter>(sceneAdapter_)) {
sceneAdapter->Deinit();
}
sceneAdapter_.reset();
#endif
environmentETS_.reset();
scene_.reset();
resources_.reset();
ResetAnimations();
}
void SceneETS::ResetAnimations()
{
if (animations_) {
animations_.value().clear();
}
animations_ = std::nullopt;
nativeAnimations_.clear();
}
}