Merge remote-tracking branch 'origin/master' into AndersTest
This commit is contained in:
@@ -17,4 +17,4 @@ Libraries that are too big to be bundled with the project.
|
|||||||
|
|
||||||
| Project | Version | License | Root folder environment variable (Windows) |
|
| Project | Version | License | Root folder environment variable (Windows) |
|
||||||
| ---------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- | ------------------------------------------ |
|
| ---------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- | ------------------------------------------ |
|
||||||
| **[Boost](http://www.boost.org)** | 1.59.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT |
|
| **[Boost](http://www.boost.org)** | 1.60.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT |
|
||||||
|
|||||||
+1
-1
Submodule assets updated: 95823e122a...673d4a4e4c
+1
-1
Submodule deps updated: f20b9cc13b...1ae6ba5b12
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef EFileDropped_h__
|
||||||
|
#define EFileDropped_h__
|
||||||
|
|
||||||
|
#include "EventBroker.h"
|
||||||
|
|
||||||
|
namespace Events
|
||||||
|
{
|
||||||
|
|
||||||
|
struct FileDropped : Event
|
||||||
|
{
|
||||||
|
std::string Path;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "ELockMouse.h"
|
#include "ELockMouse.h"
|
||||||
#include "EGamepadAxis.h"
|
#include "EGamepadAxis.h"
|
||||||
#include "EGamepadButton.h"
|
#include "EGamepadButton.h"
|
||||||
|
#include "EFileDropped.h"
|
||||||
|
|
||||||
class InputManager
|
class InputManager
|
||||||
{
|
{
|
||||||
@@ -71,6 +72,8 @@ private:
|
|||||||
static void GLFWCharCallback(GLFWwindow* window, unsigned int c);
|
static void GLFWCharCallback(GLFWwindow* window, unsigned int c);
|
||||||
static std::vector<std::pair<double, double>> GLFWScrollCallbackQueue;
|
static std::vector<std::pair<double, double>> GLFWScrollCallbackQueue;
|
||||||
static void GLFWScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
static void GLFWScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||||
|
static std::vector<std::string> GLFWDropCallbackQueue;
|
||||||
|
static void GLFWDropCallback(GLFWwindow* window, int count, const char* paths[]);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ public:
|
|||||||
const ComponentPool* GetComponents(std::string componentType);
|
const ComponentPool* GetComponents(std::string componentType);
|
||||||
// Get entity parent
|
// Get entity parent
|
||||||
EntityID GetParent(EntityID entity);
|
EntityID GetParent(EntityID entity);
|
||||||
|
// Change the parent of an entity
|
||||||
|
void SetParent(EntityID entity, EntityID parent);
|
||||||
// Get all component pools
|
// Get all component pools
|
||||||
const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; }
|
const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; }
|
||||||
// Get the entity children map
|
// Get the entity children map
|
||||||
@@ -40,6 +42,7 @@ private:
|
|||||||
EntityID m_CurrentEntityID = 1;
|
EntityID m_CurrentEntityID = 1;
|
||||||
|
|
||||||
std::unordered_map<EntityID, EntityID> m_EntityParents;
|
std::unordered_map<EntityID, EntityID> m_EntityParents;
|
||||||
|
// TODO: This should be a more effective structure
|
||||||
std::unordered_multimap<EntityID, EntityID> m_EntityChildren;
|
std::unordered_multimap<EntityID, EntityID> m_EntityChildren;
|
||||||
std::unordered_map<std::string, ComponentPool*> m_ComponentPools;
|
std::unordered_map<std::string, ComponentPool*> m_ComponentPools;
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,79 @@
|
|||||||
#include <imgui/imgui.h>
|
#include <imgui/imgui.h>
|
||||||
#include <glm/gtx/common.hpp>
|
#include <glm/gtx/common.hpp>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
#include "../Core/System.h"
|
#include "../Core/System.h"
|
||||||
#include "../Core/EMousePress.h"
|
#include "../Core/EMousePress.h"
|
||||||
|
#include "../Core/EMouseRelease.h"
|
||||||
|
#include "../Core/EMouseMove.h"
|
||||||
#include "../Core/ConfigFile.h"
|
#include "../Core/ConfigFile.h"
|
||||||
#include "../Input/EInputCommand.h"
|
#include "../Input/EInputCommand.h"
|
||||||
|
#include "../Rendering/IRenderer.h"
|
||||||
#include "../Rendering/EPicking.h"
|
#include "../Rendering/EPicking.h"
|
||||||
|
#include "../Core/EFileDropped.h"
|
||||||
#include "../Rendering/RenderQueueFactory.h"
|
#include "../Rendering/RenderQueueFactory.h"
|
||||||
|
|
||||||
class EditorSystem : public ImpureSystem
|
class EditorSystem : public ImpureSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EditorSystem(EventBroker* eventBroker);
|
EditorSystem(EventBroker* eventBroker, IRenderer* renderer);
|
||||||
|
|
||||||
virtual void Update(World* world, double dt) override;
|
virtual void Update(World* world, double dt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
IRenderer* m_Renderer;
|
||||||
|
World* m_World = nullptr;
|
||||||
|
|
||||||
bool m_Enabled;
|
bool m_Enabled;
|
||||||
bool m_Visible;
|
bool m_Visible;
|
||||||
std::vector<glm::vec2> m_PickingQueue;
|
std::vector<glm::vec2> m_PickingQueue;
|
||||||
|
|
||||||
|
enum class WidgetMode
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Translate,
|
||||||
|
Rotate,
|
||||||
|
Scale
|
||||||
|
} m_WidgetMode = WidgetMode::None;
|
||||||
|
|
||||||
|
enum class WidgetSpace
|
||||||
|
{
|
||||||
|
Local,
|
||||||
|
Global
|
||||||
|
} m_WidgetSpace = WidgetSpace::Global;
|
||||||
|
|
||||||
EntityID m_Widget = 0;
|
EntityID m_Widget = 0;
|
||||||
|
EntityID m_WidgetX = 0;
|
||||||
|
EntityID m_WidgetPlaneX = 0;
|
||||||
|
EntityID m_WidgetY = 0;
|
||||||
|
EntityID m_WidgetPlaneY = 0;
|
||||||
|
EntityID m_WidgetZ = 0;
|
||||||
|
EntityID m_WidgetPlaneZ = 0;
|
||||||
|
EntityID m_WidgetOrigin = 0;
|
||||||
|
glm::vec3 m_WidgetCurrentAxis;
|
||||||
|
float m_WidgetPickingDepth = 0.f;
|
||||||
|
|
||||||
EntityID m_Selection = 0;
|
EntityID m_Selection = 0;
|
||||||
EntityID m_LastSelection = 0;
|
EntityID m_LastSelection = 0;
|
||||||
glm::vec3 m_Position;
|
glm::vec3 m_Position;
|
||||||
|
std::string m_LastDroppedFile;
|
||||||
|
|
||||||
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
|
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
|
||||||
bool OnInputCommand(const Events::InputCommand& e);
|
bool OnInputCommand(const Events::InputCommand& e);
|
||||||
|
EventRelay<EditorSystem, Events::MouseRelease> m_EMouseRelease;
|
||||||
|
bool OnMouseRelease(const Events::MouseRelease& e);
|
||||||
EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
|
EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
|
||||||
bool OnMousePress(const Events::MousePress& e);
|
bool OnMousePress(const Events::MousePress& e);
|
||||||
|
EventRelay<EditorSystem, Events::MouseMove> m_EMouseMove;
|
||||||
|
bool OnMouseMove(const Events::MouseMove& e);
|
||||||
EventRelay<EditorSystem, Events::Picking> m_EPicking;
|
EventRelay<EditorSystem, Events::Picking> m_EPicking;
|
||||||
bool OnPicking(const Events::Picking& e);
|
bool OnPicking(const Events::Picking& e);
|
||||||
|
EventRelay<EditorSystem, Events::FileDropped> m_EFileDropped;
|
||||||
|
bool OnFileDropped(const Events::FileDropped& e);
|
||||||
|
|
||||||
|
void updateWidget();
|
||||||
|
void setWidgetMode(WidgetMode newMode);
|
||||||
|
void setWidgetSpace(WidgetSpace space);
|
||||||
void drawUI(World* world, double dt);
|
void drawUI(World* world, double dt);
|
||||||
bool createDeleteButton(std::string componentType);
|
bool createDeleteButton(std::string componentType);
|
||||||
|
void changeParent(EntityID entity, EntityID newParent);
|
||||||
};
|
};
|
||||||
@@ -34,6 +34,8 @@ public:
|
|||||||
EntityID Entity;
|
EntityID Entity;
|
||||||
//World position of the "pick"
|
//World position of the "pick"
|
||||||
glm::vec3 Position;
|
glm::vec3 Position;
|
||||||
|
// Depth
|
||||||
|
float Depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
PickData Pick(glm::vec2 screenCoord) const
|
PickData Pick(glm::vec2 screenCoord) const
|
||||||
@@ -43,6 +45,7 @@ public:
|
|||||||
// Invert screen y coordinate
|
// Invert screen y coordinate
|
||||||
screenCoord.y = Resolution.Height - screenCoord.y;
|
screenCoord.y = Resolution.Height - screenCoord.y;
|
||||||
ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer);
|
ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer);
|
||||||
|
pickData.Depth = data.Depth;
|
||||||
|
|
||||||
auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1]));
|
auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1]));
|
||||||
if (it != PickingColorsToEntity->end()) {
|
if (it != PickingColorsToEntity->end()) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[Debug]
|
[Debug]
|
||||||
LogLevel=1
|
LogLevel=1
|
||||||
LoadMap=
|
LoadMap=
|
||||||
|
EditorEnabled=false
|
||||||
|
|
||||||
[Video]
|
[Video]
|
||||||
Fullscreen=false
|
Fullscreen=false
|
||||||
|
|||||||
@@ -14,3 +14,8 @@ R=Reload
|
|||||||
Space=Jump
|
Space=Jump
|
||||||
LeftControl=Crouch
|
LeftControl=Crouch
|
||||||
LeftShift=Sprint
|
LeftShift=Sprint
|
||||||
|
F1=ToggleEditor
|
||||||
|
1=EditorToolMove
|
||||||
|
2=EditorToolRotate
|
||||||
|
3=EditorToolScale
|
||||||
|
X=EditorToggleTransformSpace
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Position X="0" Y="0" Z="0"/>
|
<Position X="0" Y="0" Z="0"/>
|
||||||
<Orientation X="0" Y="0" Z="0" W="0"/>
|
<Orientation X="0" Y="0" Z="0"/>
|
||||||
<Scale X="1" Y="1" Z="1"/>
|
<Scale X="1" Y="1" Z="1"/>
|
||||||
</c:Transform>
|
</c:Transform>
|
||||||
@@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
|
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
|
||||||
<Components>
|
<Components>
|
||||||
<c:Transform></c:Transform>
|
<c:Transform>
|
||||||
|
<Position X="0" Y="0" Z="0"/>
|
||||||
|
<Orientation X="0" Y="0" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
</Components>
|
</Components>
|
||||||
<Children>
|
<Children>
|
||||||
<Entity>
|
<Entity>
|
||||||
@@ -19,12 +22,28 @@
|
|||||||
<Entity>
|
<Entity>
|
||||||
<Components>
|
<Components>
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Position X="0" Y="1" Z="0"/>
|
<Position X="1" Y="1" Z="0"/>
|
||||||
|
<Orientation X="0" Y="0.78539" Z="0"/>
|
||||||
</c:Transform>
|
</c:Transform>
|
||||||
<c:Model>
|
<c:Model>
|
||||||
<Resource>An error</Resource>
|
<Resource>An error</Resource>
|
||||||
</c:Model>
|
</c:Model>
|
||||||
</Components>
|
</Components>
|
||||||
|
<Children>
|
||||||
|
<Entity>
|
||||||
|
<Components>
|
||||||
|
<c:Transform>
|
||||||
|
<Position X="2" Y="0" Z="0"/>
|
||||||
|
<Orientation X="0" Y="0.78539" Z="0"/>
|
||||||
|
</c:Transform>
|
||||||
|
<c:Model>
|
||||||
|
<Resource>An error</Resource>
|
||||||
|
</c:Model>
|
||||||
|
</Components>
|
||||||
|
<Children>
|
||||||
|
</Children>
|
||||||
|
</Entity>
|
||||||
|
</Children>
|
||||||
</Entity>
|
</Entity>
|
||||||
</Children>
|
</Children>
|
||||||
</Entity>
|
</Entity>
|
||||||
@@ -431,12 +431,12 @@ float EntityXMLFile::getFloatAttribute(const xercesc::DOMElement* element, const
|
|||||||
{
|
{
|
||||||
using namespace xercesc;
|
using namespace xercesc;
|
||||||
XSValue::Status status;
|
XSValue::Status status;
|
||||||
XSValue* val = XSValue::getActualValue(element->getAttribute(XSTR(attribute)), xercesc::XSValue::DataType::dt_float, status);
|
XSValue* val = XSValue::getActualValue(element->getAttribute(XSTR(attribute)), xercesc::XSValue::DataType::dt_double, status);
|
||||||
if (val == nullptr) {
|
if (val == nullptr) {
|
||||||
LOG_ERROR("Element \"%s\" doesn't have an \"%s\" attribute!", XSTR(element->getTagName()), attribute);
|
LOG_ERROR("Element \"%s\" doesn't have an \"%s\" attribute!", XSTR(element->getTagName()), attribute);
|
||||||
return 0.f;
|
return 0.f;
|
||||||
} else {
|
} else {
|
||||||
return val->fData.fValue.f_float;
|
return static_cast<float>(val->fData.fValue.f_double);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
std::vector<unsigned int> InputManager::GLFWCharCallbackQueue;
|
std::vector<unsigned int> InputManager::GLFWCharCallbackQueue;
|
||||||
std::vector<std::pair<double, double>> InputManager::GLFWScrollCallbackQueue;
|
std::vector<std::pair<double, double>> InputManager::GLFWScrollCallbackQueue;
|
||||||
|
std::vector<std::string> InputManager::GLFWDropCallbackQueue;
|
||||||
|
|
||||||
void InputManager::Initialize()
|
void InputManager::Initialize()
|
||||||
{
|
{
|
||||||
@@ -10,6 +11,7 @@ void InputManager::Initialize()
|
|||||||
//m_LastGamepadButtonState = std::array<GamepadButtonState, XUSER_MAX_COUNT>();
|
//m_LastGamepadButtonState = std::array<GamepadButtonState, XUSER_MAX_COUNT>();
|
||||||
glfwSetCharCallback(m_GLFWWindow, &InputManager::GLFWCharCallback);
|
glfwSetCharCallback(m_GLFWWindow, &InputManager::GLFWCharCallback);
|
||||||
glfwSetScrollCallback(m_GLFWWindow, &InputManager::GLFWScrollCallback);
|
glfwSetScrollCallback(m_GLFWWindow, &InputManager::GLFWScrollCallback);
|
||||||
|
glfwSetDropCallback(m_GLFWWindow, &InputManager::GLFWDropCallback);
|
||||||
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse);
|
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse);
|
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse);
|
||||||
@@ -95,6 +97,14 @@ void InputManager::Update(double dt)
|
|||||||
}
|
}
|
||||||
GLFWScrollCallbackQueue.clear();
|
GLFWScrollCallbackQueue.clear();
|
||||||
|
|
||||||
|
// File drop
|
||||||
|
for (auto& path : GLFWDropCallbackQueue) {
|
||||||
|
Events::FileDropped e;
|
||||||
|
e.Path = path;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
}
|
||||||
|
GLFWDropCallbackQueue.clear();
|
||||||
|
|
||||||
// // Lock mouse while holding LMB
|
// // Lock mouse while holding LMB
|
||||||
// if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT])
|
// if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT])
|
||||||
// {
|
// {
|
||||||
@@ -229,6 +239,14 @@ void InputManager::GLFWScrollCallback(GLFWwindow* window, double xoffset, double
|
|||||||
GLFWScrollCallbackQueue.push_back(std::make_pair(xoffset, yoffset));
|
GLFWScrollCallbackQueue.push_back(std::make_pair(xoffset, yoffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InputManager::GLFWDropCallback(GLFWwindow* window, int count, const char* paths[])
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
GLFWDropCallbackQueue.push_back(std::string(paths[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool InputManager::OnLockMouse(const Events::LockMouse &event)
|
bool InputManager::OnLockMouse(const Events::LockMouse &event)
|
||||||
{
|
{
|
||||||
m_MouseLocked = true;
|
m_MouseLocked = true;
|
||||||
|
|||||||
@@ -99,6 +99,22 @@ EntityID World::GetParent(EntityID entity)
|
|||||||
return m_EntityParents.at(entity);
|
return m_EntityParents.at(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void World::SetParent(EntityID entity, EntityID parent)
|
||||||
|
{
|
||||||
|
EntityID lastParent = m_EntityParents.at(entity);
|
||||||
|
auto parentChildren = m_EntityChildren.equal_range(lastParent);
|
||||||
|
for (auto it = parentChildren.first; it != parentChildren.second; it++) {
|
||||||
|
if (it->second == entity) {
|
||||||
|
m_EntityChildren.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_EntityParents[entity] = parent;
|
||||||
|
m_EntityChildren.insert(std::make_pair(parent, entity));
|
||||||
|
}
|
||||||
|
|
||||||
EntityID World::generateEntityID()
|
EntityID World::generateEntityID()
|
||||||
{
|
{
|
||||||
// TODO: Make EntityID generation smarter
|
// TODO: Make EntityID generation smarter
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||||
#include <imgui/imgui_internal.h>
|
#include <imgui/imgui_internal.h>
|
||||||
|
|
||||||
EditorSystem::EditorSystem(EventBroker* eventBroker)
|
EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer)
|
||||||
: ImpureSystem(eventBroker)
|
: ImpureSystem(eventBroker)
|
||||||
|
, m_Renderer(renderer)
|
||||||
{
|
{
|
||||||
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
|
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||||
m_Enabled = config->Get<bool>("Debug.EditorEnabled", false);
|
m_Enabled = config->Get<bool>("Debug.EditorEnabled", false);
|
||||||
@@ -15,51 +16,58 @@ EditorSystem::EditorSystem(EventBroker* eventBroker)
|
|||||||
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystem::OnInputCommand);
|
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystem::OnInputCommand);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
|
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystem::OnMouseMove);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EPicking, &EditorSystem::OnPicking);
|
EVENT_SUBSCRIBE_MEMBER(m_EPicking, &EditorSystem::OnPicking);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystem::OnFileDropped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorSystem::Update(World* world, double dt)
|
void EditorSystem::Update(World* world, double dt)
|
||||||
{
|
{
|
||||||
|
m_World = world;
|
||||||
|
|
||||||
if (!m_Enabled) {
|
if (!m_Enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Widget == 0) {
|
|
||||||
m_Widget = world->CreateEntity();
|
|
||||||
world->AttachComponent(m_Widget, "Transform");
|
|
||||||
auto& model = world->AttachComponent(m_Widget, "Model");
|
|
||||||
model["Resource"] = "Models/TranslationWidget.obj";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Selection != m_LastSelection) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& widgetModel = world->GetComponent(m_Widget, "Model");
|
|
||||||
widgetModel["Visible"] = m_Visible;
|
|
||||||
if (m_Selection != 0) {
|
|
||||||
if (world->HasComponent(m_Selection, "Transform")) {
|
|
||||||
glm::vec3 pos = RenderQueueFactory::AbsolutePosition(world, m_Selection);
|
|
||||||
auto widgetTransform = world->GetComponent(m_Widget, "Transform");
|
|
||||||
widgetTransform["Position"] = pos;
|
|
||||||
} else {
|
|
||||||
m_Selection = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_Visible) {
|
if (!m_Visible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawUI(world, dt);
|
updateWidget();
|
||||||
}
|
|
||||||
|
|
||||||
|
drawUI(world, dt);
|
||||||
|
|
||||||
|
// Clear drop queue if it wasn't handled by any UI element
|
||||||
|
if (!m_LastDroppedFile.empty()) {
|
||||||
|
m_LastDroppedFile = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool EditorSystem::OnInputCommand(const Events::InputCommand& e)
|
bool EditorSystem::OnInputCommand(const Events::InputCommand& e)
|
||||||
{
|
{
|
||||||
if (e.Command == "ToggleEditor" && e.Value > 0) {
|
if (e.Command == "ToggleEditor" && e.Value > 0) {
|
||||||
m_Visible = !m_Visible;
|
m_Visible = !m_Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e.Command == "EditorToolMove" && e.Value > 0) {
|
||||||
|
setWidgetMode(WidgetMode::Translate);
|
||||||
|
}
|
||||||
|
if (e.Command == "EditorToolRotate" && e.Value > 0) {
|
||||||
|
setWidgetMode(WidgetMode::Rotate);
|
||||||
|
}
|
||||||
|
if (e.Command == "EditorToolScale" && e.Value > 0) {
|
||||||
|
setWidgetMode(WidgetMode::Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.Command == "EditorToggleTransformSpace" && e.Value > 0) {
|
||||||
|
if (m_WidgetSpace == WidgetSpace::Global) {
|
||||||
|
setWidgetSpace(WidgetSpace::Local);
|
||||||
|
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
||||||
|
setWidgetSpace(WidgetSpace::Global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,17 +79,273 @@ bool EditorSystem::OnMousePress(const Events::MousePress& e)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EditorSystem::OnMouseMove(const Events::MouseMove& e)
|
||||||
|
{
|
||||||
|
if (m_Widget == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Selection == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
||||||
|
glm::vec3 widgetOrientation = widgetTransform["Orientation"];
|
||||||
|
|
||||||
|
glm::quat totalOrientation = m_Renderer->Camera()->Orientation() * glm::inverse(glm::quat(widgetOrientation));
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
glfwGetFramebufferSize(m_Renderer->Window(), &width, &height);
|
||||||
|
Rectangle res(width, height);
|
||||||
|
|
||||||
|
glm::vec2 delta2(res.Width / 2.f + e.DeltaX, res.Height / 2.f + -e.DeltaY);
|
||||||
|
glm::vec3 deltaWorld = ScreenCoords::ToWorldPos(
|
||||||
|
delta2,
|
||||||
|
m_WidgetPickingDepth,
|
||||||
|
res,
|
||||||
|
m_Renderer->Camera()->ProjectionMatrix(),
|
||||||
|
glm::toMat4(glm::inverse(totalOrientation))
|
||||||
|
);
|
||||||
|
glm::vec3 origin = ScreenCoords::ToWorldPos(
|
||||||
|
glm::vec2(res.Width / 2.f, res.Height / 2.f),
|
||||||
|
m_WidgetPickingDepth,
|
||||||
|
res,
|
||||||
|
m_Renderer->Camera()->ProjectionMatrix(),
|
||||||
|
glm::toMat4(glm::inverse(totalOrientation))
|
||||||
|
);
|
||||||
|
deltaWorld = deltaWorld - origin;
|
||||||
|
glm::vec3 movement = deltaWorld * m_WidgetCurrentAxis;
|
||||||
|
|
||||||
|
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
|
||||||
|
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
||||||
|
if (m_WidgetMode == WidgetMode::Translate) {
|
||||||
|
if (m_WidgetSpace == WidgetSpace::Global) {
|
||||||
|
EntityID parent = m_World->GetParent(m_Selection);
|
||||||
|
glm::quat inverseParentOrientation;
|
||||||
|
if (parent != 0) {
|
||||||
|
inverseParentOrientation = glm::inverse(RenderQueueFactory::AbsoluteOrientation(m_World, parent));
|
||||||
|
}
|
||||||
|
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Position"] += inverseParentOrientation * movement;
|
||||||
|
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
||||||
|
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
||||||
|
(glm::vec3&)selectionTransform["Position"] += glm::quat((glm::vec3)selectionTransform["Orientation"]) * movement;
|
||||||
|
}
|
||||||
|
} else if (m_WidgetMode == WidgetMode::Rotate) {
|
||||||
|
glm::vec3 finalMovement;
|
||||||
|
finalMovement.x = -deltaWorld.y * m_WidgetCurrentAxis.x;
|
||||||
|
finalMovement.y = deltaWorld.x * m_WidgetCurrentAxis.y;
|
||||||
|
finalMovement.z = deltaWorld.y * m_WidgetCurrentAxis.z;
|
||||||
|
if (m_WidgetSpace == WidgetSpace::Global) {
|
||||||
|
EntityID parent = m_World->GetParent(m_Selection);
|
||||||
|
glm::quat parentOrientation;
|
||||||
|
if (parent != 0) {
|
||||||
|
parentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, parent);
|
||||||
|
}
|
||||||
|
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
|
||||||
|
//glm::quat currentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection);
|
||||||
|
glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation);
|
||||||
|
glm::quat deltaOrientation(finalMovement);
|
||||||
|
selectionOrientation = glm::eulerAngles(glm::inverse(parentOrientation) * (deltaOrientation * currentOrientation));
|
||||||
|
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
||||||
|
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
|
||||||
|
glm::quat currentOrientation(selectionOrientation);
|
||||||
|
glm::quat deltaOrientation(finalMovement);
|
||||||
|
selectionOrientation = glm::eulerAngles(currentOrientation * deltaOrientation);
|
||||||
|
}
|
||||||
|
} else if (m_WidgetMode == WidgetMode::Scale) {
|
||||||
|
glm::vec3& scaleX = m_World->GetComponent(m_WidgetX, "Transform")["Scale"];
|
||||||
|
glm::vec3& scaleY = m_World->GetComponent(m_WidgetY, "Transform")["Scale"];
|
||||||
|
glm::vec3& scaleZ = m_World->GetComponent(m_WidgetZ, "Transform")["Scale"];
|
||||||
|
|
||||||
|
if (m_WidgetCurrentAxis.x > 0 && m_WidgetCurrentAxis.y > 0 && m_WidgetCurrentAxis.z > 0) {
|
||||||
|
float movementLength = glm::length(movement);
|
||||||
|
float dot = glm::dot((glm::vec3)widgetOrientation, movement);
|
||||||
|
movement = glm::vec3(movementLength) * glm::sign(dot);
|
||||||
|
(glm::vec3&)m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] += movement;
|
||||||
|
}
|
||||||
|
if (m_WidgetCurrentAxis.x > 0) {
|
||||||
|
scaleX.x += movement.x;
|
||||||
|
}
|
||||||
|
if (m_WidgetCurrentAxis.y > 0) {
|
||||||
|
scaleY.y += movement.y;
|
||||||
|
}
|
||||||
|
if (m_WidgetCurrentAxis.z > 0) {
|
||||||
|
scaleZ.z += movement.z;
|
||||||
|
}
|
||||||
|
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Scale"] += movement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*LOG_DEBUG("DELTA %f", e.DeltaX);
|
||||||
|
if (e.X < 0) {
|
||||||
|
glfwSetCursorPos(m_Renderer->Window(), width - 1, e.Y);
|
||||||
|
}
|
||||||
|
if (e.X >= width) {
|
||||||
|
glfwSetCursorPos(m_Renderer->Window(), 0, e.Y);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e)
|
||||||
|
{
|
||||||
|
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
|
||||||
|
m_WidgetCurrentAxis = glm::vec3(0.f);
|
||||||
|
//setWidgetMode(m_WidgetMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool EditorSystem::OnPicking(const Events::Picking& e)
|
bool EditorSystem::OnPicking(const Events::Picking& e)
|
||||||
{
|
{
|
||||||
for (auto& pos : m_PickingQueue) {
|
for (auto& pos : m_PickingQueue) {
|
||||||
auto result = e.Pick(pos);
|
auto result = e.Pick(pos);
|
||||||
LOG_INFO("Selected %i", result.Entity);
|
EntityID entity = result.Entity;
|
||||||
m_Selection = result.Entity;
|
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
|
||||||
|
} else {
|
||||||
|
LOG_INFO("Selected %i", entity);
|
||||||
|
if (entity != 0) {
|
||||||
|
EntityID parent = m_World->GetParent(entity);
|
||||||
|
if (parent == m_Widget) {
|
||||||
|
m_WidgetCurrentAxis = glm::vec3(
|
||||||
|
(entity == m_WidgetX) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneY || entity == m_WidgetPlaneZ),
|
||||||
|
(entity == m_WidgetY) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneZ),
|
||||||
|
(entity == m_WidgetZ) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneY)
|
||||||
|
);
|
||||||
|
m_WidgetPickingDepth = result.Depth;
|
||||||
|
|
||||||
|
//auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
||||||
|
//auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
||||||
|
//widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"];
|
||||||
|
} else {
|
||||||
|
ImGui::SetActiveID(0, nullptr);
|
||||||
|
m_Selection = entity;
|
||||||
|
setWidgetMode(m_WidgetMode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_Selection = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_PickingQueue.clear();
|
m_PickingQueue.clear();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool EditorSystem::OnFileDropped(const Events::FileDropped& e)
|
||||||
|
{
|
||||||
|
m_LastDroppedFile = boost::filesystem::path(e.Path).lexically_relative(boost::filesystem::current_path()).string();
|
||||||
|
std::replace(m_LastDroppedFile.begin(), m_LastDroppedFile.end(), '\\', '/');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorSystem::updateWidget()
|
||||||
|
{
|
||||||
|
if (m_Widget == 0) {
|
||||||
|
m_Widget = m_World->CreateEntity();
|
||||||
|
m_World->AttachComponent(m_Widget, "Transform");
|
||||||
|
m_WidgetX = m_World->CreateEntity(m_Widget);
|
||||||
|
m_World->AttachComponent(m_WidgetX, "Transform");
|
||||||
|
m_World->AttachComponent(m_WidgetX, "Model");
|
||||||
|
m_WidgetPlaneX = m_World->CreateEntity(m_Widget);
|
||||||
|
m_World->AttachComponent(m_WidgetPlaneX, "Transform");
|
||||||
|
m_World->AttachComponent(m_WidgetPlaneX, "Model");
|
||||||
|
m_World->GetComponent(m_WidgetPlaneX, "Model")["Resource"] = "Models/WidgetPlaneX.obj";
|
||||||
|
m_WidgetY = m_World->CreateEntity(m_Widget);
|
||||||
|
m_World->AttachComponent(m_WidgetY, "Transform");
|
||||||
|
m_World->AttachComponent(m_WidgetY, "Model");
|
||||||
|
m_WidgetPlaneY = m_World->CreateEntity(m_Widget);
|
||||||
|
m_World->AttachComponent(m_WidgetPlaneY, "Transform");
|
||||||
|
m_World->AttachComponent(m_WidgetPlaneY, "Model");
|
||||||
|
m_World->GetComponent(m_WidgetPlaneY, "Model")["Resource"] = "Models/WidgetPlaneY.obj";
|
||||||
|
m_WidgetZ = m_World->CreateEntity(m_Widget);
|
||||||
|
m_World->AttachComponent(m_WidgetZ, "Transform");
|
||||||
|
m_World->AttachComponent(m_WidgetZ, "Model");
|
||||||
|
m_WidgetPlaneZ = m_World->CreateEntity(m_Widget);
|
||||||
|
m_World->AttachComponent(m_WidgetPlaneZ, "Transform");
|
||||||
|
m_World->AttachComponent(m_WidgetPlaneZ, "Model");
|
||||||
|
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Resource"] = "Models/WidgetPlaneZ.obj";
|
||||||
|
m_WidgetOrigin = m_World->CreateEntity(m_Widget);
|
||||||
|
m_World->AttachComponent(m_WidgetOrigin, "Transform");
|
||||||
|
m_World->AttachComponent(m_WidgetOrigin, "Model");
|
||||||
|
setWidgetMode(WidgetMode::Translate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Selection != 0) {
|
||||||
|
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
||||||
|
glm::vec3 selectionPosition = RenderQueueFactory::AbsolutePosition(m_World, m_Selection);
|
||||||
|
widgetTransform["Position"] = selectionPosition;
|
||||||
|
if (m_WidgetSpace == WidgetSpace::Local) {
|
||||||
|
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorSystem::setWidgetMode(WidgetMode newMode)
|
||||||
|
{
|
||||||
|
if (m_Widget == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
||||||
|
widgetTransform["Orientation"] = glm::vec3(0.f);
|
||||||
|
m_World->GetComponent(m_WidgetX, "Transform")["Scale"] = glm::vec3(1.f);
|
||||||
|
m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = false;
|
||||||
|
m_World->GetComponent(m_WidgetY, "Transform")["Scale"] = glm::vec3(1.f);
|
||||||
|
m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = false;
|
||||||
|
m_World->GetComponent(m_WidgetZ, "Transform")["Scale"] = glm::vec3(1.f);
|
||||||
|
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = false;
|
||||||
|
m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(1.f);
|
||||||
|
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false;
|
||||||
|
|
||||||
|
if (newMode == WidgetMode::Translate) {
|
||||||
|
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/TranslationWidgetX.obj";
|
||||||
|
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/TranslationWidgetY.obj";
|
||||||
|
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/TranslationWidgetZ.obj";
|
||||||
|
// Temporarily disabled for local space until I can figure out what's wrong with the math
|
||||||
|
if (m_WidgetSpace != WidgetSpace::Local) {
|
||||||
|
m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = true;
|
||||||
|
m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = true;
|
||||||
|
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = true;
|
||||||
|
}
|
||||||
|
if (m_Selection != 0) {
|
||||||
|
if (m_WidgetSpace == WidgetSpace::Local) {
|
||||||
|
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
||||||
|
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (newMode == WidgetMode::Scale) {
|
||||||
|
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/ScaleWidgetX.obj";
|
||||||
|
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/ScaleWidgetY.obj";
|
||||||
|
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/ScaleWidgetZ.obj";
|
||||||
|
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = true;
|
||||||
|
m_World->GetComponent(m_WidgetOrigin, "Model")["Resource"] = "Models/ScaleWidgetOrigin.obj";
|
||||||
|
if (m_Selection != 0) {
|
||||||
|
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
||||||
|
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
||||||
|
}
|
||||||
|
} else if (newMode == WidgetMode::Rotate) {
|
||||||
|
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj";
|
||||||
|
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/RotationWidgetY.obj";
|
||||||
|
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/RotationWidgetZ.obj";
|
||||||
|
if (m_Selection != 0) {
|
||||||
|
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
||||||
|
if (m_WidgetSpace == WidgetSpace::Local) {
|
||||||
|
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_WidgetMode = newMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EditorSystem::setWidgetSpace(WidgetSpace space)
|
||||||
|
{
|
||||||
|
m_WidgetSpace = space;
|
||||||
|
setWidgetMode(m_WidgetMode);
|
||||||
|
}
|
||||||
|
|
||||||
void EditorSystem::drawUI(World* world, double dt)
|
void EditorSystem::drawUI(World* world, double dt)
|
||||||
{
|
{
|
||||||
ImGui::ShowTestWindow();
|
ImGui::ShowTestWindow();
|
||||||
@@ -102,24 +366,32 @@ void EditorSystem::drawUI(World* world, double dt)
|
|||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Move")) {
|
if (ImGui::Button("Move")) {
|
||||||
auto& model = world->GetComponent(m_Widget, "Model");
|
setWidgetMode(WidgetMode::Translate);
|
||||||
model["Resource"] = "Models/TranslationWidget.obj";
|
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Rotate")) {
|
if (ImGui::Button("Rotate")) {
|
||||||
auto& model = world->GetComponent(m_Widget, "Model");
|
setWidgetMode(WidgetMode::Rotate);
|
||||||
model["Resource"] = "Models/RotationWidget.obj";
|
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Scale")) {
|
if (ImGui::Button("Scale")) {
|
||||||
auto& model = world->GetComponent(m_Widget, "Model");
|
setWidgetMode(WidgetMode::Scale);
|
||||||
model["Resource"] = "Models/ScaleWidget.obj";
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (m_WidgetSpace == WidgetSpace::Global) {
|
||||||
|
if (ImGui::Button("(Global)")) {
|
||||||
|
setWidgetSpace(WidgetSpace::Local);
|
||||||
|
}
|
||||||
|
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
||||||
|
if (ImGui::Button("(Local)")) {
|
||||||
|
setWidgetSpace(WidgetSpace::Global);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Begin("Components")) {
|
std::string title = std::string("Components #") + std::to_string(m_Selection) + std::string("###Components");
|
||||||
|
if (ImGui::Begin(title.c_str())) {
|
||||||
if (m_Selection != 0) {
|
if (m_Selection != 0) {
|
||||||
auto& pools = world->GetComponentPools();
|
auto& pools = world->GetComponentPools();
|
||||||
|
|
||||||
@@ -164,37 +436,53 @@ void EditorSystem::drawUI(World* world, double dt)
|
|||||||
const std::string& field = pair.first;
|
const std::string& field = pair.first;
|
||||||
const std::string& type = pair.second;
|
const std::string& type = pair.second;
|
||||||
|
|
||||||
|
ImGui::PushID(field.c_str());
|
||||||
if (type == "Vector") {
|
if (type == "Vector") {
|
||||||
auto& val = component.Property<glm::vec3>(field);
|
auto& val = component.Property<glm::vec3>(field);
|
||||||
if (field == "Scale") {
|
if (field == "Scale") {
|
||||||
ImGui::DragFloat3(field.c_str(), glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
|
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
|
||||||
} else if (field == "Orientation") {
|
} else if (field == "Orientation") {
|
||||||
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
|
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
|
||||||
if (ImGui::SliderFloat3(field.c_str(), glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
|
if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
|
||||||
val = tempVal;
|
val = tempVal;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ImGui::DragFloat3(field.c_str(), glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
|
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
|
||||||
}
|
}
|
||||||
} else if (type == "Color") {
|
} else if (type == "Color") {
|
||||||
auto& val = component.Property<glm::vec4>(field);
|
auto& val = component.Property<glm::vec4>(field);
|
||||||
ImGui::ColorEdit4(field.c_str(), glm::value_ptr(val), true);
|
ImGui::ColorEdit4("", glm::value_ptr(val), true);
|
||||||
} else if (type == "string") {
|
} else if (type == "string") {
|
||||||
std::string& val = component.Property<std::string>(field);
|
std::string& val = component.Property<std::string>(field);
|
||||||
char tempString[1024];
|
char tempString[1024];
|
||||||
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString)));
|
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString)));
|
||||||
if (ImGui::InputText(field.c_str(), tempString, sizeof(tempString))) {
|
if (ImGui::InputText("", tempString, sizeof(tempString))) {
|
||||||
val = std::string(tempString);
|
val = std::string(tempString);
|
||||||
LOG_DEBUG("%s::%s changed!", componentType.c_str(), field.c_str());
|
LOG_DEBUG("%s::%s changed!", componentType.c_str(), field.c_str());
|
||||||
}
|
}
|
||||||
|
// DROP STUFF
|
||||||
|
if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) {
|
||||||
|
val = m_LastDroppedFile;
|
||||||
|
m_LastDroppedFile = "";
|
||||||
|
}
|
||||||
|
|
||||||
} else if (type == "double") {
|
} else if (type == "double") {
|
||||||
float tempVal = static_cast<float>(component.Property<double>(field));
|
float tempVal = static_cast<float>(component.Property<double>(field));
|
||||||
if (ImGui::InputFloat(field.c_str(), &tempVal, 0.01f, 1.f)) {
|
if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) {
|
||||||
component.SetProperty(field, static_cast<double>(tempVal));
|
component.SetProperty(field, static_cast<double>(tempVal));
|
||||||
}
|
}
|
||||||
} else if (type == "bool") {
|
} else if (type == "bool") {
|
||||||
auto& val = component.Property<bool>(field);
|
auto& val = component.Property<bool>(field);
|
||||||
ImGui::Checkbox(field.c_str(), &val);
|
ImGui::Checkbox("", &val);
|
||||||
|
} else {
|
||||||
|
ImGui::TextDisabled(type.c_str());
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text(field.c_str());
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("field annotation goes here");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,23 +493,62 @@ void EditorSystem::drawUI(World* world, double dt)
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if (ImGui::Begin("Entitites")) {
|
if (ImGui::Begin("Entitites")) {
|
||||||
|
static EntityID draggingEntity = 0;
|
||||||
auto entityChildren = world->GetEntityChildren();
|
auto entityChildren = world->GetEntityChildren();
|
||||||
std::function<void(EntityID)> recurse = [&](EntityID parent) {
|
std::function<void(EntityID)> recurse = [&](EntityID parent) {
|
||||||
auto range = entityChildren.equal_range(parent);
|
auto range = entityChildren.equal_range(parent);
|
||||||
for (auto it = range.first; it != range.second; it++) {
|
for (auto it = range.first; it != range.second; it++) {
|
||||||
|
|
||||||
|
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||||
|
float width = ImGui::GetContentRegionAvailWidth();
|
||||||
|
ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 13));
|
||||||
|
auto window = ImGui::GetCurrentWindow();
|
||||||
|
if (m_Selection == it->second) {
|
||||||
|
const ImU32 col = window->Color(ImGuiCol_HeaderActive);
|
||||||
|
window->DrawList->AddRectFilled(bb.Min, bb.Max, col);
|
||||||
|
}
|
||||||
|
ImGuiID id = window->GetID((std::string("#SelectButton") + std::to_string(it->second)).c_str());
|
||||||
|
bool hovered = false;
|
||||||
|
bool held = false;
|
||||||
|
if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) {
|
||||||
|
m_Selection = it->second;
|
||||||
|
}
|
||||||
|
if (held) {
|
||||||
|
ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0);
|
||||||
|
if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) {
|
||||||
|
if (draggingEntity == 0) {
|
||||||
|
draggingEntity = it->second;
|
||||||
|
LOG_DEBUG("Started drag of entity %i", draggingEntity);
|
||||||
|
}
|
||||||
|
ImGui::SetNextWindowPos(ImGui::GetIO().MousePos + ImVec2(20, 0));
|
||||||
|
ImGui::Begin("Change parent", nullptr, ImVec2(0, 0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings);
|
||||||
|
ImGui::Text("#%i", draggingEntity);
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
|
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
|
||||||
if (ImGui::TreeNode((std::string("#") + std::to_string(it->second)).c_str())) {
|
if (ImGui::TreeNode((std::string("#") + std::to_string(it->second)).c_str())) {
|
||||||
if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(0)) {
|
if (draggingEntity != 0 && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) {
|
||||||
m_Selection = it->second;
|
LOG_DEBUG("Changed parent of %i to %i", draggingEntity, it->second);
|
||||||
|
changeParent(draggingEntity, it->second);
|
||||||
|
draggingEntity = 0;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Add")) {
|
if (ImGui::BeginPopupContextItem("item context menu")) {
|
||||||
EntityID entity = world->CreateEntity(it->second);
|
if (ImGui::Button("Add")) {
|
||||||
world->AttachComponent(entity, "Transform");
|
EntityID entity = world->CreateEntity(it->second);
|
||||||
}
|
world->AttachComponent(entity, "Transform");
|
||||||
ImGui::SameLine();
|
}
|
||||||
if (ImGui::Button("Delete")) {
|
ImGui::SameLine();
|
||||||
world->DeleteEntity(it->second);
|
if (ImGui::Button("Delete")) {
|
||||||
|
world->DeleteEntity(it->second);
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
if (m_Selection == it->second) {
|
||||||
|
m_Selection = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
recurse(it->second);
|
recurse(it->second);
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
@@ -250,3 +577,20 @@ bool EditorSystem::createDeleteButton(std::string componentType)
|
|||||||
window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16);
|
window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16);
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorSystem::changeParent(EntityID entity, EntityID newParent)
|
||||||
|
{
|
||||||
|
if (entity == newParent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An entity can't be a child to one of its own children
|
||||||
|
auto children = m_World->GetEntityChildren().equal_range(entity);
|
||||||
|
for (auto it = children.first; it != children.second; it++) {
|
||||||
|
if (it->second == newParent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_World->SetParent(entity, newParent);
|
||||||
|
}
|
||||||
|
|||||||
@@ -76,13 +76,15 @@ RawModel::RawModel(std::string fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Material diffuse color
|
// Material diffuse color
|
||||||
aiColor4D diffuse;
|
aiColor3D diffuse;
|
||||||
material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
|
material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
|
||||||
desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, diffuse.a);
|
float opacity;
|
||||||
|
material->Get(AI_MATKEY_OPACITY, opacity);
|
||||||
|
desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, opacity);
|
||||||
// Material specular color
|
// Material specular color
|
||||||
aiColor4D specular;
|
aiColor3D specular;
|
||||||
material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
|
material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
|
||||||
desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, specular.a);
|
desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, 1.f);
|
||||||
|
|
||||||
m_Vertices.push_back(desc);
|
m_Vertices.push_back(desc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,8 +139,6 @@ void Renderer::Draw(RenderQueueCollection& rq)
|
|||||||
//CullLights();
|
//CullLights();
|
||||||
|
|
||||||
glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 1.f);
|
glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 1.f);
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
m_DrawScenePass->Draw(rq);
|
m_DrawScenePass->Draw(rq);
|
||||||
GLERROR("Renderer::Draw m_DrawScenePass->Draw");
|
GLERROR("Renderer::Draw m_DrawScenePass->Draw");
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ Game::Game(int argc, char* argv[])
|
|||||||
m_SystemPipeline = new SystemPipeline(m_EventBroker);
|
m_SystemPipeline = new SystemPipeline(m_EventBroker);
|
||||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>();
|
m_SystemPipeline->AddSystem<RaptorCopterSystem>();
|
||||||
m_SystemPipeline->AddSystem<PlayerSystem>();
|
m_SystemPipeline->AddSystem<PlayerSystem>();
|
||||||
m_SystemPipeline->AddSystem<EditorSystem>();
|
m_SystemPipeline->AddSystem<EditorSystem>(m_Renderer);
|
||||||
|
|
||||||
m_LastTime = glfwGetTime();
|
m_LastTime = glfwGetTime();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user