diff --git a/radiant/ui/surfaceinspector/SurfaceInspector.cpp b/radiant/ui/surfaceinspector/SurfaceInspector.cpp index 5f232d1b5b..b0d571f90b 100644 --- a/radiant/ui/surfaceinspector/SurfaceInspector.cpp +++ b/radiant/ui/surfaceinspector/SurfaceInspector.cpp @@ -161,9 +161,10 @@ void SurfaceInspector::connectEvents() { // Be sure to connect these signals BEFORE the buttons are connected // to the events, so that the doUpdate() call gets invoked after the actual event has been fired. - _fitTexture.fitButton->Bind(wxEVT_BUTTON, [=](wxCommandEvent&) { onFit(); }); + _fitTexture.fitButton->Bind(wxEVT_BUTTON, + [=](wxCommandEvent&) { onFit(Axis::BOTH); }); - _flipTexture.flipX->Connect(wxEVT_BUTTON, wxCommandEventHandler(SurfaceInspector::onUpdateAfterButtonClick), NULL, this); + _flipTexture.flipX->Connect(wxEVT_BUTTON, wxCommandEventHandler(SurfaceInspector::onUpdateAfterButtonClick), NULL, this); _flipTexture.flipY->Connect(wxEVT_BUTTON, wxCommandEventHandler(SurfaceInspector::onUpdateAfterButtonClick), NULL, this); _alignTexture.top->Connect(wxEVT_BUTTON, wxCommandEventHandler(SurfaceInspector::onUpdateAfterButtonClick), NULL, this); _alignTexture.bottom->Connect(wxEVT_BUTTON, wxCommandEventHandler(SurfaceInspector::onUpdateAfterButtonClick), NULL, this); @@ -217,7 +218,7 @@ void SurfaceInspector::keyChanged() _callbackActive = false; } -wxSpinCtrlDouble* SurfaceInspector::makeFitSpinBox() +wxSpinCtrlDouble* SurfaceInspector::makeFitSpinBox(Axis axis) { wxSpinCtrlDouble* box = new wxSpinCtrlDouble(this, wxID_ANY); @@ -229,7 +230,7 @@ wxSpinCtrlDouble* SurfaceInspector::makeFitSpinBox() box->SetDigits(2); // Perform a fit operation when the value changes - box->Bind(wxEVT_SPINCTRLDOUBLE, [=](wxSpinDoubleEvent&) { onFit(); }); + box->Bind(wxEVT_SPINCTRLDOUBLE, [=](wxSpinDoubleEvent&) { onFit(axis); }); return box; } @@ -240,13 +241,13 @@ wxBoxSizer* SurfaceInspector::createFitTextureRow() // Create widgets from left to right _fitTexture.label = new wxStaticText(this, wxID_ANY, _(LABEL_FIT_TEXTURE)); - _fitTexture.width = makeFitSpinBox(); + _fitTexture.width = makeFitSpinBox(Axis::X); _fitTexture.width->SetToolTip( "Number of whole texture images to fit horizontally. Use the spin " "buttons to change the value and apply the result immediately." ); _fitTexture.x = new wxStaticText(this, wxID_ANY, "x"); - _fitTexture.height = makeFitSpinBox(); + _fitTexture.height = makeFitSpinBox(Axis::Y); _fitTexture.height->SetToolTip( "Number of whole texture images to fit vertically. Use the spin " "buttons to change the value and apply the result immediately." @@ -615,15 +616,23 @@ void SurfaceInspector::doUpdate() ui::PatchInspector::Instance().queueUpdate(); } -void SurfaceInspector::fitTexture() +void SurfaceInspector::fitTexture(Axis axis) { + // If the preserve aspect button is disabled, we always fit on both axes + if (!_fitTexture.preserveAspectButton->GetValue()) + axis = Axis::BOTH; + double repeatX = _fitTexture.width->GetValue(); double repeatY = _fitTexture.height->GetValue(); if (repeatX > 0.0 && repeatY > 0.0) { - GlobalCommandSystem().executeCommand("FitTexture", repeatX, repeatY); - } + // User-specified fit values must always be >0, but we use -1 internally + // to signal not to fit on a particular axis. + GlobalCommandSystem().executeCommand("FitTexture", + (axis == Axis::Y ? -1 : repeatX), + (axis == Axis::X ? -1 : repeatY)); + } else { // Invalid repeatX && repeatY values @@ -631,10 +640,10 @@ void SurfaceInspector::fitTexture() } } -void SurfaceInspector::onFit() +void SurfaceInspector::onFit(Axis axis) { - // Call the according member method - fitTexture(); + // Fit the texture then update our widget values with the new transform + fitTexture(axis); doUpdate(); } diff --git a/radiant/ui/surfaceinspector/SurfaceInspector.h b/radiant/ui/surfaceinspector/SurfaceInspector.h index 76953def2f..1adc75ffbb 100644 --- a/radiant/ui/surfaceinspector/SurfaceInspector.h +++ b/radiant/ui/surfaceinspector/SurfaceInspector.h @@ -146,7 +146,6 @@ class SurfaceInspector : // Widget construction void populateWindow(); - wxSpinCtrlDouble* makeFitSpinBox(); wxBoxSizer* createFitTextureRow(); // Connect IEvents to the widgets @@ -161,15 +160,15 @@ class SurfaceInspector : // Applies the entered shader to the current selection void emitShader(); - // Executes the fit command for the selection - void fitTexture(); + // Fit texture on one or both axes + enum class Axis { X, Y, BOTH }; + wxSpinCtrlDouble* makeFitSpinBox(Axis axis); + void fitTexture(Axis axis); + void onFit(Axis axis); // The callback when the "select shader" button is pressed, opens the ShaderChooser dialog void onShaderSelect(wxCommandEvent& ev); - // The callback for the Fit Texture button - void onFit(); - // If any of the control button get clicked, an update is performed void onUpdateAfterButtonClick(wxCommandEvent& ev); diff --git a/radiantcore/brush/TextureProjection.cpp b/radiantcore/brush/TextureProjection.cpp index 7a98cda629..e38b0a1afe 100644 --- a/radiantcore/brush/TextureProjection.cpp +++ b/radiantcore/brush/TextureProjection.cpp @@ -169,10 +169,13 @@ void TextureProjection::transformLocked(std::size_t width, std::size_t height, c setTransform((float)width, (float)height, stTransformed2stOriginal); normalise((float)width, (float)height); - } +} // Fits a texture to a brush face -void TextureProjection::fitTexture(std::size_t width, std::size_t height, const Vector3& normal, const Winding& w, float s_repeat, float t_repeat) { +void TextureProjection::fitTexture(std::size_t width, std::size_t height, + const Vector3& normal, const Winding& w, + float s_repeat, float t_repeat) +{ if (w.size() < 3) { return; } @@ -198,7 +201,12 @@ void TextureProjection::fitTexture(std::size_t width, std::size_t height, const bounds.extents.z() = 1; // the bounds of a perfectly fitted texture transform - AABB perfect(Vector3(s_repeat * 0.5, t_repeat * 0.5, 0), Vector3(s_repeat * 0.5, t_repeat * 0.5, 1)); + AABB perfect(Vector3(s_repeat > 0 ? s_repeat * 0.5 : bounds.origin.x(), + t_repeat > 0 ? t_repeat * 0.5 : bounds.origin.y(), + 0), + Vector3(s_repeat > 0 ? s_repeat * 0.5 : bounds.extents.x(), + t_repeat > 0 ? t_repeat * 0.5 : bounds.extents.y(), + 1)); // the difference between the current texture transform and the perfectly fitted transform Matrix4 diffMatrix = Matrix4::getTranslation(bounds.origin - perfect.origin);