Improved editor camera support
This commit is contained in:
@@ -132,6 +132,8 @@ int main(int argc, char* argv[])
|
||||
Nuake::Engine::Tick();
|
||||
Nuake::Engine::Draw();
|
||||
|
||||
Timestep ts = Nuake::Engine::GetTimestep();
|
||||
|
||||
Nuake::Vector2 WindowSize = window->GetSize();
|
||||
glViewport(0, 0, WindowSize.x, WindowSize.y);
|
||||
Nuake::Renderer2D::BeginDraw(WindowSize);
|
||||
@@ -153,6 +155,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
sceneFramebuffer->Unbind();
|
||||
|
||||
editor.Update(ts);
|
||||
editor.Draw();
|
||||
|
||||
Nuake::Engine::EndDraw();
|
||||
|
||||
@@ -96,6 +96,13 @@ namespace Nuake {
|
||||
Ref<Texture> texture = framebuffer->GetTexture();
|
||||
ImGui::Image((void*)texture->GetID(), regionAvail, ImVec2(0, 1), ImVec2(1, 0));
|
||||
|
||||
const Vector2& mousePos = Input::GetMousePosition();
|
||||
const ImVec2& windowPos = ImGui::GetWindowPos();
|
||||
const ImVec2& windowSize = ImGui::GetWindowSize();
|
||||
const bool isInsideWidth = mousePos.x > windowPos.x && mousePos.x < windowPos.x + windowSize.x;
|
||||
const bool isInsideHeight = mousePos.y > windowPos.y && mousePos.y < windowPos.y + windowSize.y;
|
||||
m_IsHoveringViewport = isInsideWidth && isInsideHeight;
|
||||
|
||||
ImGuizmo::SetDrawlist();
|
||||
ImGuizmo::AllowAxisFlip(false);
|
||||
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, ImGui::GetWindowWidth(), ImGui::GetWindowHeight());
|
||||
@@ -1091,10 +1098,11 @@ namespace Nuake {
|
||||
CurrentOperation = ImGuizmo::OPERATION::SCALE;
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::End();
|
||||
|
||||
|
||||
int corner2 = 1;
|
||||
|
||||
window_flags |= ImGuiWindowFlags_NoMove;
|
||||
@@ -1107,10 +1115,23 @@ namespace Nuake {
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 32.0f);
|
||||
ImGui::SetNextWindowSize(ImVec2(25, ImGui::GetContentRegionAvail().y - DISTANCE * 2.0));
|
||||
if (ImGui::Begin("Controls", &m_ShowOverlay, window_flags))
|
||||
{
|
||||
const auto& editorCam = Engine::GetCurrentScene()->m_EditorCamera;
|
||||
const float camSpeed = editorCam->Speed;
|
||||
|
||||
const float maxSpeed = 50.0f;
|
||||
const float minSpeed = 0.1f;
|
||||
const float normalizedSpeed = camSpeed / maxSpeed;
|
||||
|
||||
ImVec2 start = ImGui::GetWindowPos();
|
||||
ImVec2 end = start + ImGui::GetWindowSize();
|
||||
|
||||
ImVec2 startOffset = ImVec2(start.x, end.y - (normalizedSpeed * ImGui::GetWindowHeight()));
|
||||
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(startOffset, end, IM_COL32(255, 255, 255, 180), 200.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 100);
|
||||
if (ImGui::Button("...")) {};
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
@@ -1374,6 +1395,19 @@ namespace Nuake {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void EditorInterface::Update(float ts)
|
||||
{
|
||||
auto& editorCam = Engine::GetCurrentScene()->m_EditorCamera;
|
||||
editorCam->Update(ts, m_IsHoveringViewport);
|
||||
|
||||
const bool entityIsSelected = Selection.Type == EditorSelectionType::Entity && Selection.Entity.IsValid();
|
||||
if (entityIsSelected && Input::IsKeyPressed(GLFW_KEY_F))
|
||||
{
|
||||
editorCam->IsMoving = true;
|
||||
editorCam->TargetPos = Vector3(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorInterface::BuildFonts()
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.5f, 0.5f));
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace Nuake {
|
||||
bool m_ShowImGuiDemo = false;
|
||||
bool m_DebugCollisions = false;
|
||||
bool m_ShowOverlay = true;
|
||||
bool m_IsHoveringViewport = false;
|
||||
|
||||
ImGuizmo::OPERATION CurrentOperation = ImGuizmo::TRANSLATE;
|
||||
ImGuizmo::MODE CurrentMode = ImGuizmo::WORLD;
|
||||
Ref<Material> m_SelectedMaterial;
|
||||
@@ -36,6 +38,7 @@ namespace Nuake {
|
||||
void BuildFonts();
|
||||
void Init();
|
||||
void Draw();
|
||||
void Update(float ts);
|
||||
void DrawMenuBar();
|
||||
void DrawViewport();
|
||||
void DrawEntityTree(Entity ent);
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Nuake
|
||||
float Engine::m_FixedUpdateRate = 1.0f / 90.0f;
|
||||
float Engine::m_FixedUpdateDifference = 0.f;
|
||||
float Engine::m_Time = 0.f;
|
||||
Timestep Engine::m_TimeStep = 0.f;
|
||||
|
||||
bool Engine::IsPlayMode = false;
|
||||
|
||||
@@ -35,6 +36,8 @@ namespace Nuake
|
||||
CurrentWindow = Window::Get();
|
||||
Logger::Log("Window initialized");
|
||||
|
||||
Input::Init();
|
||||
|
||||
Renderer2D::Init();
|
||||
Logger::Log("2D renderer initialized");
|
||||
|
||||
@@ -44,18 +47,18 @@ namespace Nuake
|
||||
void Engine::Tick()
|
||||
{
|
||||
m_Time = (float)glfwGetTime();
|
||||
Timestep timestep = m_Time - m_LastFrameTime;
|
||||
m_TimeStep = m_Time - m_LastFrameTime;
|
||||
m_LastFrameTime = m_Time;
|
||||
|
||||
// Dont update if no scene is loaded.
|
||||
if (CurrentWindow->GetScene())
|
||||
{
|
||||
CurrentWindow->Update(timestep);
|
||||
CurrentWindow->Update(m_TimeStep);
|
||||
|
||||
// Play mode update all the entities, Editor does not.
|
||||
if (Engine::IsPlayMode)
|
||||
{
|
||||
m_FixedUpdateDifference += timestep;
|
||||
m_FixedUpdateDifference += m_TimeStep;
|
||||
|
||||
// Fixed update
|
||||
if (m_FixedUpdateDifference >= m_FixedUpdateRate)
|
||||
@@ -67,7 +70,7 @@ namespace Nuake
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCurrentScene()->EditorUpdate(timestep);
|
||||
GetCurrentScene()->EditorUpdate(m_TimeStep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Nuake
|
||||
static float m_FixedUpdateRate;
|
||||
static float m_FixedUpdateDifference;
|
||||
static float m_Time;
|
||||
static Timestep m_TimeStep;
|
||||
public:
|
||||
static bool IsPlayMode; // Is currently in runtime..
|
||||
|
||||
@@ -40,6 +41,7 @@ namespace Nuake
|
||||
static void Draw(); // Start new frame
|
||||
static void EndDraw(); // Swap buffer
|
||||
static inline float GetTime() { return m_Time; }
|
||||
static inline Timestep GetTimestep() { return m_TimeStep; }
|
||||
static Ref<Window> GetCurrentWindow();
|
||||
|
||||
static bool LoadScene(Ref<Scene> scene);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "Input.h"
|
||||
#include "../Window.h"
|
||||
|
||||
#include <Imgui/imgui_impl_glfw.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
namespace Nuake
|
||||
@@ -7,6 +9,16 @@ namespace Nuake
|
||||
Input* Input::s_Instance;
|
||||
std::map<int, bool> Input::m_Keys = std::map<int, bool>();
|
||||
bool Input::m_MouseButtons[5] = { false, false, false, false, false };
|
||||
float Input::XScroll = 0.0f;
|
||||
float Input::YScroll = 0.0f;
|
||||
|
||||
void Input::ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
XScroll = (float)xoffset;
|
||||
YScroll = (float)yoffset;
|
||||
|
||||
ImGui_ImplGlfw_ScrollCallback(window, xoffset, yoffset);
|
||||
}
|
||||
|
||||
#pragma region Keys
|
||||
// Only true if the key is currently being pressed
|
||||
@@ -82,7 +94,6 @@ namespace Nuake
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
|
||||
|
||||
// Action
|
||||
bool Input::IsMouseButtonDown(int button)
|
||||
{
|
||||
@@ -150,6 +161,7 @@ namespace Nuake
|
||||
{
|
||||
//auto window = Application::Get().GetWindow()->GetNative();
|
||||
//glfwSetKeyCallback(window, Input::HandleInputCallback);
|
||||
glfwSetScrollCallback(Window::Get()->GetHandle(), Input::ScrollCallback);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "../Core/Maths.h"
|
||||
#include <map>
|
||||
|
||||
struct GLFWwindow;
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class Input
|
||||
@@ -15,6 +17,9 @@ namespace Nuake
|
||||
static bool IsKeyDown(int keycode);
|
||||
static bool IsKeyReleased(int keycode);
|
||||
|
||||
static float YScroll;
|
||||
static float XScroll;
|
||||
static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
|
||||
static void HideMouse();
|
||||
static void ShowMouse();
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Nuake
|
||||
sample = glm::normalize(sample);
|
||||
sample *= randomFloats(generator);
|
||||
|
||||
float scale = (float)i / 64.0;
|
||||
float scale = (float)i / 64.0f;
|
||||
scale = lerp(0.1f, 1.0f, scale * scale);
|
||||
sample *= scale;
|
||||
_ssaoKernel.push_back(sample);
|
||||
|
||||
@@ -6,100 +6,167 @@
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
void EditorCamera::Update(Timestep ts)
|
||||
void EditorCamera::Update(Timestep ts, const bool hover)
|
||||
{
|
||||
float x = Input::GetMouseX();
|
||||
float y = Input::GetMouseY();
|
||||
|
||||
if (!controlled && Input::IsMouseButtonDown(1))
|
||||
if (IsMoving)
|
||||
{
|
||||
mouseLastX = x;
|
||||
mouseLastY = y;
|
||||
Translation = glm::mix(Translation, TargetPos, 3.1f * ts);
|
||||
Direction = glm::mix(Direction, TargetPos - Translation, 3.1f * ts);
|
||||
if (glm::length(Translation - TargetPos) < 3.0f)
|
||||
{
|
||||
IsMoving = false;
|
||||
Translation = Translation - TargetPos;
|
||||
}
|
||||
}
|
||||
|
||||
controlled = Input::IsMouseButtonDown(1);
|
||||
const float x = Input::GetMouseX();
|
||||
const float y = Input::GetMouseY();
|
||||
|
||||
//if (!controlled)
|
||||
// Input::ShowMouse();
|
||||
//else
|
||||
// Input::HideMouse();
|
||||
const bool isFlying = Input::IsMouseButtonDown(1) || Input::IsMouseButtonDown(2);
|
||||
const bool isPressingMouse = isFlying || Input::YScroll != 0.0f;
|
||||
|
||||
if (hover)
|
||||
{
|
||||
controlled = isPressingMouse;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (controlled && !isPressingMouse)
|
||||
{
|
||||
controlled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Should probably not have speed binding in here.
|
||||
if (Input::IsKeyDown(GLFW_KEY_UP))
|
||||
Speed += 0.1f;
|
||||
else if (Input::IsKeyDown(GLFW_KEY_DOWN))
|
||||
Speed -= 0.1f;
|
||||
|
||||
if (Speed < 0)
|
||||
Speed = 0;
|
||||
|
||||
// Keyboard
|
||||
if (!controlled)
|
||||
return;
|
||||
|
||||
if (m_Type == CAMERA_TYPE::ORTHO)
|
||||
{
|
||||
if (Input::IsKeyDown(GLFW_KEY_RIGHT))
|
||||
Translation.x += Speed * ts;
|
||||
if (Input::IsKeyDown(GLFW_KEY_LEFT))
|
||||
Translation.x -= Speed * ts;
|
||||
if (Input::IsKeyDown(GLFW_KEY_UP))
|
||||
Translation.y += Speed * ts;
|
||||
if (Input::IsKeyDown(GLFW_KEY_DOWN))
|
||||
Translation.y -= Speed * ts;
|
||||
Input::ShowMouse();
|
||||
}
|
||||
else
|
||||
else if(hover)
|
||||
{
|
||||
glm::vec3 movement = glm::vec3(0, 0, 0);
|
||||
|
||||
if (Input::IsKeyDown(GLFW_KEY_D))
|
||||
movement -= Right * (Speed * ts);
|
||||
if (Input::IsKeyDown(GLFW_KEY_A))
|
||||
movement += Right * (Speed * ts);
|
||||
|
||||
if (Input::IsKeyDown(GLFW_KEY_W))
|
||||
movement += Direction * (Speed * ts);
|
||||
if (Input::IsKeyDown(GLFW_KEY_S))
|
||||
movement -= Direction * (Speed * ts);
|
||||
if (Input::IsKeyDown(GLFW_KEY_LEFT_SHIFT))
|
||||
movement -= Up * (Speed * ts);
|
||||
if (Input::IsKeyDown(GLFW_KEY_SPACE))
|
||||
movement += Up * (Speed * ts);
|
||||
|
||||
Translation += Vector3(movement);
|
||||
Input::HideMouse();
|
||||
}
|
||||
|
||||
if (firstMouse)
|
||||
if (Input::IsKeyDown(GLFW_KEY_LEFT_ALT))
|
||||
{
|
||||
mouseLastX = x;
|
||||
mouseLastY = y;
|
||||
firstMouse = false;
|
||||
if (Input::YScroll != 0.0f)
|
||||
{
|
||||
this->Fov += Input::YScroll;
|
||||
|
||||
if (Fov < 5.0f)
|
||||
{
|
||||
Fov = 5.0f;
|
||||
}
|
||||
|
||||
Input::YScroll = 0.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keyboard
|
||||
if (!controlled)
|
||||
{
|
||||
mouseLastX = x;
|
||||
mouseLastY = y;
|
||||
return;
|
||||
}
|
||||
|
||||
// mouse
|
||||
float diffx = x - mouseLastX;
|
||||
float diffy = mouseLastY - y;
|
||||
mouseLastX = x;
|
||||
mouseLastY = y;
|
||||
if (Input::IsMouseButtonDown(1))
|
||||
{
|
||||
// Should probably not have speed binding in here.
|
||||
if (Input::YScroll != 0)
|
||||
{
|
||||
Speed += Input::YScroll;
|
||||
Input::YScroll = 0.0f;
|
||||
}
|
||||
|
||||
const float sensitivity = 0.1f;
|
||||
diffx *= sensitivity;
|
||||
diffy *= sensitivity;
|
||||
if (Speed < 0)
|
||||
Speed = 0;
|
||||
|
||||
Yaw += diffx;
|
||||
Pitch += diffy;
|
||||
|
||||
if (Pitch > 89.0f)
|
||||
Pitch = 89.0f;
|
||||
if (Pitch < -89.0f)
|
||||
Pitch = -89.0f;
|
||||
if (m_Type == CAMERA_TYPE::ORTHO)
|
||||
{
|
||||
if (Input::IsKeyDown(GLFW_KEY_RIGHT))
|
||||
Translation.x += Speed * ts;
|
||||
if (Input::IsKeyDown(GLFW_KEY_LEFT))
|
||||
Translation.x -= Speed * ts;
|
||||
if (Input::IsKeyDown(GLFW_KEY_UP))
|
||||
Translation.y += Speed * ts;
|
||||
if (Input::IsKeyDown(GLFW_KEY_DOWN))
|
||||
Translation.y -= Speed * ts;
|
||||
}
|
||||
else
|
||||
{
|
||||
glm::vec3 movement = glm::vec3(0, 0, 0);
|
||||
|
||||
Direction.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
|
||||
Direction.y = sin(glm::radians(Pitch));
|
||||
Direction.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
|
||||
Direction = glm::normalize(Direction);
|
||||
Right = glm::normalize(glm::cross(Up, Direction));
|
||||
if (Input::IsKeyDown(GLFW_KEY_D))
|
||||
movement -= Right * (Speed * ts);
|
||||
if (Input::IsKeyDown(GLFW_KEY_A))
|
||||
movement += Right * (Speed * ts);
|
||||
|
||||
if (Input::IsKeyDown(GLFW_KEY_W))
|
||||
movement += Direction * (Speed * ts);
|
||||
if (Input::IsKeyDown(GLFW_KEY_S))
|
||||
movement -= Direction * (Speed * ts);
|
||||
if (Input::IsKeyDown(GLFW_KEY_LEFT_SHIFT))
|
||||
movement -= Up * (Speed * ts);
|
||||
if (Input::IsKeyDown(GLFW_KEY_SPACE))
|
||||
movement += Up * (Speed * ts);
|
||||
|
||||
Translation += Vector3(movement);
|
||||
}
|
||||
|
||||
if (firstMouse)
|
||||
{
|
||||
mouseLastX = x;
|
||||
mouseLastY = y;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
// mouse
|
||||
float diffx = x - mouseLastX;
|
||||
float diffy = mouseLastY - y;
|
||||
mouseLastX = x;
|
||||
mouseLastY = y;
|
||||
|
||||
const float sensitivity = 0.1f;
|
||||
diffx *= sensitivity;
|
||||
diffy *= sensitivity;
|
||||
|
||||
Yaw += diffx;
|
||||
Pitch += diffy;
|
||||
|
||||
if (Pitch > 89.0f)
|
||||
Pitch = 89.0f;
|
||||
if (Pitch < -89.0f)
|
||||
Pitch = -89.0f;
|
||||
|
||||
Direction.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
|
||||
Direction.y = sin(glm::radians(Pitch));
|
||||
Direction.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
|
||||
Direction = glm::normalize(Direction);
|
||||
Right = glm::normalize(glm::cross(Up, Direction));
|
||||
}
|
||||
else if (Input::IsMouseButtonDown(2))
|
||||
{
|
||||
Vector3 movement = Vector3(0);
|
||||
const float deltaX = x - mouseLastX;
|
||||
const float deltaY = y - mouseLastY;
|
||||
movement += Right * (deltaX * ts);
|
||||
movement += Up * (deltaY * ts);
|
||||
Translation += Vector3(movement) * 0.5f;
|
||||
|
||||
mouseLastX = x;
|
||||
mouseLastY = y;
|
||||
controlled = true;
|
||||
}
|
||||
else if (Input::YScroll != 0)
|
||||
{
|
||||
Translation += Vector3(Direction) * Input::YScroll;
|
||||
Input::YScroll = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<EditorCamera> EditorCamera::Copy()
|
||||
{
|
||||
Ref<EditorCamera> copy = CreateRef<EditorCamera>();
|
||||
|
||||
@@ -14,9 +14,10 @@ namespace Nuake
|
||||
SetDirection(Vector3(-1, -1, -1));
|
||||
}
|
||||
|
||||
void Update(Timestep ts);
|
||||
|
||||
void Update(Timestep ts, const bool hover);
|
||||
|
||||
Vector3 TargetPos = Vector3(0, 0, 0);
|
||||
bool IsMoving = false;
|
||||
Ref<EditorCamera> Copy();
|
||||
private:
|
||||
bool controlled = false;
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Nuake {
|
||||
|
||||
void Scene::EditorUpdate(Timestep ts)
|
||||
{
|
||||
m_EditorCamera->Update(ts);
|
||||
|
||||
}
|
||||
|
||||
void Scene::Draw(FrameBuffer& framebuffer)
|
||||
|
||||
Reference in New Issue
Block a user