Skip to content

Commit

Permalink
Add option to use the entity origin as center point of the exported m…
Browse files Browse the repository at this point in the history
…odel.
  • Loading branch information
codereader committed Aug 22, 2017
1 parent e1bf73d commit 36ffcbf
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 15 deletions.
98 changes: 93 additions & 5 deletions install/ui/exportasmodeldialog.fbp
Expand Up @@ -661,7 +661,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Center Objects at 0,0,0 Origin</property>
<property name="label">Center Objects around Origin</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
Expand Down Expand Up @@ -717,7 +717,7 @@
</object>
</object>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="border">6</property>
<property name="flag">wxBOTTOM|wxTOP</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="0">
Expand Down Expand Up @@ -805,8 +805,8 @@
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxTOP</property>
<property name="border">6</property>
<property name="flag">wxBOTTOM|wxTOP</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
Expand Down Expand Up @@ -837,7 +837,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Replace selection with exported model</property>
<property name="label">Replace Selection with exported Model</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
Expand Down Expand Up @@ -892,6 +892,94 @@
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">6</property>
<property name="flag">wxBOTTOM|wxTOP</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Use Entity Origin as export Origin</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">ExportDialogUseEntityOrigin</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnCheckBox"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
Expand Down
19 changes: 14 additions & 5 deletions install/ui/exportasmodeldialog.xrc
Expand Up @@ -93,25 +93,34 @@
<flag>wxBOTTOM|wxTOP</flag>
<border>6</border>
<object class="wxCheckBox" name="ExportDialogCenterObjects">
<label>Center Objects at 0,0,0 Origin</label>
<label>Center Objects around Origin</label>
<checked>0</checked>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxBOTTOM|wxTOP</flag>
<border>5</border>
<border>6</border>
<object class="wxCheckBox" name="ExportDialogSkipCaulk">
<label>Skip Surfaces textured with Caulk</label>
<checked>0</checked>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxTOP</flag>
<border>5</border>
<flag>wxBOTTOM|wxTOP</flag>
<border>6</border>
<object class="wxCheckBox" name="ExportDialogReplaceWithModel">
<label>Replace selection with exported model</label>
<label>Replace Selection with exported Model</label>
<checked>0</checked>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxBOTTOM|wxTOP</flag>
<border>6</border>
<object class="wxCheckBox" name="ExportDialogUseEntityOrigin">
<label>Use Entity Origin as export Origin</label>
<checked>0</checked>
</object>
</object>
Expand Down
38 changes: 34 additions & 4 deletions radiant/map/algorithm/Export.cpp
Expand Up @@ -8,8 +8,10 @@

#include "os/path.h"

#include "selectionlib.h"
#include "selection/algorithm/Entity.h"
#include "selection/algorithm/General.h"
#include "string/convert.h"
#include "model/ModelExporter.h"
#include "registry/registry.h"
#include "Traverse.h"
Expand Down Expand Up @@ -54,6 +56,27 @@ void exportSelectedAsModel(const ModelExportOptions& options)
exporter.setCenterObjects(options.centerObjects);
exporter.setSkipCaulkMaterial(options.skipCaulk);

if (options.useEntityOrigin)
{
// Check if we have a single entity selected
const SelectionInfo& info = GlobalSelectionSystem().getSelectionInfo();

if (info.totalCount == 1 && info.entityCount == 1)
{
Entity* entity = Node_getEntity(GlobalSelectionSystem().ultimateSelected());

if (entity != nullptr)
{
Vector3 entityOrigin = string::convert<Vector3>(entity->getKeyValue("origin"));
exporter.setOrigin(entityOrigin);
}
}
else
{
rWarning() << "Will ignore the UseEntityOrigin setting as we don't have a single entity selected." << std::endl;
}
}

exporter.processNodes();

// Extract the output filename
Expand Down Expand Up @@ -113,13 +136,14 @@ void exportSelectedAsModel(const ModelExportOptions& options)

