Skip to content

Commit

Permalink
Save and load masks #229
Browse files Browse the repository at this point in the history
  • Loading branch information
ousnius committed Mar 21, 2020
1 parent 0733001 commit 2e05866
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 28 deletions.
9 changes: 9 additions & 0 deletions lang/BodySlide.pot
Original file line number Diff line number Diff line change
Expand Up @@ -2570,3 +2570,12 @@ msgstr ""

msgid "Rotation"
msgstr ""

msgid "Masks"
msgstr ""

msgid "New Mask"
msgstr ""

msgid "Please enter a new unique name for the mask."
msgstr ""
Binary file modified lang/de/BodySlide.mo
Binary file not shown.
9 changes: 9 additions & 0 deletions lang/de/BodySlide.po
Original file line number Diff line number Diff line change
Expand Up @@ -2981,3 +2981,12 @@ msgstr "Ausgangspunkt"

msgid "Rotation"
msgstr "Rotation"

msgid "Masks"
msgstr "Masken"

msgid "New Mask"
msgstr "Neue Maske"

msgid "Please enter a new unique name for the mask."
msgstr "Bitte geben Sie einen neuen, einzigartigen Namen für die Maske ein."
66 changes: 60 additions & 6 deletions res/xrc/OutfitStudio.xrc
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,66 @@
</object>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL|wxEXPAND|wxLEFT</flag>
<border>2</border>
<object class="wxCollapsiblePane" name="masksPane">
<style>wxCP_DEFAULT_STYLE</style>
<collapsed>1</collapsed>
<label>Masks</label>
<bg>wxSYS_COLOUR_MENU</bg>
<hidden>0</hidden>
<object class="panewindow">
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<option>0</option>
<flag>wxALL|wxEXPAND</flag>
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<option>1</option>
<flag>wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND</flag>
<border>5</border>
<object class="wxChoice" name="cMaskName">
<selection>0</selection>
<content />
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxBOTTOM|wxEXPAND</flag>
<border>5</border>
<object class="wxButton" name="saveMask">
<size>-1,25</size>
<label>Save</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxBOTTOM|wxEXPAND</flag>
<border>5</border>
<object class="wxButton" name="saveAsMask">
<size>-1,25</size>
<label>Save As</label>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxBOTTOM|wxEXPAND</flag>
<border>5</border>
<object class="wxButton" name="deleteMask">
<size>-1,25</size>
<label>Delete</label>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL|wxEXPAND|wxLEFT</flag>
Expand Down Expand Up @@ -1857,12 +1917,6 @@
<label>Clear Mask\tCtrl+A</label>
<help>Clear Mask</help>
</object>
<object class="wxMenuItem" name="btnShowMask">
<label>Show Mask\tM</label>
<help>Shade meshes to indicate areas that are currently masked.</help>
<checked>1</checked>
<checkable>1</checkable>
</object>
</object>
</object>

Expand Down
104 changes: 89 additions & 15 deletions src/program/OutfitStudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ wxBEGIN_EVENT_TABLE(OutfitStudioFrame, wxFrame)
EVT_COMMAND_SCROLL(XRCID("brushFocus"), OutfitStudioFrame::OnBrushSettingsSlider)
EVT_COMMAND_SCROLL(XRCID("brushSpace"), OutfitStudioFrame::OnBrushSettingsSlider)

EVT_COLLAPSIBLEPANE_CHANGED(XRCID("posePane"), OutfitStudioFrame::OnPosePaneCollapse)
EVT_COLLAPSIBLEPANE_CHANGED(XRCID("masksPane"), OutfitStudioFrame::OnPaneCollapse)
EVT_CHOICE(XRCID("cMaskName"), OutfitStudioFrame::OnSelectMask)
EVT_BUTTON(XRCID("saveMask"), OutfitStudioFrame::OnSaveMask)
EVT_BUTTON(XRCID("saveAsMask"), OutfitStudioFrame::OnSaveAsMask)
EVT_BUTTON(XRCID("deleteMask"), OutfitStudioFrame::OnDeleteMask)

