VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
entity.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Created by Arnis Lektasuers on 18.10.2025.
5//
6#include "entity.h"
7
10
11namespace visutwin::canvas
12{
14 {
15
16 }
17
19 {
20 // Let GraphNode update _enabledInHierarchy and handle frozen state.
22
23 // Propagate enable/disable to components.
24 //
25 // A component is "active" when BOTH its own enabled flag AND the
26 // entity's hierarchy enabled state are true.
27 for (auto& [_, component] : _components) {
28 if (!component || !component->enabled()) {
29 continue;
30 }
31
32 if (enabled) {
33 component->onEnable();
34 } else {
35 component->onDisable();
36 }
37 }
38 }
39
41 {
42 if (_engine) {
43 return _engine;
44 }
45 auto* p = parent();
46 while (p) {
47 auto* entity = dynamic_cast<Entity*>(p);
48 if (entity && entity->_engine) {
49 return entity->_engine;
50 }
51 p = p->parent();
52 }
53 return nullptr;
54 }
55
57 {
58 //
59 // 1. Create new entity
60 auto* cloned = new Entity();
61
62 // Find engine: prefer direct reference, then walk hierarchy.
63 // Entities from parsers (e.g., GLB) don't have _engine set directly,
64 // but their ancestor (root node) does.
65 auto* engine = findEngine();
66 cloned->setEngine(engine);
67
68 // 2. Copy GraphNode state (JS: GraphNode._cloneInternal)
69 cloned->setName(name());
70 cloned->setLocalPosition(localPosition());
71 cloned->setLocalRotation(localRotation());
72 cloned->setLocalScale(localScale());
73 cloned->setEnabled(enabledLocal());
74 // Clone is not in hierarchy yet — _enabledInHierarchy stays false until addChild.
75
76 // 3. Clone each component via system->addComponent + cloneFrom
77 //cloneComponent(this, clone) for each component
78 for (const auto& [typeId, srcComponent] : _components) {
79 auto* system = srcComponent->system();
80
81 // Components created outside the system (e.g., by the GLB parser) may have
82 // a null system pointer. Fall back to the engine's system registry using the
83 // component's runtime type to find the correct system.
84 if (!system && engine && engine->systems()) {
85 system = engine->systems()->getByComponentTypeInfo(typeid(*srcComponent));
86 }
87 if (!system) {
88 continue;
89 }
90
91 auto newComponent = system->addComponent(cloned);
92 if (!newComponent) {
93 continue;
94 }
95
96 // Copy data from source component
97 newComponent->cloneFrom(srcComponent);
98
99 auto* raw = newComponent.get();
100 cloned->_components[typeId] = raw;
101 cloned->_componentStorage.push_back(std::move(newComponent));
102
103 if (typeId == componentTypeID<ScriptComponent>()) {
104 cloned->_script = static_cast<ScriptComponent*>(raw);
105 }
106 }
107
108 // 4. Recursively clone children
109 // for each child, child._cloneRecursively(), clone.addChild(newChild)
110 for (const auto* child : children()) {
111 const auto* childEntity = dynamic_cast<const Entity*>(child);
112 if (childEntity) {
113 auto* clonedChild = childEntity->clone();
114 cloned->addChild(clonedChild);
115 }
116 }
117
118 return cloned;
119 }
120}
Central application orchestrator managing scenes, rendering, input, and resource loading.
Definition engine.h:38
ECS entity — a GraphNode that hosts components defining its behavior.
Definition entity.h:32
Engine * engine() const
Definition entity.h:123
void onHierarchyStateChanged(bool enabled) override
Definition entity.cpp:18
Engine * findEngine() const
Definition entity.cpp:40
Entity * clone() const
Definition entity.cpp:56
const Vector3 & localScale() const
Definition graphNode.h:46
const Quaternion & localRotation() const
Definition graphNode.h:45
const Vector3 & localPosition() const
Definition graphNode.h:44
virtual void onHierarchyStateChanged(bool enabled)
const std::vector< GraphNode * > & children() const
Definition graphNode.h:79
GraphNode * parent() const
Definition graphNode.h:88
const std::string & name() const
Definition graphNode.h:35
ComponentTypeID componentTypeID()
Definition component.h:25