add ImViewzmo, add floating window for QWER(select, translate, rotate, scale) , and add new debug button to floating (Experimental)

This commit is contained in:
2026-03-02 17:10:03 +08:00
parent a0086020c1
commit 57e14bc3d2
11 changed files with 337 additions and 134 deletions

3
.gitmodules vendored
View File

@ -29,3 +29,6 @@
[submodule "Prism/vendor/PhysX"]
path = Prism/vendor/PhysX
url = https://github.com/NVIDIA-Omniverse/PhysX.git
[submodule "Prism/vendor/ImViewGuizmo"]
path = Prism/vendor/ImViewGuizmo
url = https://github.com/Ka1serM/ImViewGuizmo

View File

@ -6,6 +6,9 @@
#include <ImGuizmo.h>
#include <filesystem>
#define IMVIEWGUIZMO_IMPLEMENTATION
#include "ImViewGuizmo.h"
#define GLM_ENABLE_EXPERIMENTAL
#include "glm/gtx/matrix_decompose.hpp"
@ -46,7 +49,7 @@ namespace Prism
// OpenScene("assets/scenes/FPSDemo.scene");
NewScene();
m_CurrentScene = m_RuntimeScene;
m_CurrentScene = m_EditorScene;
AssetEditorPanel::RegisterDefaultEditors();
FileSystem::StartWatching();
@ -589,122 +592,272 @@ namespace Prism
auto viewportOffset = ImGui::GetCursorPos(); // includes tab bar
auto viewportSize = ImGui::GetContentRegionAvail();
SceneRenderer::SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
m_EditorScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
if (m_RuntimeScene)
m_RuntimeScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
m_EditorCamera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
m_EditorCamera.SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
static int counter = 0;
auto windowSize = ImGui::GetWindowSize();
ImVec2 minBound = ImGui::GetWindowPos();
minBound.x += viewportOffset.x;
minBound.y += viewportOffset.y;
ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y };
m_ViewportBounds[0] = { minBound.x, minBound.y };
m_ViewportBounds[1] = { maxBound.x, maxBound.y };
m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound);
// ImGuizmo
if (m_GizmoType != -1 && !m_SelectionContext.empty())
if (viewportSize.x != 0 && viewportSize.y != 0)
{
auto& selection = m_SelectionContext[0];
SceneRenderer::SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
m_EditorScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
m_EditorCamera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
m_EditorCamera.SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
const auto rw = (float)ImGui::GetWindowWidth();
const auto rh = (float)ImGui::GetWindowHeight();
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist();
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, rw, rh);
bool snap = Input::IsKeyPressed(Key::LEFT_CONTROL);
TransformComponent& entityTransform = selection.Entity.Transform();
// glm::mat4 transform = entityTransform.GetTransform();
glm::mat4 transform = m_CurrentScene->GetTransformRelativeToParent(selection.Entity);
float snapValue = GetSnapValue();
float snapValues[3] = { snapValue, snapValue, snapValue };
if (m_SelectionMode == SelectionMode::Entity)
if (ImGui::BeginDragDropTarget())
{
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
(ImGuizmo::OPERATION)m_GizmoType,
ImGuizmo::LOCAL,
glm::value_ptr(transform),
nullptr,
snap ? snapValues : nullptr);
if (ImGuizmo::IsUsing())
auto payload = ImGui::AcceptDragDropPayload("asset_payload");
if (payload)
{
glm::vec3 translation, rotation, scale;
Math::DecomposeTransform(transform, translation,rotation,scale);
int count = payload->DataSize / sizeof(AssetHandle);
if (Entity parent = m_CurrentScene->FindEntityByUUID(selection.Entity.GetParentUUID()))
for (int i = 0; i < count; i++)
{
glm::vec3 parentTranslation, parentRotation, parentScale;
Math::DecomposeTransform(m_CurrentScene->GetTransformRelativeToParent(parent), parentTranslation, parentRotation, parentScale);
AssetHandle assetHandle = *(((AssetHandle*)payload->Data) + i);
Ref<Asset> asset = AssetsManager::GetAsset<Asset>(assetHandle);
glm::vec3 deltaRotation = (rotation - parentRotation) - entityTransform.Rotation;
entityTransform.Translation = translation - parentTranslation;
entityTransform.Rotation += deltaRotation;
entityTransform.Scale = scale;
}
else
{
glm::vec3 deltaRotation = rotation - entityTransform.Rotation;
entityTransform.Translation = translation;
entityTransform.Rotation += deltaRotation;
entityTransform.Scale = scale;
// We can't really support dragging and dropping scenes when we're dropping multiple assets
if (count == 1 && asset->Type == AssetType::Scene)
{
OpenScene(asset->FilePath);
}
if (asset->Type == AssetType::Mesh)
{
Entity entity = m_EditorScene->CreateEntity(asset->FileName);
entity.AddComponent<MeshComponent>(Ref<Mesh>(asset));
SelectEntity(entity);
}
}
}
}else
{
glm::mat4 transformBase = transform * selection.Mesh->Transform;
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
(ImGuizmo::OPERATION)m_GizmoType,
ImGuizmo::LOCAL,
glm::value_ptr(transformBase),
nullptr,
snap ? snapValues : nullptr);
if (ImGuizmo::IsUsing())
{
selection.Mesh->Transform = glm::inverse(entityTransform.GetTransform()) * transformBase;
}
ImGui::EndDragDropTarget();
}
}
if (ImGui::BeginDragDropTarget())
{
auto payload = ImGui::AcceptDragDropPayload("asset_payload");
if (payload)
auto windowSize = ImGui::GetWindowSize();
ImVec2 minBound = ImGui::GetWindowPos();
minBound.x += viewportOffset.x;
minBound.y += viewportOffset.y;
ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y };
m_ViewportBounds[0] = { minBound.x, minBound.y };
m_ViewportBounds[1] = { maxBound.x, maxBound.y };
m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound);
// ImGuizmo
if (m_GizmoType != -1 && !m_SelectionContext.empty())
{
int count = payload->DataSize / sizeof(AssetHandle);
auto& selection = m_SelectionContext[0];
for (int i = 0; i < count; i++)
const auto rw = (float)ImGui::GetWindowWidth();
const auto rh = (float)ImGui::GetWindowHeight();
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist();
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, rw, rh);
bool snap = Input::IsKeyPressed(Key::LEFT_CONTROL);
TransformComponent& entityTransform = selection.Entity.Transform();
// glm::mat4 transform = entityTransform.GetTransform();
glm::mat4 transform = m_CurrentScene->GetTransformRelativeToParent(selection.Entity);
float snapValue = GetSnapValue();
float snapValues[3] = { snapValue, snapValue, snapValue };
if (m_SelectionMode == SelectionMode::Entity)
{
AssetHandle assetHandle = *(((AssetHandle*)payload->Data) + i);
Ref<Asset> asset = AssetsManager::GetAsset<Asset>(assetHandle);
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
(ImGuizmo::OPERATION)m_GizmoType,
ImGuizmo::LOCAL,
glm::value_ptr(transform),
nullptr,
snap ? snapValues : nullptr);
// We can't really support dragging and dropping scenes when we're dropping multiple assets
if (count == 1 && asset->Type == AssetType::Scene)
if (ImGuizmo::IsUsing())
{
OpenScene(asset->FilePath);
glm::vec3 translation, rotation, scale;
Math::DecomposeTransform(transform, translation,rotation,scale);
if (Entity parent = m_CurrentScene->FindEntityByUUID(selection.Entity.GetParentUUID()))
{
glm::vec3 parentTranslation, parentRotation, parentScale;
Math::DecomposeTransform(m_CurrentScene->GetTransformRelativeToParent(parent), parentTranslation, parentRotation, parentScale);
glm::vec3 deltaRotation = (rotation - parentRotation) - entityTransform.Rotation;
entityTransform.Translation = translation - parentTranslation;
entityTransform.Rotation += deltaRotation;
entityTransform.Scale = scale;
}
else
{
glm::vec3 deltaRotation = rotation - entityTransform.Rotation;
entityTransform.Translation = translation;
entityTransform.Rotation += deltaRotation;
entityTransform.Scale = scale;
}
}
}else
{
glm::mat4 transformBase = transform * selection.Mesh->Transform;
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
(ImGuizmo::OPERATION)m_GizmoType,
ImGuizmo::LOCAL,
glm::value_ptr(transformBase),
nullptr,
snap ? snapValues : nullptr);
if (asset->Type == AssetType::Mesh)
if (ImGuizmo::IsUsing())
{
Entity entity = m_EditorScene->CreateEntity(asset->FileName);
entity.AddComponent<MeshComponent>(Ref<Mesh>(asset));
SelectEntity(entity);
selection.Mesh->Transform = glm::inverse(entityTransform.GetTransform()) * transformBase;
}
}
}
ImGui::EndDragDropTarget();
// ImZmoToolBar
{
const float iconSize = 28.0f;
const float padding = 6.0f;
const ImU32 backgroundColor = IM_COL32(30, 30, 30, 140);
const ImVec4 orangeMain = ImVec4(0.92f, 0.45f, 0.11f, 0.8f);
ImGuiChildFlags child_flags = ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY;
ImGuiWindowFlags Gizmo_window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav |
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground;
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(padding, padding));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 0));
ImGui::SetCursorPos(ImVec2(10.0f, viewportOffset.y + 10.0f));
if (m_SceneState != SceneState::Play)
{
if (ImGui::BeginChild("GizmoToolbar", ImVec2(0, 0), child_flags, Gizmo_window_flags))
{
ImDrawList *draw_list = ImGui::GetWindowDrawList();
draw_list->AddRectFilled(ImGui::GetWindowPos(),
ImVec2(ImGui::GetWindowPos().x + ImGui::GetWindowWidth(), ImGui::GetWindowPos().y + ImGui::GetWindowHeight()),
backgroundColor, 6.0f);
auto drawGizmoBtn = [&](const char *label, int type, const char *tooltip)
{
bool isActive = (m_GizmoType == type);
if (isActive)
ImGui::PushStyleColor(ImGuiCol_Button, orangeMain);
else
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
if (ImGui::Button(label, ImVec2(iconSize, iconSize)))
m_GizmoType = type;
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort))
ImGui::SetTooltip("%s", tooltip);
ImGui::PopStyleColor();
};
drawGizmoBtn("Q", -1, "Select (Q)");
ImGui::SameLine();
drawGizmoBtn("W", (int)ImGuizmo::TRANSLATE, "Translate (W)");
ImGui::SameLine();
drawGizmoBtn("E", (int)ImGuizmo::ROTATE, "Rotate (E)");
ImGui::SameLine();
drawGizmoBtn("R", (int)ImGuizmo::SCALE, "Scale (R)");
}
ImGui::EndChild();
}
float centerX = minBound.x + viewportOffset.x + viewportSize.x * 0.5f;
float topY = minBound.y + 10.0f;
ImGui::SetNextWindowPos(ImVec2(centerX, topY), ImGuiCond_Always, ImVec2(0.5f, 0.0f));
if (ImGui::BeginChild("DebugButton", ImVec2(0, 0), child_flags, Gizmo_window_flags))
{
ImDrawList *draw_list = ImGui::GetWindowDrawList();
draw_list->AddRectFilled(ImGui::GetWindowPos(),
ImVec2(ImGui::GetWindowPos().x + ImGui::GetWindowWidth(), ImGui::GetWindowPos().y + ImGui::GetWindowHeight()),
backgroundColor, 6.0f);
// Scene control buttons
const bool toolbarEnabled = (bool)m_CurrentScene;
ImVec4 tintColor = toolbarEnabled ? ImVec4(1, 1, 1, 1) : ImVec4(1, 1, 1, 0.5f);
bool isEdit = m_SceneState == SceneState::Edit;
bool isPlay = m_SceneState == SceneState::Play;
// bool isSim = m_SceneState == SceneState::Pause;
auto drawImgBtn = [&](const char *id, Ref<Texture2D> iconRef, ImVec4 bg, auto func)
{
ImGui::PushStyleColor(ImGuiCol_Button, bg);
const auto textureID = (ImTextureID)(uintptr_t)iconRef->GetRendererID();
if (ImGui::ImageButton(id, textureID, ImVec2(iconSize - 6, iconSize - 6), {0, 0}, {1, 1}, {0, 0, 0, 0}, tintColor))
{
if (toolbarEnabled)
func();
}
ImGui::PopStyleColor();
};
if (isEdit)
{
drawImgBtn("##Play", m_PlayButtonTex, ImVec4(0, 0, 0, 0), [this]()
{ OnScenePlay(); });
}
else if (isPlay)
{
drawImgBtn("##Stop", m_StopButtonTex, ImVec4(0.8f, 0.1f, 0.1f, 0.6f), [this]()
{ OnSceneStop(); });
}
}
ImGui::EndChild();
ImGui::PopStyleVar(3);
}
// ImViewGuizmo
if (m_SceneState != SceneState::Play)
{
ImViewGuizmo::BeginFrame();
auto &style = ImViewGuizmo::GetStyle();
style.scale = 0.8f;
const float gizmoSize = 256.0f * style.scale;
const float inset = gizmoSize * 0.1f;
const ImVec2 gizmoCenter = ImVec2(
maxBound.x - gizmoSize * 0.5f + inset,
minBound.y + gizmoSize * 0.5f - inset);
glm::vec3 cameraPos = m_EditorCamera.GetPosition();
glm::vec3 focusPosition = m_EditorCamera.GetFocusPosition();
float CameraYaw = m_EditorCamera.GetYaw();
float CameraPitch = -m_EditorCamera.GetPitch();
glm::quat qYaw = glm::angleAxis(CameraYaw, glm::vec3(0.0f, 1.0f, 0.0f));
glm::quat qPitch = glm::angleAxis(CameraPitch, glm::vec3(1.0f, 0.0f, 0.0f));
glm::quat cameraRot = qYaw * qPitch;
if (ImViewGuizmo::Rotate(cameraPos, cameraRot, glm::vec3(0.0f), gizmoCenter))
{
glm::vec3 forward = cameraRot * glm::vec3(0.0f, 0.0f, -1.0f);
float newPitch = glm::asin(glm::clamp(-forward.y, -1.0f, 1.0f));
float newYaw = -glm::atan(forward.x, -forward.z);
float distance = glm::length(cameraPos - focusPosition);
m_EditorCamera.SetDistance(distance);
m_EditorCamera.SetFocusPosition(focusPosition);
m_EditorCamera.SetYawPitch(newYaw, newPitch);
}
}
if (m_RuntimeScene)
m_RuntimeScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
}
}
@ -756,7 +909,7 @@ namespace Prism
break;
Entity selectedEntity = m_SelectionContext[0].Entity;
m_EditorCamera.Focus(selectedEntity.Transform().Translation);
m_EditorCamera.SetFocusPosition(selectedEntity.Transform().Translation);
break;
}
}
@ -1059,23 +1212,25 @@ namespace Prism
m_RuntimeScene = Ref<Scene>::Create();
m_EditorScene->CopyTo(m_RuntimeScene);
m_RuntimeScene->OnRuntimeStart();
m_SceneHierarchyPanel->SetContext(m_RuntimeScene);
m_CurrentScene = m_RuntimeScene;
m_SceneHierarchyPanel->SetContext(m_CurrentScene);
m_CurrentScene->OnRuntimeStart();
}
void EditorLayer::OnSceneStop()
{
m_RuntimeScene->OnRuntimeStop();
m_CurrentScene->OnRuntimeStop();
m_SceneState = SceneState::Edit;
// Unload runtime scene
m_RuntimeScene = nullptr;
m_SelectionContext.clear();
ScriptEngine::SetSceneContext(m_EditorScene);
m_SceneHierarchyPanel->SetContext(m_EditorScene);
m_CurrentScene = m_EditorScene;
ScriptEngine::SetSceneContext(m_CurrentScene);
m_SceneHierarchyPanel->SetContext(m_CurrentScene);
}
float EditorLayer::GetSnapValue() const

