diff --git a/core/Node.cpp b/core/Node.cpp index f40ec0b..068540b 100644 --- a/core/Node.cpp +++ b/core/Node.cpp @@ -24,6 +24,13 @@ #include "Node.h" #include "Util.h" +NodeList::NodeList() { + isPrefabList = true; +} +NodeList::NodeList(bool isPrefabList) { + this->isPrefabList = isPrefabList; +} + void NodeList::Append(Node *node) { if (this->isPrefabList and not node->isPrefab) { Util::Die("Attempt to add instanced node to prefab list!"); @@ -34,10 +41,22 @@ void NodeList::Append(Node *node) { push_back(node); } +void NodeList::Remove(Node *node) { + remove(node); +} + bool NodeList::IsPrefabList() { return isPrefabList; } +void NodeList::FreeList() { + for(Node *node : *this) { + node->children.FreeList(); + delete node; + } + clear(); +} + Name Node::GetType() const {return "Node";} bool Node::IsPrefab() { @@ -49,9 +68,26 @@ NodeList Node::GetChildren() { } void Node::AddChild(Node *child) { + child->parent = this; children.Append(child); } +Node *Node::GetParent() { + return parent; +} + +void Node::QueueFree() { + parent->children.Remove(this); + freeList->Append(this); +} + +void Node::DoFree() { + if (this != root) { + Util::Die("Tried to call DoFree from non-root node"); + } + freeList->FreeList(); +} + Node *Node::GetRoot() { return root; } @@ -79,4 +115,5 @@ Node* Node::Instance() { return instance; } +NodeList *Node::freeList = new NodeList(false); Node *Node::root = {Node().Instance()}; diff --git a/core/Node.h b/core/Node.h index e580393..0f7a2b8 100644 --- a/core/Node.h +++ b/core/Node.h @@ -25,7 +25,7 @@ #ifndef NODE_H #define NODE_H -#include +#include #include "types.h" @@ -34,22 +34,33 @@ class Node; // Forwards declare A list of nodes, tagged as either a list of prefabs or a list of instanced nodes. */ -class NodeList : public std::vector { +class NodeList : public std::list { public: + NodeList(); + NodeList(bool isPrefabList); /** Add a node to this list, will check if it is a prefab or an instance. @param node The node to add */ void Append(Node *node); + /** + Remove a node from this list + @param node The node to remove + */ + void Remove(Node *node); /** Whether or not this is a list of prefabs @returns true if this is a prefab list, false if it is an instanced list. */ bool IsPrefabList(); + /** + Recursively frees all nodes in the list + */ + void FreeList(); private: - bool isPrefabList = true; + bool isPrefabList; friend class Node; }; @@ -78,6 +89,21 @@ public: @param child The node to add */ void AddChild(Node *child); + /** + @return This node's parent; + */ + Node *GetParent(); + /** + Remove this node and it's children from the tree + and queue their memory for freeing + */ + void QueueFree(); + + /** + Actually frees the memory + Should only be called from root + */ + void DoFree(); /** Gets the root of the game scene tree @@ -108,7 +134,9 @@ public: private: NodeList children; + static NodeList *freeList; static Node *root; + Node *parent; bool isPrefab = true; friend class NodeList; }; diff --git a/core/couch.cpp b/core/couch.cpp index 73af364..a13b478 100644 --- a/core/couch.cpp +++ b/core/couch.cpp @@ -121,7 +121,10 @@ int main() { // Start rendering to texture; screen.Enable(); + // Call update function lua->Update(delta); + // Delete freed nodes + root->DoFree(); shader->Use(); shader->UpdateProjection(projection); @@ -176,7 +179,7 @@ int main() { delete screenShader; delete skyboxShader; - delete flatShader() + delete shader; lua->Close(); delete lua; diff --git a/demo/main.lua b/demo/main.lua index 6a1cdc9..d2f34dc 100644 --- a/demo/main.lua +++ b/demo/main.lua @@ -5,6 +5,9 @@ local physics_ball local character local ball local camera +local die_cube + +local total = 0.0 local vx = 0.0 local vy = 0.0 @@ -90,6 +93,9 @@ function init() cube_prefab:AddChild(orbiter) cube = cube_prefab:Instance() couch.Node.GetRoot():AddChild(cube) + die_cube = cube_prefab:Instance() + couch.Node.GetRoot():AddChild(die_cube) + die_cube:Translate(couch.Vector3(0.0, 0.0, 3.0)) local ball_prefab = couch.Mesh.FromFile("ball.obj") material = ball_prefab:GetMaterial(0) @@ -131,6 +137,7 @@ function init() end function update(delta) + total = total + delta local move_vec = couch.Vector3() local camera_transform = camera:GetTransform() move_vec = camera_transform.position + camera_transform:Forward() * delta * vz * SPEED @@ -152,12 +159,17 @@ function update(delta) elseif loc.y < 2.0 then ballvy = 1.0 end - ball:Translate(couch.Vector3(ballvy * delta, 0.0, 0.0)) + ball:Translate(couch.Vector3(0.0, ballvy * delta, 0.0)) cube:RotateY(2.0 * delta) cube:RotateZ(1.0 * delta) character:ApplyForce(character_move_vec * 10.0) + + if total > 1.0 and die_cube then + die_cube:QueueFree() + die_cube = nil + end end function action_dir(key, action, pos, neg, curr)