EVT_COLLAPSIBLEPANE_CHANGED(XRCID("posePane"), OutfitStudioFrame::OnPaneCollapse)
EVT_CHOICE(XRCID("cPoseBone"), OutfitStudioFrame::OnPoseBoneChanged)
EVT_COMMAND_SCROLL(XRCID("rxPoseSlider"), OutfitStudioFrame::OnRXPoseSlider)
EVT_COMMAND_SCROLL(XRCID("ryPoseSlider"), OutfitStudioFrame::OnRYPoseSlider)
Expand Down Expand Up @@ -158,7 +164,6 @@ wxBEGIN_EVENT_TABLE(OutfitStudioFrame, wxFrame)
EVT_MENU(XRCID("btnMaskMore"), OutfitStudioFrame::OnMaskMore)
EVT_MENU(XRCID("btnClearMask"), OutfitStudioFrame::OnClearMask)
EVT_MENU(XRCID("btnInvertMask"), OutfitStudioFrame::OnInvertMask)
EVT_MENU(XRCID("btnShowMask"), OutfitStudioFrame::OnShowMask)

EVT_MENU(XRCID("btnRecalcNormals"), OutfitStudioFrame::OnRecalcNormals)
EVT_MENU(XRCID("btnSmoothSeams"), OutfitStudioFrame::OnSmoothNormalSeams)
Expand Down Expand Up @@ -2888,6 +2893,10 @@ void OutfitStudioFrame::ClearProject() {

glView->DestroyOverlays();
activePartition.Unset();
activeSegment.Unset();

wxChoice* cMaskName = (wxChoice*)FindWindowByName("cMaskName");
cMaskName->Clear();

SetTitle("Outfit Studio");
}
Expand Down Expand Up @@ -5531,6 +5540,11 @@ void OutfitStudioFrame::OnReadoutChange(wxCommandEvent& event) {
void OutfitStudioFrame::OnTabButtonClick(wxCommandEvent& event) {
int id = event.GetId();

if (id != XRCID("meshTabButton")) {
wxCollapsiblePane* masksPane = dynamic_cast<wxCollapsiblePane*>(FindWindowByName("masksPane"));
masksPane->Hide();
}

if (id != XRCID("segmentTabButton")) {
wxStaticText* segmentTypeLabel = (wxStaticText*)FindWindowByName("segmentTypeLabel");
wxChoice* segmentType = (wxChoice*)FindWindowByName("segmentType");
Expand Down Expand Up @@ -5559,12 +5573,10 @@ void OutfitStudioFrame::OnTabButtonClick(wxCommandEvent& event) {
glView->SetGlobalBrushCollision();

GetMenuBar()->Check(XRCID("btnBrushCollision"), true);
GetMenuBar()->Check(XRCID("btnShowMask"), true);
GetMenuBar()->Enable(XRCID("btnBrushCollision"), true);
GetMenuBar()->Enable(XRCID("btnSelect"), true);
GetMenuBar()->Enable(XRCID("btnClearMask"), true);
GetMenuBar()->Enable(XRCID("btnInvertMask"), true);
GetMenuBar()->Enable(XRCID("btnShowMask"), true);
GetMenuBar()->Enable(XRCID("deleteVerts"), true);

GetToolBar()->ToggleTool(XRCID("btnBrushCollision"), true);
Expand Down Expand Up @@ -5592,12 +5604,10 @@ void OutfitStudioFrame::OnTabButtonClick(wxCommandEvent& event) {
glView->SetGlobalBrushCollision();

GetMenuBar()->Check(XRCID("btnBrushCollision"), true);
GetMenuBar()->Check(XRCID("btnShowMask"), true);
GetMenuBar()->Enable(XRCID("btnBrushCollision"), true);
GetMenuBar()->Enable(XRCID("btnSelect"), true);
GetMenuBar()->Enable(XRCID("btnClearMask"), true);
GetMenuBar()->Enable(XRCID("btnInvertMask"), true);
GetMenuBar()->Enable(XRCID("btnShowMask"), true);
GetMenuBar()->Enable(XRCID("deleteVerts"), true);

GetToolBar()->ToggleTool(XRCID("btnBrushCollision"), true);
Expand Down Expand Up @@ -5705,12 +5715,15 @@ void OutfitStudioFrame::OnTabButtonClick(wxCommandEvent& event) {
wxStateButton* segmentTabButton = (wxStateButton*)FindWindowByName("segmentTabButton");
wxStateButton* partitionTabButton = (wxStateButton*)FindWindowByName("partitionTabButton");
wxStateButton* lightsTabButton = (wxStateButton*)FindWindowByName("lightsTabButton");
wxCollapsiblePane* masksPane = dynamic_cast<wxCollapsiblePane*>(FindWindowByName("masksPane"));

boneTabButton->SetCheck(false);
colorsTabButton->SetCheck(false);
segmentTabButton->SetCheck(false);
partitionTabButton->SetCheck(false);
lightsTabButton->SetCheck(false);

masksPane->Show();
}
else if (id == XRCID("boneTabButton")) {
outfitShapes->Hide();
Expand Down Expand Up @@ -5892,7 +5905,6 @@ void OutfitStudioFrame::OnTabButtonClick(wxCommandEvent& event) {
GetMenuBar()->Check(XRCID("btnMaskBrush"), true);
GetMenuBar()->Check(XRCID("btnXMirror"), false);
GetMenuBar()->Check(XRCID("btnBrushCollision"), false);
GetMenuBar()->Check(XRCID("btnShowMask"), false);
GetMenuBar()->Enable(XRCID("btnSelect"), false);
GetMenuBar()->Enable(XRCID("btnTransform"), false);
GetMenuBar()->Enable(XRCID("btnPivot"), false);
Expand All @@ -5904,7 +5916,6 @@ void OutfitStudioFrame::OnTabButtonClick(wxCommandEvent& event) {
GetMenuBar()->Enable(XRCID("btnBrushCollision"), false);
GetMenuBar()->Enable(XRCID("btnClearMask"), false);
GetMenuBar()->Enable(XRCID("btnInvertMask"), false);
GetMenuBar()->Enable(XRCID("btnShowMask"), false);
GetMenuBar()->Enable(XRCID("deleteVerts"), false);

GetToolBar()->ToggleTool(XRCID("btnMaskBrush"), true);
Expand Down Expand Up @@ -5964,7 +5975,6 @@ void OutfitStudioFrame::OnTabButtonClick(wxCommandEvent& event) {
GetMenuBar()->Check(XRCID("btnMaskBrush"), true);
GetMenuBar()->Check(XRCID("btnXMirror"), false);
GetMenuBar()->Check(XRCID("btnBrushCollision"), false);
GetMenuBar()->Check(XRCID("btnShowMask"), false);
GetMenuBar()->Enable(XRCID("btnSelect"), false);
GetMenuBar()->Enable(XRCID("btnTransform"), false);
GetMenuBar()->Enable(XRCID("btnPivot"), false);
Expand All @@ -5976,7 +5986,6 @@ void OutfitStudioFrame::OnTabButtonClick(wxCommandEvent& event) {
GetMenuBar()->Enable(XRCID("btnBrushCollision"), false);
GetMenuBar()->Enable(XRCID("btnClearMask"), false);
GetMenuBar()->Enable(XRCID("btnInvertMask"), false);
GetMenuBar()->Enable(XRCID("btnShowMask"), false);
GetMenuBar()->Enable(XRCID("deleteVerts"), false);

GetToolBar()->ToggleTool(XRCID("btnMaskBrush"), true);
Expand Down Expand Up @@ -8513,6 +8522,76 @@ void OutfitStudioFrame::OnEditUV(wxCommandEvent& WXUNUSED(event)) {
}
}

void OutfitStudioFrame::OnSelectMask(wxCommandEvent& WXUNUSED(event)) {
wxChoice* cMaskName = (wxChoice*)FindWindowByName("cMaskName");
int maskSel = cMaskName->GetSelection();
if (maskSel != wxNOT_FOUND) {
auto maskData = (std::map<std::string, std::unordered_map<ushort, float>>*)cMaskName->GetClientData(maskSel);
for (auto mask : (*maskData)) {
glView->SetShapeMask(mask.second, mask.first);
}
}

glView->Render();
}

void OutfitStudioFrame::OnSaveMask(wxCommandEvent& WXUNUSED(event)) {
wxChoice* cMaskName = (wxChoice*)FindWindowByName("cMaskName");
int maskSel = cMaskName->GetSelection();
if (maskSel != wxNOT_FOUND) {
auto maskData = new std::map<std::string, std::unordered_map<ushort, float>>();

std::vector<std::string> shapes = GetShapeList();
for (auto &s : shapes) {
std::unordered_map<ushort, float> mask;
glView->GetShapeMask(mask, s);
(*maskData)[s] = std::move(mask);
}

cMaskName->SetClientData(maskSel, maskData);
}
else {
wxCommandEvent evt;
OnSaveAsMask(evt);
}
}

void OutfitStudioFrame::OnSaveAsMask(wxCommandEvent& WXUNUSED(event)) {
wxChoice* cMaskName = (wxChoice*)FindWindowByName("cMaskName");

wxString maskName;
do {
maskName = wxGetTextFromUser(_("Please enter a new unique name for the mask."), _("New Mask"));
if (maskName.empty())
return;

} while (cMaskName->FindString(maskName) != wxNOT_FOUND);

auto maskData = new std::map<std::string, std::unordered_map<ushort, float>>();

std::vector<std::string> shapes = GetShapeList();
for (auto &s : shapes) {
std::unordered_map<ushort, float> mask;
glView->GetShapeMask(mask, s);
(*maskData)[s] = std::move(mask);
}

cMaskName->Append(maskName, maskData);
}

void OutfitStudioFrame::OnDeleteMask(wxCommandEvent& WXUNUSED(event)) {
wxChoice* cMaskName = (wxChoice*)FindWindowByName("cMaskName");
int maskSel = cMaskName->GetSelection();
if (maskSel != wxNOT_FOUND) {
cMaskName->Delete(maskSel);
}
}

void OutfitStudioFrame::OnPaneCollapse(wxCollapsiblePaneEvent& WXUNUSED(event)) {
wxWindow* parentPanel = FindWindowByName("bottomSplitPanel");
parentPanel->Layout();
}

void OutfitStudioFrame::ApplyPose() {
for (auto &shape : project->GetWorkNif()->GetShapes()) {
std::vector<Vector3> verts;
Expand All @@ -8527,11 +8606,6 @@ void OutfitStudioFrame::ApplyPose() {
glView->Render();
}

void OutfitStudioFrame::OnPosePaneCollapse(wxCollapsiblePaneEvent& WXUNUSED(event)) {
wxWindow* parentPanel = FindWindowByName("bottomSplitPanel");
parentPanel->Layout();
}

AnimBone *OutfitStudioFrame::GetPoseBonePtr() {
int selind = cPoseBone->GetSelection();
if (selind == wxNOT_FOUND) return nullptr;
Expand Down
26 changes: 20 additions & 6 deletions src/program/OutfitStudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,21 @@ class wxGLPanel : public wxGLCanvas {
mask[i] = m->vcolors[i].x;
}

void SetShapeMask(std::unordered_map<ushort, float>& mask, const std::string& shapeName) {
mesh* m = gls.GetMesh(shapeName);
if (!m)
return;

for (int i = 0; i < m->nVerts; i++) {
if (mask.find(i) != mask.end())
m->vcolors[i].x = mask[i];
else
m->vcolors[i].x = 0.0f;
}

m->QueueUpdate(mesh::UpdateType::VertexColors);
}

void MaskLess() {
for (auto &m : gls.GetActiveMeshes()) {
std::set<int> unmaskPoints;
Expand Down Expand Up @@ -1273,11 +1288,6 @@ class OutfitStudioFrame : public wxFrame {
glView->Render();
}

void OnShowMask(wxCommandEvent& event) {
glView->SetMaskVisible(event.IsChecked());
glView->Render();
}

void OnIncBrush(wxCommandEvent& WXUNUSED(event)) {
if (glView->GetActiveBrush() && glView->GetBrushSize() < 1.0f) {
float v = glView->IncBrush() / 3.0f;
Expand Down Expand Up @@ -1353,8 +1363,12 @@ class OutfitStudioFrame : public wxFrame {
wxLaunchDefaultBrowser(url);
}

void OnSelectMask(wxCommandEvent& event);
void OnSaveMask(wxCommandEvent& event);
void OnSaveAsMask(wxCommandEvent& event);
void OnDeleteMask(wxCommandEvent& event);
void OnPaneCollapse(wxCollapsiblePaneEvent& event);
void ApplyPose();
void OnPosePaneCollapse(wxCollapsiblePaneEvent &event);
AnimBone *GetPoseBonePtr();
void PoseToGUI();
void OnPoseBoneChanged(wxCommandEvent& event);
Expand Down
2 changes: 1 addition & 1 deletion src/render/GLSurface.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class GLSurface {
bool bWireframe = false;
bool bLighting = true;
bool bTextured = true;
bool bMaskVisible = false;
bool bMaskVisible = true;
bool bWeightColors = false;
bool bVertexColors = false;
bool bSegmentColors = false;
Expand Down

0 comments on commit 2e05866

Please sign in to comment.