Commit e78c388a authored by Johannes Braun's avatar Johannes Braun
Browse files

Unified scene entity methods

parent d6eff563
......@@ -126,7 +126,7 @@ void loadScene(const fs::path& path, float scale)
console::prompt("Scene could not be loaded: " + path.string() + ". Press [ENTER] to exit.", 1);
}
std::shared_ptr<core::GraphNode> cam_node = core::state::graph_root->find<core::Camera>();
std::shared_ptr<core::SceneNode> cam_node = core::state::graph_root->find<core::Camera>();
if (cam_node)
{
//If there are any cameras in the collada file, take the first one.
......@@ -135,7 +135,7 @@ void loadScene(const fs::path& path, float scale)
else
{
//Add a camera to render from
cam_node = std::make_shared<core::GraphNode>("custom_camera");
cam_node = std::make_shared<core::SceneNode>("custom_camera");
cam_node->addComponent(core::state::camera);
core::state::graph_root->attach(cam_node);
}
......@@ -160,11 +160,11 @@ void drawSceneWindow()
{
ImGui::BeginChild("Graph", ImVec2(0, ImGui::GetContentRegionAvail().y * 0.5f));
ImGui::BeginSelectableTree("tree_scene_graph");
core::state::graph_root->gui();
core::state::graph_root->debugGui();
ImGui::EndSelectableTree();
ImGui::EndChild();
ImGui::Separator();
core::GraphNode* selected_node = reinterpret_cast<core::GraphNode*>(ImGui::GetSelectableTreeData("tree_scene_graph"));
core::SceneNode* selected_node = reinterpret_cast<core::SceneNode*>(ImGui::GetSelectableTreeData("tree_scene_graph"));
if(selected_node)
{
ImGui::BeginChild("Settings For Tree Node");
......@@ -201,7 +201,7 @@ void drawSceneWindow()
if(ImGui::AntiFeatureButton("Yes"))
{
if(selected_node)
selected_node->detachSelf();
selected_node->destroy();
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
......@@ -222,7 +222,7 @@ void drawSceneWindow()
if (ImGui::AntiFeatureButton("Attach!"))
{
if (selected_node)
selected_node->attach(std::make_shared<core::GraphNode>(buf));
selected_node->attach(std::make_shared<core::SceneNode>(buf));
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
......@@ -297,12 +297,12 @@ void drawSceneWindow()
ImGui::DragFloat3("Scale", reinterpret_cast<float*>(&(selected_node->transform.scale)), 0.01f);
break;
case 2: // Components (if available)
selected_node->iterateComponentsStable([](core::GraphNodeComponent& component)
selected_node->iterateComponentsStable([](core::SceneComponent& component)
{
ImGui::PushID(("component-"+std::to_string(component.id())).c_str());
if (ImGui::CollapsingHeader(component.typeName().c_str()))
{
component.onGui();
component.debugGui();
if (ImGui::AntiFeatureButton("Delete", ImVec2(ImGui::GetContentRegionAvailWidth(), 24)))
{
ImGui::OpenPopup("del_comp");
......@@ -314,7 +314,7 @@ void drawSceneWindow()
if (ImGui::AntiFeatureButton("Yes"))
{
component.detachAs<core::GraphNodeComponent>();
component.destroy();
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
......@@ -339,9 +339,6 @@ void drawSceneWindow()
if (ImGui::BeginPopup("add_comp"))
{
ImGui::Text("New Component Type?");
ImGui::BeginChild("component_list");
if(ImGui::Button("Light", ImVec2(180, 24)))
{
if (selected_node)
......@@ -374,7 +371,6 @@ void drawSceneWindow()
selected_node->makeComponent<component::FramerateCounter>();
}
ImGui::EndChild();
if (ImGui::Button("Cancel"))
{
ImGui::CloseCurrentPopup();
......
......@@ -8,7 +8,7 @@
namespace glare::component
{
FramerateCounter::FramerateCounter()
: GraphNodeComponent("Framerate Counter")
: SceneComponent("Framerate Counter")
{
}
......
......@@ -5,11 +5,12 @@
namespace glare::component
{
class FramerateCounter : public core::GraphNodeComponent
class FramerateCounter : public core::SceneComponent
{
public:
FramerateCounter();
protected:
void onUpdate() override;
private:
......
......@@ -12,7 +12,7 @@ namespace glare::component
size_t PlayerController::s_current_id = 0;
PlayerController::PlayerController()
: GraphNodeComponent("Player Controller"), m_id(s_current_id++)
: SceneComponent("Player Controller"), m_id(s_current_id++)
{
core::Callbacks::addKeyActionCallback("player_controller" + std::to_string(m_id), std::bind(&PlayerController::onKeyAction, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
core::Callbacks::addMouseButtonCallback("player_controller" + std::to_string(m_id), std::bind(&PlayerController::onMouseButtonAction, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
......@@ -77,7 +77,7 @@ namespace glare::component
}
}
void PlayerController::onGui()
void PlayerController::onDebugGui()
{
ImGui::DragFloat("Movement Speed", &m_speed, 0.5f);
ImGui::DragFloat("Rotation Speed", &m_rotation_speed, 0.01f);
......
......@@ -8,7 +8,7 @@
namespace glare::component
{
class PlayerController : public core::GraphNodeComponent, public messaging::Receiver
class PlayerController : public core::SceneComponent, public messaging::Receiver
{
public:
PlayerController();
......@@ -19,12 +19,12 @@ namespace glare::component
void onKeyAction(controls::Key key, controls::ButtonAction action, controls::KeyMods mods);
void onMouseButtonAction(controls::MouseButton button, controls::ButtonAction action, controls::KeyMods mods);
void onUpdate() override;
void onGui() override;
bool isPossessed() const;
protected:
void onUpdate() override;
void onDebugGui() override;
private:
static size_t s_current_id;
size_t m_id;
......
......@@ -5,7 +5,7 @@ namespace glare::component
{
Rotator::Rotator()
: GraphNodeComponent("Rotator")
: SceneComponent("Rotator")
{
}
......
......@@ -5,12 +5,13 @@
namespace glare::component
{
class Rotator : public core::GraphNodeComponent
class Rotator : public core::SceneComponent
{
public:
Rotator();
~Rotator();
protected:
void onUpdate() override;
};
......
......@@ -3,7 +3,7 @@
namespace glare::core
{
SoundSource::SoundSource()
: GraphNodeComponent("Sound Source")
: SceneComponent("Sound Source")
{
al::sourcef(m_source, al::SourceParam::ePitch, m_pitch);
al::sourcef(m_source, al::SourceParam::eGain, m_gain);
......
......@@ -9,17 +9,12 @@ namespace glare::core
/**
* \brief Can be attached to a scene graph to either play a sound locally or globally. Uses the id of a SoundBuffer to play sounds.
*/
class SoundSource : public GraphNodeComponent
class SoundSource : public SceneComponent
{
public:
SoundSource();
SoundSource(unsigned buffer);
/**
* \brief Important for local sound sources: Updates the position and velocity of this sound source.
*/
void onUpdate() override;
void play() const;
void pause() const;
void stop() const;
......@@ -29,6 +24,12 @@ namespace glare::core
void setBuffer(unsigned buffer);
unsigned getBuffer() const;
protected:
/**
* \brief Important for local sound sources: Updates the position and velocity of this sound source.
*/
void onUpdate() override;
private:
al::handle::source m_source;
unsigned m_buffer_id = 0;
......
#ifndef INCLUDE_BASE_CONTAINER_H
#define INCLUDE_BASE_CONTAINER_H
#include <algorithm>
#include <functional>
#include <memory>
#include <map>
......@@ -70,6 +71,8 @@ namespace glare::core
void ComponentContainer<TNode, TComponent>::addComponent(std::shared_ptr<T> component)
{
component->m_owner = std::enable_shared_from_this<TNode>::shared_from_this();
if(component)
component->start();
m_components[typeid(T).name()].push_back(component);
}
......@@ -80,10 +83,15 @@ namespace glare::core
if (m_components.size() != 0 && m_components.count(typeid(T).name()) != 0)
{
auto&& list = m_components[typeid(T).name()];
list.erase(std::remove_if(list.begin(), list.end(), [&component](std::shared_ptr<TComponent> current) {
auto rm_it = std::remove_if(list.begin(), list.end(), [&component](std::shared_ptr<TComponent> current) {
return current.get() == component.get();
}));
});
if (rm_it != list.end())
{
(*rm_it)->end();
list.erase(rm_it);
}
if (list.empty())
m_components.erase(typeid(T).name());
......
......@@ -29,10 +29,6 @@ namespace glare::core
void clearChildren();
// Those can be overridden in case you want to be notified when adding/removing nodes.
virtual void onNodeAttached(std::shared_ptr<NodeType> node);
virtual void onNodeDetached(std::shared_ptr<NodeType> node);
std::shared_ptr<NodeType> parent() const;
const std::vector<std::shared_ptr<NodeType>>& children();
......@@ -73,6 +69,10 @@ namespace glare::core
StableChildIterator iterateChildren();
protected:
// Those can be overridden in case you want to be notified when adding/removing nodes.
virtual void onAttached(std::shared_ptr<NodeType> node);
virtual void onDetached(std::shared_ptr<NodeType> node);
std::weak_ptr<NodeType> m_parent;
std::vector<std::shared_ptr<NodeType>> m_children;
};
......@@ -131,7 +131,7 @@ namespace glare::core
{
node->m_parent = std::enable_shared_from_this<NodeType>::shared_from_this();
m_children.push_back(node);
onNodeAttached(node);
onAttached(node);
return int(m_children.size() - 1);
}
......@@ -144,7 +144,7 @@ namespace glare::core
{
if (!node->m_parent.expired())
node->m_parent.reset();
onNodeDetached(node);
onDetached(node);
m_children.erase(it);
}
}
......@@ -164,7 +164,7 @@ namespace glare::core
{
if (!node->m_parent.expired())
node->m_parent.reset();
onNodeDetached(node);
onDetached(node);
}
m_children.clear();
}
......@@ -194,12 +194,12 @@ namespace glare::core
}
template <typename NodeType, typename ComponentType>
void Node<NodeType, ComponentType>::onNodeAttached(std::shared_ptr<NodeType> node)
void Node<NodeType, ComponentType>::onAttached(std::shared_ptr<NodeType> node)
{
}
template <typename NodeType, typename ComponentType>
void Node<NodeType, ComponentType>::onNodeDetached(std::shared_ptr<NodeType> node)
void Node<NodeType, ComponentType>::onDetached(std::shared_ptr<NodeType> node)
{
}
......@@ -276,7 +276,7 @@ namespace glare::core
template <typename TComponent>
std::shared_ptr<NodeType> Node<NodeType, ComponentType>::find()
{
return find([](const GraphNode& node)
return find([](const SceneNode& node)
{
return bool(node.getComponent<TComponent>());
});
......
......@@ -3,83 +3,92 @@
#include <memory>
#include <string>
#include "entity.h"
namespace glare::core
{
template <typename TNode, typename TComponent>
class ComponentContainer;
class GraphNode;
class SceneNode;
enum class DrawMode;
/**
* \brief Can be attached to a GraphNode to add functionality to it (decorator)
*/
class GraphNodeComponent : public std::enable_shared_from_this<GraphNodeComponent>
class SceneComponent : public std::enable_shared_from_this<SceneComponent>, public Entity
{
friend class ComponentContainer<GraphNode, GraphNodeComponent>;
friend class ComponentContainer<SceneNode, SceneComponent>;
friend class GraphNode;
public:
GraphNodeComponent(const std::string& type_name) : m_type_name(type_name) {}
virtual ~GraphNodeComponent();
SceneComponent(const std::string& type_name) : m_type_name(type_name) {}
virtual ~SceneComponent();
template <typename T>
std::shared_ptr<T> detachAs();
std::shared_ptr<SceneNode> owner() const;
uint64_t id();
const std::string& typeName() const;
protected:
/**
* \brief Will get called when the parent node transformation has changed.
*/
virtual void onTransform();
virtual void onTransform() override;
/**
* \brief Can be used to draw the component settings via ImGui.
*/
virtual void onGui();
virtual void onUpdate();
virtual void onDraw(DrawMode mode);
virtual void onGui() override;
virtual void onUpdate() override;
virtual void onDestroy() override { detachAs<SceneComponent>(); };
virtual void onStart() override {}
virtual void onEnd() override {}
virtual void onActivate() override {}
virtual void onDeactivate() override {}
template <typename T>
std::shared_ptr<T> detachAs();
std::shared_ptr<GraphNode> owner() const;
uint64_t id();
const std::string& typeName() const;
virtual void onDebugGui() override {}
virtual void onDraw(DrawMode mode = DrawMode::eShaded) override;
private:
std::string m_type_name;
std::weak_ptr<GraphNode> m_owner;
std::weak_ptr<SceneNode> m_owner;
uint64_t m_id = 0;
};
inline GraphNodeComponent::~GraphNodeComponent()
inline SceneComponent::~SceneComponent()
{
}
inline void GraphNodeComponent::onTransform()
inline void SceneComponent::onTransform()
{
}
inline void GraphNodeComponent::onGui()
inline void SceneComponent::onGui()
{
}
inline void GraphNodeComponent::onUpdate()
inline void SceneComponent::onUpdate()
{
}
inline void GraphNodeComponent::onDraw(DrawMode mode)
inline void SceneComponent::onDraw(DrawMode mode)
{
}
inline std::shared_ptr<GraphNode> GraphNodeComponent::owner() const
inline std::shared_ptr<SceneNode> SceneComponent::owner() const
{
return m_owner.lock();
}
template <typename T>
std::shared_ptr<T> GraphNodeComponent::detachAs()
std::shared_ptr<T> SceneComponent::detachAs()
{
auto shared = std::static_pointer_cast<T>(shared_from_this());
m_owner.lock()->removeComponent(shared);
return shared;
}
inline uint64_t GraphNodeComponent::id()
inline uint64_t SceneComponent::id()
{
if (m_id == 0)
{
......@@ -89,12 +98,12 @@ namespace glare::core
return m_id;
}
inline const std::string& GraphNodeComponent::typeName() const
inline const std::string& SceneComponent::typeName() const
{
return m_type_name;
}
}
#include "node.h"
#include "scene_node.h"
#endif //INCLUDE_COMPONENT_H
#include "entity.h"
namespace glare::core
{
void Entity::start()
{
onStart();
setActive(true);
}
void Entity::end()
{
setActive(false);
onEnd();
}
void Entity::gui()
{
onGui();
}
void Entity::debugGui()
{
onDebugGui();
}
void Entity::update()
{
onUpdate();
}
void Entity::draw(DrawMode mode)
{
onDraw(mode);
}
void Entity::setActive(bool active)
{
if (active != m_active)
{
m_active = active;
m_active ? onActivate() : onDeactivate();
}
}
bool Entity::isActive() const
{
return m_active;
}
void Entity::destroy()
{
onDestroy();
end();
}
void Entity::notifyTransform()
{
onTransform();
}
}
\ No newline at end of file
#ifndef INCLUDE_INTERACTABLE_H
#define INCLUDE_INTERACTABLE_H
#include <string>
namespace glare::core
{
enum class DrawMode
{
eShaded = 0,
eUnshaded
};
class Entity
{
public:
void start();
void end();
void gui();
void debugGui();
void update();
void draw(DrawMode mode = DrawMode::eShaded);
void setActive(bool active);
bool isActive() const;
void destroy();
void notifyTransform();
private:
virtual void onDestroy() = 0;
virtual void onStart() {}
virtual void onEnd() {}
virtual void onActivate() {}
virtual void onDeactivate() {}
virtual void onGui() {}
virtual void onDebugGui() {}
virtual void onUpdate() {}
virtual void onDraw(DrawMode mode = DrawMode::eShaded) {}
virtual void onTransform() {}
private:
bool m_active;
};
}
#endif //!INCLUDE_INTERACTABLE_H
\ No newline at end of file
#ifndef INCLUDE_INTERACTABLE_H
#define INCLUDE_INTERACTABLE_H
namespace glare::core
{
enum class DrawMode;
class Interactable
{
public:
void onGui();
void onUpdate();
void onDraw(DrawMode mode);
/**
* \brief Will get called when this node's transformation has changed.
*/
void onTransfform();
};
}
#endif //!INCLUDE_INTERACTABLE_H
\ No newline at end of file
#include "node.h"
#include <core/message_tags.h>
#include <imgui/imgui_glfw.h>
namespace glare::core
{
GraphNode::GraphNode(std::string name)
: m_name(name)
{
}
void GraphNode::gui()
{
ImGui::PushID(("Node::" + m_name).c_str());
if (ImGui::SelectableTreeNode("tree_scene_graph", m_name.c_str(), this, m_children.empty() ? ImGuiTreeNodeFlags_Bullet : 0))
{
for (auto && child : iterateChildren())