Skip to content

Commit

Permalink
#5643: Start working on the UI part. Extend Map interface to create a…
Browse files Browse the repository at this point in the history
… three-way merge operation when a base map is available.
  • Loading branch information
codereader committed Jun 18, 2021
1 parent 6217c99 commit c9684c6
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 34 deletions.
6 changes: 6 additions & 0 deletions include/imap.h
Expand Up @@ -192,6 +192,12 @@ class IMap :
// Will throw exceptions when the given map cannot be found, or this map doesn't have a root
virtual void startMergeOperation(const std::string& sourceMap) = 0;

// Starts a merge operation which imports the changes made to the source map into this one
// baseMap defines the path to a map that both the source map and this map started from,
// which makes the merge process more precise and enables conflict detection.
// Will throw exceptions when the given map cannot be found, or this map doesn't have a root
virtual void startMergeOperation(const std::string& sourceMap, const std::string& baseMap) = 0;

// When called in EditMode::Merge, this will apply the currently active set of actions
virtual void finishMergeOperation() = 0;

Expand Down
8 changes: 4 additions & 4 deletions install/ui/mergecontroldialog.fbp
Expand Up @@ -43,7 +43,7 @@
<property name="minimum_size">300,-1</property>
<property name="name">MergeControlDialogMainPanel</property>
<property name="pos"></property>
<property name="size">391,354</property>
<property name="size">391,417</property>
<property name="subclass"></property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
Expand Down Expand Up @@ -490,11 +490,11 @@
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">1</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size">-1,0</property>
<property name="maximum_size">-1,-1</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
Expand All @@ -508,7 +508,7 @@
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size">-1,0</property>
<property name="size">-1,-1</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
Expand Down
4 changes: 1 addition & 3 deletions install/ui/mergecontroldialog.xrc
Expand Up @@ -2,7 +2,7 @@
<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
<object class="wxPanel" name="MergeControlDialogMainPanel">
<style>wxTAB_TRAVERSAL</style>
<size>391,354</size>
<size>391,417</size>
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
Expand Down Expand Up @@ -91,8 +91,6 @@
<border>0</border>
<object class="wxPanel" name="BaseMapPanel">
<style>wxTAB_TRAVERSAL</style>
<size>-1,0</size>
<hidden>1</hidden>
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
Expand Down
12 changes: 4 additions & 8 deletions radiant/ui/merge/MergeControlDialog.cpp
Expand Up @@ -10,6 +10,7 @@
#include "wxutil/PathEntry.h"
#include "scenelib.h"
#include "string/convert.h"
#include "os/path.h"

#include <wx/textctrl.h>
#include <wx/button.h>
Expand All @@ -36,7 +37,7 @@ MergeControlDialog::MergeControlDialog() :
GetSizer()->Add(loadNamedPanel(this, "MergeControlDialogMainPanel"), 1, wxEXPAND);

auto* targetMapFilename = findNamedObject<wxTextCtrl>(this, "TargetMapFilename");
targetMapFilename->SetValue(GlobalMapModule().getMapName());
targetMapFilename->SetValue(os::getFilename(GlobalMapModule().getMapName()));
targetMapFilename->Disable();

convertTextCtrlToPathEntry("MergeMapFilename");
Expand Down Expand Up @@ -128,26 +129,21 @@ void MergeControlDialog::onMergeSourceChanged(wxCommandEvent& ev)
void MergeControlDialog::onLoadAndCompare(wxCommandEvent& ev)
{
auto sourceMapPath = findNamedObject<wxutil::PathEntry>(this, "MergeMapFilename")->getValue();
#if false
auto baseMapPath = findNamedObject<wxutil::PathEntry>(this, "BaseMapFilename")->getValue();
#endif

if (sourceMapPath.empty())
{
return;
}

#if false
if (!baseMapPath.empty())
{
GlobalCommandSystem().executeCommand("StartMergeOperation", sourceMapPath, baseMapPath);
GlobalMapModule().startMergeOperation(sourceMapPath, baseMapPath);
}
else
{
GlobalCommandSystem().executeCommand("StartMergeOperation", sourceMapPath);
GlobalMapModule().startMergeOperation(sourceMapPath);
}
#endif
GlobalMapModule().startMergeOperation(sourceMapPath);

updateSummary();
updateControlSensitivity();
Expand Down
77 changes: 60 additions & 17 deletions radiantcore/map/Map.cpp
Expand Up @@ -60,6 +60,7 @@
#include "scene/ChildPrimitives.h"
#include "scene/merge/GraphComparer.h"
#include "scene/merge/MergeOperation.h"
#include "scene/merge/ThreeWayMergeOperation.h"

namespace map
{
Expand Down Expand Up @@ -1086,11 +1087,8 @@ void Map::exportSelected(std::ostream& out, const MapFormatPtr& format)
exporter.exportMap(GlobalSceneGraph().root(), scene::traverseSelected);
}

void Map::createMergeOperation(const scene::merge::ComparisonResult& result)
void Map::createMergeActions()
{
// Create the merge actions
_mergeOperation = scene::merge::MergeOperation::CreateFromComparisonResult(result);

// Group spawnarg actions into one single node if applicable
std::map<scene::INodePtr, std::vector<scene::merge::IMergeAction::Ptr>> entityChanges;
std::vector<scene::merge::IMergeAction::Ptr> otherChanges;
Expand Down Expand Up @@ -1129,18 +1127,13 @@ void Map::createMergeOperation(const scene::merge::ComparisonResult& result)
}
}