void exportSelectedAsModelCmd(const cmd::ArgumentList& args)
{
if (args.size() < 2 || args.size() > 5)
if (args.size() < 2 || args.size() > 6)
{
rMessage() << "Usage: ExportSelectedAsModel <Path> <ExportFormat> [<CenterObjects>] [<SkipCaulk>] [<ReplaceSelectionWithModel>]" << std::endl;
rMessage() << "Usage: ExportSelectedAsModel <Path> <ExportFormat> [<CenterObjects>] [<SkipCaulk>] [<ReplaceSelectionWithModel>] [<UseEntityOrigin>]" << std::endl;
rMessage() << " <Path> must be an absolute file system path" << std::endl;
rMessage() << " pass [<CenterObjects>] as 1 to center objects at 0,0,0 origin" << std::endl;
rMessage() << " pass [<CenterObjects>] as 1 to center objects around the origin" << std::endl;
rMessage() << " pass [<SkipCaulk>] as 1 to skip caulked surfaces" << std::endl;
rMessage() << " pass [<ReplaceSelectionWithModel>] as 1 to delete the selection and put the exported model in its place" << std::endl;
rMessage() << " pass [<UseEntityOrigin>] as 1 to use the entity origin as export origin (only applicable if a single entity is selected)" << std::endl;
return;
}

Expand All @@ -130,6 +154,7 @@ void exportSelectedAsModelCmd(const cmd::ArgumentList& args)
options.skipCaulk = false;
options.centerObjects = false;
options.replaceSelectionWithModel = false;
options.useEntityOrigin = false;

if (args.size() >= 3)
{
Expand All @@ -141,11 +166,16 @@ void exportSelectedAsModelCmd(const cmd::ArgumentList& args)
options.skipCaulk = (args[3].getInt() != 0);
}

if (args.size() >= 4)
if (args.size() >= 5)
{
options.replaceSelectionWithModel = (args[4].getInt() != 0);
}

if (args.size() >= 6)
{
options.useEntityOrigin = (args[5].getInt() != 0);
}

try
{
exportSelectedAsModel(options);
Expand Down
1 change: 1 addition & 0 deletions radiant/map/algorithm/Export.h
Expand Up @@ -16,6 +16,7 @@ struct ModelExportOptions
bool skipCaulk; // whether to skip caulk
bool centerObjects; // whether to center objects
bool replaceSelectionWithModel; // delete the selection and put the exported model in its place
bool useEntityOrigin; // use entity origin as model origin (only applicable if a single entity is selected)
};

/**
Expand Down
14 changes: 13 additions & 1 deletion radiant/model/ModelExporter.cpp
Expand Up @@ -53,6 +53,8 @@ ModelExporter::ModelExporter(const model::IModelExporterPtr& exporter) :
_skipCaulk(false),
_caulkMaterial(registry::getValue<std::string>(RKEY_CLIPPER_CAULK_SHADER)),
_centerObjects(false),
_origin(0,0,0),
_useOriginAsCenter(false),
_centerTransform(Matrix4::getIdentity())
{
if (!_exporter)
Expand All @@ -72,6 +74,12 @@ void ModelExporter::setCenterObjects(bool centerObjects)
_centerObjects = centerObjects;
}

void ModelExporter::setOrigin(const Vector3& origin)
{
_origin = origin;
_useOriginAsCenter = true;
}

bool ModelExporter::pre(const scene::INodePtr& node)
{
// Skip worldspawn
Expand All @@ -93,7 +101,11 @@ void ModelExporter::processNodes()

if (_centerObjects)
{
_centerTransform = Matrix4::getTranslation(-bounds.origin);
// Depending on the center point, we need to use the object bounds
// or just the translation towards the user-defined origin, ignoring bounds
_centerTransform = _useOriginAsCenter ?
Matrix4::getTranslation(-_origin) :
Matrix4::getTranslation(-bounds.origin);
}

for (const scene::INodePtr& node : _nodes)
Expand Down
9 changes: 9 additions & 0 deletions radiant/model/ModelExporter.h
Expand Up @@ -5,6 +5,7 @@
#include "imodelsurface.h"
#include "math/AABB.h"
#include "math/Matrix4.h"
#include "math/Vector3.h"
#include <map>
#include <list>

Expand All @@ -22,6 +23,11 @@ class ModelExporter :

bool _centerObjects;

// Optional origin to use for the centering transformation
// instead of the object bounds origin
Vector3 _origin;
bool _useOriginAsCenter;

std::list<scene::INodePtr> _nodes;

// The translation centering the objects
Expand All @@ -37,6 +43,9 @@ class ModelExporter :
// Define whether we should arrange the objects around the world origin
void setCenterObjects(bool centerObjects);

// Define the origin to use for centering the objects
void setOrigin(const Vector3& origin);

bool pre(const scene::INodePtr& node) override;

// Processes the nodes previously collected in the pre() method
Expand Down
22 changes: 22 additions & 0 deletions radiant/ui/modelexport/ExportAsModelDialog.cpp
Expand Up @@ -14,6 +14,7 @@
#include <wx/sizer.h>
#include <boost/algorithm/string/case_conv.hpp>

#include "selectionlib.h"
#include "os/path.h"
#include "os/file.h"
#include "os/dir.h"
Expand All @@ -35,6 +36,7 @@ namespace
const char* RKEY_MODEL_EXPORT_REPLACE_WITH_MODEL = "user/ui/exportAsModel/replaceSelectionWithModel";
const char* RKEY_MODEL_EXPORT_OUTPUT_PATH = "user/ui/exportAsModel/outputPath";
const char* RKEY_MODEL_EXPORT_OUTPUT_FORMAT = "user/ui/exportAsModel/outputFormat";
const char* RKEY_MODEL_EXPORT_USE_ENTITY_ORIGIN = "user/ui/exportAsModel/keepEntityOrigin";
}

ExportAsModelDialog::ExportAsModelDialog(wxWindow* parent) :
Expand Down Expand Up @@ -127,6 +129,22 @@ void ExportAsModelDialog::populateWindow()
bool replaceSelectionWithModel = registry::getValue<bool>(RKEY_MODEL_EXPORT_REPLACE_WITH_MODEL);
findNamedObject<wxCheckBox>(this, "ExportDialogReplaceWithModel")->SetValue(replaceSelectionWithModel);

bool keepEntityOrigin = registry::getValue<bool>(RKEY_MODEL_EXPORT_USE_ENTITY_ORIGIN);
wxCheckBox* keepOriginBox = findNamedObject<wxCheckBox>(this, "ExportDialogUseEntityOrigin");

const SelectionInfo& info = GlobalSelectionSystem().getSelectionInfo();

if (info.totalCount == 1 && info.entityCount == 1)
{
keepOriginBox->SetValue(keepEntityOrigin);
keepOriginBox->Enable(true);
}
else
{
keepOriginBox->SetValue(false);
keepOriginBox->Enable(false);
}

Layout();
Fit();
CenterOnScreen();
Expand All @@ -141,6 +159,7 @@ void ExportAsModelDialog::onExport(wxCommandEvent& ev)
options.outputFilename = findNamedObject<wxutil::PathEntry>(this, "ExportDialogFilePicker")->getValue();
options.outputFormat = wxutil::ChoiceHelper::GetSelectedStoredString(findNamedObject<wxChoice>(this, "ExportDialogFormatChoice"));
options.replaceSelectionWithModel = findNamedObject<wxCheckBox>(this, "ExportDialogReplaceWithModel")->GetValue();
options.useEntityOrigin = findNamedObject<wxCheckBox>(this, "ExportDialogUseEntityOrigin")->GetValue();

if (options.outputFilename.empty())
{
Expand Down Expand Up @@ -207,6 +226,9 @@ void ExportAsModelDialog::saveOptionsToRegistry()

registry::setValue(RKEY_MODEL_EXPORT_REPLACE_WITH_MODEL,
findNamedObject<wxCheckBox>(this, "ExportDialogReplaceWithModel")->GetValue());

registry::setValue(RKEY_MODEL_EXPORT_USE_ENTITY_ORIGIN,
findNamedObject<wxCheckBox>(this, "ExportDialogUseEntityOrigin")->GetValue());
}

void ExportAsModelDialog::ShowDialog(const cmd::ArgumentList& args)
Expand Down

0 comments on commit 36ffcbf

Please sign in to comment.