From 58dde92a405de9d8f57b46dbd51451c15d9c9cd8 Mon Sep 17 00:00:00 2001 From: codereader Date: Mon, 21 Jun 2021 10:45:36 +0200 Subject: [PATCH] #5643: Add "FocusView" command accepting two vector3 arguments (origin and angles). Implement Jump to next Conflict functionality. --- install/ui/mergecontroldialog.fbp | 249 ++++++++++++++++-------- install/ui/mergecontroldialog.xrc | 78 +++++--- libs/scenelib.h | 17 ++ radiant/ui/entitylist/EntityList.cpp | 15 +- radiant/ui/merge/MergeControlDialog.cpp | 97 ++++++--- radiant/ui/merge/MergeControlDialog.h | 4 + radiantcore/map/Map.cpp | 12 ++ radiantcore/map/Map.h | 9 +- radiantcore/map/MapPosition.cpp | 3 +- radiantcore/map/MapPositionManager.cpp | 3 +- 10 files changed, 333 insertions(+), 154 deletions(-) diff --git a/install/ui/mergecontroldialog.fbp b/install/ui/mergecontroldialog.fbp index 37d3aa880b..c64369e5f7 100644 --- a/install/ui/mergecontroldialog.fbp +++ b/install/ui/mergecontroldialog.fbp @@ -1007,7 +1007,7 @@ none 6 - wxBOTTOM|wxTOP + wxTOP 0 1 @@ -1068,9 +1068,9 @@ 12 - wxEXPAND|wxLEFT + wxEXPAND|wxLEFT|wxTOP 1 - + 4 wxBOTH 1,3 @@ -1081,10 +1081,10 @@ wxFLEX_GROWMODE_SPECIFIED none 4 - 0 + 6 - 5 - wxALIGN_RIGHT|wxALL + 6 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT 0 1 @@ -1144,8 +1144,8 @@ - 5 - wxALL + 0 + wxALIGN_CENTER_VERTICAL|wxALL 0 1 @@ -1205,8 +1205,8 @@ - 5 - wxALL + 6 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT 0 1 @@ -1266,8 +1266,8 @@ - 5 - wxALL + 0 + wxALIGN_CENTER_VERTICAL|wxALL 0 1 @@ -1327,8 +1327,8 @@ - 5 - wxALIGN_RIGHT|wxALL + 6 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT 0 1 @@ -1388,8 +1388,8 @@ - 5 - wxALL + 0 + wxALIGN_CENTER_VERTICAL|wxALL 0 1 @@ -1471,8 +1471,8 @@ - 5 - wxALIGN_RIGHT|wxALL + 6 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT 0 1 @@ -1532,8 +1532,8 @@ - 5 - wxALL + 0 + wxALIGN_CENTER_VERTICAL|wxALL 0 1 @@ -1593,8 +1593,8 @@ - 5 - wxALIGN_RIGHT|wxALL + 6 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT 0 1 @@ -1654,8 +1654,8 @@ - 5 - wxALL + 0 + wxALIGN_CENTER_VERTICAL|wxALL 0 1 @@ -1715,8 +1715,8 @@ - 5 - wxALL + 6 + wxALIGN_CENTER_VERTICAL|wxRIGHT 0 1 @@ -1775,65 +1775,148 @@ -1 - + 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Unresolved Conflicts - 0 - - 0 - - - 0 + wxEXPAND + 1 + - 1 - UnresolvedConflictsLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 + bSizer32 + wxHORIZONTAL + none + + 0 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Unresolved Conflicts + 0 + + 0 + + + 0 + + 1 + UnresolvedConflictsLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 6 + wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + Load From Art Provider; wxART_GO_FORWARD; + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Jump to next conflict + + 0 + + 0 + + + 0 + + 1 + JumpToNextConflictButton + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + Jump to next conflict + + wxFILTER_NONE + wxDefaultValidator + + + + + + diff --git a/install/ui/mergecontroldialog.xrc b/install/ui/mergecontroldialog.xrc index 431f8cb735..d2f4fa1513 100644 --- a/install/ui/mergecontroldialog.xrc +++ b/install/ui/mergecontroldialog.xrc @@ -194,7 +194,7 @@ wxVERTICAL - wxBOTTOM|wxTOP + wxTOP 6 @@ -208,19 +208,19 @@ - wxEXPAND|wxLEFT + wxEXPAND|wxLEFT|wxTOP 12 4 4 - 0 + 6 0 1,3 - wxALIGN_RIGHT|wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT + 6 @@ -233,8 +233,8 @@ - wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 -1 @@ -242,8 +242,8 @@ - wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT + 6 @@ -256,8 +256,8 @@ - wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 -1 @@ -265,8 +265,8 @@ - wxALIGN_RIGHT|wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT + 6 @@ -279,8 +279,8 @@ - wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 -1 @@ -304,8 +304,8 @@ - wxALIGN_RIGHT|wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT + 6 @@ -318,8 +318,8 @@ - wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 -1 @@ -327,8 +327,8 @@ - wxALIGN_RIGHT|wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxRIGHT + 6 @@ -341,8 +341,8 @@ - wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 -1 @@ -350,8 +350,8 @@ - wxALL - 5 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 6 @@ -363,12 +363,30 @@ - - wxALL + + wxEXPAND 5 - - - -1 + + wxHORIZONTAL + + + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + + -1 + + + + + wxLEFT + 6 + + Jump to next conflict + undefined.png + 0 + + diff --git a/libs/scenelib.h b/libs/scenelib.h index 9a5db238c4..faae5f4720 100644 --- a/libs/scenelib.h +++ b/libs/scenelib.h @@ -6,6 +6,7 @@ #include "iselectable.h" #include "ipatch.h" #include "ibrush.h" +#include "icameraview.h" #include "scene/Node.h" @@ -282,4 +283,20 @@ inline void assignVisibilityFlagsFromNode(INode& target, const INode& source) } } +inline std::pair getOriginAndAnglesToLookAtNode(const scene::INode& node) +{ + const AABB& aabb = node.worldAABB(); + Vector3 origin(aabb.origin); + + // Move the camera a bit off the AABB origin + origin += Vector3(aabb.extents.getLength() * 5, 0, aabb.extents.getLength() * 5); + + // Rotate the camera a bit towards the "ground" + Vector3 angles(0, 0, 0); + angles[camera::CAMERA_PITCH] = -40; + angles[camera::CAMERA_YAW] = 180; + + return std::make_pair(origin, angles); +} + } // namespace scene diff --git a/radiant/ui/entitylist/EntityList.cpp b/radiant/ui/entitylist/EntityList.cpp index 9c4dde0351..c9c8d60353 100644 --- a/radiant/ui/entitylist/EntityList.cpp +++ b/radiant/ui/entitylist/EntityList.cpp @@ -2,9 +2,11 @@ #include "ieventmanager.h" #include "imainframe.h" +#include "icommandsystem.h" #include "registry/Widgets.h" #include "entitylib.h" +#include "scenelib.h" #include "iselectable.h" #include "icameraview.h" #include "i18n.h" @@ -332,17 +334,8 @@ void EntityList::onSelection(wxDataViewEvent& ev) if (isSelected && _focusSelected->GetValue()) { - const AABB& aabb = node->worldAABB(); - Vector3 origin(aabb.origin); - - // Move the camera a bit off the AABB origin - origin += Vector3(-50, 0, 50); - - // Rotate the camera a bit towards the "ground" - Vector3 angles(0, 0, 0); - angles[camera::CAMERA_PITCH] = -30; - - GlobalCameraManager().focusAllCameras(origin, angles); + auto originAndAngles = scene::getOriginAndAnglesToLookAtNode(*node); + GlobalCommandSystem().executeCommand("FocusViews", cmd::ArgumentList{ originAndAngles.first, originAndAngles.second }); } // Now reactivate the callbacks diff --git a/radiant/ui/merge/MergeControlDialog.cpp b/radiant/ui/merge/MergeControlDialog.cpp index a19bbed4a8..d877a84f63 100644 --- a/radiant/ui/merge/MergeControlDialog.cpp +++ b/radiant/ui/merge/MergeControlDialog.cpp @@ -33,7 +33,8 @@ namespace MergeControlDialog::MergeControlDialog() : TransientWindow(_(WINDOW_TITLE), GlobalMainFrame().getWxTopLevelWindow(), true), - _updateNeeded(false) + _updateNeeded(false), + _numUnresolvedConflicts(0) { SetSizer(new wxBoxSizer(wxVERTICAL)); GetSizer()->Add(loadNamedPanel(this, "MergeControlDialogMainPanel"), 1, wxEXPAND); @@ -59,6 +60,9 @@ MergeControlDialog::MergeControlDialog() : auto* resolveRejectButton = findNamedObject(this, "ResolveRejectButton"); resolveRejectButton->Bind(wxEVT_BUTTON, &MergeControlDialog::onResolveReject, this); + auto* jumpToNextConflict = findNamedObject(this, "JumpToNextConflictButton"); + jumpToNextConflict->Bind(wxEVT_BUTTON, &MergeControlDialog::onJumpToNextConflict, this); + findNamedObject(this, "KeepSelectionGroupsIntact")->SetValue(true); findNamedObject(this, "MergeLayers")->SetValue(true); @@ -123,8 +127,7 @@ void MergeControlDialog::convertTextCtrlToPathEntry(const std::string& ctrlName) void MergeControlDialog::onMergeSourceChanged(wxCommandEvent& ev) { - updateSummary(); - updateControls(); + update(); } void MergeControlDialog::onLoadAndCompare(wxCommandEvent& ev) @@ -146,15 +149,13 @@ void MergeControlDialog::onLoadAndCompare(wxCommandEvent& ev) GlobalMapModule().startMergeOperation(sourceMapPath); } - updateSummary(); - updateControls(); + update(); } void MergeControlDialog::onAbortMerge(wxCommandEvent& ev) { GlobalMapModule().abortMergeOperation(); - updateSummary(); - updateControls(); + update(); } void MergeControlDialog::onResolveAccept(wxCommandEvent& ev) @@ -172,8 +173,7 @@ void MergeControlDialog::onResolveAccept(wxCommandEvent& ev) }); } - updateSummary(); - updateControls(); + update(); } void MergeControlDialog::rejectSelectedNodesByDeletion() @@ -187,8 +187,7 @@ void MergeControlDialog::rejectSelectedNodesByDeletion() scene::removeNodeFromParent(mergeNode); } - updateSummary(); - updateControls(); + update(); } void MergeControlDialog::onResolveReject(wxCommandEvent& ev) @@ -197,6 +196,54 @@ void MergeControlDialog::onResolveReject(wxCommandEvent& ev) rejectSelectedNodesByDeletion(); } +void MergeControlDialog::onJumpToNextConflict(wxCommandEvent& ev) +{ + std::vector> mergeNodes; + + // Remove the selected nodes + GlobalMapModule().getRoot()->foreachNode([&](const scene::INodePtr& node) + { + if (node->getNodeType() == scene::INode::Type::MergeAction) + { + auto mergeNode = std::dynamic_pointer_cast(node); + + if (mergeNode && mergeNode->getActionType() == scene::merge::ActionType::ConflictResolution) + { + mergeNodes.push_back(mergeNode); + } + } + + return true; + }); + + if (mergeNodes.empty()) + { + return; + } + + scene::INodePtr current; + + if (GlobalSelectionSystem().countSelected() == 1 && + GlobalSelectionSystem().ultimateSelected()->getNodeType() == scene::INode::Type::MergeAction) + { + current = GlobalSelectionSystem().ultimateSelected(); + } + + auto nextNode = mergeNodes.front(); + auto currentNode = std::find(mergeNodes.begin(), mergeNodes.end(), current); + + if (currentNode != mergeNodes.end() && ++currentNode != mergeNodes.end()) + { + nextNode = *currentNode; + } + + GlobalSelectionSystem().setSelectedAll(false); + Node_setSelected(nextNode, true); + + auto originAndAngles = scene::getOriginAndAnglesToLookAtNode(*nextNode->getAffectedNode()); + GlobalCommandSystem().executeCommand("FocusViews", cmd::ArgumentList{ originAndAngles.first, originAndAngles.second }); +} + void MergeControlDialog::onFinishMerge(wxCommandEvent& ev) { auto operation = GlobalMapModule().getActiveMergeOperation(); @@ -218,7 +265,7 @@ void MergeControlDialog::onFinishMerge(wxCommandEvent& ev) } } - updateControls(); + update(); } std::vector MergeControlDialog::getSelectedMergeNodes() @@ -388,6 +435,7 @@ void MergeControlDialog::updateControls() findNamedObject(this, "NoMergeNodeSelected")->Show(selectedMergeNodes.size() != 1); findNamedObject(this, "ResolveAcceptButton")->Show(mergeInProgress && conflictNode != nullptr); findNamedObject(this, "ResolveRejectButton")->Show(mergeInProgress && !selectedMergeNodes.empty()); + findNamedObject(this, "JumpToNextConflictButton")->Enable(mergeInProgress && _numUnresolvedConflicts > 0); actionDescriptionPanel->Show(selectedMergeNodes.size() == 1); actionDescriptionPanel->DestroyChildren(); @@ -437,8 +485,7 @@ void MergeControlDialog::_preShow() sigc::mem_fun(this, &MergeControlDialog::queueUpdate)); // Check for selection changes before showing the dialog again - updateControls(); - updateSummary(); + update(); } void MergeControlDialog::selectionChanged(const scene::INodePtr& node, bool isComponent) @@ -451,6 +498,13 @@ void MergeControlDialog::selectionChanged(const scene::INodePtr& node, bool isCo queueUpdate(); } +void MergeControlDialog::update() +{ + // Update the stats first to be able to enable/disable controls based on the numbers + updateSummary(); + updateControls(); +} + void MergeControlDialog::queueUpdate() { _updateNeeded = true; @@ -461,9 +515,7 @@ void MergeControlDialog::onIdle(wxIdleEvent& ev) if (!_updateNeeded) return; _updateNeeded = false; - - updateControls(); - updateSummary(); + update(); } void MergeControlDialog::onMapEvent(IMap::MapEvent ev) @@ -476,8 +528,7 @@ void MergeControlDialog::onMapEvent(IMap::MapEvent ev) void MergeControlDialog::onMapEditModeChanged(IMap::EditMode newMode) { - updateSummary(); - updateControls(); + update(); } void MergeControlDialog::updateSummary() @@ -489,7 +540,7 @@ void MergeControlDialog::updateSummary() std::size_t entitiesRemoved = 0; std::size_t primitivesAdded = 0; std::size_t primitivesRemoved = 0; - std::size_t unresolvedConflicts = 0; + _numUnresolvedConflicts = 0; if (operation) { @@ -524,7 +575,7 @@ void MergeControlDialog::updateSummary() if (conflict && conflict->getResolution() == scene::merge::ResolutionType::Unresolved) { - unresolvedConflicts++; + _numUnresolvedConflicts++; } break; } @@ -539,9 +590,9 @@ void MergeControlDialog::updateSummary() findNamedObject(this, "EntitiesModified")->SetLabel(string::to_string(entitiesModified)); findNamedObject(this, "PrimitivesAdded")->SetLabel(string::to_string(primitivesAdded)); findNamedObject(this, "PrimitivesRemoved")->SetLabel(string::to_string(primitivesRemoved)); - findNamedObject(this, "UnresolvedConflicts")->SetLabel(string::to_string(unresolvedConflicts)); + findNamedObject(this, "UnresolvedConflicts")->SetLabel(string::to_string(_numUnresolvedConflicts)); - if (unresolvedConflicts > 0) + if (_numUnresolvedConflicts > 0) { makeLabelBold(this, "UnresolvedConflicts"); makeLabelBold(this, "UnresolvedConflictsLabel"); diff --git a/radiant/ui/merge/MergeControlDialog.h b/radiant/ui/merge/MergeControlDialog.h index d24897409f..ff0022bc1e 100644 --- a/radiant/ui/merge/MergeControlDialog.h +++ b/radiant/ui/merge/MergeControlDialog.h @@ -24,6 +24,7 @@ class MergeControlDialog : sigc::connection _mapEditModeHandler; bool _updateNeeded; + std::size_t _numUnresolvedConflicts; public: MergeControlDialog(); @@ -54,6 +55,7 @@ class MergeControlDialog : void onAbortMerge(wxCommandEvent& ev); void onResolveAccept(wxCommandEvent& ev); void onResolveReject(wxCommandEvent& ev); + void onJumpToNextConflict(wxCommandEvent& ev); void updateControls(); void queueUpdate(); void onIdle(wxIdleEvent& ev); @@ -61,6 +63,8 @@ class MergeControlDialog : void onMapEditModeChanged(IMap::EditMode newMode); void updateSummary(); + void update(); + std::size_t getNumSelectedMergeNodes(); std::vector getSelectedMergeNodes(); std::shared_ptr getSingleSelectedConflictNode(); diff --git a/radiantcore/map/Map.cpp b/radiantcore/map/Map.cpp index ed4337bd6c..a90d933797 100644 --- a/radiantcore/map/Map.cpp +++ b/radiantcore/map/Map.cpp @@ -447,6 +447,17 @@ void Map::focusViews(const Vector3& point, const Vector3& angles) } } +void Map::focusViewCmd(const cmd::ArgumentList& args) +{ + if (args.size() != 2) + { + rWarning() << "Usage: FocusViews " << std::endl; + return; + } + + focusViews(args[0].getVector3(), args[1].getVector3()); +} + scene::INodePtr Map::findWorldspawn() { scene::INodePtr worldspawn; @@ -884,6 +895,7 @@ void Map::registerCommands() GlobalCommandSystem().addCommand("ExportMap", Map::exportMap); GlobalCommandSystem().addCommand("SaveSelected", Map::exportSelection); GlobalCommandSystem().addCommand("ReloadSkins", map::algorithm::reloadSkins); + GlobalCommandSystem().addCommand("FocusViews", std::bind(&Map::focusViewCmd, this, std::placeholders::_1), { cmd::ARGTYPE_VECTOR3, cmd::ARGTYPE_VECTOR3 }); GlobalCommandSystem().addCommand("ExportSelectedAsModel", map::algorithm::exportSelectedAsModelCmd, { cmd::ARGTYPE_STRING, cmd::ARGTYPE_STRING, diff --git a/radiantcore/map/Map.h b/radiantcore/map/Map.h index c537405557..f3e6e1dc19 100644 --- a/radiantcore/map/Map.h +++ b/radiantcore/map/Map.h @@ -200,10 +200,6 @@ class Map : */ MapFormatPtr getFormat(); - /** greebo: Focus the XYViews and the Camera to the given point/angle. - */ - static void focusViews(const Vector3& point, const Vector3& angles); - /** greebo: Registers the commands with the EventManager. */ void registerCommands(); @@ -276,6 +272,11 @@ class Map : void clearMapResource(); void cleanupMergeOperation(); + + /** greebo: Focus the XYViews and the Camera to the given point/angle. + */ + void focusViews(const Vector3& point, const Vector3& angles); + void focusViewCmd(const cmd::ArgumentList& args); }; } // namespace map diff --git a/radiantcore/map/MapPosition.cpp b/radiantcore/map/MapPosition.cpp index b7ed8ba042..b89bc1409b 100644 --- a/radiantcore/map/MapPosition.cpp +++ b/radiantcore/map/MapPosition.cpp @@ -2,6 +2,7 @@ #include "ientity.h" #include "icameraview.h" +#include "icommandsystem.h" #include "itextstream.h" #include "string/string.h" #include "map/Map.h" @@ -149,7 +150,7 @@ void MapPosition::recall(const cmd::ArgumentList& args) rMessage() << "Restoring map position #" << _index << std::endl; // Focus the view with the default angle - Map::focusViews(_position, _angle); + GlobalCommandSystem().executeCommand("FocusViews", cmd::ArgumentList{ _position, _angle }); } else { diff --git a/radiantcore/map/MapPositionManager.cpp b/radiantcore/map/MapPositionManager.cpp index 7ac1f6d674..08260553fc 100644 --- a/radiantcore/map/MapPositionManager.cpp +++ b/radiantcore/map/MapPositionManager.cpp @@ -208,8 +208,7 @@ void MapPositionManager::gotoLastCameraPosition() tryGetStartPositionFromPlayerStart(origin, angles)) { // Focus the view with the given parameters - Map::focusViews(origin, angles); - return; + GlobalCommandSystem().executeCommand("FocusViews", cmd::ArgumentList{ origin, angles }); } }