Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion include/public/Core/GameObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Sleak {
namespace Math {class Vector3D;};
class SceneBase;
/// Scene entity holding components and an optional parent/child transform
/// hierarchy. Scene owns the instance; destroy via Scene::DestroyObject().
///
Expand All @@ -31,6 +32,10 @@ namespace Sleak {
/// for deferred destruction, which is what you want while iterating, or
/// SceneBase::RemoveObject() for immediate destruction.
///
/// A parent owns every child that was not itself added to a scene, so a
/// hierarchy built with SetParent() (for example by ModelLoader) only
/// needs its root added. Deleting a parent deletes those children too.
///
/// Camera, Light, and its subclasses all derive from GameObject, so
/// they are added and found the same way as anything else.
///
Expand Down Expand Up @@ -116,7 +121,7 @@ namespace Sleak {
return GetComponent<T>() != nullptr;
}

/// Initializes the object and its components; repeat calls no-op.
/// Initializes the object, components and children; repeats no-op.
virtual void Initialize();
bool IsInitialized() const { return bIsInitialized; }
virtual void Update(float deltaTime);
Expand All @@ -138,6 +143,8 @@ namespace Sleak {
void RemoveChild(GameObject* child);
bool HasParent() const { return m_parent != nullptr; }
bool HasChildren() const { return m_children.GetSize() > 0; }
/// True once a scene took ownership through SceneBase::AddObject().
bool IsOwnedByScene() const { return m_ownedByScene; }

virtual bool IsLight() const { return false; }

Expand All @@ -159,6 +166,7 @@ namespace Sleak {
private:
bool m_isActive;
bool m_pendingDestroy;
bool m_ownedByScene = false;
std::string m_tag = "Untagged";

List<RefPtr<Component>> Components;
Expand All @@ -171,6 +179,8 @@ namespace Sleak {
void DestroyComponents();
/// Initializes a component once, then enables it if active.
void InitializeComponent(Component* component);

friend class SceneBase;
};
}

Expand Down
20 changes: 11 additions & 9 deletions include/public/Core/Object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,20 @@ namespace Sleak {
/// @ingroup core
class Object {
public:
Object(const std::string& name = "Object")
: m_uniqueID(s_nextUniqueID.fetch_add(1, std::memory_order_relaxed)),
m_name(name)
{
SetName(m_name + "-" + std::to_string(m_uniqueID));
}
Object(const std::string& name = "Object")
: m_name(name),
m_uniqueID(s_nextUniqueID.fetch_add(1, std::memory_order_relaxed)) {}

virtual ~Object() = default;
virtual ~Object() = default;

uint64_t GetUniqueID() const { return m_uniqueID; }
uint64_t GetUniqueID() const { return m_uniqueID; }

const std::string& GetName() const { return m_name; }
const std::string& GetName() const { return m_name; }

/// Name plus unique ID, for logs where names can repeat.
std::string GetDebugName() const {
return m_name + "-" + std::to_string(m_uniqueID);
}

inline void SetName(const std::string& value) { m_name = value; }

Expand Down
20 changes: 11 additions & 9 deletions include/public/Core/SceneBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ namespace Sleak {
namespace Physics { class PhysicsWorld; }

/// Non-templated scene interface: object ownership, state machine, and
/// per-frame update hooks. Game scenes derive from Scene, not this directly.
/// per-frame update hooks. Game scenes derive from Scene, not this
/// directly.
///
/// SceneBase defines what every scene can do regardless of subclass:
/// hold objects, move through the SceneState machine, and answer
Expand All @@ -42,9 +43,10 @@ namespace Sleak {
/// object (and its children) for deletion at the end of the frame,
/// which is the safe choice while iterating.
///
/// Objects added to the scene are registered with the LightManager if
/// they report IsLight(), and their colliders are registered with the
/// PhysicsWorld, hierarchy included.
/// Children of an added object that were never added themselves are
/// owned by their parent and belong to the scene through it. Lights and
/// colliders anywhere in that hierarchy are registered with the
/// LightManager and PhysicsWorld, and the queries below search it too.
///
/// @code{.cpp}
/// // Destroy safely from inside an update
Expand Down Expand Up @@ -124,19 +126,19 @@ namespace Sleak {
// Object management — scene takes ownership of added objects
/// Takes ownership of object, registering it with lighting and physics as needed.
virtual void AddObject(GameObject* object);
/// Unregisters and deletes object immediately.
/// Cancels a queued DestroyObject() on the same object.
/// Unregisters and deletes object and its whole hierarchy immediately.
/// Cancels a queued DestroyObject() on anything it deletes.
virtual void RemoveObject(GameObject* object);
/// Queues an object for destruction; actually freed on the next ProcessPendingDestroy().
void DestroyObject(GameObject* object);
const List<GameObject*>& GetObjects() const { return Objects; }

// Object queries
/// Linear search for the first object with a matching name.
/// First object with a matching name, children included.
GameObject* FindObjectByName(const std::string& name);
/// Linear search for the object with a matching unique ID.
/// Object with a matching unique ID, children included.
GameObject* FindObjectByID(uint64_t id);
/// Collects every object whose tag matches.
/// Collects every object whose tag matches, children included.
List<GameObject*> FindObjectsByTag(const std::string& tag);
size_t GetObjectCount() const { return Objects.GetSize(); }

Expand Down
10 changes: 1 addition & 9 deletions src/Assets/ModelLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@

namespace Sleak {

/// Recursively initialize a GameObject and all its children.
static void InitializeRecursive(GameObject* obj) {
obj->Initialize();
for (size_t i = 0; i < obj->GetChildren().GetSize(); ++i) {
InitializeRecursive(obj->GetChildren()[i]);
}
}

Math::Matrix4 ModelLoader::ConvertMatrix(const void* aiMatPtr) {
const auto& m = *static_cast<const aiMatrix4x4*>(
static_cast<const void*>(aiMatPtr));
Expand Down Expand Up @@ -109,7 +101,7 @@ GameObject* ModelLoader::Load(const std::string& filePath,
textureCache, materialCache, skeleton, clips);
}

InitializeRecursive(root);
root->Initialize();
return root;
}

Expand Down
27 changes: 20 additions & 7 deletions src/Scene/GameObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@
namespace Sleak {

GameObject::~GameObject() {
List<GameObject*> children = std::move(m_children);
for (size_t i = 0; i < children.GetSize(); ++i) {
GameObject* child = children[i];
if (!child) continue;
child->m_parent = nullptr;
if (!child->m_ownedByScene) delete child;
}

DestroyComponents();

if (m_parent) {
m_parent->RemoveChild(this);
m_parent = nullptr;
}

for (size_t i = 0; i < m_children.GetSize(); ++i) {
if (m_children[i]) {
m_children[i]->m_parent = nullptr;
}
}
m_children.clear();
}

void GameObject::Initialize() {
Expand All @@ -34,6 +35,10 @@ namespace Sleak {
for (size_t i = 0; i < Components.GetSize(); ++i) {
if (Components[i]) InitializeComponent(Components[i].get());
}

for (size_t i = 0; i < m_children.GetSize(); ++i) {
if (m_children[i]) m_children[i]->Initialize();
}
}

void GameObject::InitializeComponent(Component* component) {
Expand Down Expand Up @@ -106,6 +111,14 @@ namespace Sleak {
void GameObject::SetParent(GameObject* parent) {
if (m_parent == parent) return;

for (GameObject* p = parent; p; p = p->m_parent) {
if (p == this) {
SLEAK_WARN("Cannot parent '{}' to its own descendant",
GetName());
return;
}
}

if (m_parent) {
m_parent->RemoveChild(this);
}
Expand Down
Loading
Loading