diff --git a/assets b/assets index 9b2fa74a..091ad5c0 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 9b2fa74a6d535d512c13429997385f7aa3fb50f5 +Subproject commit 091ad5c01bf7b6ef5501fc907fc610576a4a45ea diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 29a0d2e0..cd10dbb2 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -59,7 +59,6 @@ bool AABBVsAABB(const AABB& a, const AABB& b); //Return true if the boxes are intersecting. //Also outputs the minimum translation that box [a] would need in order to resolve collision. bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation); -bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon = 0.0001f); // Calculates an absolute AABB from an entity AABB component boost::optional EntityAbsoluteAABB(EntityWrapper& entity); diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index aff5f8ea..f3a7e4fe 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -7,7 +7,6 @@ #include "../Common.h" #include "../Core/System.h" #include "../Core/EventBroker.h" -#include "../Core/EKeyUp.h" #include "../Core/Octree.h" #include "EntityAABB.h" @@ -18,20 +17,13 @@ public: : System(world, eventBroker) , PureSystem("Collidable") , m_Octree(octree) - , zPress(false) - { - //TODO: Debug stuff, remove later. - EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp); - } + { } virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: Octree* m_Octree; - bool zPress; - - EventRelay m_EKeyUp; - bool OnKeyUp(const Events::KeyUp &event); + std::vector m_OctreeResult; }; #endif \ No newline at end of file diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 973f6a90..7a0289c6 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "../Common.h" #include "../GLM.h" #include @@ -18,6 +19,8 @@ #include "../Core/ResourceManager.h" #include "../Core/EPause.h" #include "../Core/EKeyDown.h" +#include "../Core/ELockMouse.h" +#include "../Core/EFileDropped.h" #include "../Rendering/Texture.h" class EditorGUI @@ -32,6 +35,12 @@ public: Scale }; + enum class WidgetSpace + { + Global, + Local + }; + void Draw(); void SelectEntity(EntityWrapper entity); @@ -73,6 +82,9 @@ public: // Called when the user selects a widget mode. typedef std::function OnWidgetMode_t; void SetWidgetModeCallback(OnWidgetMode_t f) { m_OnWidgetMode = f; } + // Called when the user selects a widget space. + typedef std::function OnWidgetSpace_t; + void SetWidgetSpaceCallback(OnWidgetSpace_t f) { m_OnWidgetSpace = f; } private: World* m_World; @@ -93,8 +105,12 @@ private: EntityWrapper m_CurrentlyDragging = EntityWrapper::Invalid; std::string m_LastErrorMessage; WidgetMode m_CurrentWidgetMode = WidgetMode::Translate; + WidgetSpace m_CurrentWidgetSpace = WidgetSpace::Global; std::set m_ModalsToOpen; std::map m_ModalData; + std::string m_DroppedFile = ""; + bool m_Paused = false; + bool m_MouseLocked = false; // Callbacks OnEntitySelectedCallback_t m_OnEntitySelected = nullptr; @@ -107,10 +123,21 @@ private: OnComponentAttach_t m_OnComponentAttach = nullptr; OnComponentDelete_t m_OnComponentDelete = nullptr; OnWidgetMode_t m_OnWidgetMode = nullptr; + OnWidgetSpace_t m_OnWidgetSpace = nullptr; // Events EventRelay m_EKeyDown; bool OnKeyDown(const Events::KeyDown& e); + EventRelay m_EFileDropped; + bool OnFileDropped(const Events::FileDropped& e); + EventRelay m_EPause; + bool OnPause(const Events::Pause& e); + EventRelay m_EResume; + bool OnResume(const Events::Resume& e); + EventRelay m_ELockMouse; + bool OnLockMouse(const Events::LockMouse& e); + EventRelay m_EUnlockMouse; + bool OnUnlockMouse(const Events::UnlockMouse& e); // Utility functions boost::filesystem::path fileOpenDialog(); @@ -118,6 +145,9 @@ private: const std::string formatEntityName(EntityWrapper entity); GLuint tryLoadTexture(std::string filePath); void openModal(const std::string& modal); + void setWidgetMode(WidgetMode mode); + void toggleWidgetSpace(); + static bool compareCharArray(const char* c1, const char* c2); // Entity file handling methods void entityImport(World* world); diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 2db24ba3..accf66e4 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -41,6 +41,7 @@ private: double m_LastTime = 0.f; bool m_Enabled = true; EditorGUI::WidgetMode m_WidgetMode = EditorGUI::WidgetMode::Translate; + EditorGUI::WidgetSpace m_WidgetSpace = EditorGUI::WidgetSpace::Global; EntityWrapper m_Widget = EntityWrapper::Invalid; EntityWrapper m_CurrentSelection = EntityWrapper::Invalid; @@ -57,6 +58,7 @@ private: void OnEntityChangeName(EntityWrapper entity, const std::string& name); void OnComponentAttach(EntityWrapper entity, const std::string& componentType); void OnComponentDelete(EntityWrapper entity, const std::string& componentType); + void OnWidgetSpace(EditorGUI::WidgetSpace widgetSpace); // Events EventRelay m_EMousePress; diff --git a/include/Engine/Rendering/IRenderer.h b/include/Engine/Rendering/IRenderer.h index 708b87a6..b399aefa 100644 --- a/include/Engine/Rendering/IRenderer.h +++ b/include/Engine/Rendering/IRenderer.h @@ -25,16 +25,15 @@ class IRenderer { public: GLFWwindow* Window() const { return m_Window; } - //Returns screensize including window border and header + //Returns screen size including window border and header Rectangle Resolution() const { return m_Resolution; } - void SetResolution(const Rectangle& resolution) { m_Resolution = resolution; } + virtual void SetResolution(const Rectangle& resolution) { m_Resolution = resolution; } bool Fullscreen() { return m_Fullscreen; } - void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; } + virtual void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; } bool VSYNC() const { return m_VSYNC; } - void SetVSYNC(bool vsync) { m_VSYNC = vsync; } - //Returns screensize excluding window border and header - Rectangle GetViewPortSize() const { return m_ViewPortWidth; } - void SetViewPortSize(const Rectangle& viewportWidth) { m_ViewPortWidth = viewportWidth; } + virtual void SetVSYNC(bool vsync) { m_VSYNC = vsync; } + //Returns screen size excluding window border and header + Rectangle GetViewportSize() const { return m_ViewportSize; } virtual void Initialize() = 0; virtual void Update(double dt) = 0; virtual void Draw(RenderFrame& rq) = 0; @@ -42,7 +41,7 @@ public: protected: Rectangle m_Resolution = Rectangle::Rectangle(1280, 720); - Rectangle m_ViewPortWidth = Rectangle::Rectangle(1280, 720); + Rectangle m_ViewportSize = Rectangle::Rectangle(1280, 720); bool m_Fullscreen = false; bool m_VSYNC = false; int m_GLVersion[2]; diff --git a/resources/DefaultInput.ini b/resources/DefaultInput.ini index d07ed6a3..a3f7d166 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -15,10 +15,6 @@ Space=Jump LeftControl=Crouch LeftShift=Sprint F1=ToggleEditor -1=EditorToolMove -2=EditorToolRotate -3=EditorToolScale -X=EditorToggleTransformSpace C=ConnectToServer N=SwitchToServer M=SwitchToClient diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index aad012da..3f5cf0d3 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -239,20 +239,6 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model return hit; } -bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) -{ - const glm::vec3& ma1 = first.MaxCorner(); - const glm::vec3& ma2 = second.MaxCorner(); - const glm::vec3& mi1 = first.MinCorner(); - const glm::vec3& mi2 = second.MinCorner(); - return (std::abs(ma1.x - ma2.x) < epsilon) && - (std::abs(mi1.x - mi2.x) < epsilon) && - (std::abs(ma1.z - ma2.z) < epsilon) && - (std::abs(mi1.z - mi2.z) < epsilon) && - (std::abs(ma1.y - ma2.y) < epsilon) && - (std::abs(mi1.y - mi2.y) < epsilon); -} - bool attachAABBComponentFromModel(World* world, EntityID id) { if (!world->HasComponent(id, "Model")) { diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 3c07db11..382238e7 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -16,22 +16,20 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c ComponentWrapper& cTransform = entity["Transform"]; EntityAABB& boxA = *boundingBox; - //Press 'Z' to enable/disable collision. - if (zPress) { - return; - } - - // Collide against octree - std::vector octreeResult; - m_Octree->ObjectsInSameRegion(*boundingBox, octreeResult); - for (auto& boxB : octreeResult) { + // Collide against octree items + m_OctreeResult.clear(); + m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult); + for (auto& boxB : m_OctreeResult) { glm::vec3 resolutionVector; - if (Collision::IsSameBoxProbably(boxA, boxB)) { + if (boxA.Entity == boxB.Entity) { continue; } + if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; - ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; + if (resolutionVector.y > 0) { + ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; + } } } @@ -56,12 +54,4 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c // (glm::vec3&)cTransform["Position"] += resolutionVector; // } //} -} - -bool CollisionSystem::OnKeyUp(const Events::KeyUp & event) -{ - if (event.KeyCode == GLFW_KEY_Z) { - zPress = !zPress; - } - return false; -} +} \ No newline at end of file diff --git a/src/Engine/Core/Octree.cpp b/src/Engine/Core/Octree.cpp index 18effea5..f3cafcfc 100644 --- a/src/Engine/Core/Octree.cpp +++ b/src/Engine/Core/Octree.cpp @@ -105,8 +105,7 @@ bool Child::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const for (int i : m_DynamicObjIndices) { if (!m_DynamicObjectsRef[i].Checked) { const AABB& objBox = *m_DynamicObjectsRef[i].Box; - if (!Collision::IsSameBoxProbably(boxToTest, objBox) && - Collision::AABBVsAABB(boxToTest, objBox)) { + if (Collision::AABBVsAABB(boxToTest, objBox)) { outBoxIntersected = objBox; return true; } diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index 8b212d31..69c25f61 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -96,6 +96,13 @@ EntityID World::GetParent(EntityID entity) void World::SetParent(EntityID entity, EntityID parent) { + // Don't allow an entity to be a child to itself! + if (entity == parent) { + // HACK: We purposely don't check the whole hierarchy of children here, since it would be way too slow. + // This might result in infinite loops if an entity somehow ends up as a child. + return; + } + EntityID lastParent = m_EntityParents.at(entity); auto parentChildren = m_EntityChildren.equal_range(lastParent); for (auto it = parentChildren.first; it != parentChildren.second; it++) { diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 1200ce34..06938064 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -6,6 +6,11 @@ EditorGUI::EditorGUI(World* world, EventBroker* eventBroker) , m_EventBroker(eventBroker) { EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &EditorGUI::OnKeyDown); + EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorGUI::OnFileDropped); + EVENT_SUBSCRIBE_MEMBER(m_EPause, &EditorGUI::OnPause); + EVENT_SUBSCRIBE_MEMBER(m_EResume, &EditorGUI::OnResume); + EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &EditorGUI::OnLockMouse); + EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &EditorGUI::OnUnlockMouse); } void EditorGUI::Draw() @@ -37,39 +42,60 @@ void EditorGUI::drawTools() return; } + // Widget modes createWidgetToolButton(WidgetMode::Translate); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Translate"); + ImGui::SetTooltip("Translate (W)"); } ImGui::SameLine(); createWidgetToolButton(WidgetMode::Rotate); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Rotate"); + ImGui::SetTooltip("Rotate (E)"); } ImGui::SameLine(); createWidgetToolButton(WidgetMode::Scale); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Scale"); + ImGui::SetTooltip("Scale (R)"); } + + ImGui::SameLine(); + ImGui::ItemSize(ImVec2(5, 0)); + + // Widget space + ImGui::SameLine(); + GLuint spaceTexture = 0; + if (m_CurrentWidgetSpace == WidgetSpace::Global) { + spaceTexture = tryLoadTexture("Textures/Icons/Global.png"); + } else if (m_CurrentWidgetSpace == WidgetSpace::Local) { + spaceTexture = tryLoadTexture("Textures/Icons/Local.png"); + } + if (ImGui::ImageButton((void*)spaceTexture, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1))) { + toggleWidgetSpace(); + } + if (ImGui::IsItemHovered()) { + if (m_CurrentWidgetSpace == WidgetSpace::Global) { + ImGui::SetTooltip("Widget space: Global (X)"); + } else if (m_CurrentWidgetSpace == WidgetSpace::Local) { + ImGui::SetTooltip("Widget space: Local (X)"); + } + } + ImGui::SameLine(); ImGui::ItemSize(ImVec2(5, 0)); // Play button ImGui::SameLine(); - static bool paused = false; - if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Play.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { + if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Play.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!m_Paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { Events::Resume e; e.World = m_World; m_EventBroker->Publish(e); - paused = false; } // Pause button ImGui::SameLine(); - if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Pause.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { + if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Pause.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (m_Paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { Events::Pause e; e.World = m_World; m_EventBroker->Publish(e); - paused = true; } ImGui::End(); @@ -168,10 +194,7 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) ImGui::Text(formatEntityName(entity).c_str()); ImGui::End(); } - }/* else if (m_CurrentlyDragging == entity) { - LOG_DEBUG("Stopped dragging %i", entity.ID); - m_CurrentlyDragging = EntityWrapper::Invalid; - }*/ + } // Entity context menu std::string contextMenuUniqueID = std::string("EntityContextMenu") + std::to_string(entity.ID); if (hovered && ImGui::IsMouseClicked(1)) { @@ -234,10 +257,12 @@ void EditorGUI::drawComponents(EntityWrapper entity) componentTypes.push_back(pair.first.c_str()); } } + // Sort components in alphabetical order + std::sort(componentTypes.begin(), componentTypes.end(), compareCharArray); // Draw combo box ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - 10.f); int selectedItem = -1; - if (ImGui::Combo("", &selectedItem, componentTypes.data(), componentTypes.size())) { + if (ImGui::Combo("", &selectedItem, componentTypes.data(), componentTypes.size(), componentTypes.size())) { if (selectedItem != -1) { if (m_OnComponentAttach != nullptr) { std::string chosenComponentType(componentTypes.at(selectedItem)); @@ -283,9 +308,8 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci) // Draw component fields ComponentWrapper& component = entity.World->GetComponent(entity.ID, ci.Name); - for (auto& kv : ci.Fields) { - const std::string& fieldName = kv.first; - const ComponentInfo::Field_t& field = kv.second; + for (auto& fieldName : ci.FieldsInOrder) { + const ComponentInfo::Field_t& field = ci.Fields.at(fieldName); // Draw the field widget based on its type bool dirty = drawComponentField(component, field); @@ -435,18 +459,31 @@ bool EditorGUI::drawComponentField_bool(ComponentWrapper &c, const ComponentInfo bool EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field) { + bool result = false; + auto& val = c.Field(field.Name); + char tempString[1024]; // Let's just hope this is an sufficiently large buffer for strings :) tempString[1023] = '\0'; // Null terminator just in case the string is larger than the buffer // Copy the string into the buffer, taking the null terminator into account memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString) - 1)); if (ImGui::InputText("", tempString, sizeof(tempString))) { val = std::string(tempString); - return true; - } else { - return false; + result = true; } - // TODO: Handle drag and drop of files + + // Handle file drag and drop + if (ImGui::IsItemHovered() && !m_DroppedFile.empty()) { + // Unset potential input focus or our newly set value will be overwritten! + if (ImGui::IsItemActive()) { + ImGui::SetActiveID(0, nullptr); + } + // Set the actual dropped value + val = m_DroppedFile; + m_DroppedFile = ""; + } + + return result; } void EditorGUI::drawModals() @@ -537,10 +574,7 @@ void EditorGUI::createWidgetToolButton(WidgetMode mode) (m_CurrentWidgetMode == mode) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1) ) ) { - if (m_OnWidgetMode != nullptr) { - m_OnWidgetMode(mode); - } - m_CurrentWidgetMode = mode; + setWidgetMode(mode); } } @@ -570,6 +604,61 @@ bool EditorGUI::OnKeyDown(const Events::KeyDown& e) } } + if (!m_MouseLocked) { + if (e.KeyCode == GLFW_KEY_W) { + setWidgetMode(WidgetMode::Translate); + } + if (e.KeyCode == GLFW_KEY_E) { + setWidgetMode(WidgetMode::Rotate); + } + if (e.KeyCode == GLFW_KEY_R) { + setWidgetMode(WidgetMode::Scale); + } + + if (e.KeyCode == GLFW_KEY_X) { + toggleWidgetSpace(); + } + } + + return true; +} + +bool EditorGUI::OnFileDropped(const Events::FileDropped& e) +{ + // Make a best effort to make the path relative to the working directory of the executable + m_DroppedFile = boost::filesystem::path(e.Path).lexically_relative(boost::filesystem::current_path()).string(); + // Compensate for Windows retardedness + std::replace(m_DroppedFile.begin(), m_DroppedFile.end(), '\\', '/'); + // Special case for when people drop from the asset folder instead of from the symlink to the asset folders in bin + boost::algorithm::replace_first(m_DroppedFile, "../assets/", ""); + return true; +} + +bool EditorGUI::OnPause(const Events::Pause& e) +{ + if (e.World == m_World) { + m_Paused = true; + } + return true; +} + +bool EditorGUI::OnResume(const Events::Resume& e) +{ + if (e.World == m_World) { + m_Paused = false; + } + return true; +} + +bool EditorGUI::OnLockMouse(const Events::LockMouse& e) +{ + m_MouseLocked = true; + return true; +} + +bool EditorGUI::OnUnlockMouse(const Events::UnlockMouse& e) +{ + m_MouseLocked = false; return true; } @@ -644,6 +733,32 @@ void EditorGUI::openModal(const std::string& modal) m_ModalsToOpen.insert(modal); } +void EditorGUI::setWidgetMode(WidgetMode mode) +{ + if (m_OnWidgetMode != nullptr) { + m_OnWidgetMode(mode); + } + m_CurrentWidgetMode = mode; +} + +void EditorGUI::toggleWidgetSpace() +{ + if (m_CurrentWidgetSpace == WidgetSpace::Global) { + m_CurrentWidgetSpace = WidgetSpace::Local; + } else if (m_CurrentWidgetSpace == WidgetSpace::Local) { + m_CurrentWidgetSpace = WidgetSpace::Global; + } + + if (m_OnWidgetSpace != nullptr) { + m_OnWidgetSpace(m_CurrentWidgetSpace); + } +} + +bool EditorGUI::compareCharArray(const char* c1, const char* c2) +{ + return strcmp(c1, c2) < 0; +} + void EditorGUI::SetDirty(EntityWrapper entity) { EntityWrapper baseParent = entity; @@ -731,7 +846,7 @@ void EditorGUI::entityDelete(EntityWrapper entity) void EditorGUI::entityChangeParent(EntityWrapper entity, EntityWrapper parent) { - if (entity == parent) { + if (entity == parent || parent.IsChildOf(entity)) { return; } diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 6ffd0e24..ccbc1b48 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -31,6 +31,7 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetWidgetModeCallback(std::bind(&EditorSystem::setWidgetMode, this, std::placeholders::_1)); + m_EditorGUI->SetWidgetSpaceCallback(std::bind(&EditorSystem::OnWidgetSpace, this, std::placeholders::_1)); EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress); EVENT_SUBSCRIBE_MEMBER(m_EWidgetDelta, &EditorSystem::OnWidgetDelta); @@ -65,7 +66,12 @@ void EditorSystem::Update(double dt) m_EditorStats->Draw(actualDelta); if (m_CurrentSelection.Valid() && m_Widget.Valid()) { - (glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID); + (glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection); + if (m_WidgetSpace == EditorGUI::WidgetSpace::Local) { + (glm::vec3&)m_Widget["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(m_CurrentSelection); + } else { + (glm::vec3&)m_Widget["Transform"]["Orientation"] = glm::vec3(0, 0, 0); + } } m_EditorWorldSystemPipeline->Update(actualDelta); @@ -82,11 +88,22 @@ void EditorSystem::Update(double dt) void EditorSystem::Enable() { m_EditorCameraInputController->Enable(); + m_EventBroker->Publish(Events::UnlockMouse()); - Events::SetCamera e; - e.CameraEntity = m_EditorCamera; - m_EventBroker->Publish(e); - (glm::vec3&)m_EditorCamera["Transform"]["Position"] = Transform::AbsolutePosition(m_ActualCamera); + + // Enable editor camera + Events::SetCamera eSetCamera; + eSetCamera.CameraEntity = m_EditorCamera; + m_EventBroker->Publish(eSetCamera); + if (m_ActualCamera.Valid()) { + (glm::vec3&)m_EditorCamera["Transform"]["Position"] = Transform::AbsolutePosition(m_ActualCamera); + } + + // Pause the world we're editing + Events::Pause ePause; + ePause.World = m_World; + m_EventBroker->Publish(ePause); + m_Enabled = true; } @@ -154,6 +171,11 @@ void EditorSystem::OnComponentDelete(EntityWrapper entity, const std::string& co } } +void EditorSystem::OnWidgetSpace(EditorGUI::WidgetSpace widgetSpace) +{ + m_WidgetSpace = widgetSpace; +} + bool EditorSystem::OnMousePress(const Events::MousePress& e) { ImGuiIO& io = ImGui::GetIO(); @@ -170,12 +192,18 @@ bool EditorSystem::OnMousePress(const Events::MousePress& e) bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e) { if (m_CurrentSelection.Valid()) { - glm::quat parentOrientation; - EntityWrapper parent = m_CurrentSelection.Parent(); - if (parent.Valid()) { - parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent.World, parent.ID)); + if (m_WidgetSpace == EditorGUI::WidgetSpace::Global) { + glm::quat parentOrientation; + EntityWrapper parent = m_CurrentSelection.Parent(); + if (parent.Valid()) { + parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent)); + } + (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation; + } else if (m_WidgetSpace == EditorGUI::WidgetSpace::Local) { + glm::quat selectionOri = glm::quat((glm::vec3)m_CurrentSelection["Transform"]["Orientation"]); + glm::vec3 localTranslation = selectionOri * e.Translation; + (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += localTranslation; } - (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation; m_EditorGUI->SetDirty(m_CurrentSelection); } return true; diff --git a/src/Engine/Editor/EditorWidgetSystem.cpp b/src/Engine/Editor/EditorWidgetSystem.cpp index 8352c5c1..7c20a7c7 100644 --- a/src/Engine/Editor/EditorWidgetSystem.cpp +++ b/src/Engine/Editor/EditorWidgetSystem.cpp @@ -23,14 +23,18 @@ void EditorWidgetSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper Events::WidgetDelta e; - EntityWrapper moveEntity = entity.Parent(); - if (!moveEntity.Valid()) { - moveEntity = entity; + // Widget axes should have a common parent + EntityWrapper widgetBase = entity.Parent(); + if (!widgetBase.Valid()) { + widgetBase = entity; } + glm::vec3 widgetBasePos = widgetBase["Transform"]["Position"]; + glm::quat widgetBaseOri = glm::quat((glm::vec3)widgetBase["Transform"]["Orientation"]); auto camera = m_PickData.Camera; - glm::vec3 axis = cEditorWidget["Axis"]; - glm::vec2 axisScreen = camera->WorldToScreen(axis, m_Renderer->GetViewPortSize()) - camera->WorldToScreen(glm::vec3(0, 0, 0), m_Renderer->GetViewPortSize()); + glm::vec3 axis = (glm::vec3)cEditorWidget["Axis"]; + glm::vec3 axisOriented = widgetBaseOri * axis; + glm::vec2 axisScreen = camera->WorldToScreen(widgetBasePos + axisOriented, m_Renderer->GetViewportSize()) - camera->WorldToScreen(widgetBasePos, m_Renderer->GetViewportSize()); float dot = glm::dot(m_MouseDelta, glm::normalize(axisScreen)) / glm::length(axisScreen); glm::vec3 worldMovement = dot * axis; diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 4f48831b..5d8b2359 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -34,12 +34,12 @@ void DrawBloomPass::InitializeShaderPrograms() void DrawBloomPass::InitializeBuffers() { - GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0))); m_GaussianFrameBuffer_horiz.Generate(); - GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0))); m_GaussianFrameBuffer_vert.Generate(); diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 4fde4eae..ae2ebefc 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -21,11 +21,11 @@ void DrawFinalPass::InitializeFrameBuffers() { glGenRenderbuffers(1, &m_DepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); - GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); //GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); //GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_FLOAT, 4); m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); @@ -172,6 +172,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& if (modelJob) { //bind forward program m_ForwardPlusProgram->Bind(); + glUniform2f(glGetUniformLocation(forwardHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); //bind uniforms BindModelUniforms(forwardHandle, modelJob, scene); diff --git a/src/Engine/Rendering/LightCullingPass.cpp b/src/Engine/Rendering/LightCullingPass.cpp index 46a17286..5e6da64d 100644 --- a/src/Engine/Rendering/LightCullingPass.cpp +++ b/src/Engine/Rendering/LightCullingPass.cpp @@ -25,8 +25,8 @@ void LightCullingPass::GenerateNewFrustum(RenderScene& scene) glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height); - glDispatchCompute((int)(m_Renderer->GetViewPortSize().Width/(TILE_SIZE*TILE_SIZE) + 1), (int)(m_Renderer->GetViewPortSize().Height/(TILE_SIZE*TILE_SIZE) + 1), 1); + glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glDispatchCompute((int)(m_Renderer->GetViewportSize().Width/(TILE_SIZE*TILE_SIZE) + 1), (int)(m_Renderer->GetViewportSize().Height/(TILE_SIZE*TILE_SIZE) + 1), 1); GLERROR("CalculateFrustum Error: End"); } @@ -40,7 +40,7 @@ void LightCullingPass::OnResolutionChange() void LightCullingPass::SetSSBOSizes() { - m_NumberOfTiles = (int)(m_Renderer->GetViewPortSize().Width/TILE_SIZE) * (int)(m_Renderer->GetViewPortSize().Height/TILE_SIZE); + m_NumberOfTiles = (int)(m_Renderer->GetViewportSize().Width/TILE_SIZE) * (int)(m_Renderer->GetViewportSize().Height/TILE_SIZE); m_Frustums = new Frustum[m_NumberOfTiles]; m_LightGrid = new LightGrid[m_NumberOfTiles]; @@ -67,14 +67,14 @@ void LightCullingPass::CullLights(RenderScene& scene) glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); m_LightCullProgram->Bind(); - glUniform2f(glGetUniformLocation(m_LightCullProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height); + glUniform2f(glGetUniformLocation(m_LightCullProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(scene.Camera->ViewMatrix())); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); - glDispatchCompute(glm::ceil(m_Renderer->GetViewPortSize().Width/ TILE_SIZE), glm::ceil(m_Renderer->GetViewPortSize().Height / TILE_SIZE), 1); + glDispatchCompute(glm::ceil(m_Renderer->GetViewportSize().Width/ TILE_SIZE), glm::ceil(m_Renderer->GetViewportSize().Height / TILE_SIZE), 1); GLERROR("CullLights Error: End"); } diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index ec7533bd..792539f8 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -18,14 +18,14 @@ PickingPass::~PickingPass() void PickingPass::InitializeTextures() { GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, - glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE); + glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE); } void PickingPass::InitializeFrameBuffers() { glGenRenderbuffers(1, &m_DepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); m_PickingBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); m_PickingBuffer.AddResource(std::shared_ptr(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0))); diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 0ec593df..a63e02a0 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -59,10 +59,9 @@ void Renderer::InitializeWindow() exit(EXIT_FAILURE); } - int res[2]; - glfwGetWindowSize(m_Window, &res[0], &res[1]); - SetViewPortSize(Rectangle::Rectangle(res[0], res[1])); - + int windowSize[2]; + glfwGetWindowSize(m_Window, &windowSize[0], &windowSize[1]); + m_ViewportSize = Rectangle(windowSize[0], windowSize[1]); } void Renderer::InitializeShaders() diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 243a2186..515540bf 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -89,6 +89,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); // Populate Octree with collidables ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); @@ -100,7 +101,6 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); ++updateOrderLevel; - m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 0f6588be..6eab02c5 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -80,14 +80,14 @@ void PlayerMovementSystem::Update(double dt) velocity.y += 4.f; } - //if (player.HasComponent("AABB")) { - // glm::vec3& size = player["AABB"]["Size"]; - // if (controller->Crouching()) { - // size = glm::vec3(1.f, 1.f, 1.f); - // } else { - // size = glm::vec3(1.f, 1.6f, 1.f); - // } - //} + if (player.HasComponent("AABB")) { + glm::vec3& size = player["AABB"]["Size"]; + if (controller->Crouching()) { + size = glm::vec3(1.f, 1.f, 1.f); + } else { + size = glm::vec3(1.f, 1.6f, 1.f); + } + } // Animations EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); diff --git a/src/Game/Systems/WeaponSystem.cpp b/src/Game/Systems/WeaponSystem.cpp index 4b4b8da2..1613cb7a 100644 --- a/src/Game/Systems/WeaponSystem.cpp +++ b/src/Game/Systems/WeaponSystem.cpp @@ -104,7 +104,7 @@ bool WeaponSystem::OnShoot(Events::Shoot& eShoot) // Screen center, based on current resolution! // TODO: check if player has enough ammo and if weapon has a cooldown or not - Rectangle screenResolution = m_Renderer->GetViewPortSize(); + Rectangle screenResolution = m_Renderer->GetViewportSize(); glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2); // TODO: check if player has enough ammo and if weapon has a cooldown or not