Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/orbweaver/master'
Browse files Browse the repository at this point in the history
# Conflicts:
#	include/imap.h
#	radiant/ui/UserInterfaceModule.cpp
#	radiant/ui/einspector/EntityInspector.cpp
#	radiantcore/map/Map.cpp
#	radiantcore/map/Map.h
  • Loading branch information
codereader committed Jun 2, 2021
2 parents 8af189c + e3238ac commit 3112676
Show file tree
Hide file tree
Showing 16 changed files with 435 additions and 168 deletions.
31 changes: 28 additions & 3 deletions include/imap.h
Expand Up @@ -8,6 +8,8 @@
#include "ikeyvaluestore.h"
#include <sigc++/signal.h>

#include <os/fs.h>

// Registry setting for suppressing the map load progress dialog
const char* const RKEY_MAP_SUPPRESS_LOAD_STATUS_DIALOG = "user/ui/map/suppressMapLoadDialog";

Expand All @@ -29,8 +31,8 @@ class ITargetManager;
// see ilayer.h
class ILayerManager;

namespace selection
{
namespace selection
{
class ISelectionSetManager;
class ISelectionGroupManager;
}
Expand Down Expand Up @@ -174,7 +176,7 @@ class IMap :
// Create a MapExporter instance which can be used to export a scene,
// including the necessary preparation, info-file handling, etc.
// This is mainly a service method for external code, like the gameconnection.
virtual map::IMapExporter::Ptr createMapExporter(map::IMapWriter& writer,
virtual map::IMapExporter::Ptr createMapExporter(map::IMapWriter& writer,
const scene::IMapRootNodePtr& root, std::ostream& mapStream) = 0;

// Exports the current selection to the given output stream, using the map's format
Expand All @@ -191,6 +193,29 @@ class IMap :

// Returns the currently active merge operation (or an empty reference if no merge is ongoing)
virtual scene::merge::IMergeOperation::Ptr getActiveMergeOperation() = 0;

/* POINTFILE MANAGEMENT */

/// Functor to receive pointfile paths
using PointfileFunctor = std::function<void(const fs::path&)>;

/// Enumerate pointfiles associated with the current map
virtual void forEachPointfile(PointfileFunctor func) const = 0;

/**
* \brief Show the point trace contained in the specified file.
*
* \param filePath
* Filesystem path of the file to parse for point coordinates, or an empty
* path to hide any current point trace.
*
* \exception std::runtime_error
* Thrown if filePath is not empty but the file is inaccessible.
*/
virtual void showPointFile(const fs::path& filePath) = 0;

/// Return true if a point trace is currently visible
virtual bool isPointTraceVisible() const = 0;
};
typedef std::shared_ptr<IMap> IMapPtr;

Expand Down
2 changes: 1 addition & 1 deletion install/menu.xml
Expand Up @@ -30,7 +30,7 @@
<menuSeparator />
<menuItem name="gameSelector" caption="&amp;Game/Project Setup..." command="ProjectSettings" />
<menuSeparator />
<menuItem name="pointfile" caption="&amp;Pointfile" command="TogglePointfile" icon="pointfile16.png"/>
<menuItem name="pointfile" caption="&amp;Pointfile" command="ChooseAndTogglePointfile" icon="pointfile16.png"/>
<menuSeparator />
<!-- MRU is inserted automatically at this position -->
<menuItem name="exit" caption="E&amp;xit" command="Exit" />
Expand Down
36 changes: 36 additions & 0 deletions libs/scene/PointTrace.h
@@ -0,0 +1,36 @@
#pragma once

#include "math/Vector3.h"

namespace map
{

/// Parsed point positions from a .lin file
class PointTrace
{
public:
using Points = std::vector<Vector3>;

private:

// List of point positions
Points _points;

public:

/// Construct a PointTrace to read point data from the given stream
explicit PointTrace(std::istream& stream)
{
// Point file consists of one point per line, with three components
double x, y, z;
while (stream >> x >> y >> z)
{
_points.push_back(Vector3(x, y, z));
}
}

/// Return points parsed
const Points& points() const { return _points; }
};

}
1 change: 1 addition & 0 deletions radiant/CMakeLists.txt
Expand Up @@ -149,6 +149,7 @@ add_executable(darkradiant
ui/patch/PatchCreateDialog.cpp
ui/patch/PatchInspector.cpp
ui/patch/PatchThickenDialog.cpp
ui/PointFileChooser.cpp
ui/prefabselector/PrefabSelector.cpp
ui/prefdialog/GameSetupDialog.cpp
ui/prefdialog/GameSetupPage.cpp
Expand Down
77 changes: 77 additions & 0 deletions radiant/ui/PointFileChooser.cpp
@@ -0,0 +1,77 @@
#include "PointFileChooser.h"

#include "imainframe.h"
#include "imap.h"
#include "icommandsystem.h"
#include "os/fs.h"
#include "command/ExecutionFailure.h"

#include <wx/frame.h>
#include <wx/sizer.h>
#include <wx/choice.h>
#include <list>

namespace ui
{

PointFileChooser::PointFileChooser(const wxArrayString& files)
: wxDialog(GlobalMainFrame().getWxTopLevelWindow(), wxID_ANY,
"Choose pointfile")
{
SetSizer(new wxBoxSizer(wxVERTICAL));

// Construct and populate the dropdown list
_pfChoice.reset(
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, files)
);
_pfChoice->SetSelection(0);
GetSizer()->Add(_pfChoice.get(), 0, wxEXPAND | wxALL, 12);

// Add dialog buttons
auto btnSizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
GetSizer()->Add(btnSizer, 0, wxALIGN_RIGHT | wxALIGN_BOTTOM | wxBOTTOM, 12);

Fit();
}

void PointFileChooser::chooseAndToggle()
{
// If the point trace is currently visible, toggle it to invisible and we're
// done.
if (GlobalMapModule().isPointTraceVisible())
{
GlobalMapModule().showPointFile({});
return;
}

// Determine the list of pointfiles
std::vector<fs::path> pointfiles;
GlobalMapModule().forEachPointfile([&](const fs::path& p)
{ pointfiles.push_back(p); });
if (pointfiles.empty())
throw cmd::ExecutionFailure("No pointfiles found for current map.");

// If there is a choice to make, show the dialog
std::size_t chosenPointfile = 0;
if (pointfiles.size() > 1)
{
// Construct list of wxString filenames
wxArrayString filenames;
for (const fs::path& p: pointfiles)
filenames.Add(static_cast<std::string>(p.filename()));

// Show dialog with list of pointfiles
PointFileChooser chooser(filenames);
if (chooser.ShowModal() == wxID_OK)
chosenPointfile = chooser._pfChoice->GetSelection();
else
// Dialog cancelled, don't proceed to showing point trace
return;
}

// Show the chosen (or only) pointfile
if (chosenPointfile >= 0 && chosenPointfile < pointfiles.size())
GlobalMapModule().showPointFile(pointfiles[chosenPointfile]);
}

}
32 changes: 32 additions & 0 deletions radiant/ui/PointFileChooser.h
@@ -0,0 +1,32 @@
#pragma once

#include <wx/dialog.h>
#include <wx/choice.h>
#include <wx/windowptr.h>

namespace ui
{

/// Selector dialog for pointfiles associated with the current map
class PointFileChooser: public wxDialog
{
// wxChoice containing the chosen pointfile
wxWindowPtr<wxChoice> _pfChoice;

// Dialog constructor
PointFileChooser(const wxArrayString& files);

public:

/**
* \brief Toggle pointfile visibility, showing the chooser if necessary.
*
* If there is only a single pointfile available, this method acts as a
* simple visibility toggle. If there is more than one pointfile, the
* chooser dialog will be shown before toggling visibility on. If there are
* no pointfiles available, an error dialog will be shown.
*/
static void chooseAndToggle();
};

}
28 changes: 16 additions & 12 deletions radiant/ui/UserInterfaceModule.cpp
Expand Up @@ -62,6 +62,7 @@
#include "ui/mousetool/RegistrationHelper.h"
#include "ui/mapselector/MapSelector.h"
#include "ui/merge/MergeControlDialog.h"
#include "ui/PointFileChooser.h"

#include <wx/version.h>

Expand Down Expand Up @@ -131,19 +132,19 @@ void UserInterfaceModule::initialiseModule(const IApplicationContext& ctx)

// Add the orthocontext menu's layer actions
GlobalOrthoContextMenu().addItem(
std::make_shared<LayerOrthoContextMenuItem>(_(ADD_TO_LAYER_TEXT),
std::make_shared<LayerOrthoContextMenuItem>(_(ADD_TO_LAYER_TEXT),
LayerOrthoContextMenuItem::AddToLayer),
IOrthoContextMenu::SECTION_LAYER
);

GlobalOrthoContextMenu().addItem(
std::make_shared<LayerOrthoContextMenuItem>(_(MOVE_TO_LAYER_TEXT),
std::make_shared<LayerOrthoContextMenuItem>(_(MOVE_TO_LAYER_TEXT),
LayerOrthoContextMenuItem::MoveToLayer),
IOrthoContextMenu::SECTION_LAYER
);

GlobalOrthoContextMenu().addItem(
std::make_shared<LayerOrthoContextMenuItem>(_(REMOVE_FROM_LAYER_TEXT),
std::make_shared<LayerOrthoContextMenuItem>(_(REMOVE_FROM_LAYER_TEXT),
LayerOrthoContextMenuItem::RemoveFromLayer),
IOrthoContextMenu::SECTION_LAYER
);
Expand Down Expand Up @@ -240,7 +241,7 @@ void UserInterfaceModule::shutdownModule()
_editStopwatchStatus.reset();
_manipulatorToggle.reset();
_selectionModeToggle.reset();

_mruMenu.reset();
}

Expand All @@ -266,17 +267,17 @@ void UserInterfaceModule::HandleNotificationMessage(radiant::NotificationMessage
switch (msg.getType())
{
case radiant::NotificationMessage::Information:
wxutil::Messagebox::Show(msg.hasTitle() ? msg.getTitle() : _("Notification"),
wxutil::Messagebox::Show(msg.hasTitle() ? msg.getTitle() : _("Notification"),
msg.getMessage(), IDialog::MessageType::MESSAGE_CONFIRM, parentWindow);
break;

case radiant::NotificationMessage::Warning:
wxutil::Messagebox::Show(msg.hasTitle() ? msg.getTitle() : _("Warning"),
wxutil::Messagebox::Show(msg.hasTitle() ? msg.getTitle() : _("Warning"),
msg.getMessage(), IDialog::MessageType::MESSAGE_WARNING, parentWindow);
break;

case radiant::NotificationMessage::Error:
wxutil::Messagebox::Show(msg.hasTitle() ? msg.getTitle() : _("Error"),
wxutil::Messagebox::Show(msg.hasTitle() ? msg.getTitle() : _("Error"),
msg.getMessage(), IDialog::MessageType::MESSAGE_ERROR, parentWindow);
break;
};
Expand All @@ -301,9 +302,9 @@ void UserInterfaceModule::initialiseEntitySettings()
applyPatchVertexColours();

_coloursUpdatedConn = ColourSchemeEditor::signal_ColoursChanged().connect(
[this]() {
applyEntityVertexColours();
applyBrushVertexColours();
[this]() {
applyEntityVertexColours();
applyBrushVertexColours();
applyPatchVertexColours();
}
);
Expand Down Expand Up @@ -344,7 +345,7 @@ void UserInterfaceModule::refreshShadersCmd(const cmd::ArgumentList& args)
// Disable screen updates for the scope of this function
auto blocker = GlobalMainFrame().getScopedScreenUpdateBlocker(_("Processing..."), _("Loading Shaders"));

// Reload the Shadersystem, this will also trigger an
// Reload the Shadersystem, this will also trigger an
// OpenGLRenderSystem unrealise/realise sequence as the rendersystem
// is attached to this class as Observer
// We can't do this refresh() operation in a thread it seems due to context binding
Expand All @@ -367,8 +368,11 @@ void UserInterfaceModule::registerUICommands()
GlobalCommandSystem().addCommand("MergeControlDialog", MergeControlDialog::ShowDialog);
GlobalCommandSystem().addCommand("OverlayDialog", OverlayDialog::toggle);
GlobalCommandSystem().addCommand("TransformDialog", TransformDialog::toggle);
GlobalCommandSystem().addCommand("ChooseAndTogglePointfile",
[](const cmd::ArgumentList&)
{ PointFileChooser::chooseAndToggle(); });

GlobalCommandSystem().addCommand("FindBrush", FindBrushDialog::Show);
GlobalCommandSystem().addCommand("FindBrush", FindBrushDialog::Show);
GlobalCommandSystem().addCommand("AnimationPreview", MD5AnimationViewer::Show);
GlobalCommandSystem().addCommand("EditColourScheme", ColourSchemeEditor::DisplayDialog);

Expand Down
2 changes: 1 addition & 1 deletion radiant/ui/einspector/EntityInspector.cpp
Expand Up @@ -1235,7 +1235,7 @@ void EntityInspector::addClassAttribute(const EntityClassAttribute& a)
wxutil::TreeModel::Row row = _kvStore->AddItem();

wxDataViewItemAttr grey;
grey.SetColour(wxColor(112, 112, 112));
grey.SetItalic(true);

row[_columns.name] = wxVariant(wxDataViewIconText(a.getName(), _emptyIcon));
row[_columns.value] = a.getValue();
Expand Down

0 comments on commit 3112676

Please sign in to comment.