Added Lighting to Animation components

This commit is contained in:
OusmBlueNinja 2025-05-06 09:07:27 -05:00
parent b80d730ef3
commit 3aa23acd63
13 changed files with 6607 additions and 2194 deletions

View File

@ -7,6 +7,8 @@ src_dirs:
- src/vendor/box2d
- src/vendor/xxhash
- src/vendor/miniaudio
- src/vendor/imguizmo
@ -19,6 +21,8 @@ include_dirs:
- src/vendor/box2d
- src/vendor/xxhash
- src/vendor/miniaudio
- src/vendor/imguizmo
- C:/msys64/mingw64/include

View File

@ -1,3 +1,3 @@
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -Isrc/vendor/miniaudio -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Engine.cpp -o src\build\Engine.o
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\AudioPlayerComponent.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\audio\AudioEngine.o src\build\core\utils\AssetManager.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\LoadingWindow.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\AudioInfo.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o src\build\xxhash.o src\build\miniaudio.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto -ldbghelp
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -Isrc/vendor/miniaudio -Isrc/vendor/imguizmo -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\Renderer.cpp -o src\build\Renderer.o
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\AudioPlayerComponent.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\audio\AudioEngine.o src\build\core\utils\AssetManager.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\LoadingWindow.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\AudioInfo.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o src\build\xxhash.o src\build\miniaudio.o src\build\ImGuizmo.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto -ldbghelp
[RUN] Executed app.exe successfully.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,14 +15,14 @@ void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texe
{
textureUAID = uaid;
const auto* asset = AssetManager::GetAssetByID(uaid);
const auto *asset = AssetManager::GetAssetByID(uaid);
if (!asset || !asset->loaded)
{
Logger::LogError("SetTextureAtlas: Asset not found or not loaded (UAID: %llu)", uaid);
return;
}
const auto* imageAsset = dynamic_cast<const ImageAssetInfo*>(asset);
const auto *imageAsset = dynamic_cast<const ImageAssetInfo *>(asset);
if (!imageAsset)
{
Logger::LogError("SetTextureAtlas: Asset with UAID %llu is not an image", uaid);
@ -68,7 +68,6 @@ void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texe
renderType = RenderType::Unlit;
}
void AnimationComponent::Play() { playing = true; }
void AnimationComponent::Stop() { playing = false; }
void AnimationComponent::SetLooping(bool loop_) { loop = loop_; }
@ -139,6 +138,8 @@ void AnimationComponent::Save(YAML::Emitter &out) const
out << YAML::Key << "FrameDuration" << YAML::Value << frameDuration;
out << YAML::Key << "StartFrame" << YAML::Value << startFrame;
out << YAML::Key << "EndFrame" << YAML::Value << endFrame;
out << YAML::Key << "renderType" << YAML::Value << (renderType == RenderType::Lit ? "Lit" : "Unlit");
out << YAML::EndMap;
}
@ -152,5 +153,18 @@ void AnimationComponent::Load(const YAML::Node &node)
int start = node["StartFrame"] ? node["StartFrame"].as<int>() : 0;
int end = node["EndFrame"] ? node["EndFrame"].as<int>() : 0;
if (node["renderType"] && node["renderType"].IsScalar())
{
std::string typeStr = node["renderType"].as<std::string>();
if (typeStr == "Lit")
renderType = RenderType::Lit;
else if (typeStr == "Unlit")
renderType = RenderType::Unlit;
else
RecoverableError("Invalid 'renderType' value in AnimationComponent: " + typeStr,
Create::Exceptions::InvalidFormat)
.Handle();
}
SetTextureAtlas(uaid, texelWidth, texelHeight, duration, start, end);
}

View File