View File

@ -12,9 +12,8 @@ uniform mat4 u_Projection;
uniform vec3 u_CameraPosition;
out CameraData{
mat4 View;
mat4 Projection;
vec3 CameraPosition;
mat4 ViewProjection;
vec3 Position;
}CameraOutput;
out vec3 v_NearPoint;
@ -31,9 +30,8 @@ void main() {
v_NearPoint = unprojectPoint(a_Position.x, a_Position.y, 0.0);
v_FarPoint = unprojectPoint(a_Position.x, a_Position.y, 1.0);
CameraOutput.View = u_View;
CameraOutput.Projection = u_Projection;
CameraOutput.CameraPosition = u_CameraPosition;
CameraOutput.ViewProjection = u_Projection * u_View;
CameraOutput.Position = u_CameraPosition;
gl_Position = vec4(a_Position, 1.0);
}
@ -47,22 +45,21 @@ in vec3 v_NearPoint;
in vec3 v_FarPoint;
in CameraData{
mat4 View;
mat4 Projection;
vec3 CameraPosition;
mat4 ViewProjection;
vec3 Position;
}CameraInput;
// Grid plane: 0 = XZ (Y up), 1 = XY (Z forward), 2 = YZ (X right)
uniform int u_GridPlane = 0;
uniform float u_GridScale = 1.0;
uniform vec4 u_GridColorThin = vec4(0.5, 0.5, 0.5, 0.4);
uniform vec4 u_GridColorThick = vec4(0.5, 0.5, 0.5, 0.6);
uniform vec4 u_AxisColorX = vec4(0.9, 0.2, 0.2, 1.0);
uniform vec4 u_AxisColorZ = vec4(0.2, 0.2, 0.9, 1.0);
uniform float u_FadeDistance = 500.0;
uniform int u_GridPlane;
uniform float u_GridScale;
uniform vec4 u_GridColorThin;
uniform vec4 u_GridColorThick;
uniform vec4 u_AxisColorX;
uniform vec4 u_AxisColorZ;
uniform float u_FadeDistance;
float computeDepth(vec3 pos) {
vec4 clipSpacePos = CameraInput.Projection * CameraInput.View * vec4(pos, 1.0);
vec4 clipSpacePos = CameraInput.ViewProjection * vec4(pos, 1.0);
return clipSpacePos.z / clipSpacePos.w;
}
@ -155,11 +152,11 @@ void main() {
// === Fading ===
// Radial fade
float dist = length(fragPos3D - CameraInput.CameraPosition);
float dist = length(fragPos3D - CameraInput.Position);
float radialFade = 1.0 - smoothstep(u_FadeDistance * 0.3, u_FadeDistance, dist);
// Normal fade (view angle)
vec3 viewDir = normalize(fragPos3D - CameraInput.CameraPosition);
vec3 viewDir = normalize(fragPos3D - CameraInput.Position);
float viewAngle = getViewAngleComponent(viewDir);
float normalFade = smoothstep(0.0, 0.15, viewAngle);
@ -179,7 +176,8 @@ void main() {
// LOD blend
vec2 deriv1 = fwidth(gridCoord1);
float lodFactor = smoothstep(0.3, 0.6, max(deriv1.x, deriv1.y));
float lodFactor = smoothstep(20.0, 200.0, dist);
// float lodFactor = smoothstep(0.2, 0.5, max(deriv1.x, deriv1.y));
// Combine grids
float gridIntensity = mix(max(grid1, grid10 * 0.7), grid10, lodFactor);

View File

@ -45,6 +45,11 @@ file(GLOB IMGUIZMO_SOURCE ${IMGUIZMO_DIR}/*.cpp)
list(APPEND SRC_SOURCE ${IMGUIZMO_SOURCE})
# ----------- ImViewGuizmo -------------
set(IMVIEWGUIZMO_DIR vendor/ImViewGuizmo)
# ------------- NVIDIA PhysX -------------
# PhysX/physx/buildtools/presets/*.xml
# PX_GENERATE_STATIC_LIBRARIES=True
@ -117,6 +122,7 @@ set(TARGET_INCLUDE_DIR
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
${IMGUI_DIR}
${IMGUIZMO_DIR}
${IMVIEWGUIZMO_DIR}
)
# ------------- debug Defines -------------

View File

@ -33,7 +33,7 @@ namespace Prism
UpdateCameraView();
}
void EditorCamera::Focus(const glm::vec3& focusPoint)
void EditorCamera::SetFocusPosition(const glm::vec3& focusPoint)
{
m_FocalPoint = focusPoint;
if (m_Distance > m_MinFocusDistance)

View File

@ -21,7 +21,8 @@ namespace Prism
EditorCamera() = default;
EditorCamera(const glm::mat4& projectionMatrix);
void Focus(const glm::vec3& focusPoint);
void SetFocusPosition(const glm::vec3& focusPoint);
glm::vec3 GetFocusPosition() const {return m_FocalPoint; }
void OnUpdate(TimeStep deltaTime);
void OnEvent(Event& e);
@ -42,6 +43,7 @@ namespace Prism
float GetPitch() const { return m_Pitch; }
void SetYawPitch(const float yaw, const float pitch) { m_Yaw = yaw; m_Pitch = pitch; }
float GetYaw() const { return m_Yaw; }
void OnImGuiRender();

View File

@ -144,7 +144,9 @@ namespace Prism
{
if (!m_SelectionContext.HasComponent<T>())
{
if (ImGui::Button(componentName))
const float buttonWidth = ImGui::GetContentRegionAvail().x;
if (ImGui::Button(componentName, ImVec2(buttonWidth, 0)))
{
m_SelectionContext.AddComponent<T>();
ImGui::CloseCurrentPopup();
@ -157,7 +159,8 @@ namespace Prism
{
if (!m_SelectionContext.HasComponent<T>())
{
if (ImGui::Button(componentName))
const float buttonWidth = ImGui::GetContentRegionAvail().x;
if (ImGui::Button(componentName, ImVec2(buttonWidth, 0)))
{
T& component = m_SelectionContext.AddComponent<T>();
function(component);
@ -169,7 +172,7 @@ namespace Prism
void SceneHierarchyPanel::OnImGuiRender()
{
ImGui::Begin("Scene Hierarchy");
ImRect windowRect = { ImGui::GetWindowContentRegionMin(), ImGui::GetWindowContentRegionMax() };
const ImRect windowRect = { ImGui::GetWindowContentRegionMin(), ImGui::GetWindowContentRegionMax() };
if (m_Context)
{
@ -217,15 +220,19 @@ namespace Prism
if (ImGui::BeginMenu("Create"))
{
bool isCreated = false;
if (ImGui::MenuItem("Empty Entity"))
{
auto newEntity = m_Context->CreateEntity("Empty Entity");
isCreated = true;
SetSelected(newEntity);
}
if (ImGui::MenuItem("Mesh"))
{
auto newEntity = m_Context->CreateEntity("Mesh");
newEntity.AddComponent<MeshComponent>();
isCreated = true;
SetSelected(newEntity);
}
ImGui::Separator();
@ -233,15 +240,23 @@ namespace Prism
{
auto newEntity = m_Context->CreateEntity("Directional Light");
newEntity.AddComponent<DirectionalLightComponent>();
isCreated = true;
SetSelected(newEntity);
}
if (ImGui::MenuItem("Sky Light"))
{
auto newEntity = m_Context->CreateEntity("Sky Light");
newEntity.AddComponent<SkyLightComponent>();
isCreated = true;
SetSelected(newEntity);
}
ImGui::EndMenu();
if (isCreated)
{
if (m_SelectionChangedCallback)
m_SelectionChangedCallback(m_SelectionContext);
}
}
ImGui::EndPopup();
}
@ -522,20 +537,18 @@ namespace Prism
if (ImGui::BeginPopup("AddComponentPanel"))
{
AddComponentPopup<CameraComponent>("Camera");
AddComponentPopup<MeshComponent>("Mesh");
AddComponentPopup<DirectionalLightComponent>("Directional Light");
AddComponentPopup<SkyLightComponent>("sky Light");
AddComponentPopup<ScriptComponent>("Script");
AddComponentPopup<SpriteRendererComponent>("SpriteRenderer");
ImGui::SeparatorText("2D Component");
AddComponentPopup<RigidBody2DComponent>("RigidBody2D");
AddComponentPopup<SpriteRendererComponent>("SpriteRenderer2D");
AddComponentPopup<BoxCollider2DComponent>("BoxCollider2D");
AddComponentPopup<CircleCollider2DComponent>("CircleCollider2D");
ImGui::SeparatorText("3D Component");
AddComponentPopup<MeshComponent>("Mesh");
AddComponentPopup<RigidBodyComponent>("RigidBody");
AddComponentPopup<BoxColliderComponent>("BoxCollider");
AddComponentPopup<SphereColliderComponent>("SphereCollider");
AddComponentPopup<CapsuleColliderComponent>("CapsuleCollider");
AddComponentPopup<MeshColliderComponent>("MeshCollider", [&](MeshColliderComponent& component)
{
if (m_SelectionContext.HasComponent<MeshComponent>())
@ -545,6 +558,13 @@ namespace Prism
}
});
ImGui::SeparatorText("Light Component");
AddComponentPopup<DirectionalLightComponent>("Directional Light");
AddComponentPopup<SkyLightComponent>("sky Light");
ImGui::SeparatorText("Other Component");
AddComponentPopup<CameraComponent>("Camera");
AddComponentPopup<ScriptComponent>("Script");
ImGui::EndPopup();
}

View File

@ -339,7 +339,7 @@ namespace Prism
}
glm::vec3 submeshTranslation, submeshRotation, submeshScale;
Math::DecomposeTransform(submesh.LocalTransform, submeshTranslation, submeshRotation, submeshScale);
Math::DecomposeTransform(submesh.Transform, submeshTranslation, submeshRotation, submeshScale);
auto triangleGeometry = physx::PxTriangleMeshGeometry(triangleMesh, physx::PxMeshScale(ToPhysXVector(submeshScale * scale)));
physx::PxMaterial* material = s_Physics->createMaterial(0, 0, 0); // Dummy material, will be replaced at runtime.

View File

@ -20,7 +20,6 @@ namespace Prism
m_Name = found != std::string::npos ? m_Name.substr(0, found) : m_Name;
OpenGLShader::Reload();
}
Ref<OpenGLShader> OpenGLShader::CreateFromString(const std::string& source)
@ -60,6 +59,7 @@ namespace Prism
}
m_Loaded = true;
PM_CORE_INFO("shader loaded: {}", m_Name);
});
}

View File

@ -1130,8 +1130,26 @@ namespace Prism
if (UI::BeginTreeNode("Grid Config", false))
{
// Grid plane: 0 = XZ (Y up), 1 = XY (Z forward), 2 = YZ (X right)
const char* projTypeStrings[] = { "XZ (Y up)", "XY (Z forward)", "YZ (X right)" };
const char* currentMode = projTypeStrings[s_Data.GridData.GridPlane];
if (ImGui::BeginCombo("Grid Plane Mode", currentMode))
{
for (int type = 0; type < 3; type++)
{
const bool is_selected = (currentMode == projTypeStrings[type]);
if (ImGui::Selectable(projTypeStrings[type], is_selected))
{
currentMode = projTypeStrings[type];
s_Data.GridData.GridPlane = type;
}
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
UI::BeginPropertyGrid();
UI::PropertySlider("GridPlane", s_Data.GridData.GridPlane, 0, 2);
UI::Property("GridScale", s_Data.GridData.GridScale);
UI::PropertyColor("GridColorThin", s_Data.GridData.GridColorThin);
UI::PropertyColor("GridColorThick", s_Data.GridData.GridColorThick);

1
Prism/vendor/ImViewGuizmo vendored Submodule