feat: expand editor scripting asset and viewport flow
This commit is contained in:
@@ -3,8 +3,13 @@
|
||||
#include "Core/ISceneManager.h"
|
||||
#include "Core/ISelectionManager.h"
|
||||
#include "SceneViewPanel.h"
|
||||
#include "Viewport/SceneViewportEditorOverlayData.h"
|
||||
#include "Viewport/SceneViewportOverlayHandleBuilder.h"
|
||||
#include "Viewport/SceneViewportOverlayHitTester.h"
|
||||
#include "Viewport/SceneViewportMath.h"
|
||||
#include "Viewport/SceneViewportOrientationGizmo.h"
|
||||
#include "Viewport/SceneViewportOverlayRenderer.h"
|
||||
#include "Viewport/SceneViewportTransformGizmoFrameBuilder.h"
|
||||
#include "ViewportPanelContent.h"
|
||||
#include "Platform/Win32Utf8.h"
|
||||
#include "UI/UI.h"
|
||||
@@ -13,9 +18,11 @@
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
@@ -28,13 +35,209 @@ struct SceneViewportToolOverlayResult {
|
||||
SceneViewportToolMode clickedTool = SceneViewportToolMode::Move;
|
||||
};
|
||||
|
||||
enum class SceneViewportActiveGizmoKind : uint8_t {
|
||||
enum class SceneViewportInteractionKind : uint8_t {
|
||||
None = 0,
|
||||
Move,
|
||||
Rotate,
|
||||
Scale
|
||||
MoveGizmo,
|
||||
RotateGizmo,
|
||||
ScaleGizmo,
|
||||
OrientationGizmo,
|
||||
SceneIcon
|
||||
};
|
||||
|
||||
struct SceneViewportInteractionCandidate {
|
||||
SceneViewportInteractionKind kind = SceneViewportInteractionKind::None;
|
||||
int priority = 0;
|
||||
int secondaryPriority = 0;
|
||||
float distanceSq = Math::FLOAT_MAX;
|
||||
float depth = Math::FLOAT_MAX;
|
||||
uint64_t entityId = 0;
|
||||
SceneViewportGizmoAxis moveAxis = SceneViewportGizmoAxis::None;
|
||||
SceneViewportGizmoPlane movePlane = SceneViewportGizmoPlane::None;
|
||||
SceneViewportRotateGizmoAxis rotateAxis = SceneViewportRotateGizmoAxis::None;
|
||||
SceneViewportScaleGizmoHandle scaleHandle = SceneViewportScaleGizmoHandle::None;
|
||||
SceneViewportOrientationAxis orientationAxis = SceneViewportOrientationAxis::None;
|
||||
|
||||
bool HasHit() const {
|
||||
return kind != SceneViewportInteractionKind::None;
|
||||
}
|
||||
};
|
||||
|
||||
const char* GetSceneViewportPivotModeLabel(SceneViewportPivotMode mode) {
|
||||
return mode == SceneViewportPivotMode::Pivot ? "Pivot" : "Center";
|
||||
}
|
||||
|
||||
const char* GetSceneViewportTransformSpaceModeLabel(SceneViewportTransformSpaceMode mode) {
|
||||
return mode == SceneViewportTransformSpaceMode::Global ? "Global" : "Local";
|
||||
}
|
||||
|
||||
SceneViewportActiveGizmoKind ToActiveGizmoKind(SceneViewportInteractionKind kind) {
|
||||
switch (kind) {
|
||||
case SceneViewportInteractionKind::MoveGizmo:
|
||||
return SceneViewportActiveGizmoKind::Move;
|
||||
case SceneViewportInteractionKind::RotateGizmo:
|
||||
return SceneViewportActiveGizmoKind::Rotate;
|
||||
case SceneViewportInteractionKind::ScaleGizmo:
|
||||
return SceneViewportActiveGizmoKind::Scale;
|
||||
case SceneViewportInteractionKind::OrientationGizmo:
|
||||
case SceneViewportInteractionKind::SceneIcon:
|
||||
case SceneViewportInteractionKind::None:
|
||||
default:
|
||||
return SceneViewportActiveGizmoKind::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBetterSceneViewportInteractionCandidate(
|
||||
const SceneViewportInteractionCandidate& candidate,
|
||||
const SceneViewportInteractionCandidate& current) {
|
||||
constexpr float kMetricEpsilon = 0.001f;
|
||||
|
||||
if (!candidate.HasHit()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!current.HasHit()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (candidate.priority != current.priority) {
|
||||
return candidate.priority > current.priority;
|
||||
}
|
||||
|
||||
if (candidate.distanceSq + kMetricEpsilon < current.distanceSq) {
|
||||
return true;
|
||||
}
|
||||
if (current.distanceSq + kMetricEpsilon < candidate.distanceSq) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (candidate.depth + kMetricEpsilon < current.depth) {
|
||||
return true;
|
||||
}
|
||||
if (current.depth + kMetricEpsilon < candidate.depth) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return candidate.secondaryPriority > current.secondaryPriority;
|
||||
}
|
||||
|
||||
void AccumulateSceneViewportInteractionCandidate(
|
||||
const SceneViewportInteractionCandidate& candidate,
|
||||
SceneViewportInteractionCandidate& bestCandidate) {
|
||||
if (IsBetterSceneViewportInteractionCandidate(candidate, bestCandidate)) {
|
||||
bestCandidate = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
SceneViewportInteractionCandidate BuildOrientationGizmoInteractionCandidate(
|
||||
SceneViewportOrientationAxis axis) {
|
||||
SceneViewportInteractionCandidate candidate = {};
|
||||
if (axis == SceneViewportOrientationAxis::None) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
candidate.kind = SceneViewportInteractionKind::OrientationGizmo;
|
||||
candidate.priority = 200;
|
||||
candidate.distanceSq = 0.0f;
|
||||
candidate.depth = 0.0f;
|
||||
candidate.orientationAxis = axis;
|
||||
return candidate;
|
||||
}
|
||||
|
||||
SceneViewportInteractionCandidate BuildOverlayHandleInteractionCandidate(
|
||||
const SceneViewportOverlayHandleHitResult& hitResult) {
|
||||
SceneViewportInteractionCandidate candidate = {};
|
||||
if (!hitResult.HasHit()) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
candidate.priority = hitResult.priority;
|
||||
candidate.distanceSq = hitResult.distanceSq;
|
||||
candidate.depth = hitResult.depth;
|
||||
candidate.entityId = hitResult.entityId;
|
||||
switch (hitResult.kind) {
|
||||
case SceneViewportOverlayHandleKind::SceneIcon:
|
||||
candidate.kind = SceneViewportInteractionKind::SceneIcon;
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::MoveAxis:
|
||||
candidate.kind = SceneViewportInteractionKind::MoveGizmo;
|
||||
candidate.moveAxis = static_cast<SceneViewportGizmoAxis>(hitResult.handleId);
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::MovePlane:
|
||||
candidate.kind = SceneViewportInteractionKind::MoveGizmo;
|
||||
candidate.movePlane = static_cast<SceneViewportGizmoPlane>(hitResult.handleId);
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::RotateAxis:
|
||||
candidate.kind = SceneViewportInteractionKind::RotateGizmo;
|
||||
candidate.rotateAxis = static_cast<SceneViewportRotateGizmoAxis>(hitResult.handleId);
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::ScaleAxis:
|
||||
case SceneViewportOverlayHandleKind::ScaleUniform:
|
||||
candidate.kind = SceneViewportInteractionKind::ScaleGizmo;
|
||||
candidate.scaleHandle = static_cast<SceneViewportScaleGizmoHandle>(hitResult.handleId);
|
||||
return candidate;
|
||||
case SceneViewportOverlayHandleKind::None:
|
||||
default:
|
||||
return SceneViewportInteractionCandidate{};
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
float GetSceneToolbarToggleWidth(const char* firstLabel, const char* secondLabel) {
|
||||
constexpr float kHorizontalPadding = 10.0f;
|
||||
constexpr float kMinWidth = 68.0f;
|
||||
const float maxLabelWidth = (std::max)(
|
||||
ImGui::CalcTextSize(firstLabel).x,
|
||||
ImGui::CalcTextSize(secondLabel).x);
|
||||
return (std::max)(kMinWidth, maxLabelWidth + kHorizontalPadding * 2.0f);
|
||||
}
|
||||
|
||||
void RenderSceneViewportTopBar(
|
||||
SceneViewportPivotMode& pivotMode,
|
||||
SceneViewportTransformSpaceMode& transformSpaceMode) {
|
||||
constexpr float kSceneToolbarHeight = 24.0f;
|
||||
constexpr float kSceneToolbarPaddingY = 0.0f;
|
||||
constexpr float kSceneToolbarButtonHeight = kSceneToolbarHeight - kSceneToolbarPaddingY * 2.0f;
|
||||
constexpr ImVec2 kSceneToolbarButtonFramePadding(8.0f, 1.0f);
|
||||
|
||||
UI::PanelToolbarScope toolbar(
|
||||
"SceneToolbar",
|
||||
kSceneToolbarHeight,
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse,
|
||||
true,
|
||||
ImVec2(UI::ToolbarPadding().x, kSceneToolbarPaddingY),
|
||||
ImVec2(0.0f, UI::ToolbarItemSpacing().y),
|
||||
ImVec4(0.23f, 0.23f, 0.23f, 1.0f));
|
||||
if (!toolbar.IsOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, kSceneToolbarButtonFramePadding);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
|
||||
|
||||
if (UI::ToolbarButton(
|
||||
GetSceneViewportPivotModeLabel(pivotMode),
|
||||
true,
|
||||
ImVec2(GetSceneToolbarToggleWidth("Pivot", "Center"), kSceneToolbarButtonHeight))) {
|
||||
pivotMode = pivotMode == SceneViewportPivotMode::Pivot
|
||||
? SceneViewportPivotMode::Center
|
||||
: SceneViewportPivotMode::Pivot;
|
||||
}
|
||||
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
|
||||
if (UI::ToolbarButton(
|
||||
GetSceneViewportTransformSpaceModeLabel(transformSpaceMode),
|
||||
true,
|
||||
ImVec2(GetSceneToolbarToggleWidth("Global", "Local"), kSceneToolbarButtonHeight))) {
|
||||
transformSpaceMode = transformSpaceMode == SceneViewportTransformSpaceMode::Global
|
||||
? SceneViewportTransformSpaceMode::Local
|
||||
: SceneViewportTransformSpaceMode::Global;
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
const char* GetSceneViewportToolTooltip(SceneViewportToolMode toolMode) {
|
||||
switch (toolMode) {
|
||||
case SceneViewportToolMode::ViewMove:
|
||||
@@ -69,6 +272,19 @@ const char* GetSceneViewportToolIconBaseName(SceneViewportToolMode toolMode) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string BuildSceneViewportIconPath(const char* iconBaseName, bool active = false) {
|
||||
const std::filesystem::path exeDir(
|
||||
XCEngine::Editor::Platform::Utf8ToWide(XCEngine::Editor::Platform::GetExecutableDirectoryUtf8()));
|
||||
std::filesystem::path iconPath =
|
||||
exeDir / L".." / L".." / L"resources" / L"Icons" /
|
||||
std::filesystem::path(XCEngine::Editor::Platform::Utf8ToWide(iconBaseName));
|
||||
if (active) {
|
||||
iconPath += L"_on";
|
||||
}
|
||||
iconPath += L".png";
|
||||
return XCEngine::Editor::Platform::WideToUtf8(iconPath.lexically_normal().wstring());
|
||||
}
|
||||
|
||||
const std::string& GetSceneViewportToolIconPath(SceneViewportToolMode toolMode, bool active) {
|
||||
static std::string cachedPaths[5][2] = {};
|
||||
const size_t toolIndex = static_cast<size_t>(toolMode);
|
||||
@@ -78,16 +294,7 @@ const std::string& GetSceneViewportToolIconPath(SceneViewportToolMode toolMode,
|
||||
return cachedPath;
|
||||
}
|
||||
|
||||
const std::filesystem::path exeDir(
|
||||
XCEngine::Editor::Platform::Utf8ToWide(XCEngine::Editor::Platform::GetExecutableDirectoryUtf8()));
|
||||
std::filesystem::path iconPath =
|
||||
(exeDir / L".." / L".." / L"resources" / L"Icons" /
|
||||
std::filesystem::path(XCEngine::Editor::Platform::Utf8ToWide(GetSceneViewportToolIconBaseName(toolMode))));
|
||||
if (active) {
|
||||
iconPath += L"_on";
|
||||
}
|
||||
iconPath += L".png";
|
||||
cachedPath = XCEngine::Editor::Platform::WideToUtf8(iconPath.lexically_normal().wstring());
|
||||
cachedPath = BuildSceneViewportIconPath(GetSceneViewportToolIconBaseName(toolMode), active);
|
||||
return cachedPath;
|
||||
}
|
||||
|
||||
@@ -205,72 +412,6 @@ bool ShouldBeginSceneViewportNavigationDrag(
|
||||
ImGui::IsMouseClicked(button);
|
||||
}
|
||||
|
||||
SceneViewportMoveGizmoContext BuildMoveGizmoContext(
|
||||
IEditorContext& context,
|
||||
const SceneViewportOverlayData& overlay,
|
||||
const ViewportPanelContentResult& content,
|
||||
const ImVec2& mousePosition) {
|
||||
SceneViewportMoveGizmoContext gizmoContext = {};
|
||||
gizmoContext.overlay = overlay;
|
||||
gizmoContext.viewportSize = Math::Vector2(content.availableSize.x, content.availableSize.y);
|
||||
gizmoContext.mousePosition = Math::Vector2(
|
||||
mousePosition.x - content.itemMin.x,
|
||||
mousePosition.y - content.itemMin.y);
|
||||
|
||||
if (context.GetSelectionManager().GetSelectionCount() == 1) {
|
||||
const uint64_t selectedEntity = context.GetSelectionManager().GetSelectedEntity();
|
||||
if (selectedEntity != 0) {
|
||||
gizmoContext.selectedObject = context.GetSceneManager().GetEntity(selectedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
return gizmoContext;
|
||||
}
|
||||
|
||||
SceneViewportRotateGizmoContext BuildRotateGizmoContext(
|
||||
IEditorContext& context,
|
||||
const SceneViewportOverlayData& overlay,
|
||||
const ViewportPanelContentResult& content,
|
||||
const ImVec2& mousePosition) {
|
||||
SceneViewportRotateGizmoContext gizmoContext = {};
|
||||
gizmoContext.overlay = overlay;
|
||||
gizmoContext.viewportSize = Math::Vector2(content.availableSize.x, content.availableSize.y);
|
||||
gizmoContext.mousePosition = Math::Vector2(
|
||||
mousePosition.x - content.itemMin.x,
|
||||
mousePosition.y - content.itemMin.y);
|
||||
|
||||
if (context.GetSelectionManager().GetSelectionCount() == 1) {
|
||||
const uint64_t selectedEntity = context.GetSelectionManager().GetSelectedEntity();
|
||||
if (selectedEntity != 0) {
|
||||
gizmoContext.selectedObject = context.GetSceneManager().GetEntity(selectedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
return gizmoContext;
|
||||
}
|
||||
|
||||
SceneViewportScaleGizmoContext BuildScaleGizmoContext(
|
||||
IEditorContext& context,
|
||||
const SceneViewportOverlayData& overlay,
|
||||
const ViewportPanelContentResult& content,
|
||||
const ImVec2& mousePosition) {
|
||||
SceneViewportScaleGizmoContext gizmoContext = {};
|
||||
gizmoContext.overlay = overlay;
|
||||
gizmoContext.viewportSize = Math::Vector2(content.availableSize.x, content.availableSize.y);
|
||||
gizmoContext.mousePosition = Math::Vector2(
|
||||
mousePosition.x - content.itemMin.x,
|
||||
mousePosition.y - content.itemMin.y);
|
||||
|
||||
if (context.GetSelectionManager().GetSelectionCount() == 1) {
|
||||
const uint64_t selectedEntity = context.GetSelectionManager().GetSelectedEntity();
|
||||
if (selectedEntity != 0) {
|
||||
gizmoContext.selectedObject = context.GetSceneManager().GetEntity(selectedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
return gizmoContext;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SceneViewPanel::SceneViewPanel() : Panel("Scene") {}
|
||||
@@ -283,6 +424,7 @@ void SceneViewPanel::Render() {
|
||||
return;
|
||||
}
|
||||
|
||||
RenderSceneViewportTopBar(m_pivotMode, m_transformSpaceMode);
|
||||
const ViewportPanelContentResult content = RenderViewportPanelContent(*m_context, EditorViewportKind::Scene);
|
||||
if (IViewportHostService* viewportHostService = m_context->GetViewportHostService()) {
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
@@ -304,8 +446,20 @@ void SceneViewPanel::Render() {
|
||||
m_toolMode = toolOverlay.clickedTool;
|
||||
}
|
||||
|
||||
if (content.focused && !io.WantTextInput && !m_lookDragging && !m_panDragging) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_W, false)) {
|
||||
const bool allowToolShortcut = !io.WantTextInput && !m_lookDragging && !m_panDragging;
|
||||
if (allowToolShortcut) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Q, false)) {
|
||||
if (m_moveGizmo.IsActive()) {
|
||||
m_moveGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
if (m_rotateGizmo.IsActive()) {
|
||||
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
if (m_scaleGizmo.IsActive()) {
|
||||
m_scaleGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
m_toolMode = SceneViewportToolMode::ViewMove;
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_W, false)) {
|
||||
if (m_rotateGizmo.IsActive()) {
|
||||
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
@@ -337,103 +491,68 @@ void SceneViewPanel::Render() {
|
||||
const bool showingMoveGizmo = m_toolMode == SceneViewportToolMode::Move || usingTransformTool;
|
||||
const bool showingRotateGizmo = m_toolMode == SceneViewportToolMode::Rotate || usingTransformTool;
|
||||
const bool showingScaleGizmo = m_toolMode == SceneViewportToolMode::Scale || usingTransformTool;
|
||||
const bool useCenterPivot = m_pivotMode == SceneViewportPivotMode::Center;
|
||||
const bool localSpace = m_transformSpaceMode == SceneViewportTransformSpaceMode::Local;
|
||||
const Math::Vector2 viewportSize(content.availableSize.x, content.availableSize.y);
|
||||
const Math::Vector2 localMousePosition(
|
||||
io.MousePos.x - content.itemMin.x,
|
||||
io.MousePos.y - content.itemMin.y);
|
||||
SceneViewportOverlayData overlay = {};
|
||||
SceneViewportMoveGizmoContext moveGizmoContext = {};
|
||||
SceneViewportRotateGizmoContext rotateGizmoContext = {};
|
||||
SceneViewportScaleGizmoContext scaleGizmoContext = {};
|
||||
SceneViewportTransformGizmoFrameState gizmoFrameState = {};
|
||||
SceneViewportOverlayFrameData emptySceneOverlayFrameData = {};
|
||||
SceneViewportActiveGizmoKind activeGizmoKind = SceneViewportActiveGizmoKind::None;
|
||||
|
||||
if (hasInteractiveViewport) {
|
||||
overlay = viewportHostService->GetSceneViewOverlayData();
|
||||
if (showingMoveGizmo) {
|
||||
moveGizmoContext = BuildMoveGizmoContext(*m_context, overlay, content, io.MousePos);
|
||||
if (m_moveGizmo.IsActive() &&
|
||||
(moveGizmoContext.selectedObject == nullptr ||
|
||||
m_context->GetSelectionManager().GetSelectedEntity() != m_moveGizmo.GetActiveEntityId())) {
|
||||
m_moveGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
} else if (m_moveGizmo.IsActive()) {
|
||||
m_moveGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
|
||||
if (showingRotateGizmo) {
|
||||
rotateGizmoContext = BuildRotateGizmoContext(*m_context, overlay, content, io.MousePos);
|
||||
if (m_rotateGizmo.IsActive() &&
|
||||
(rotateGizmoContext.selectedObject == nullptr ||
|
||||
m_context->GetSelectionManager().GetSelectedEntity() != m_rotateGizmo.GetActiveEntityId())) {
|
||||
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
} else if (m_rotateGizmo.IsActive()) {
|
||||
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
|
||||
if (showingScaleGizmo) {
|
||||
scaleGizmoContext = BuildScaleGizmoContext(*m_context, overlay, content, io.MousePos);
|
||||
scaleGizmoContext.uniformOnly = usingTransformTool;
|
||||
if (m_scaleGizmo.IsActive() &&
|
||||
(scaleGizmoContext.selectedObject == nullptr ||
|
||||
m_context->GetSelectionManager().GetSelectedEntity() != m_scaleGizmo.GetActiveEntityId())) {
|
||||
m_scaleGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
} else if (m_scaleGizmo.IsActive()) {
|
||||
m_scaleGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
|
||||
if (m_moveGizmo.IsActive()) {
|
||||
activeGizmoKind = SceneViewportActiveGizmoKind::Move;
|
||||
} else if (m_rotateGizmo.IsActive()) {
|
||||
activeGizmoKind = SceneViewportActiveGizmoKind::Rotate;
|
||||
} else if (m_scaleGizmo.IsActive()) {
|
||||
activeGizmoKind = SceneViewportActiveGizmoKind::Scale;
|
||||
}
|
||||
|
||||
if (showingMoveGizmo) {
|
||||
SceneViewportMoveGizmoContext updateContext = moveGizmoContext;
|
||||
if (activeGizmoKind != SceneViewportActiveGizmoKind::None &&
|
||||
activeGizmoKind != SceneViewportActiveGizmoKind::Move) {
|
||||
updateContext.mousePosition = Math::Vector2(-1.0f, -1.0f);
|
||||
}
|
||||
m_moveGizmo.Update(updateContext);
|
||||
}
|
||||
if (showingRotateGizmo) {
|
||||
SceneViewportRotateGizmoContext updateContext = rotateGizmoContext;
|
||||
if (activeGizmoKind != SceneViewportActiveGizmoKind::None &&
|
||||
activeGizmoKind != SceneViewportActiveGizmoKind::Rotate) {
|
||||
updateContext.mousePosition = Math::Vector2(-1.0f, -1.0f);
|
||||
}
|
||||
m_rotateGizmo.Update(updateContext);
|
||||
}
|
||||
if (showingScaleGizmo) {
|
||||
SceneViewportScaleGizmoContext updateContext = scaleGizmoContext;
|
||||
if (activeGizmoKind != SceneViewportActiveGizmoKind::None &&
|
||||
activeGizmoKind != SceneViewportActiveGizmoKind::Scale) {
|
||||
updateContext.mousePosition = Math::Vector2(-1.0f, -1.0f);
|
||||
}
|
||||
m_scaleGizmo.Update(updateContext);
|
||||
}
|
||||
gizmoFrameState = RefreshSceneViewportTransformGizmos(
|
||||
*m_context,
|
||||
overlay,
|
||||
viewportSize,
|
||||
localMousePosition,
|
||||
useCenterPivot,
|
||||
localSpace,
|
||||
usingTransformTool,
|
||||
showingMoveGizmo,
|
||||
m_moveGizmo,
|
||||
showingRotateGizmo,
|
||||
m_rotateGizmo,
|
||||
showingScaleGizmo,
|
||||
m_scaleGizmo);
|
||||
activeGizmoKind = gizmoFrameState.activeGizmoKind;
|
||||
} else {
|
||||
if (m_moveGizmo.IsActive()) {
|
||||
m_moveGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
if (m_rotateGizmo.IsActive()) {
|
||||
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
if (m_scaleGizmo.IsActive()) {
|
||||
m_scaleGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||
}
|
||||
CancelSceneViewportTransformGizmoDrags(*m_context, m_moveGizmo, m_rotateGizmo, m_scaleGizmo);
|
||||
}
|
||||
|
||||
const bool moveGizmoHovering = showingMoveGizmo && m_moveGizmo.IsHoveringHandle();
|
||||
const bool rotateGizmoHovering = showingRotateGizmo && m_rotateGizmo.IsHoveringHandle();
|
||||
const bool scaleGizmoHovering = showingScaleGizmo && m_scaleGizmo.IsHoveringHandle();
|
||||
const SceneViewportTransformGizmoHandleBuildInputs interactionGizmoInputs =
|
||||
hasInteractiveViewport
|
||||
? BuildSceneViewportTransformGizmoHandleBuildInputs(
|
||||
showingMoveGizmo,
|
||||
m_moveGizmo,
|
||||
gizmoFrameState.moveContext,
|
||||
showingRotateGizmo,
|
||||
m_rotateGizmo,
|
||||
gizmoFrameState.rotateContext,
|
||||
showingScaleGizmo,
|
||||
m_scaleGizmo,
|
||||
gizmoFrameState.scaleContext)
|
||||
: SceneViewportTransformGizmoHandleBuildInputs{};
|
||||
const SceneViewportOverlayFrameData& interactionOverlayFrameData =
|
||||
hasInteractiveViewport
|
||||
? viewportHostService->GetSceneViewInteractionOverlayFrameData(
|
||||
*m_context,
|
||||
overlay,
|
||||
interactionGizmoInputs)
|
||||
: emptySceneOverlayFrameData;
|
||||
const SceneViewportOverlayHandleHitResult overlayHandleHit =
|
||||
hasInteractiveViewport
|
||||
? HitTestSceneViewportOverlayHandles(
|
||||
interactionOverlayFrameData,
|
||||
Math::Vector2(content.availableSize.x, content.availableSize.y),
|
||||
localMousePosition)
|
||||
: SceneViewportOverlayHandleHitResult{};
|
||||
const bool moveGizmoActive = showingMoveGizmo && m_moveGizmo.IsActive();
|
||||
const bool rotateGizmoActive = showingRotateGizmo && m_rotateGizmo.IsActive();
|
||||
const bool scaleGizmoActive = showingScaleGizmo && m_scaleGizmo.IsActive();
|
||||
const SceneViewportActiveGizmoKind hoveredGizmoKind = scaleGizmoHovering
|
||||
? SceneViewportActiveGizmoKind::Scale
|
||||
: (moveGizmoHovering ? SceneViewportActiveGizmoKind::Move
|
||||
: (rotateGizmoHovering ? SceneViewportActiveGizmoKind::Rotate
|
||||
: SceneViewportActiveGizmoKind::None));
|
||||
if (moveGizmoActive) {
|
||||
activeGizmoKind = SceneViewportActiveGizmoKind::Move;
|
||||
} else if (rotateGizmoActive) {
|
||||
@@ -443,44 +562,83 @@ void SceneViewPanel::Render() {
|
||||
} else {
|
||||
activeGizmoKind = SceneViewportActiveGizmoKind::None;
|
||||
}
|
||||
const bool gizmoHovering = hoveredGizmoKind != SceneViewportActiveGizmoKind::None;
|
||||
const bool gizmoActive = activeGizmoKind != SceneViewportActiveGizmoKind::None;
|
||||
|
||||
const bool beginTransformGizmo =
|
||||
hasInteractiveViewport &&
|
||||
content.clickedLeft &&
|
||||
!m_lookDragging &&
|
||||
!m_panDragging &&
|
||||
!toolOverlay.hovered &&
|
||||
gizmoHovering;
|
||||
const SceneViewportOrientationAxis orientationAxisHit =
|
||||
SceneViewportInteractionCandidate hoveredInteraction = {};
|
||||
const bool canResolveViewportInteraction =
|
||||
hasInteractiveViewport &&
|
||||
viewportContentHovered &&
|
||||
!usingViewMoveTool &&
|
||||
!m_lookDragging &&
|
||||
!m_panDragging &&
|
||||
!gizmoHovering &&
|
||||
!gizmoActive
|
||||
? HitTestSceneViewportOrientationGizmo(
|
||||
overlay,
|
||||
content.itemMin,
|
||||
content.itemMax,
|
||||
io.MousePos)
|
||||
: SceneViewportOrientationAxis::None;
|
||||
!toolOverlay.hovered &&
|
||||
!gizmoActive;
|
||||
if (canResolveViewportInteraction) {
|
||||
AccumulateSceneViewportInteractionCandidate(
|
||||
BuildOverlayHandleInteractionCandidate(overlayHandleHit),
|
||||
hoveredInteraction);
|
||||
|
||||
AccumulateSceneViewportInteractionCandidate(
|
||||
BuildOrientationGizmoInteractionCandidate(
|
||||
HitTestSceneViewportOrientationGizmo(
|
||||
overlay,
|
||||
content.itemMin,
|
||||
content.itemMax,
|
||||
io.MousePos)),
|
||||
hoveredInteraction);
|
||||
}
|
||||
|
||||
if (!gizmoActive) {
|
||||
if (showingMoveGizmo) {
|
||||
m_moveGizmo.SetHoveredHandle(
|
||||
hoveredInteraction.kind == SceneViewportInteractionKind::MoveGizmo
|
||||
? hoveredInteraction.moveAxis
|
||||
: SceneViewportGizmoAxis::None,
|
||||
hoveredInteraction.kind == SceneViewportInteractionKind::MoveGizmo
|
||||
? hoveredInteraction.movePlane
|
||||
: SceneViewportGizmoPlane::None);
|
||||
}
|
||||
if (showingRotateGizmo) {
|
||||
m_rotateGizmo.SetHoveredHandle(
|
||||
hoveredInteraction.kind == SceneViewportInteractionKind::RotateGizmo
|
||||
? hoveredInteraction.rotateAxis
|
||||
: SceneViewportRotateGizmoAxis::None);
|
||||
}
|
||||
if (showingScaleGizmo) {
|
||||
m_scaleGizmo.SetHoveredHandle(
|
||||
hoveredInteraction.kind == SceneViewportInteractionKind::ScaleGizmo
|
||||
? hoveredInteraction.scaleHandle
|
||||
: SceneViewportScaleGizmoHandle::None);
|
||||
}
|
||||
}
|
||||
|
||||
const SceneViewportActiveGizmoKind hoveredGizmoKind =
|
||||
ToActiveGizmoKind(hoveredInteraction.kind);
|
||||
const bool gizmoHovering = hoveredGizmoKind != SceneViewportActiveGizmoKind::None;
|
||||
const SceneViewportOrientationAxis orientationAxisHit =
|
||||
hoveredInteraction.kind == SceneViewportInteractionKind::OrientationGizmo
|
||||
? hoveredInteraction.orientationAxis
|
||||
: SceneViewportOrientationAxis::None;
|
||||
const uint64_t clickedSceneIconEntity =
|
||||
hoveredInteraction.kind == SceneViewportInteractionKind::SceneIcon
|
||||
? hoveredInteraction.entityId
|
||||
: 0;
|
||||
const bool beginTransformGizmo =
|
||||
hasInteractiveViewport &&
|
||||
content.clickedLeft &&
|
||||
gizmoHovering;
|
||||
const bool orientationGizmoClick =
|
||||
hasInteractiveViewport &&
|
||||
content.clickedLeft &&
|
||||
orientationAxisHit != SceneViewportOrientationAxis::None;
|
||||
const bool sceneIconClick =
|
||||
hasInteractiveViewport &&
|
||||
content.clickedLeft &&
|
||||
clickedSceneIconEntity != 0;
|
||||
const bool selectClick =
|
||||
hasInteractiveViewport &&
|
||||
content.clickedLeft &&
|
||||
viewportContentHovered &&
|
||||
!usingViewMoveTool &&
|
||||
!m_lookDragging &&
|
||||
!m_panDragging &&
|
||||
!orientationGizmoClick &&
|
||||
!gizmoHovering &&
|
||||
!gizmoActive;
|
||||
canResolveViewportInteraction &&
|
||||
!hoveredInteraction.HasHit();
|
||||
const bool beginLeftPanDrag = usingViewMoveTool
|
||||
? ShouldBeginSceneViewportNavigationDrag(
|
||||
hasInteractiveViewport,
|
||||
@@ -525,47 +683,32 @@ void SceneViewPanel::Render() {
|
||||
io.MouseDelta.y);
|
||||
}
|
||||
|
||||
if (toolOverlay.clicked || beginTransformGizmo || orientationGizmoClick || selectClick || beginLookDrag ||
|
||||
if (toolOverlay.clicked || beginTransformGizmo || orientationGizmoClick || sceneIconClick || selectClick || beginLookDrag ||
|
||||
beginPanDrag) {
|
||||
ImGui::SetWindowFocus();
|
||||
}
|
||||
|
||||
if (beginTransformGizmo) {
|
||||
if (hoveredGizmoKind == SceneViewportActiveGizmoKind::Scale) {
|
||||
m_scaleGizmo.TryBeginDrag(scaleGizmoContext, m_context->GetUndoManager());
|
||||
m_scaleGizmo.TryBeginDrag(gizmoFrameState.scaleContext, m_context->GetUndoManager());
|
||||
} else if (hoveredGizmoKind == SceneViewportActiveGizmoKind::Move) {
|
||||
m_moveGizmo.TryBeginDrag(moveGizmoContext, m_context->GetUndoManager());
|
||||
m_moveGizmo.TryBeginDrag(gizmoFrameState.moveContext, m_context->GetUndoManager());
|
||||
} else if (hoveredGizmoKind == SceneViewportActiveGizmoKind::Rotate) {
|
||||
m_rotateGizmo.TryBeginDrag(rotateGizmoContext, m_context->GetUndoManager());
|
||||
m_rotateGizmo.TryBeginDrag(gizmoFrameState.rotateContext, m_context->GetUndoManager());
|
||||
}
|
||||
}
|
||||
|
||||
if (orientationGizmoClick) {
|
||||
viewportHostService->AlignSceneViewToOrientationAxis(orientationAxisHit);
|
||||
overlay = viewportHostService->GetSceneViewOverlayData();
|
||||
if (showingMoveGizmo) {
|
||||
moveGizmoContext = BuildMoveGizmoContext(*m_context, overlay, content, io.MousePos);
|
||||
m_moveGizmo.Update(moveGizmoContext);
|
||||
}
|
||||
if (showingRotateGizmo) {
|
||||
rotateGizmoContext = BuildRotateGizmoContext(*m_context, overlay, content, io.MousePos);
|
||||
m_rotateGizmo.Update(rotateGizmoContext);
|
||||
}
|
||||
if (showingScaleGizmo) {
|
||||
scaleGizmoContext = BuildScaleGizmoContext(*m_context, overlay, content, io.MousePos);
|
||||
scaleGizmoContext.uniformOnly = usingTransformTool;
|
||||
m_scaleGizmo.Update(scaleGizmoContext);
|
||||
}
|
||||
}
|
||||
|
||||
if (selectClick) {
|
||||
const ImVec2 localMousePosition(
|
||||
io.MousePos.x - content.itemMin.x,
|
||||
io.MousePos.y - content.itemMin.y);
|
||||
if (sceneIconClick) {
|
||||
m_context->GetSelectionManager().SetSelectedEntity(clickedSceneIconEntity);
|
||||
} else if (selectClick) {
|
||||
const uint64_t selectedEntity = viewportHostService->PickSceneViewEntity(
|
||||
*m_context,
|
||||
content.availableSize,
|
||||
localMousePosition);
|
||||
ImVec2(localMousePosition.x, localMousePosition.y));
|
||||
if (selectedEntity != 0) {
|
||||
m_context->GetSelectionManager().SetSelectedEntity(selectedEntity);
|
||||
} else {
|
||||
@@ -576,11 +719,11 @@ void SceneViewPanel::Render() {
|
||||
if (gizmoActive) {
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
|
||||
if (activeGizmoKind == SceneViewportActiveGizmoKind::Move) {
|
||||
m_moveGizmo.UpdateDrag(moveGizmoContext);
|
||||
m_moveGizmo.UpdateDrag(gizmoFrameState.moveContext);
|
||||
} else if (activeGizmoKind == SceneViewportActiveGizmoKind::Rotate) {
|
||||
m_rotateGizmo.UpdateDrag(rotateGizmoContext);
|
||||
m_rotateGizmo.UpdateDrag(gizmoFrameState.rotateContext);
|
||||
} else if (activeGizmoKind == SceneViewportActiveGizmoKind::Scale) {
|
||||
m_scaleGizmo.UpdateDrag(scaleGizmoContext);
|
||||
m_scaleGizmo.UpdateDrag(gizmoFrameState.scaleContext);
|
||||
}
|
||||
} else {
|
||||
if (activeGizmoKind == SceneViewportActiveGizmoKind::Move) {
|
||||
@@ -707,52 +850,41 @@ void SceneViewPanel::Render() {
|
||||
|
||||
if (content.hasViewportArea && content.frame.hasTexture) {
|
||||
overlay = viewportHostService->GetSceneViewOverlayData();
|
||||
SceneViewportActiveGizmoKind drawActiveGizmoKind = SceneViewportActiveGizmoKind::None;
|
||||
if (m_moveGizmo.IsActive()) {
|
||||
drawActiveGizmoKind = SceneViewportActiveGizmoKind::Move;
|
||||
} else if (m_rotateGizmo.IsActive()) {
|
||||
drawActiveGizmoKind = SceneViewportActiveGizmoKind::Rotate;
|
||||
} else if (m_scaleGizmo.IsActive()) {
|
||||
drawActiveGizmoKind = SceneViewportActiveGizmoKind::Scale;
|
||||
}
|
||||
if (showingMoveGizmo) {
|
||||
moveGizmoContext = BuildMoveGizmoContext(*m_context, overlay, content, io.MousePos);
|
||||
SceneViewportMoveGizmoContext updateContext = moveGizmoContext;
|
||||
if (drawActiveGizmoKind != SceneViewportActiveGizmoKind::None &&
|
||||
drawActiveGizmoKind != SceneViewportActiveGizmoKind::Move) {
|
||||
updateContext.mousePosition = Math::Vector2(-1.0f, -1.0f);
|
||||
}
|
||||
m_moveGizmo.Update(updateContext);
|
||||
}
|
||||
if (showingRotateGizmo) {
|
||||
rotateGizmoContext = BuildRotateGizmoContext(*m_context, overlay, content, io.MousePos);
|
||||
SceneViewportRotateGizmoContext updateContext = rotateGizmoContext;
|
||||
if (drawActiveGizmoKind != SceneViewportActiveGizmoKind::None &&
|
||||
drawActiveGizmoKind != SceneViewportActiveGizmoKind::Rotate) {
|
||||
updateContext.mousePosition = Math::Vector2(-1.0f, -1.0f);
|
||||
}
|
||||
m_rotateGizmo.Update(updateContext);
|
||||
}
|
||||
if (showingScaleGizmo) {
|
||||
scaleGizmoContext = BuildScaleGizmoContext(*m_context, overlay, content, io.MousePos);
|
||||
scaleGizmoContext.uniformOnly = usingTransformTool;
|
||||
SceneViewportScaleGizmoContext updateContext = scaleGizmoContext;
|
||||
if (drawActiveGizmoKind != SceneViewportActiveGizmoKind::None &&
|
||||
drawActiveGizmoKind != SceneViewportActiveGizmoKind::Scale) {
|
||||
updateContext.mousePosition = Math::Vector2(-1.0f, -1.0f);
|
||||
}
|
||||
m_scaleGizmo.Update(updateContext);
|
||||
}
|
||||
const SceneViewportTransformGizmoFrameState drawGizmoFrameState =
|
||||
RefreshSceneViewportTransformGizmos(
|
||||
*m_context,
|
||||
overlay,
|
||||
viewportSize,
|
||||
localMousePosition,
|
||||
useCenterPivot,
|
||||
localSpace,
|
||||
usingTransformTool,
|
||||
showingMoveGizmo,
|
||||
m_moveGizmo,
|
||||
showingRotateGizmo,
|
||||
m_rotateGizmo,
|
||||
showingScaleGizmo,
|
||||
m_scaleGizmo);
|
||||
|
||||
viewportHostService->SetSceneViewTransientTransformGizmoOverlayData(
|
||||
overlay,
|
||||
BuildSceneViewportTransformGizmoHandleBuildInputs(
|
||||
showingMoveGizmo,
|
||||
m_moveGizmo,
|
||||
drawGizmoFrameState.moveContext,
|
||||
showingRotateGizmo,
|
||||
m_rotateGizmo,
|
||||
drawGizmoFrameState.rotateContext,
|
||||
showingScaleGizmo,
|
||||
m_scaleGizmo,
|
||||
drawGizmoFrameState.scaleContext));
|
||||
|
||||
DrawSceneViewportOverlay(
|
||||
ImGui::GetWindowDrawList(),
|
||||
overlay,
|
||||
content.itemMin,
|
||||
content.itemMax,
|
||||
content.availableSize,
|
||||
showingMoveGizmo ? &m_moveGizmo.GetDrawData() : nullptr,
|
||||
showingRotateGizmo ? &m_rotateGizmo.GetDrawData() : nullptr,
|
||||
showingScaleGizmo ? &m_scaleGizmo.GetDrawData() : nullptr);
|
||||
content.availableSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user