Hazel Game Engine (093) Change Gizmos

If there are errors in the code, terminology, etc. in the text, please correct me

foreword

  • Purpose

    In order to realize like most 3D software, click on the object, and there will be auxiliary applets for dragging, zooming, and rotating.

  • How to achieve

    Using the open source imguizmo library, URL

  • Introducing imguizmo

    ImGizmo is a small (.h and .cpp) library built on top of Dear ImGui that allows you to manipulate (currently rotation and translation) 4x4 floating point matrices, with no other dependencies. Written with the idea of ​​Immediate Mode (IM) in mind.

  • gizmos achieve small points

    • Pan, zoom, and rotate can be switched with shortcut keys
    • You can set the amount of each movement or rotation like Unity, snap

How to import ImGuiZmo library

  • git join submodule

    git submodule add https://github.com/TheCherno/ImGuizmo GameEngineLightWeight/vendor/ImGuizmo
    
  • premake5.lua modification

    Like the glm library, only the directory needs to be included , but it needs to be filtered and precompiled headers are not included

    IncludeDir["ImGuizmo"] = "GameEngineLightWeight/vendor/ImGuizmo" 
    
    files{
          
          
        "%{prj.name}/src/**.h",
        "%{prj.name}/src/**.cpp",
        "%{prj.name}/vendor/stb_image/**.cpp",
        "%{prj.name}/vendor/stb_image/**.h",
        "%{prj.name}/vendor/glm/glm/**.hpp",
        "%{prj.name}/vendor/glm/glm/**.inl",
        "%{prj.name}/vendor/ImGuizmo/ImGuizmo.h",
        "%{prj.name}/vendor/ImGuizmo/ImGuizmo.cpp"
    }
    includedirs{
          
          
        "%{prj.name}/src",
        "%{prj.name}/vendor/spdlog/include",
        "%{IncludeDir.Glad}",
        "%{IncludeDir.GLFW}",
        "%{IncludeDir.ImGui}",
        "%{IncludeDir.glm}",
        "%{IncludeDir.stb_image}",
        "%{IncludeDir.entt}",
        "%{IncludeDir.yaml_cpp}",
        "%{IncludeDir.ImGuizmo}"
    }
    -- imguizmo不使用编译头? 没用 这句
    filter "files:%{prj.name}/vendor/ImGuizmo/**.cpp"
    flags {
          
           "NoPCH" }
    

key code

void EditorLayer::OnImGuiRender()
{
    
    
    // ImGuizmos
Entity selectedEntity = m_SceneHierarchyPanel.GetSelectedEntity();
if (selectedEntity && m_GizmoType != -1) {
    
    
    ImGuizmo::SetOrthographic(false);
    ImGuizmo::SetDrawlist();

    float windowWidth = (float)ImGui::GetWindowWidth();
    float windowHeight = (float)ImGui::GetWindowHeight();
    ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, windowWidth, windowHeight);

    // Camera
    auto cameraEntity = m_ActiveScene->GetPrimaryCameraEntity();
    const auto& camera = cameraEntity.GetComponent<CameraComponent>().camera;
    const glm::mat4& cameraProjection = camera.GetProjection();
    glm::mat4 cameraView = glm::inverse(cameraEntity.GetComponent<TransformComponent>().GetTransform());

    // Entity transform
    auto& tc = selectedEntity.GetComponent<TransformComponent>();
    glm::mat4 transform = tc.GetTransform();

    // Snapping
    bool snap = Input::IsKeyPressed(Key::LeftControl);
    float snapValue = 0.5f; // 平移的snap
    if (m_GizmoType == ImGuizmo::OPERATION::ROTATE) {
    
    // rotate的度数
        snapValue = 45.0f;
    }
    float snapValues[3] = {
    
     snapValue, snapValue,snapValue };

    // 这里可以说是传入相应参数,得到绘画出来的gizmos
    ImGuizmo::Manipulate(glm::value_ptr(cameraView), glm::value_ptr(cameraProjection),
                         (ImGuizmo::OPERATION)m_GizmoType, ImGuizmo::LOCAL, glm::value_ptr(transform),
                         nullptr, snap ? snapValues : nullptr);

    // 如果gizmos被使用 或者 说被移动
    if (ImGuizmo::IsUsing()) {
    
    
        glm::vec3 translation, rotation, scale;
        Math::DecomposeTransform(transform, translation, rotation, scale);

        // 用增量旋转,解决矩阵可能会造成万向锁。
        glm::vec3 deltaRotation = rotation - tc.Rotation;
        tc.Translation = translation;
        tc.Rotation += deltaRotation; // 每一帧增加没有限制角度,而不是固定在360度数。
        tc.Scale = scale;
    }
}
bool EditorLayer::OnKeyPressed(KeyPressedEvent& e)
{
    
    
    if (e.GetRepeatCount() > 0) {
    
    
        return false;
    }
    bool control = Input::IsKeyPressed(Key::LeftControl) || Input::IsKeyPressed(Key::RightControl);
    bool shift = Input::IsKeyPressed(Key::LeftShift) || Input::IsKeyPressed(Key::RightShift);
    switch (e.GetKeyCode()) {
    
    
        case Key::N: {
    
    
            if (control) {
    
    
                NewScene();
            }
            break;
        }
        case Key::O: {
    
    
            if (control) {
    
    
                OpenScene();
            }
            break;
        }
        case Key::S: {
    
    
            if (control && shift) {
    
    
                SaveSceneAs();
            }
            // 保存当前场景:要有一个记录当前场景的路径。
            //if (control) {
    
    

            //}
            break;
        }
            // Gizmos
        case Key::Q:
            m_GizmoType = -1;
            break;
        case Key::W:
            m_GizmoType = ImGuizmo::OPERATION::TRANSLATE;
            break;
        case Key::E:
            m_GizmoType = ImGuizmo::OPERATION::ROTATE;
            break;
        case Key::R:
            m_GizmoType = ImGuizmo::OPERATION::SCALE;
            break;
    }

Effect

Please add a picture description

Modify bugs

  • Question details

    After the entity is clicked in the Hierarchy, even if the mouse hovers over the viewport window and the shortcut key is pressed, the type of gizmos will not be switched

    To modify the mouse to stop on the viewport window, press the shortcut key to switch the type of gizmos

  • before modification

    Application::Get().GetImGuiLayer()->BlockEvents(!m_ViewportFocused || !m_ViewportHovered);
    // 修改之前:意思是当鼠标点击面板并且悬停在面板上,才能接受事件,其它情况均不能接收事件
    bool canshu = !m_ViewportFocused || !m_ViewportHovered;
    m_ViewportFocused = true,  m_ViewportHovered = true; canshu = false, m_BlockEvents:false-> viewport面板 能 接收事件
    m_ViewportFocused = true,  m_ViewportHovered = false;canshu = true,  m_BlockEvents:true->  viewport面板 不 能接收事件
    m_ViewportFocused = false, m_ViewportHovered = true; canshu = true,  m_BlockEvents:true->  viewport面板 不 能接收事件
    m_ViewportFocused = false, m_ViewportHovered = false;canshu = true,  m_BlockEvents:true->  viewport面板 不 能接收事件
    
  • after modification

    Application::Get().GetImGuiLayer()->BlockEvents(!m_ViewportFocused && !m_ViewportHovered);
    // 修改之后:意思是当鼠标没有点击面板并且没有悬停在面板上,就不接受事件,其它情况均可接收事件
    bool canshu = !m_ViewportFocused && !m_ViewportHovered;
    m_ViewportFocused = true,  m_ViewportHovered = true; canshu = false, m_BlockEvents:false-> viewport面板 能 接收事件
    m_ViewportFocused = true,  m_ViewportHovered = false;canshu = false,  m_BlockEvents:true-> viewport面板 能 接收事件
    m_ViewportFocused = false, m_ViewportHovered = true; canshu = false,  m_BlockEvents:true-> viewport面板 能 接收事件
    m_ViewportFocused = false, m_ViewportHovered = false;canshu = true,  m_BlockEvents:true->  viewport面板 不 能接收事件		
    

Guess you like

Origin blog.csdn.net/qq_34060370/article/details/132241365