@ -52,13 +52,18 @@ public:
uint64_t GetTextureUAID() const;
void SetTextureUAID(uint64_t uaid);
void SetRenderType(RenderType type) { renderType = type; }
RenderType GetRenderType() const { return renderType; }
// Timing
float GetFrameDuration() const;
void SetFrameDuration(float duration);
// Access atlas
TextureAtlas* GetAtlas();
const TextureAtlas* GetAtlas() const;
TextureAtlas *GetAtlas();
const TextureAtlas *GetAtlas() const;
// Update per tick
void Update(float dt);
@ -68,7 +73,6 @@ public:
void Save(YAML::Emitter &out) const override;
void Load(const YAML::Node &node) override;
RenderType renderType;
private:
std::shared_ptr<Texture> texture;
@ -90,4 +94,9 @@ private:
float speed = 1.0f;
uint64_t textureUAID = 0;
RenderType renderType;
};

View File

@ -12,6 +12,8 @@
#include "core/utils/FileDialog.h"
#include "core/utils/Logging.h"
#include "core/utils/Input.h"
#include "core/audio/AudioEngine.h"
@ -21,6 +23,7 @@
#include "core/utils/utils.h"
#include "core/utils/LoadingWindow.h"
#include "editor/windows/AssetBrowser.h"
#include "editor/windows/Inspector.h"
#include "editor/windows/AudioInfo.h"
@ -30,6 +33,9 @@
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include "ImGuizmo.h"
#include <glm/gtc/type_ptr.hpp>
#include <functional>
#include <fstream>
@ -432,6 +438,53 @@ void ShowColorCorrectionWindow()
ImGui::End();
}
void DrawGizmoForObject(const std::shared_ptr<Object>& obj, const glm::mat4& view, const glm::mat4& projection)
{
if (!obj)
return;
glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(obj->GetLocalPosition(), 0.0f));
model = glm::rotate(model, obj->GetLocalRotation(), glm::vec3(0.0f, 0.0f, 1.0f));
// Setup ImGuizmo
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist();
ImVec2 windowPos = ImGui::GetWindowPos();
ImVec2 windowSize = ImGui::GetWindowSize();
ImGuizmo::SetRect(windowPos.x, windowPos.y, windowSize.x, windowSize.y);
static ImGuizmo::OPERATION operation = ImGuizmo::TRANSLATE;
if (ImGui::IsKeyPressed(ImGuiKey_T)) operation = ImGuizmo::TRANSLATE;
if (ImGui::IsKeyPressed(ImGuiKey_R)) operation = ImGuizmo::ROTATE;
glm::mat4 manipulated = model;
ImGuizmo::Manipulate(glm::value_ptr(view), glm::value_ptr(projection),
operation, ImGuizmo::LOCAL, glm::value_ptr(manipulated));
if (ImGuizmo::IsUsing())
{
glm::vec3 translation, rotation, dummyScale;
ImGuizmo::DecomposeMatrixToComponents(glm::value_ptr(manipulated),
glm::value_ptr(translation),
glm::value_ptr(rotation),
glm::value_ptr(dummyScale));
obj->SetLocalPosition(translation);
obj->SetLocalRotation(rotation.z);
}
}
void Engine::Init()
{
@ -523,6 +576,12 @@ void Engine::Init()
AudioEngine::Init();
Logger::LogVerbose("Init Input Core");
Input::Init(window);
// AssetManager::LoadAssetAsync("C:\\Users\\spenc\\Music\\creative-technology-showreel-241274.mp3", AssetType::Audio);
Logger::LogVerbose("Resverving Objects");
@ -624,6 +683,8 @@ void Engine::Run()
glfwPollEvents();
profiler.EndEngineSection();
Input::Update();
profiler.BeginEngineSection("NewFrame");
profiler.BeginEngineSection("ImGui_ImplOpenGL3_NewFrame");
@ -1197,6 +1258,19 @@ void Engine::Run()
previewUAID = 0;
}
glm::mat4 projection = glm::ortho(
0.0f, static_cast<float>(size.x), // left, right
static_cast<float>(size.y), 0.0f, // bottom, top (y-down)
-1.0f, 1.0f // near, far
);
glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraPos, 0.0f));
DrawGizmoForObject(selected, view, projection);
ImGui::End();
profiler.EndEngineSection();
@ -1250,7 +1324,7 @@ void Engine::Run()
}
}
void Engine::DrawObjectNode(const std::shared_ptr<Object>& obj)
void Engine::DrawObjectNode(const std::shared_ptr<Object> &obj)
{
if (!obj)
return;
@ -1262,7 +1336,7 @@ void Engine::DrawObjectNode(const std::shared_ptr<Object>& obj)
ImGuiTreeNodeFlags_DefaultOpen |
(obj == selected ? ImGuiTreeNodeFlags_Selected : 0);
bool open = ImGui::TreeNodeEx((void*)(intptr_t)obj->uid.id, flags, "%s", obj->GetName().c_str());
bool open = ImGui::TreeNodeEx((void *)(intptr_t)obj->uid.id, flags, "%s", obj->GetName().c_str());
if (ImGui::IsItemClicked())
selected = obj;
@ -1293,12 +1367,12 @@ void Engine::DrawObjectNode(const std::shared_ptr<Object>& obj)
{
if (auto payload = ImGui::AcceptDragDropPayload("OBJECT"))
{
auto dragged = *static_cast<std::shared_ptr<Object>*>(payload->Data);
auto dragged = *static_cast<std::shared_ptr<Object> *>(payload->Data);
if (dragged && dragged != obj)
{
bool valid = true;
for (Object* a = obj.get(); a; a = a->GetParent())
for (Object *a = obj.get(); a; a = a->GetParent())
if (a == dragged.get())
{
valid = false;
@ -1312,11 +1386,9 @@ void Engine::DrawObjectNode(const std::shared_ptr<Object>& obj)
else
objects.erase(std::remove(objects.begin(), objects.end(), dragged), objects.end());
obj->AddChild(dragged);
dragged->SetWorldPosition(
dragged->GetWorldPosition() - obj->GetWorldPosition()
);
dragged->GetWorldPosition() - obj->GetWorldPosition());
}
}
}
@ -1325,15 +1397,13 @@ void Engine::DrawObjectNode(const std::shared_ptr<Object>& obj)
if (open)
{
for (auto& child : obj->GetChildren())
for (auto &child : obj->GetChildren())
if (child)
DrawObjectNode(child);
ImGui::TreePop();
}
}
bool VerifySceneHash(const YAML::Node &root)
{
if (!root["scene_hash"] || !root["objects"])

View File

@ -683,18 +683,25 @@ void Renderer::DrawAnimator(const AnimationComponent *anim, const core::types::V
entry.rotationRad = 0.0f;
entry.textureID = tex->GetID();
entry.normalMapID = defaultNormalMap;
entry.renderType = anim->renderType;
entry.renderType = anim->GetRenderType();
entry.sprite = nullptr;
entry.texCoords = glm::vec4(uvMin.x, uvMin.y, uvMax.x, uvMax.y);
SortedDrawEntry drawEntry;
drawEntry.sprite = entry;
drawEntry.shader = &unlitShader;
drawEntry.useLighting = false;
drawEntry.shader = (g_engineConfig.settings.lighting_enabled && entry.renderType == RenderType::Lit)
? &spriteShader
: &unlitShader;
drawEntry.useLighting = (drawEntry.shader == &spriteShader);
drawEntry.usesUV = true;
sortedDrawList.push_back(drawEntry);
}
void Renderer::FlushQuads()
{
PROFILE_ENGINE_SCOPE("Renderer::FlushQuads");

View File

@ -1,20 +1,62 @@
#include "input.h"
#include "Logging.h"
#include "Profiler.h"
#include <GLFW/glfw3.h>
#include <imgui.h>
extern GLFWwindow* window;
namespace Input
void Input::Init(GLFWwindow* window)
{
bool IsKeyDown(Keycode key)
{
return glfwGetKey(window, static_cast<int>(key)) == GLFW_PRESS;
}
core::types::Vec2 GetMousePosition()
{
ImVec2 p = ImGui::GetMousePos();
return core::types::Vec2 { p.x, p.y };
}
s_Window = window;
Logger::LogOk("Input Core");
}
void Input::Update()
{
PROFILE_ENGINE_SCOPE("Input::Update");
std::copy(std::begin(s_KeysCurrent), std::end(s_KeysCurrent), s_KeysPrevious);
std::copy(std::begin(s_MouseCurrent), std::end(s_MouseCurrent), s_MousePrevious);
for (int key = 0; key <= GLFW_KEY_LAST; ++key)
s_KeysCurrent[key] = glfwGetKey(s_Window, key) == GLFW_PRESS;
for (int button = 0; button <= GLFW_MOUSE_BUTTON_LAST; ++button)
s_MouseCurrent[button] = glfwGetMouseButton(s_Window, button) == GLFW_PRESS;
}
bool Input::IsKeyDown(Keycode key)
{
return s_KeysCurrent[static_cast<int>(key)];
}
bool Input::IsKeyPressed(Keycode key)
{
int k = static_cast<int>(key);
return s_KeysCurrent[k] && !s_KeysPrevious[k];
}
bool Input::IsKeyReleased(Keycode key)
{
int k = static_cast<int>(key);
return !s_KeysCurrent[k] && s_KeysPrevious[k];
}
bool Input::IsMouseButtonDown(int button)
{
return s_MouseCurrent[button];
}
bool Input::IsMouseButtonPressed(int button)
{
return s_MouseCurrent[button] && !s_MousePrevious[button];
}
bool Input::IsMouseButtonReleased(int button)
{
return !s_MouseCurrent[button] && s_MousePrevious[button];
}
core::types::Vec2 Input::GetMousePosition()
{
double x, y;
glfwGetCursorPos(s_Window, &x, &y);
return { static_cast<float>(x), static_cast<float>(y) };
}

View File

@ -2,9 +2,32 @@
#include "keycode.h"
#include "../types/vec2.h"
#include <GLFW/glfw3.h>
#include <unordered_map>
namespace Input
class Input
{
bool IsKeyDown(Keycode key);
core::types::Vec2 GetMousePosition();
}
public:
static void Init(GLFWwindow* window);
static void Update();
static bool IsKeyDown(Keycode key);
static bool IsKeyPressed(Keycode key);
static bool IsKeyReleased(Keycode key);
static bool IsMouseButtonDown(int button);
static bool IsMouseButtonPressed(int button);
static bool IsMouseButtonReleased(int button);
static core::types::Vec2 GetMousePosition();
private:
static inline GLFWwindow* s_Window = nullptr;
static inline bool s_KeysCurrent[GLFW_KEY_LAST + 1]{};
static inline bool s_KeysPrevious[GLFW_KEY_LAST + 1]{};
static inline bool s_MouseCurrent[GLFW_MOUSE_BUTTON_LAST + 1]{};
static inline bool s_MousePrevious[GLFW_MOUSE_BUTTON_LAST + 1]{};
};

View File

@ -278,6 +278,11 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
{
ImGui::SeparatorText("Animation Component");
const char *renderTypes[] = {"Unlit", "Lit"};
int currentTypeIndex = static_cast<int>(anim->GetRenderType());
if (ImGui::Combo("Render Type", &currentTypeIndex, renderTypes, IM_ARRAYSIZE(renderTypes)))
anim->SetRenderType(static_cast<RenderType>(currentTypeIndex));
static int frameWidth = anim->GetAtlas()->frameWidth;
static int frameHeight = anim->GetAtlas()->frameHeight;
static float frameDuration = anim->GetFrameDuration();

3151
src/vendor/imguizmo/ImGuizmo.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

306
src/vendor/imguizmo/ImGuizmo.h vendored Normal file
View File

@ -0,0 +1,306 @@
// https://github.com/CedricGuillemet/ImGuizmo
// v1.91.3 WIP
//
// The MIT License(MIT)
//
// Copyright(c) 2021 Cedric Guillemet
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// -------------------------------------------------------------------------------------------
// History :
// 2019/11/03 View gizmo
// 2016/09/11 Behind camera culling. Scaling Delta matrix not multiplied by source matrix scales. local/world rotation and translation fixed. Display message is incorrect (X: ... Y:...) in local mode.
// 2016/09/09 Hatched negative axis. Snapping. Documentation update.
// 2016/09/04 Axis switch and translation plan autohiding. Scale transform stability improved
// 2016/09/01 Mogwai changed to Manipulate. Draw debug cube. Fixed inverted scale. Mixing scale and translation/rotation gives bad results.
// 2016/08/31 First version
//
// -------------------------------------------------------------------------------------------
// Future (no order):
//
// - Multi view
// - display rotation/translation/scale infos in local/world space and not only local
// - finish local/world matrix application
// - OPERATION as bitmask
//
// -------------------------------------------------------------------------------------------
// Example
#if 0
void EditTransform(const Camera& camera, matrix_t& matrix)
{
static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::ROTATE);
static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::WORLD);
if (ImGui::IsKeyPressed(90))
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
if (ImGui::IsKeyPressed(69))
mCurrentGizmoOperation = ImGuizmo::ROTATE;
if (ImGui::IsKeyPressed(82)) // r Key
mCurrentGizmoOperation = ImGuizmo::SCALE;
if (ImGui::RadioButton("Translate", mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
ImGui::SameLine();
if (ImGui::RadioButton("Rotate", mCurrentGizmoOperation == ImGuizmo::ROTATE))
mCurrentGizmoOperation = ImGuizmo::ROTATE;
ImGui::SameLine();
if (ImGui::RadioButton("Scale", mCurrentGizmoOperation == ImGuizmo::SCALE))
mCurrentGizmoOperation = ImGuizmo::SCALE;
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
ImGuizmo::DecomposeMatrixToComponents(matrix.m16, matrixTranslation, matrixRotation, matrixScale);
ImGui::InputFloat3("Tr", matrixTranslation, 3);
ImGui::InputFloat3("Rt", matrixRotation, 3);
ImGui::InputFloat3("Sc", matrixScale, 3);
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, matrix.m16);
if (mCurrentGizmoOperation != ImGuizmo::SCALE)
{
if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
mCurrentGizmoMode = ImGuizmo::LOCAL;
ImGui::SameLine();
if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD))
mCurrentGizmoMode = ImGuizmo::WORLD;
}
static bool useSnap(false);
if (ImGui::IsKeyPressed(83))
useSnap = !useSnap;
ImGui::Checkbox("", &useSnap);
ImGui::SameLine();
vec_t snap;
switch (mCurrentGizmoOperation)
{
case ImGuizmo::TRANSLATE:
snap = config.mSnapTranslation;
ImGui::InputFloat3("Snap", &snap.x);
break;
case ImGuizmo::ROTATE:
snap = config.mSnapRotation;
ImGui::InputFloat("Angle Snap", &snap.x);
break;
case ImGuizmo::SCALE:
snap = config.mSnapScale;
ImGui::InputFloat("Scale Snap", &snap.x);
break;
}
ImGuiIO& io = ImGui::GetIO();
ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
ImGuizmo::Manipulate(camera.mView.m16, camera.mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, matrix.m16, NULL, useSnap ? &snap.x : NULL);
}
#endif
#pragma once
#ifdef USE_IMGUI_API
#include "imconfig.h"
#endif
#ifndef IMGUI_API
#define IMGUI_API
#endif
#ifndef IMGUIZMO_NAMESPACE
#define IMGUIZMO_NAMESPACE ImGuizmo
#endif
struct ImGuiWindow;
namespace IMGUIZMO_NAMESPACE
{
// call inside your own window and before Manipulate() in order to draw gizmo to that window.
// Or pass a specific ImDrawList to draw to (e.g. ImGui::GetForegroundDrawList()).
IMGUI_API void SetDrawlist(ImDrawList* drawlist = nullptr);
// call BeginFrame right after ImGui_XXXX_NewFrame();
IMGUI_API void BeginFrame();
// this is necessary because when imguizmo is compiled into a dll, and imgui into another
// globals are not shared between them.
// More details at https://stackoverflow.com/questions/19373061/what-happens-to-global-and-static-variables-in-a-shared-library-when-it-is-dynam
// expose method to set imgui context
IMGUI_API void SetImGuiContext(ImGuiContext* ctx);
// return true if mouse cursor is over any gizmo control (axis, plan or screen component)
IMGUI_API bool IsOver();
// return true if mouse IsOver or if the gizmo is in moving state
IMGUI_API bool IsUsing();
// return true if the view gizmo is in moving state
IMGUI_API bool IsUsingViewManipulate();
// only check if your mouse is over the view manipulator - no matter whether it's active or not
IMGUI_API bool IsViewManipulateHovered();
// return true if any gizmo is in moving state
IMGUI_API bool IsUsingAny();
// enable/disable the gizmo. Stay in the state until next call to Enable.
// gizmo is rendered with gray half transparent color when disabled
IMGUI_API void Enable(bool enable);
// helper functions for manualy editing translation/rotation/scale with an input float
// translation, rotation and scale float points to 3 floats each
// Angles are in degrees (more suitable for human editing)
// example:
// float matrixTranslation[3], matrixRotation[3], matrixScale[3];
// ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation, matrixRotation, matrixScale);
// ImGui::InputFloat3("Tr", matrixTranslation, 3);
// ImGui::InputFloat3("Rt", matrixRotation, 3);
// ImGui::InputFloat3("Sc", matrixScale, 3);
// ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16);
//
// These functions have some numerical stability issues for now. Use with caution.
IMGUI_API void DecomposeMatrixToComponents(const float* matrix, float* translation, float* rotation, float* scale);
IMGUI_API void RecomposeMatrixFromComponents(const float* translation, const float* rotation, const float* scale, float* matrix);
IMGUI_API void SetRect(float x, float y, float width, float height);
// default is false
IMGUI_API void SetOrthographic(bool isOrthographic);
// Render a cube with face color corresponding to face normal. Usefull for debug/tests
IMGUI_API void DrawCubes(const float* view, const float* projection, const float* matrices, int matrixCount);
IMGUI_API void DrawGrid(const float* view, const float* projection, const float* matrix, const float gridSize);
// call it when you want a gizmo
// Needs view and projection matrices.
// matrix parameter is the source matrix (where will be gizmo be drawn) and might be transformed by the function. Return deltaMatrix is optional
// translation is applied in world space
enum OPERATION
{
TRANSLATE_X = (1u << 0),
TRANSLATE_Y = (1u << 1),
TRANSLATE_Z = (1u << 2),
ROTATE_X = (1u << 3),
ROTATE_Y = (1u << 4),
ROTATE_Z = (1u << 5),
ROTATE_SCREEN = (1u << 6),
SCALE_X = (1u << 7),
SCALE_Y = (1u << 8),
SCALE_Z = (1u << 9),
BOUNDS = (1u << 10),
SCALE_XU = (1u << 11),
SCALE_YU = (1u << 12),
SCALE_ZU = (1u << 13),
TRANSLATE = TRANSLATE_X | TRANSLATE_Y | TRANSLATE_Z,
ROTATE = ROTATE_X | ROTATE_Y | ROTATE_Z | ROTATE_SCREEN,
SCALE = SCALE_X | SCALE_Y | SCALE_Z,
SCALEU = SCALE_XU | SCALE_YU | SCALE_ZU, // universal
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
};
inline OPERATION operator|(OPERATION lhs, OPERATION rhs)
{
return static_cast<OPERATION>(static_cast<int>(lhs) | static_cast<int>(rhs));
}
enum MODE
{
LOCAL,
WORLD
};
IMGUI_API bool Manipulate(const float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float* deltaMatrix = NULL, const float* snap = NULL, const float* localBounds = NULL, const float* boundsSnap = NULL);
//
// Please note that this cubeview is patented by Autodesk : https://patents.google.com/patent/US7782319B2/en
// It seems to be a defensive patent in the US. I don't think it will bring troubles using it as
// other software are using the same mechanics. But just in case, you are now warned!
//
IMGUI_API void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);
// use this version if you did not call Manipulate before and you are just using ViewManipulate
IMGUI_API void ViewManipulate(float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);
IMGUI_API void SetAlternativeWindow(ImGuiWindow* window);
[[deprecated("Use PushID/PopID instead.")]]
IMGUI_API void SetID(int id);
// ID stack/scopes
// Read the FAQ (docs/FAQ.md or http://dearimgui.org/faq) for more details about how ID are handled in dear imgui.
// - Those questions are answered and impacted by understanding of the ID stack system:
// - "Q: Why is my widget not reacting when I click on it?"
// - "Q: How can I have widgets with an empty label?"
// - "Q: How can I have multiple widgets with the same label?"
// - Short version: ID are hashes of the entire ID stack. If you are creating widgets in a loop you most likely
// want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them.
// - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others.
// - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID,
// whereas "str_id" denote a string that is only used as an ID and not normally displayed.
IMGUI_API void PushID(const char* str_id); // push string into the ID stack (will hash string).
IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string).
IMGUI_API void PushID(const void* ptr_id); // push pointer into the ID stack (will hash pointer).
IMGUI_API void PushID(int int_id); // push integer into the ID stack (will hash integer).
IMGUI_API void PopID(); // pop from the ID stack.
IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself
IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end);
IMGUI_API ImGuiID GetID(const void* ptr_id);
// return true if the cursor is over the operation's gizmo
IMGUI_API bool IsOver(OPERATION op);
IMGUI_API void SetGizmoSizeClipSpace(float value);
// Allow axis to flip
// When true (default), the guizmo axis flip for better visibility
// When false, they always stay along the positive world/local axis
IMGUI_API void AllowAxisFlip(bool value);
// Configure the limit where axis are hidden
IMGUI_API void SetAxisLimit(float value);
// Set an axis mask to permanently hide a given axis (true -> hidden, false -> shown)
IMGUI_API void SetAxisMask(bool x, bool y, bool z);
// Configure the limit where planes are hiden
IMGUI_API void SetPlaneLimit(float value);
// from a x,y,z point in space and using Manipulation view/projection matrix, check if mouse is in pixel radius distance of that projected point
IMGUI_API bool IsOver(float* position, float pixelRadius);
enum COLOR
{
DIRECTION_X, // directionColor[0]
DIRECTION_Y, // directionColor[1]
DIRECTION_Z, // directionColor[2]
PLANE_X, // planeColor[0]
PLANE_Y, // planeColor[1]
PLANE_Z, // planeColor[2]
SELECTION, // selectionColor
INACTIVE, // inactiveColor
TRANSLATION_LINE, // translationLineColor
SCALE_LINE,
ROTATION_USING_BORDER,
ROTATION_USING_FILL,
HATCHED_AXIS_LINES,
TEXT,
TEXT_SHADOW,
COUNT
};
struct Style
{
IMGUI_API Style();
float TranslationLineThickness; // Thickness of lines for translation gizmo
float TranslationLineArrowSize; // Size of arrow at the end of lines for translation gizmo
float RotationLineThickness; // Thickness of lines for rotation gizmo
float RotationOuterLineThickness; // Thickness of line surrounding the rotation gizmo
float ScaleLineThickness; // Thickness of lines for scale gizmo
float ScaleLineCircleSize; // Size of circle at the end of lines for scale gizmo
float HatchedAxisLineThickness; // Thickness of hatched axis lines
float CenterCircleSize; // Size of circle at the center of the translate/scale gizmo
ImVec4 Colors[COLOR::COUNT];
};
IMGUI_API Style& GetStyle();
}