feat(editor): add scene view context menu

This commit is contained in:
ayuan9957 2026-06-17 18:04:11 +08:00
parent 137c3d67dd
commit 2e5b2adb0c
2 changed files with 86 additions and 0 deletions

View File

@ -784,6 +784,61 @@ void MetaCoreConfigureChineseFont() {
#endif
}
[[nodiscard]] std::optional<MetaCoreId> MetaCoreCreateSceneViewObject(
MetaCoreEditorContext& editorContext,
const std::string& objectName,
bool withMeshRenderer,
std::optional<MetaCoreId> forcedParentId
) {
const auto sceneEditingService = editorContext.GetModuleRegistry().ResolveService<MetaCoreISceneEditingService>();
if (sceneEditingService == nullptr) {
return std::nullopt;
}
return sceneEditingService->CreateGameObject(editorContext, objectName, withMeshRenderer, forcedParentId);
}
[[nodiscard]] bool MetaCoreDuplicateSceneViewSelection(MetaCoreEditorContext& editorContext) {
const auto clipboardService = editorContext.GetModuleRegistry().ResolveService<MetaCoreIClipboardService>();
return clipboardService != nullptr && clipboardService->DuplicateSelection(editorContext);
}
[[nodiscard]] bool MetaCoreDeleteSceneViewSelection(MetaCoreEditorContext& editorContext) {
const auto clipboardService = editorContext.GetModuleRegistry().ResolveService<MetaCoreIClipboardService>();
return clipboardService != nullptr && clipboardService->DeleteSelection(editorContext);
}
void MetaCoreDrawSceneViewContextMenu(MetaCoreEditorContext& editorContext, MetaCoreId contextObjectId) {
const MetaCoreGameObject contextObject = editorContext.GetScene().FindGameObject(contextObjectId);
const bool hasContextObject = static_cast<bool>(contextObject);
const std::optional<MetaCoreId> forcedParentId = hasContextObject ? std::optional<MetaCoreId>(contextObjectId) : std::nullopt;
if (hasContextObject) {
ImGui::TextDisabled("Object: %s", contextObject.GetName().c_str());
ImGui::Separator();
}
if (ImGui::MenuItem(hasContextObject ? "Create Empty Child" : "Create Empty")) {
(void)MetaCoreCreateSceneViewObject(editorContext, "GameObject", false, forcedParentId);
}
if (ImGui::MenuItem(hasContextObject ? "Create Cube Child" : "Create Cube")) {
(void)MetaCoreCreateSceneViewObject(editorContext, "Cube", true, forcedParentId);
}
if (ImGui::MenuItem(hasContextObject ? "Create Plane Child" : "Create Plane")) {
(void)MetaCoreCreateSceneViewObject(editorContext, "Plane", true, forcedParentId);
}
ImGui::Separator();
if (ImGui::MenuItem("Focus", "F", false, hasContextObject)) {
editorContext.GetCameraController().FocusGameObject(contextObject);
}
if (ImGui::MenuItem("Duplicate", "Ctrl+D", false, !editorContext.GetSelectedObjectIds().empty())) {
(void)MetaCoreDuplicateSceneViewSelection(editorContext);
}
if (ImGui::MenuItem("Delete", "Delete", false, !editorContext.GetSelectedObjectIds().empty())) {
(void)MetaCoreDeleteSceneViewSelection(editorContext);
}
}
} // namespace
MetaCoreEditorApp::~MetaCoreEditorApp() {
@ -1927,6 +1982,35 @@ void MetaCoreEditorApp::DrawSceneViewWindow() {
}
}
}
if (viewportState.Hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
SceneViewRightMouseDragged_ = false;
}
if (viewportState.Hovered && ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
SceneViewRightMouseDragged_ = true;
}
if (viewportState.Hovered && !gizmoHovering && !gizmoUsing && ImGui::IsMouseReleased(ImGuiMouseButton_Right) &&
!SceneViewRightMouseDragged_) {
const MetaCoreId pickedObjectId = SceneInteractionService_.PickGameObjectFromViewport(
Scene_,
sceneView,
viewportState,
EditorContext_->GetInput().GetCursorPosition()
);
if (pickedObjectId != 0 && !EditorContext_->IsObjectSelected(pickedObjectId)) {
EditorContext_->SelectOnly(pickedObjectId);
}
PendingSceneViewContextObjectId_ = pickedObjectId;
ImGui::OpenPopup("MetaCoreSceneViewContextMenu");
}
if (ImGui::IsMouseReleased(ImGuiMouseButton_Right)) {
SceneViewRightMouseDragged_ = false;
}
if (ImGui::BeginPopup("MetaCoreSceneViewContextMenu")) {
MetaCoreDrawSceneViewContextMenu(*EditorContext_, PendingSceneViewContextObjectId_);
ImGui::EndPopup();
}
drewSceneViewport = true;
}
ImGui::End();

View File

@ -58,6 +58,8 @@ private:
std::filesystem::path ImGuiLayoutProjectRoot_{};
std::filesystem::path ViewportProjectRoot_{};
std::string ImGuiIniPath_{};
MetaCoreId PendingSceneViewContextObjectId_ = 0;
bool SceneViewRightMouseDragged_ = false;
bool PendingExitPopup_ = false;
bool Initialized_ = false;
};