Commit 16c0b334 authored by Johannes Braun's avatar Johannes Braun
Browse files

Added ability to add and remove components and nodes and attach collada scenes...

Added ability to add and remove components and nodes and attach collada scenes to any existing node.
parent 35539c0a
......@@ -15,6 +15,7 @@
#include <components/FramerateCounter.h>
#include <components/PlayerController.h>
#include "core/res/collada.h"
#include "components/Rotator.h"
using namespace glare;
......@@ -168,15 +169,101 @@ void drawSceneWindow()
{
ImGui::BeginChild("Settings For Tree Node");
static int curr_settings_tab = 0;
if(selected_node->hasComponents())
ImGui::Tabs(std::array<std::string, 2>{"Transformation", "Components"}, curr_settings_tab);
else
ImGui::Tabs(std::array<std::string, 1>{"Transformation"}, curr_settings_tab);
ImGui::Tabs(std::array<std::string, 3>{"Settings", "Transformation", "Components"}, curr_settings_tab);
switch (curr_settings_tab)
{
default:
case 0:
case 0: // Settings
{
if(ImGui::AntiFeatureButton("Delete", ImVec2(ImGui::GetContentRegionAvailWidth() / 2, 32)))
{
ImGui::OpenPopup("del_curr_node");
}
ImGui::SameLine();
if (ImGui::FeatureButton("Add Child Node", ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
{
ImGui::OpenPopup("add_to_curr_node");
}
if (ImGui::FeatureButton("Attach Scene", ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
{
ImGui::OpenPopup("attach_scene");
}
if(ImGui::BeginPopup("del_curr_node"))
{
ImGui::Text("Do you really want to delete this node?");
if(ImGui::AntiFeatureButton("Yes"))
{
if(selected_node)
selected_node->detachSelf();
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if(ImGui::Button("No"))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (ImGui::BeginPopup("add_to_curr_node"))
{
ImGui::Text("What shall be the name of the new node?");
static char buf[64] = {};
ImGui::InputText("Node Name", buf, 128);
if (ImGui::AntiFeatureButton("Attach!"))
{
if (selected_node)
selected_node->attach(std::make_shared<core::GraphNode>(buf));
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("Cancel"))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (ImGui::BeginPopup("attach_scene"))
{
static auto root = current_scene_root;
ImGui::Title(root.string().c_str());
static float import_scale = 1.f;
ImGui::DragFloat("Scale", &import_scale, 0.01f, 0.01f, 100.0f);
ImGui::BeginChild("file_browser", ImVec2(0, 200));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
// Go to parent directory
if (ImGui::Button("..", ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
root = root.parent_path();
for (auto& p : fs::directory_iterator(current_scene_root)) {
fs::path path = p;
// Either draw directory button or...
if (is_directory(path) && ImGui::Button(path.filename().string().c_str(), ImVec2(ImGui::GetContentRegionAvailWidth(), 40)))
root = path;
// ... draw a button which loads a dae file.
else if (path.extension() == ".dae" && ImGui::FeatureButton(path.filename().string().c_str(), ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
{
if (selected_node)
selected_node->attach(core::Collada().load(path, import_scale));
}
}
ImGui::PopStyleVar();
ImGui::EndChild();
ImGui::EndPopup();
}
}
break;
case 1: // Transform
// Pos
ImGui::DragFloat3("Position", reinterpret_cast<float*>(&(selected_node->transform.position)), 0.01f);
// Rotation
......@@ -184,11 +271,86 @@ void drawSceneWindow()
// Scale
ImGui::DragFloat3("Scale", reinterpret_cast<float*>(&(selected_node->transform.scale)), 0.01f);
break;
case 1:
case 2: // Components (if available)
selected_node->iterateComponentsStable([](core::GraphNodeComponent& component)
{
component.onGui();
if (ImGui::AntiFeatureButton("Delete", ImVec2(ImGui::GetContentRegionAvailWidth(), 24)))
{
ImGui::OpenPopup("del_comp");
}
if (ImGui::BeginPopup("del_comp"))
{
ImGui::Text("Do you really want to delete this node?");
if (ImGui::AntiFeatureButton("Yes"))
{
component.detachAs<core::GraphNodeComponent>();
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("No"))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
ImGui::Spacing();
});
ImGui::Spacing();
if (ImGui::FeatureButton("Add...", ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
{
ImGui::OpenPopup("add_comp");
}
if (ImGui::BeginPopup("add_comp"))
{
ImGui::Text("New Component Type?");
ImGui::BeginChild("component_list");
if(ImGui::Button("Light", ImVec2(180, 24)))
{
if (selected_node)
selected_node->makeComponent<core::LightComponent>(color::rgba32f(3), core::LightParameters::makePointLight({1, 0.1f, 0.01f}, 1.f));
}
if (ImGui::Button("Camera", ImVec2(180, 24)))
{
if (selected_node)
selected_node->makeComponent<core::Camera>();
}
ImGui::Separator();
if (ImGui::Button("Player Controller", ImVec2(180, 24)))
{
if (selected_node)
selected_node->makeComponent<component::PlayerController>();
}
if (ImGui::Button("Rotator", ImVec2(180, 24)))
{
if (selected_node)
selected_node->makeComponent<component::Rotator>();
}
if (ImGui::Button("Framerate Counter", ImVec2(180, 24)))
{
if (selected_node)
selected_node->makeComponent<component::FramerateCounter>();
}
ImGui::EndChild();
if (ImGui::Button("Cancel"))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
break;
}
ImGui::EndTabs();
......
......@@ -20,6 +20,8 @@ namespace glare::core
template<typename T>
void removeComponent(std::shared_ptr<T> component);
void removeComponent(std::shared_ptr<TComponent> component);
template<typename TComponentDerived, typename... TArgs>
std::shared_ptr<TComponentDerived> makeComponent(TArgs... args);
......@@ -88,6 +90,24 @@ namespace glare::core
}
}
template <typename TNode, typename TComponent>
void ComponentContainer<TNode, TComponent>::removeComponent(std::shared_ptr<TComponent> component)
{
for (auto& it = m_components.begin(); it != m_components.end(); ++it)
{
auto&& list = (*it).second;
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())
{
list.erase(rm_it);
break;
}
}
}
template <typename TNode, typename TComponent>
template <typename TComponentDerived, typename ... TArgs>
std::shared_ptr<TComponentDerived> ComponentContainer<TNode, TComponent>::makeComponent(TArgs ... args)
......
......@@ -41,7 +41,6 @@ namespace glare::core
Light LightComponent::buildLight() const
{
const auto& transform = owner()->worldTransform();
Light light;
......@@ -166,7 +165,24 @@ namespace glare::core
} break;
}
if(ImGui::Button("Cange Type"))
{
ImGui::OpenPopup("light_change_type");
}
if(ImGui::BeginPopup("light_change_type"))
{
if (ImGui::Button("Point", ImVec2(180, 24)))
m_data = LightParameters::makePointLight({ 1.f, 0.1f, 0.01f }, 1.f);
if (ImGui::Button("Directional", ImVec2(180, 24)))
m_data = LightParameters::makeDirectionalLight(1.f);
if (ImGui::Button("Spot", ImVec2(180, 24)))
m_data = LightParameters::makeSpotLight({ 1.f, 0.1f, 0.01f }, 1.f, glm::radians(30.f), 0.2f);
ImGui::Text("More types are not fully supported yet :(");
ImGui::EndPopup();
}
ImGui::PopID();
......@@ -196,6 +212,8 @@ namespace glare::core
messaging::Handler::getInstance().submit(tags::light, LightUpdate{ m_id, this });
}
state::lights->submit(buildLightShadow());
static auto light_shader = std::make_shared<Program>(std::vector<std::shared_ptr<Shader>>{
std::make_shared<Shader>(gl::ShaderType::eVertex, files::shader("lamp/lamp.vert")),
std::make_shared<Shader>(gl::ShaderType::eFragment, files::shader("lamp/lamp.frag"))
......
#include "batch_render_list.h"
#include <core/objects/camera.h>
#include <core/objects/light.h>
#include <core/time.h>
namespace glare::core
......@@ -58,4 +59,19 @@ namespace glare::core
m_shader_mapping.clear();
m_render_list.clear();
}
void BatchLightRenderer::submit(const LightShadow& light)
{
m_light_list.push_back(light);
}
const std::vector<LightShadow>& BatchLightRenderer::get() const
{
return m_light_list;
}
void BatchLightRenderer::clear()
{
m_light_list.clear();
}
}
......@@ -22,6 +22,22 @@ namespace glare::core
std::vector<std::vector<std::pair<std::shared_ptr<BatchDrawable>, glm::mat4>>> m_render_list;
};
struct LightShadow;
/**
* \brief Is being used as a kind of "light manager" collecting all lights on each frame and provides them for other modules like the gbuffer to use.
*/
class BatchLightRenderer
{
public:
void submit(const LightShadow& light);
const std::vector<LightShadow>& get() const;
void clear();
private:
std::vector<LightShadow> m_light_list;
};
}
#endif //!INCLUDE_BATCH_RENDER_LIST_H
......@@ -4,6 +4,7 @@
#include <util/files.h>
#include <core/objects/light.h>
#include <core/message_tags.h>
#include <core/rendering/batch_render_list.h>
namespace glare::core
{
......@@ -61,75 +62,10 @@ namespace glare::core
m_texture_renderer->shader().bindSubroutine(gl::ShaderType::eFragment, "u_light_sample[2]", "sampleDirectional");
m_texture_renderer->shader().bindSubroutine(gl::ShaderType::eFragment, "u_light_sample[3]", "sampleAmbient");
registerForMessage(tags::light);
}
GBuffer::~GBuffer()
{
cleanUp();
}
void GBuffer::cleanUp()
{
unregisterForMessage(tags::light);
}
void GBuffer::handle(messaging::message_t &message)
{
switch (message.name)
{
default: break;
case tags::light:
{
auto light_update = message.as<LightUpdate>();
if (light_update.ptr && m_light_to_index.count(light_update.light_id) == 0)
{
//Light has just been created.
m_lights.push_back(light_update.ptr->buildLightShadow());
m_light_to_index[light_update.light_id] = m_lights.size() - 1;
m_lights_buffer->upload<LightShadow>(m_lights, gl::BufferUsage::eDynamicCopy);
//Check if successfully added.
assert(m_light_to_index.count(light_update.light_id) != 0);
assert(m_lights.size() > m_light_to_index.at(light_update.light_id));
}
else if (light_update.ptr == nullptr)
{
//Light has just been removed.
if (m_light_to_index.count(light_update.light_id) != 0)
{
size_t position = m_light_to_index[light_update.light_id];
m_lights.erase(m_lights.begin() + position);
m_light_to_index.erase(light_update.light_id);
for (auto it = m_light_to_index.begin(); it != m_light_to_index.end(); ++it)
{
// decrement vector index as one element has been removed before
if (it->second >= position)
it->second = it->second - 1;
}
m_lights_buffer->upload<LightShadow>(m_lights, gl::BufferUsage::eDynamicCopy);
}
//Check if successfully added.
assert(m_light_to_index.count(light_update.light_id) == 0);
}
else
{
assert(m_light_to_index.count(light_update.light_id) != 0);
// Light has changed.
// don't change any indices, just update the buffer
auto data = light_update.ptr->buildLightShadow();
auto index = m_light_to_index[light_update.light_id];
m_lights[index] = data;
m_lights_buffer->map<LightShadow>(m_lights.size(), gl::BufferMapBit::eWrite)[index] = data;
m_lights_buffer->unmap();
}
} break;
}
}
void GBuffer::record(std::function<void()> render_function) const
......@@ -151,7 +87,8 @@ namespace glare::core
}
void GBuffer::draw() const
{
{
m_lights_buffer->upload<LightShadow>(state::lights->get(), gl::BufferUsage::eDynamicDraw);
m_temporary_framebuffer_01->activate();
static auto ssao_renderer = DefaultTextureRenderers::makeRenderer(files::shader("screenshader/ssao/ssao.frag"));
......
......@@ -21,10 +21,9 @@ namespace glare::core
public:
GBuffer(unsigned int width, unsigned int height, unsigned samples);
GBuffer();
~GBuffer();
~GBuffer() = default;
void initialize(unsigned width, unsigned height, unsigned samples);
void cleanUp();
void record(std::function<void()> render_function) const;
void activate() const;
......
......@@ -27,6 +27,7 @@ namespace glare::core
const std::shared_ptr<Skybox> skybox = std::make_shared<Skybox>();
const std::unique_ptr<GBuffer> gbuffer = std::make_unique<GBuffer>();
const std::unique_ptr<BatchRenderList> renderer = std::make_unique<BatchRenderList>();
const std::unique_ptr<BatchLightRenderer> lights = std::make_unique<BatchLightRenderer>();
void initialize(const fs::path& preferences)
{
......@@ -102,6 +103,7 @@ namespace glare::core
window->loop([&loop]() {
update();
loop();
lights->clear();
});
core::state::quit();
......@@ -169,7 +171,6 @@ namespace glare::core
//Lock message handler to not receive any messages and accessing an invalid messaging queue when destroying the node graph
messaging::Handler::getInstance().lock();
window->close();
gbuffer->cleanUp();
splash_screen.reset();
graph_root->clearChildren();
}
......
......@@ -22,6 +22,7 @@ namespace glare::core
class SplashScreen;
class Skybox;
class BatchRenderList;
class BatchLightRenderer;
namespace state
{
......@@ -37,6 +38,7 @@ namespace glare::core
extern const std::shared_ptr<GraphNode> graph_root;
extern const std::shared_ptr<Skybox> skybox;
extern const std::unique_ptr<BatchRenderList> renderer;
extern const std::unique_ptr<BatchLightRenderer> lights;
enum class DrawMode
{
......
......@@ -32,7 +32,7 @@ static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false };
static float g_MouseWheel = 0.0f;
namespace ImGui {
namespace ImGui {
std::map<ImU32, SelectableTree> nodes_cached;
namespace glfw3 {
......@@ -423,8 +423,8 @@ namespace ImGui {
void Title(const char* label)
{
ImGui::TextColored({ 0.8f, 0.6f, 0.2f, 1.0f }, label);
}
}
void TitledDescription(const char* label, const char* description)
{
ImGui::Title(label);
......@@ -432,19 +432,19 @@ namespace ImGui {
ImGui::TextWrapped(description);
}
void BeginNamedGroup(const char* name)
{
BeginGroup();
void BeginNamedGroup(const char* name)
{
BeginGroup();
PushID(name);
Title(name);
}
Title(name);
}
void EndNamedGroup()
{
PopID();
EndGroup();
}
}
bool FeatureButton(const char* label, const ImVec2& size)
{
auto &&style = ImGui::GetStyle();
......@@ -468,7 +468,31 @@ namespace ImGui {
return active;
}
bool AntiFeatureButton(const char* label, const ImVec2& size)
{
auto &&style = ImGui::GetStyle();
auto col_bt = style.Colors[ImGuiCol_Button];
auto col_bt_h = style.Colors[ImGuiCol_ButtonHovered];
auto col_bt_a = style.Colors[ImGuiCol_ButtonActive];
auto color_bt = color::hex<color::rgba32f>("#D32F2F");
auto color_bt_h = color::hex<color::rgba32f>("#F44336");
auto color_bt_a = color::hex<color::rgba32f>("#B71C1C");
style.Colors[ImGuiCol_Button] = ImVec4(color_bt.r, color_bt.g, color_bt.b, color_bt.a);
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(color_bt_h.r, color_bt_h.g, color_bt_h.b, color_bt_h.a);
style.Colors[ImGuiCol_ButtonActive] = ImVec4(color_bt_a.r, color_bt_a.g, color_bt_a.b, color_bt_a.a);
bool active = ImGui::Button(label, size);
style.Colors[ImGuiCol_Button] = col_bt;
style.Colors[ImGuiCol_ButtonHovered] = col_bt_h;
style.Colors[ImGuiCol_ButtonActive] = col_bt_a;
return active;
}
bool ComponentHeader(const char* component_name, const char* owner_name, uint64_t component_id)
{
return CollapsingHeader((std::string(component_name) + " " + std::to_string(component_id)).c_str());
......
......@@ -44,6 +44,7 @@ namespace ImGui {
void EndNamedGroup();
bool FeatureButton(const char* label, const ImVec2& size = ImVec2(0, 0));
bool AntiFeatureButton(const char* label, const ImVec2& size = ImVec2(0, 0));
bool ComponentHeader(const char* component_name, const char* owner_name, uint64_t component_id);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment