Skip to content

Commit

Permalink
#5231: Refactor export as CM functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed May 29, 2020
1 parent c118ba4 commit a182126
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 66 deletions.
2 changes: 1 addition & 1 deletion install/menu.xml
Expand Up @@ -15,7 +15,7 @@
<menuItem name="saveSelected" caption="&amp;Export selected as Map..." command="SaveSelected" />
<menuItem name="saveSelectedPrefab" caption="&amp;Export selected as Prefab..." command="SaveSelectedAsPrefab" />
<menuItem name="exportSelectedAsModel" caption="&amp;Export selected as Model..." command="ExportSelectedAsModelDialog" />
<menuItem name="createCM" caption="Export selected as Collision Model..." command="BrushExportCM" />
<menuItem name="createCM" caption="Export selected as Collision Model..." command="ExportCollisionModelDialog" />
<menuItem name="saveRegion" caption="Export &amp;Region..." command="SaveRegion" />
<menuSeparator />
<menuItem name="refreshModels" caption="&amp;Reload Models" command="RefreshModels" icon="model16red.png" />
Expand Down
3 changes: 3 additions & 0 deletions radiant/ui/UserInterfaceModule.cpp
Expand Up @@ -43,6 +43,7 @@
#include "ui/patch/PatchThickenDialog.h"
#include "textool/TexTool.h"
#include "modelexport/ExportAsModelDialog.h"
#include "modelexport/ExportCollisionModelDialog.h"
#include "ui/filters/FilterOrthoContextMenuItem.h"
#include "uimanager/colourscheme/ColourSchemeEditor.h"
#include "ui/layers/CreateLayerDialog.h"
Expand Down Expand Up @@ -302,6 +303,8 @@ void UserInterfaceModule::registerUICommands()
GlobalCommandSystem().addCommand("ThickenPatchDialog", PatchThickenDialog::Show);
GlobalCommandSystem().addCommand("CreateSimplePatchDialog", PatchCreateDialog::Show);

GlobalCommandSystem().addCommand("ExportCollisionModelDialog", ExportCollisionModelDialog::Show);

// Set up the CloneSelection command to react on key up events only
GlobalEventManager().addCommand("CloneSelection", "CloneSelection", true); // react on keyUp

Expand Down
32 changes: 32 additions & 0 deletions radiant/ui/modelexport/ExportCollisionModelDialog.cpp
@@ -0,0 +1,32 @@
#include "ExportCollisionModelDialog.h"

#include "i18n.h"
#include "selectionlib.h"
#include "command/ExecutionNotPossible.h"
#include "ui/modelselector/ModelSelector.h"

namespace ui
{

void ExportCollisionModelDialog::Show(const cmd::ArgumentList& args)
{
// Check the current selection state
const SelectionInfo& info = GlobalSelectionSystem().getSelectionInfo();

if (info.totalCount != info.entityCount || info.entityCount != 1)
{
throw cmd::ExecutionNotPossible(_("Can't export, create and select a func_* entity\
containing the collision hull primitives."));
}

auto modelAndSkin = ModelSelector::chooseModel("", false, false);

if (modelAndSkin.model.empty())
{
return;
}

GlobalCommandSystem().executeCommand("ExportSelectedAsCollisionModel", modelAndSkin.model);
}

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

#include "icommandsystem.h"

namespace ui
{

class ExportCollisionModelDialog
{
public:
static void Show(const cmd::ArgumentList& args);
};

}
2 changes: 1 addition & 1 deletion radiantcore/selection/algorithm/General.cpp
Expand Up @@ -1066,7 +1066,7 @@ void registerCommands()
GlobalCommandSystem().addCommand("CurveInsertControlPoint", insertCurveControlPoints);
GlobalCommandSystem().addCommand("CurveConvertType", convertCurveTypes);

GlobalCommandSystem().addCommand("BrushExportCM", createCMFromSelection);
GlobalCommandSystem().addCommand("ExportSelectedAsCollisionModel", createCMFromSelection, { cmd::ARGTYPE_STRING });

GlobalCommandSystem().addCommand("CreateDecalsForFaces", createDecalsForSelectedFaces);

Expand Down
134 changes: 70 additions & 64 deletions radiantcore/selection/algorithm/Primitives.cpp
Expand Up @@ -18,7 +18,6 @@
#include "brush/export/CollisionModel.h"
#include "os/fs.h"
#include "gamelib.h"
#include "ui/modelselector/ModelSelector.h"
#include "ui/brush/QuerySidesDialog.h"
#include "selection/shaderclipboard/ShaderClipboard.h"
#include "scenelib.h"
Expand All @@ -44,10 +43,6 @@ namespace
const char* const GKEY_NODRAW_SHADER = "/defaults/nodrawShader";
const char* const GKEY_VISPORTAL_SHADER = "/defaults/visportalShader";
const char* const GKEY_MONSTERCLIP_SHADER = "/defaults/monsterClipShader";

const char* const ERRSTR_WRONG_SELECTION =
N_("Can't export, create and select a func_* entity\
containing the collision hull primitives.");
}

void forEachSelectedFaceComponent(const std::function<void(Face&)>& functor)
Expand Down Expand Up @@ -131,90 +126,101 @@ FacePtrVector getSelectedFaces()
}

// Try to create a CM from the selected entity
void createCMFromSelection(const cmd::ArgumentList& args) {
void createCMFromSelection(const cmd::ArgumentList& args)
{
if (args.size() != 1)
{
rWarning() << "Usage: ExportSelectedAsCollisionModel <modelPath>" << std::endl;
return;
}

// Check the current selection state
const SelectionInfo& info = GlobalSelectionSystem().getSelectionInfo();

if (info.totalCount == info.entityCount && info.totalCount == 1)
if (info.totalCount != info.entityCount || info.entityCount != 1)
{
// Retrieve the node, instance and entity
const scene::INodePtr& entityNode = GlobalSelectionSystem().ultimateSelected();
throw cmd::ExecutionNotPossible(_("Can't export, create and select a func_* entity\
containing the collision hull primitives."));
}

// Try to retrieve the group node
scene::GroupNodePtr groupNode = Node_getGroupNode(entityNode);
std::string model = args[0].getString();

// Remove the entity origin from the brushes
if (groupNode != NULL) {
groupNode->removeOriginFromChildren();
// Retrieve the node, instance and entity
const scene::INodePtr& entityNode = GlobalSelectionSystem().ultimateSelected();

// Deselect the node
Node_setSelected(entityNode, false);
// Try to retrieve the group node
scene::GroupNodePtr groupNode = Node_getGroupNode(entityNode);

// Select all the child nodes
entityNode->foreachNode([] (const scene::INodePtr& child)->bool
{
Node_setSelected(child, true);
return true;
});
// Remove the entity origin from the brushes
if (groupNode)
{
groupNode->removeOriginFromChildren();

BrushPtrVector brushes = algorithm::getSelectedBrushes();
// Deselect the node
Node_setSelected(entityNode, false);

// Create a new collisionmodel on the heap using a shared_ptr
cmutil::CollisionModelPtr cm(new cmutil::CollisionModel());
// Select all the child nodes
entityNode->foreachNode([] (const scene::INodePtr& child)->bool
{
Node_setSelected(child, true);
return true;
});

// Add all the brushes to the collision model
for (std::size_t i = 0; i < brushes.size(); i++) {
cm->addBrush(brushes[i]->getBrush());
}
BrushPtrVector brushes = algorithm::getSelectedBrushes();

// Create a new collisionmodel on the heap using a shared_ptr
cmutil::CollisionModelPtr cm(new cmutil::CollisionModel());

ui::ModelSelectorResult modelAndSkin = ui::ModelSelector::chooseModel("", false, false);
std::string basePath = GlobalGameManager().getModPath();
// Add all the brushes to the collision model
for (std::size_t i = 0; i < brushes.size(); i++) {
cm->addBrush(brushes[i]->getBrush());
}

std::string modelPath = basePath + modelAndSkin.model;
std::string basePath = GlobalGameManager().getModPath();

std::string newExtension = "." + game::current::getValue<std::string>(GKEY_CM_EXT);
std::string modelPath = basePath + model;

// Set the model string to correctly associate the clipmodel
cm->setModel(modelAndSkin.model);
std::string newExtension = "." + game::current::getValue<std::string>(GKEY_CM_EXT);

try {
// create the new autosave filename by changing the extension
fs::path cmPath = os::replaceExtension(modelPath, newExtension);
// Set the model string to correctly associate the clipmodel
cm->setModel(model);

// Open the stream to the output file
std::ofstream outfile(cmPath.string().c_str());
try
{
// create the new autosave filename by changing the extension
fs::path cmPath = os::replaceExtension(modelPath, newExtension);

if (outfile.is_open()) {
// Insert the CollisionModel into the stream
outfile << *cm;
// Close the file
outfile.close();
// Open the stream to the output file
std::ofstream outfile(cmPath.string());

rMessage() << "CollisionModel saved to " << cmPath.string() << std::endl;
}
else {
throw cmd::ExecutionFailure(
fmt::format(_("Couldn't save to file: {0}"), cmPath.string()));
}
if (outfile.is_open())
{
// Insert the CollisionModel into the stream
outfile << *cm;

// Close the file
outfile.close();

rMessage() << "CollisionModel saved to " << cmPath.string() << std::endl;
}
catch (const fs::filesystem_error& f)
else
{
rError() << "CollisionModel: " << f.what() << std::endl;
throw cmd::ExecutionFailure(fmt::format(_("Couldn't save to file: {0}"), cmPath.string()));
}
}
catch (const fs::filesystem_error& f)
{
rError() << "CollisionModel: " << f.what() << std::endl;
}

// De-select the child brushes
GlobalSelectionSystem().setSelectedAll(false);
// De-select the child brushes
GlobalSelectionSystem().setSelectedAll(false);

// Re-add the origin to the brushes
groupNode->addOriginToChildren();
// Re-add the origin to the brushes
groupNode->addOriginToChildren();

// Re-select the node
Node_setSelected(entityNode, true);
}
}
else
{
throw cmd::ExecutionNotPossible(_(ERRSTR_WRONG_SELECTION));
// Re-select the node
Node_setSelected(entityNode, true);
}
}

Expand Down
2 changes: 2 additions & 0 deletions tools/msvc/DarkRadiant.vcxproj
Expand Up @@ -272,6 +272,7 @@
<ClCompile Include="..\..\radiant\ui\mainframe\TopLevelFrame.cpp" />
<ClCompile Include="..\..\radiant\ui\mapinfo\LayerInfoTab.cpp" />
<ClCompile Include="..\..\radiant\ui\modelexport\ExportAsModelDialog.cpp" />
<ClCompile Include="..\..\radiant\ui\modelexport\ExportCollisionModelDialog.cpp" />
<ClCompile Include="..\..\radiant\ui\modelselector\MaterialsList.cpp" />
<ClCompile Include="..\..\radiant\camera\Camera.cpp" />
<ClCompile Include="..\..\radiant\camera\CameraSettings.cpp" />
Expand Down Expand Up @@ -472,6 +473,7 @@
<ClInclude Include="..\..\radiant\ui\MapFileProgressHandler.h" />
<ClInclude Include="..\..\radiant\ui\mapinfo\LayerInfoTab.h" />
<ClInclude Include="..\..\radiant\ui\modelexport\ExportAsModelDialog.h" />
<ClInclude Include="..\..\radiant\ui\modelexport\ExportCollisionModelDialog.h" />
<ClInclude Include="..\..\radiant\ui\modelselector\MaterialsList.h" />
<ClInclude Include="..\..\radiant\camera\Camera.h" />
<ClInclude Include="..\..\radiant\camera\CameraObserver.h" />
Expand Down
6 changes: 6 additions & 0 deletions tools/msvc/DarkRadiant.vcxproj.filters
Expand Up @@ -721,6 +721,9 @@
<ClCompile Include="..\..\radiant\ui\selectionset\SelectionSetToolmenu.cpp">
<Filter>src\ui\selectionset</Filter>
</ClCompile>
<ClCompile Include="..\..\radiant\ui\modelexport\ExportCollisionModelDialog.cpp">
<Filter>src\ui\modelexport</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\radiant\RadiantModule.h">
Expand Down Expand Up @@ -1401,6 +1404,9 @@
<ClInclude Include="..\..\radiant\ui\selectionset\SelectionSetToolmenu.h">
<Filter>src\ui\selectionset</Filter>
</ClInclude>
<ClInclude Include="..\..\radiant\ui\modelexport\ExportCollisionModelDialog.h">
<Filter>src\ui\modelexport</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\radiant\darkradiant.rc" />
Expand Down
1 change: 1 addition & 0 deletions tools/msvc/libs.vcxproj
Expand Up @@ -162,6 +162,7 @@
<ClInclude Include="..\..\libs\messages\GameConfigNeededMessage.h" />
<ClInclude Include="..\..\libs\messages\LongRunningOperationMessage.h" />
<ClInclude Include="..\..\libs\messages\MapFileOperation.h" />
<ClInclude Include="..\..\libs\messages\NotificationMessage.h" />
<ClInclude Include="..\..\libs\messages\ScopedLongRunningOperation.h" />
<ClInclude Include="..\..\libs\messages\TextureChanged.h" />
<ClInclude Include="..\..\libs\ObservedSelectable.h" />
Expand Down
3 changes: 3 additions & 0 deletions tools/msvc/libs.vcxproj.filters
Expand Up @@ -212,6 +212,9 @@
<ClInclude Include="..\..\libs\messages\TextureChanged.h">
<Filter>messages</Filter>
</ClInclude>
<ClInclude Include="..\..\libs\messages\NotificationMessage.h">
<Filter>messages</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="util">
Expand Down

0 comments on commit a182126

Please sign in to comment.