7#include "scene/Scene.h"
13#include "scene/GameObject.h"
14#include "scene/components/AnimationComponent.h"
15#include "scene/components/AudioComponent.h"
16#include "scene/components/AudioListenerComponent.h"
17#include "scene/components/CameraComponent.h"
19#include "scene/components/LightComponent.h"
20#include "scene/components/MeshComponent.h"
23#include "scene/components/PhysicsComponent.h"
24#include "scene/components/PlayerControllerComponent.h"
31 AnimationComponent::Register();
32 CameraComponent::Register();
33 HealthComponent::Register();
34 LightComponent::Register();
35 MeshComponent::Register();
36 ParticleEmitterComponent::Register();
37 SkinnedMeshComponent::Register();
38 PhysicsComponent::Register();
39 PlayerControllerComponent::Register();
40 AudioComponent::Register();
41 AudioListenerComponent::Register();
46 m_objects.erase(std::remove_if(m_objects.begin(), m_objects.end(), [](
auto &obj) { return !obj->IsAlive(); }),
49 for (
auto &obj : m_objectsToAdd)
53 m_objectsToAdd.clear();
57 for (
auto it = m_objects.begin(); it != m_objects.end();)
61 (*it)->Update(deltaTime);
65 it = m_objects.erase(it);
74 m_mainCamera = camera;
84 std::vector<LightData> lights;
85 for (
auto &obj : m_objects)
87 CollectLightsRecursive(obj.get(), lights);
92void Scene::CollectLightsRecursive(
GameObject *obj, std::vector<LightData> &out)
97 data.
color = light->GetColor();
102 for (
auto &child : obj->m_children)
104 CollectLightsRecursive(child.get(), out);
110 LOG_INFO(
"Scene::Clear (%zu root objects)", m_objects.size());
123 m_objectsToAdd.push_back({obj, parent});
139 m_objectsToAdd.push_back({obj, parent});
149void Scene::LoadObject(
const nlohmann::json &jsonObject,
GameObject *parent)
157 const std::string type = jsonObject.value(
kJsonKeyType,
"");
168 LOG_ERROR(
"Scene::LoadObject failed to load GLTF '%s' for object '%s'", path.c_str(), name.c_str());
180 LOG_ERROR(
"Scene::LoadObject failed to import model '%s' for object '%s'", path.c_str(), name.c_str());
187 LOG_ERROR(
"Scene::LoadObject unknown GameObject type '%s' (name='%s')", type.c_str(), name.c_str());
226 scale.x = scaleObj.value(
kJsonKeyX, 1.0f);
227 scale.y = scaleObj.value(
kJsonKeyY, 1.0f);
228 scale.z = scaleObj.value(
kJsonKeyZ, 1.0f);
237 for (
const auto &comp : components)
247 LOG_ERROR(
"Unknown component type '%s' on object '%s' (not registered in ComponentFactory)",
257 for (
const auto &child : children)
259 LoadObject(child, gameObject);
268 LOG_INFO(
"Scene::Load '%s'", path.c_str());
270 if (contents.empty())
272 LOG_ERROR(
"Scene::Load empty or missing file '%s'", path.c_str());
279 json = nlohmann::json::parse(contents);
280 }
catch (
const nlohmann::json::parse_error &e)
282 LOG_ERROR(
"Scene::Load JSON parse error in '%s': %s", path.c_str(), e.what());
287 LOG_ERROR(
"Scene::Load JSON empty in '%s'", path.c_str());
291 auto result = std::make_shared<Scene>();
297 const auto total = objects.size();
299 for (
const auto &obj : objects)
303 std::snprintf(msg,
sizeof(msg),
"Loading %s (%zu/%zu)", objName.c_str(), i + 1, total);
305 total > 0 ?
static_cast<float>(i) /
static_cast<float>(total) : 0.0F, msg);
306 result->LoadObject(obj,
nullptr);
311 LOG_WARN(
"Scene '%s' has no 'objects' array", sceneName.c_str());
317 for (
const auto &child : result->m_objects)
319 if (
auto object = child->FindChildByName(cameraObjName))
321 result->SetMainCamera(
object);
325 if (!result->GetMainCamera())
328 "Scene '%s' camera target '%s' not found in loaded objects", sceneName.c_str(), cameraObjName.c_str());
332 LOG_WARN(
"Scene '%s' has no 'camera' key — render will use identity matrices", sceneName.c_str());
335 LOG_INFO(
"Scene '%s' loaded (%zu root objects)", sceneName.c_str(), result->m_objects.size());
343 LOG_ERROR(
"Scene::SetParent called with null object");
349 if (parent ==
nullptr)
351 if (currentParent !=
nullptr)
353 auto it = std::find_if(currentParent->m_children.begin(),
354 currentParent->m_children.end(),
355 [obj](
const std::unique_ptr<GameObject> &el) { return el.get() == obj; });
357 if (it != currentParent->m_children.end())
359 m_objects.push_back(std::move(*it));
360 obj->m_parent =
nullptr;
361 currentParent->m_children.erase(it);
371 auto it = std::find_if(m_objects.begin(),
373 [obj](
const std::unique_ptr<GameObject> &el) { return el.get() == obj; });
375 if (it == m_objects.end())
377 std::unique_ptr<GameObject> objHolder(obj);
378 m_objects.push_back(std::move(objHolder));
388 if (currentParent !=
nullptr)
390 auto it = std::find_if(m_objects.begin(),
392 [obj](
const std::unique_ptr<GameObject> &el) { return el.get() == obj; });
394 if (it != currentParent->m_children.end())
397 auto currentElement = parent;
398 while (currentParent)
400 if (currentElement == obj)
405 currentElement = currentElement->
GetParent();
410 parent->m_children.push_back(std::move(*it));
411 obj->m_parent = parent;
412 currentParent->m_children.erase(it);
423 auto it = std::find_if(m_objects.begin(),
425 [obj](
const std::unique_ptr<GameObject> &el) { return el.get() == obj; });
428 if (it == m_objects.end())
430 std::unique_ptr<GameObject> objHolder(obj);
431 parent->m_children.push_back(std::move(objHolder));
432 obj->m_parent = parent;
438 auto currentElement = parent;
439 while (currentParent)
441 if (currentElement == obj)
446 currentElement = currentElement->
GetParent();
450 parent->m_children.push_back(std::move(*it));
451 obj->m_parent = parent;
462 LOG_WARN(
"Scene::SetParent failed for object '%s' (target parent=%s)",
464 parent ? parent->
GetName().c_str() :
"<root>");
constexpr const char * kJsonKeyCamera
constexpr const char * kJsonKeyComponents
constexpr const char * kJsonKeyName
constexpr const char * kJsonKeyScale
constexpr const char * kDefaultObjectName
constexpr const char * kJsonKeyObjects
constexpr const char * kSceneTypeGltf
constexpr const char * kDefaultSceneName
constexpr const char * kJsonKeyW
constexpr const char * kJsonKeyRotation
constexpr const char * kRootObjectLabel
constexpr const char * kJsonKeyPath
constexpr const char * kJsonKeyType
constexpr const char * kJsonKeyZ
constexpr const char * kJsonKeyPosition
constexpr const char * kSceneTypeFbx
constexpr const char * kJsonKeyY
constexpr const char * kJsonKeyX
constexpr const char * kJsonKeyChildren
constexpr const char * kSceneTypeModel
Universal HP sink: damageable + killable game objects.
Console logging macros for all engine and game code.
#define LOG_WARN(fmt,...)
#define LOG_INFO(fmt,...)
#define LOG_ERROR(fmt,...)
Assimp-backed model loader. Handles FBX / glTF / OBJ.
Spawns particles each frame at the owner's world position.
Renderable component for GPU-skinned meshes driven by a Skeleton.
static ComponentFactory & GetInstance()
Component * CreateComponent(const std::string &name)
virtual void LoadProperties(const nlohmann::json &json)
FileSystem & GetFileSystem()
Returns the file system helper for asset-relative path resolution.
static Engine & GetInstance()
Returns the single Engine instance (created on first call).
void UpdateLoadingProgress(float progress, const char *message)
Update the loading panel mid-load (single swap). Cheap to call per step.
std::string LoadAssetFileText(const std::string &relativePath)
Load a text file from the assets directory into a string.
GameObject * CreateGameObject(const std::string &typeName)
static GameObjectFactory & GetInstance()
Node in the scene graph: a named transform that owns components and children.
void SetName(const str &name)
Sets the display name (used by FindChildByName).
vec3 GetWorldPosition() const
Extract the world-space position from GetWorldTransform().
void SetPosition(const vec3 &pos)
static GameObject * LoadGLTF(const std::string &path, Scene *scene)
Load a GLTF / GLB file and build a matching GameObject hierarchy.
const str & GetName() const
Returns the object's display name.
void SetRotation(const quat &rot)
void AddComponent(Component *component)
Attach a component to this object (takes ownership).
void SetScale(const vec3 &scale)
bool SetParent(GameObject *parent)
Re-parent this object in the scene hierarchy.
GameObject * GetParent()
Returns the parent node, or nullptr for root objects.
T * GetComponent()
Find and return the first component of type T attached to this object.
virtual void LoadProperties(const nlohmann::json &json)
Point light that contributes position + colour to the render pass.
static GameObject * Import(const std::string &path, Scene *scene)
Load path (relative to assets folder) and build a GameObject hierarchy under scene....
void Update(f32 deltaTime)
static std::shared_ptr< Scene > Load(const str &path)
GameObject * CreateObject(const std::string &name, GameObject *parent=nullptr)
Create a plain GameObject owned by this scene.
static void RegisterTypes()
Update all root objects (which recursively update their children).
std::vector< LightData > CollectLight()
Walk the entire object tree and collect all LightData.
void SetMainCamera(GameObject *camera)
Designate the camera object whose CameraComponent drives the view.
GameObject * GetMainCamera()
Returns the current main camera object (set via SetMainCamera).
bool SetParent(GameObject *obj, GameObject *parent)
Move a GameObject in the hierarchy.
void Clear()
Destroy all objects and reset the scene to an empty state.
std::string str
Convenience alias for std::string.
float f32
32-bit IEEE float — the standard GL scalar type.
World-space position and RGB colour of a single point light.
vec3 color
Linear RGB light colour (1,1,1 = white full-intensity).
vec3 position
World-space origin of the light source.