diff --git a/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp b/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp index 18121d6..df91b80 100644 --- a/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp +++ b/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp @@ -784,6 +784,61 @@ void MetaCoreConfigureChineseFont() { #endif } +[[nodiscard]] std::optional MetaCoreCreateSceneViewObject( + MetaCoreEditorContext& editorContext, + const std::string& objectName, + bool withMeshRenderer, + std::optional forcedParentId +) { + const auto sceneEditingService = editorContext.GetModuleRegistry().ResolveService(); + if (sceneEditingService == nullptr) { + return std::nullopt; + } + return sceneEditingService->CreateGameObject(editorContext, objectName, withMeshRenderer, forcedParentId); +} + +[[nodiscard]] bool MetaCoreDuplicateSceneViewSelection(MetaCoreEditorContext& editorContext) { + const auto clipboardService = editorContext.GetModuleRegistry().ResolveService(); + return clipboardService != nullptr && clipboardService->DuplicateSelection(editorContext); +} + +[[nodiscard]] bool MetaCoreDeleteSceneViewSelection(MetaCoreEditorContext& editorContext) { + const auto clipboardService = editorContext.GetModuleRegistry().ResolveService(); + return clipboardService != nullptr && clipboardService->DeleteSelection(editorContext); +} + +void MetaCoreDrawSceneViewContextMenu(MetaCoreEditorContext& editorContext, MetaCoreId contextObjectId) { + const MetaCoreGameObject contextObject = editorContext.GetScene().FindGameObject(contextObjectId); + const bool hasContextObject = static_cast(contextObject); + const std::optional forcedParentId = hasContextObject ? std::optional(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(); diff --git a/Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorApp.h b/Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorApp.h index d23319f..db2d3d4 100644 --- a/Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorApp.h +++ b/Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorApp.h @@ -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; };