SleakEngine 0.1.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
GameObject.cpp
Go to the documentation of this file.
1#include <Core/GameObject.hpp>
4#include <Math/Vector.hpp>
10#include <Runtime/MeshData.hpp>
11
12namespace Sleak {
13
15 List<GameObject*> children = std::move(m_children);
16 for (size_t i = 0; i < children.GetSize(); ++i) {
17 GameObject* child = children[i];
18 if (!child) continue;
19 child->m_parent = nullptr;
20 if (!child->m_ownedByScene) delete child;
21 }
22
23 DestroyComponents();
24
25 if (m_parent) {
26 m_parent->RemoveChild(this);
27 m_parent = nullptr;
28 }
29 }
30
32 if (bIsInitialized) return;
33 bIsInitialized = true;
34
35 for (size_t i = 0; i < Components.GetSize(); ++i) {
36 if (Components[i]) InitializeComponent(Components[i].get());
37 }
38
39 for (size_t i = 0; i < m_children.GetSize(); ++i) {
40 if (m_children[i]) m_children[i]->Initialize();
41 }
42 }
43
44 void GameObject::InitializeComponent(Component* component) {
45 if (component->bIsInitialized) return;
46 component->bIsInitialized = component->Initialize();
47 if (m_isActive) component->OnEnable();
48 }
49
50 void GameObject::Update(float deltaTime) {
51 if (!m_isActive || m_pendingDestroy) return;
52
53 for (size_t i = 0; i < Components.GetSize(); ++i) {
54 if (Components[i])
55 Components[i]->Update(deltaTime);
56 }
57
58 for (size_t i = 0; i < m_children.GetSize(); ++i) {
59 if (m_children[i] && m_children[i]->IsActive())
60 m_children[i]->Update(deltaTime);
61 }
62 }
63
64 void GameObject::FixedUpdate(float fixedDeltaTime) {
65 if (!m_isActive || m_pendingDestroy) return;
66
67 for (size_t i = 0; i < Components.GetSize(); ++i) {
68 if (Components[i])
69 Components[i]->FixedUpdate(fixedDeltaTime);
70 }
71
72 for (size_t i = 0; i < m_children.GetSize(); ++i) {
73 if (m_children[i] && m_children[i]->IsActive())
74 m_children[i]->FixedUpdate(fixedDeltaTime);
75 }
76 }
77
78 void GameObject::LateUpdate(float deltaTime) {
79 if (!m_isActive || m_pendingDestroy) return;
80
81 for (size_t i = 0; i < Components.GetSize(); ++i) {
82 if (Components[i])
83 Components[i]->LateUpdate(deltaTime);
84 }
85
86 for (size_t i = 0; i < m_children.GetSize(); ++i) {
87 if (m_children[i] && m_children[i]->IsActive())
88 m_children[i]->LateUpdate(deltaTime);
89 }
90 }
91
92 void GameObject::SetActive(bool active) {
93 if (m_isActive == active) return;
94 m_isActive = active;
95
96 for (size_t i = 0; i < Components.GetSize(); ++i) {
97 if (Components[i]) {
98 if (active)
99 Components[i]->OnEnable();
100 else
101 Components[i]->OnDisable();
102 }
103 }
104
105 for (size_t i = 0; i < m_children.GetSize(); ++i) {
106 if (m_children[i])
107 m_children[i]->SetActive(active);
108 }
109 }
110
112 if (m_parent == parent) return;
113
114 for (GameObject* p = parent; p; p = p->m_parent) {
115 if (p == this) {
116 SLEAK_WARN("Cannot parent '{}' to its own descendant",
117 GetName());
118 return;
119 }
120 }
121
122 if (m_parent) {
123 m_parent->RemoveChild(this);
124 }
125
126 m_parent = parent;
127
128 if (m_parent) {
129 if (m_parent->m_children.indexOf(this) == -1) {
130 m_parent->m_children.add(this);
131 }
132 }
133 }
134
136 if (!child || child == this) return;
137 child->SetParent(this);
138 }
139
141 if (!child) return;
142 int index = m_children.indexOf(child);
143 if (index != -1) {
144 m_children.erase(index);
145 child->m_parent = nullptr;
146 }
147 }
148
149 void GameObject::DestroyComponents() {
150 for (size_t i = 0; i < Components.GetSize(); ++i) {
151 if (Components[i])
152 Components[i]->OnDestroy();
153 }
154 Components.clear();
155 }
156
157 /// Fallback material for the primitive factories below, using the default shader.
159 auto* mat = new Material();
160 mat->SetShader("assets/shaders/default_shader.hlsl");
161 return mat;
162 }
163
165 GameObject* object = new GameObject("Plane");
166
167 MeshData meshData = GetPlaneMesh(width, height);
168 object->AddComponent<ColliderComponent>(meshData, Physics::ColliderType::AABB);
169 object->AddComponent<RigidbodyComponent>(BodyType::Static);
170 object->AddComponent<MaterialComponent>(CreateDefaultMaterial());
171 object->AddComponent<MeshComponent>(std::move(meshData));
172 object->AddComponent<TransformComponent>(position);
173 object->Initialize();
174
175 return object;
176 }
177
179 GameObject* object = new GameObject("Cube");
180
181 MeshData meshData = GetCubeMesh();
182 object->AddComponent<ColliderComponent>(meshData, Physics::ColliderType::AABB);
183 object->AddComponent<RigidbodyComponent>(BodyType::Static);
184 object->AddComponent<TransformComponent>(position);
185 object->AddComponent<MaterialComponent>(CreateDefaultMaterial());
186 object->AddComponent<MeshComponent>(std::move(meshData));
187 object->Initialize();
188
189 return object;
190 }
191
192 GameObject* GameObject::CreateSphere(Math::Vector3D position, int stack, int slices) {
193 GameObject* object = new GameObject("Sphere");
194
195 MeshData meshData = GetSphereMesh(stack, slices);
196 object->AddComponent<ColliderComponent>(meshData, Physics::ColliderType::Sphere);
197 object->AddComponent<RigidbodyComponent>(BodyType::Static);
198 object->AddComponent<TransformComponent>(position);
199 object->AddComponent<MaterialComponent>(CreateDefaultMaterial());
200 object->AddComponent<MeshComponent>(std::move(meshData));
201 object->Initialize();
202
203 return object;
204 }
205
206 GameObject* GameObject::CreateCapsule(Math::Vector3D position, int segments, int rings, float height, float radius) {
207 GameObject* object = new GameObject("Capsule");
208
209 MeshData meshData = GetCapsuleMesh(segments, rings, height, radius);
210 object->AddComponent<ColliderComponent>(meshData, Physics::ColliderType::Capsule);
211 object->AddComponent<RigidbodyComponent>(BodyType::Static);
212 object->AddComponent<TransformComponent>(position);
213 object->AddComponent<MaterialComponent>(CreateDefaultMaterial());
214 object->AddComponent<MeshComponent>(std::move(meshData));
215 object->Initialize();
216
217 return object;
218 }
219
220 GameObject* GameObject::CreateCylinder(Math::Vector3D position, int segments, float height, float radius) {
221 GameObject* object = new GameObject("Cylinder");
222
223 MeshData meshData = GetCylinderMesh(segments, height, radius);
224 object->AddComponent<ColliderComponent>(meshData, Physics::ColliderType::AABB);
225 object->AddComponent<RigidbodyComponent>(BodyType::Static);
226 object->AddComponent<MaterialComponent>(CreateDefaultMaterial());
227 object->AddComponent<MeshComponent>(std::move(meshData));
228 object->AddComponent<TransformComponent>(position);
229 object->Initialize();
230
231 return object;
232 }
233}
int width
int height
Sleak::MeshData GetPlaneMesh(float width, float height, int subdivisionsX=1, int subdivisionsY=1)
Builds a subdivided flat quad on the XZ plane, facing up.
Sleak::MeshData GetCapsuleMesh(int segments, int rings, float height, float radius)
Builds a capsule (cylinder with hemispherical caps) centered at the origin.
Sleak::MeshData GetCylinderMesh(int segments, float height, float radius)
Builds a capped cylinder centered at the origin, extending +/- height/2 along Y.
Sleak::MeshData GetSphereMesh(int stacks=16, int slices=16)
Builds a UV sphere of unit radius with the given stack/slice resolution.
Sleak::MeshData GetCubeMesh()
Builds a unit cube with per-face vertices for hard-edged normals.
#define SLEAK_WARN(...)
Definition Logger.hpp:21
virtual void OnEnable()
Definition Component.hpp:73
virtual bool Initialize()=0
One-time setup, called after the component is attached and the owner is initialized.
static GameObject * CreateCylinder(Math::Vector3D position, int segments=16, float height=1, float radius=0.5)
virtual void LateUpdate(float deltaTime)
virtual void Initialize()
Initializes the object, components and children; repeats no-op.
static GameObject * CreateCapsule(Math::Vector3D position, int segments=16, int rings=8, float height=1, float radius=0.5)
bool IsActive() const
virtual void Update(float deltaTime)
void RemoveChild(GameObject *child)
virtual void FixedUpdate(float fixedDeltaTime)
GameObject(const std::string &name="GameObject")
void SetActive(bool active)
Enables or disables the object, firing OnEnable/OnDisable on its components.
static GameObject * CreatePlane(Math::Vector3D position, int width=100, int height=100)
Built-in primitive factories, mainly for prototyping and debug scenes.
static GameObject * CreateCube(Math::Vector3D position)
void AddChild(GameObject *child)
~GameObject() override
static GameObject * CreateSphere(Math::Vector3D position, int stack=16, int slices=16)
void SetParent(GameObject *parent)
Reparents this object, updating both the old and new parent's child lists.
Implements a dynamic array-like list for storing and managing a collection of elements.
Definition List.hpp:20
size_t GetSize() const
Definition List.hpp:151
virtual bool Initialize() override
Validates that vertex and index buffers were created successfully.
const std::string & GetName() const
Definition Object.hpp:22
Represents the position, rotation, and scale of an entity in 3D space.
bool Initialize() override
Allocates the transform's GPU constant buffer.
Root namespace for everything the engine exposes.
Definition Camera.hpp:10
static Material * CreateDefaultMaterial()
Fallback material for the primitive factories below, using the default shader.