void Map::startMergeOperation(const std::string& sourceMap)
void Map::prepareMergeOperation()
{
if (!getRoot())
{
throw cmd::ExecutionNotPossible(_("No map loaded, cannot merge"));
}

if (!os::fileOrDirExists(sourceMap))
{
throw cmd::ExecutionFailure(fmt::format(_("File doesn't exist: {0}"), sourceMap));
}

{
// Make sure we have a worldspawn in this map
UndoableCommand cmd("ensureWorldSpawn");
Expand All @@ -1149,20 +1142,31 @@ void Map::startMergeOperation(const std::string& sourceMap)

// Stop any pending merge operation
abortMergeOperation();
}

void Map::startMergeOperation(const std::string& sourceMap)
{
if (!os::fileOrDirExists(sourceMap))
{
throw cmd::ExecutionFailure(fmt::format(_("File doesn't exist: {0}"), sourceMap));
}

prepareMergeOperation();

auto sourceMapResource = GlobalMapResourceManager().createFromPath(sourceMap);

try
{
if (sourceMapResource->load())
{
const auto& otherRoot = sourceMapResource->getRootNode();

// Compare the scenes and get the report
auto result = scene::merge::GraphComparer::Compare(otherRoot, getRoot());
auto result = scene::merge::GraphComparer::Compare(sourceMapResource->getRootNode(), getRoot());

// Create the merge actions
_mergeOperation = scene::merge::MergeOperation::CreateFromComparisonResult(*result);

// Create renderable merge actions
createMergeOperation(*result);
createMergeActions();

// Switch to merge mode
setEditMode(EditMode::Merge);
Expand All @@ -1177,6 +1181,40 @@ void Map::startMergeOperation(const std::string& sourceMap)
}
}

void Map::startMergeOperation(const std::string& sourceMap, const std::string& baseMap)
{
if (!os::fileOrDirExists(sourceMap)) throw cmd::ExecutionFailure(fmt::format(_("File doesn't exist: {0}"), sourceMap));
if (!os::fileOrDirExists(baseMap)) throw cmd::ExecutionFailure(fmt::format(_("File doesn't exist: {0}"), baseMap));

prepareMergeOperation();

auto baseMapResource = GlobalMapResourceManager().createFromPath(baseMap);
auto sourceMapResource = GlobalMapResourceManager().createFromPath(sourceMap);

try
{
if (sourceMapResource->load() && baseMapResource->load())
{
_mergeOperation = scene::merge::ThreeWayMergeOperation::Create(
baseMapResource->getRootNode(), sourceMapResource->getRootNode(), getRoot());

// Create renderable merge actions
createMergeActions();

// Switch to merge mode
setEditMode(EditMode::Merge);

// Dispose of the resources, we don't need it anymore
sourceMapResource->clear();
baseMapResource->clear();
}
}
catch (const IMapResource::OperationException& ex)
{
radiant::NotificationMessage::SendError(ex.what());
}
}

void Map::startMergeOperationCmd(const cmd::ArgumentList& args)
{
if (!getRoot())
Expand Down Expand Up @@ -1209,7 +1247,6 @@ void Map::startMergeOperationCmd(const cmd::ArgumentList& args)
throw cmd::ExecutionFailure(fmt::format(_("File doesn't exist: {0}"), sourceCandidate));
}

#if false // base map handling not yet implemented
// Do we have a second argument (base map)
if (args.size() > 1)
{
Expand All @@ -1220,9 +1257,15 @@ void Map::startMergeOperationCmd(const cmd::ArgumentList& args)
throw cmd::ExecutionFailure(fmt::format(_("File doesn't exist: {0}"), baseCandidate));
}
}
#endif

startMergeOperation(sourceCandidate);
if (!baseCandidate.empty())
{
startMergeOperation(sourceCandidate, baseCandidate);
}
else
{
startMergeOperation(sourceCandidate);
}
}

void Map::abortMergeOperationCmd(const cmd::ArgumentList& args)
Expand Down
7 changes: 5 additions & 2 deletions radiantcore/map/Map.h
Expand Up @@ -68,7 +68,7 @@ class Map :
MapEventSignal _mapEvent;
std::size_t _shutdownListener;

scene::merge::MergeOperation::Ptr _mergeOperation;
scene::merge::IMergeOperation::Ptr _mergeOperation;
std::list<MergeActionNodeBase::Ptr> _mergeActionNodes;

// Point trace for leak detection
Expand Down Expand Up @@ -170,6 +170,7 @@ class Map :
void exportSelected(std::ostream& out, const MapFormatPtr& format) override;

void startMergeOperation(const std::string& sourceMap) override;
void startMergeOperation(const std::string& sourceMap, const std::string& baseMap) override;
void finishMergeOperation() override;
void abortMergeOperation() override;
scene::merge::IMergeOperation::Ptr getActiveMergeOperation() override;
Expand Down Expand Up @@ -266,7 +267,9 @@ class Map :
void startMergeOperationCmd(const cmd::ArgumentList& args);
void abortMergeOperationCmd(const cmd::ArgumentList& args);
void finishMergeOperationCmd(const cmd::ArgumentList& args);
void createMergeOperation(const scene::merge::ComparisonResult& result);

void createMergeActions();
void prepareMergeOperation();

void emitMapEvent(MapEvent ev);

Expand Down

0 comments on commit c9684c6

Please sign in to comment.