feat(editor): add scene view selection markers
This commit is contained in:
parent
922858b135
commit
b12c88c478
@ -4,6 +4,7 @@
|
||||
#include "MetaCoreEditor/MetaCoreEditorServices.h"
|
||||
#include "MetaCoreFoundation/MetaCoreProject.h"
|
||||
#include "MetaCoreEditorCameraController.h"
|
||||
#include "MetaCoreScene/MetaCoreTransformUtils.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
@ -21,6 +22,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <exception>
|
||||
#include <filesystem>
|
||||
@ -297,6 +299,26 @@ bool MetaCoreProjectWorldPointToViewport(
|
||||
return true;
|
||||
}
|
||||
|
||||
glm::mat4 MetaCoreBuildEditorOverlayWorldMatrix(const MetaCoreScene& scene, MetaCoreId objectId) {
|
||||
const MetaCoreGameObject object = scene.FindGameObject(objectId);
|
||||
if (!object) {
|
||||
return glm::mat4(1.0F);
|
||||
}
|
||||
|
||||
glm::mat4 worldMatrix = MetaCoreBuildTransformMatrix(object.GetComponent<MetaCoreTransformComponent>());
|
||||
MetaCoreId parentId = object.GetParentId();
|
||||
while (parentId != 0) {
|
||||
const MetaCoreGameObject parentObject = scene.FindGameObject(parentId);
|
||||
if (!parentObject) {
|
||||
break;
|
||||
}
|
||||
worldMatrix = MetaCoreBuildTransformMatrix(parentObject.GetComponent<MetaCoreTransformComponent>()) * worldMatrix;
|
||||
parentId = parentObject.GetParentId();
|
||||
}
|
||||
|
||||
return worldMatrix;
|
||||
}
|
||||
|
||||
void MetaCoreDrawWorldOriginOverlay(
|
||||
const MetaCoreEditorContext&,
|
||||
const MetaCoreSceneView&,
|
||||
@ -459,13 +481,112 @@ void MetaCoreDrawViewportGridOverlay(
|
||||
}
|
||||
|
||||
void MetaCoreDrawSelectionBoundsOverlay(
|
||||
const MetaCoreEditorContext&,
|
||||
const MetaCoreScene&,
|
||||
const MetaCoreSceneView&,
|
||||
const MetaCoreSceneViewportState&
|
||||
const MetaCoreEditorContext& editorContext,
|
||||
const MetaCoreScene& scene,
|
||||
const MetaCoreSceneView& sceneView,
|
||||
const MetaCoreSceneViewportState& viewportState
|
||||
) {
|
||||
// 用户要求去掉左下角的黄色框和文字
|
||||
return;
|
||||
if (!editorContext.GetShowViewportSelectionOverlay() || viewportState.Width <= 1.0F || viewportState.Height <= 1.0F) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImDrawList* drawList = ImGui::GetForegroundDrawList();
|
||||
const ImVec2 clipMin(viewportState.Left, viewportState.Top);
|
||||
const ImVec2 clipMax(viewportState.Left + viewportState.Width, viewportState.Top + viewportState.Height);
|
||||
|
||||
const auto drawObjectMarker = [&](MetaCoreId objectId, ImU32 color, float thickness, float minimumSize) {
|
||||
const MetaCoreGameObject gameObject = scene.FindGameObject(objectId);
|
||||
if (!gameObject) {
|
||||
return;
|
||||
}
|
||||
if (gameObject.HasComponent<MetaCoreMeshRendererComponent>() && !gameObject.GetComponent<MetaCoreMeshRendererComponent>().Visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
const glm::mat4 worldMatrix = MetaCoreBuildEditorOverlayWorldMatrix(scene, objectId);
|
||||
const std::array<glm::vec3, 8> localCorners = {
|
||||
glm::vec3(-0.5F, -0.5F, -0.5F),
|
||||
glm::vec3( 0.5F, -0.5F, -0.5F),
|
||||
glm::vec3(-0.5F, 0.5F, -0.5F),
|
||||
glm::vec3( 0.5F, 0.5F, -0.5F),
|
||||
glm::vec3(-0.5F, -0.5F, 0.5F),
|
||||
glm::vec3( 0.5F, -0.5F, 0.5F),
|
||||
glm::vec3(-0.5F, 0.5F, 0.5F),
|
||||
glm::vec3( 0.5F, 0.5F, 0.5F)
|
||||
};
|
||||
|
||||
bool anyPointVisible = false;
|
||||
ImVec2 minPoint(FLT_MAX, FLT_MAX);
|
||||
ImVec2 maxPoint(-FLT_MAX, -FLT_MAX);
|
||||
for (const glm::vec3& localCorner : localCorners) {
|
||||
const glm::vec3 worldCorner = glm::vec3(worldMatrix * glm::vec4(localCorner, 1.0F));
|
||||
ImVec2 screenPoint{};
|
||||
if (!MetaCoreProjectWorldPointToViewport(sceneView, viewportState, worldCorner, screenPoint)) {
|
||||
continue;
|
||||
}
|
||||
anyPointVisible = true;
|
||||
minPoint.x = std::min(minPoint.x, screenPoint.x);
|
||||
minPoint.y = std::min(minPoint.y, screenPoint.y);
|
||||
maxPoint.x = std::max(maxPoint.x, screenPoint.x);
|
||||
maxPoint.y = std::max(maxPoint.y, screenPoint.y);
|
||||
}
|
||||
|
||||
if (!anyPointVisible) {
|
||||
const glm::vec3 worldPosition = glm::vec3(worldMatrix[3]);
|
||||
ImVec2 screenPoint{};
|
||||
if (!MetaCoreProjectWorldPointToViewport(sceneView, viewportState, worldPosition, screenPoint)) {
|
||||
return;
|
||||
}
|
||||
minPoint = screenPoint;
|
||||
maxPoint = screenPoint;
|
||||
}
|
||||
|
||||
const float halfMinimumSize = minimumSize * 0.5F;
|
||||
if (maxPoint.x - minPoint.x < minimumSize) {
|
||||
const float centerX = (minPoint.x + maxPoint.x) * 0.5F;
|
||||
minPoint.x = centerX - halfMinimumSize;
|
||||
maxPoint.x = centerX + halfMinimumSize;
|
||||
}
|
||||
if (maxPoint.y - minPoint.y < minimumSize) {
|
||||
const float centerY = (minPoint.y + maxPoint.y) * 0.5F;
|
||||
minPoint.y = centerY - halfMinimumSize;
|
||||
maxPoint.y = centerY + halfMinimumSize;
|
||||
}
|
||||
|
||||
minPoint.x = std::clamp(minPoint.x, clipMin.x, clipMax.x);
|
||||
minPoint.y = std::clamp(minPoint.y, clipMin.y, clipMax.y);
|
||||
maxPoint.x = std::clamp(maxPoint.x, clipMin.x, clipMax.x);
|
||||
maxPoint.y = std::clamp(maxPoint.y, clipMin.y, clipMax.y);
|
||||
if (maxPoint.x <= minPoint.x || maxPoint.y <= minPoint.y) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float bracketLength = std::min({18.0F, (maxPoint.x - minPoint.x) * 0.35F, (maxPoint.y - minPoint.y) * 0.35F});
|
||||
drawList->AddLine(minPoint, ImVec2(minPoint.x + bracketLength, minPoint.y), color, thickness);
|
||||
drawList->AddLine(minPoint, ImVec2(minPoint.x, minPoint.y + bracketLength), color, thickness);
|
||||
drawList->AddLine(ImVec2(maxPoint.x, minPoint.y), ImVec2(maxPoint.x - bracketLength, minPoint.y), color, thickness);
|
||||
drawList->AddLine(ImVec2(maxPoint.x, minPoint.y), ImVec2(maxPoint.x, minPoint.y + bracketLength), color, thickness);
|
||||
drawList->AddLine(ImVec2(minPoint.x, maxPoint.y), ImVec2(minPoint.x + bracketLength, maxPoint.y), color, thickness);
|
||||
drawList->AddLine(ImVec2(minPoint.x, maxPoint.y), ImVec2(minPoint.x, maxPoint.y - bracketLength), color, thickness);
|
||||
drawList->AddLine(maxPoint, ImVec2(maxPoint.x - bracketLength, maxPoint.y), color, thickness);
|
||||
drawList->AddLine(maxPoint, ImVec2(maxPoint.x, maxPoint.y - bracketLength), color, thickness);
|
||||
};
|
||||
|
||||
drawList->PushClipRect(clipMin, clipMax, true);
|
||||
const MetaCoreId hoveredObjectId = editorContext.GetHoveredObjectId();
|
||||
if (hoveredObjectId != 0 && !editorContext.IsObjectSelected(hoveredObjectId)) {
|
||||
drawObjectMarker(hoveredObjectId, IM_COL32(110, 175, 255, 190), 1.5F, 18.0F);
|
||||
}
|
||||
for (const MetaCoreId selectedObjectId : editorContext.GetSelectedObjectIds()) {
|
||||
const bool isActiveObject = selectedObjectId == editorContext.GetActiveObjectId();
|
||||
drawObjectMarker(
|
||||
selectedObjectId,
|
||||
isActiveObject ? IM_COL32(235, 87, 87, 245) : IM_COL32(235, 135, 135, 205),
|
||||
isActiveObject ? 2.0F : 1.5F,
|
||||
22.0F
|
||||
);
|
||||
}
|
||||
drawList->PopClipRect();
|
||||
}
|
||||
|
||||
void MetaCoreDrawCompatibilityScenePreviewOverlay(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user