diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bafad417b..0bb5a0448a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,6 +79,7 @@ Bug #4888: Global variable stray explicit reference calls break script compilation Bug #4896: Title screen music doesn't loop Bug #4902: Using scrollbars in settings causes resolution to change + Bug #4904: Editor: Texture painting with duplicate of a base-version texture Bug #4911: Editor: QOpenGLContext::swapBuffers() warning with Qt5 Bug #4916: Specular power (shininess) material parameter is ignored when shaders are used. Bug #4918: Abilities don't play looping VFX when they're initially applied diff --git a/CHANGELOG_PR.md b/CHANGELOG_PR.md index 3062cc9d24..8862a8448c 100644 --- a/CHANGELOG_PR.md +++ b/CHANGELOG_PR.md @@ -101,6 +101,7 @@ Editor Bug Fixes: - Colour fields in interior-cell records now also use the colour picker widget (#4745) - Cloned, added, or moved instances no longer disappear at load-time (#4748) - "Clear" function in the content selector no longer tries to execute a "Remove" action on an empty file list (#4757) +- Terrain texture editing for plugins now correctly handles drags from base file (#4904) - Engine no longer tries to swap buffers of windows which weren't exposed to Qt's window management system (#4911) - Minimap doesn't get corrupted, when editing new omwgame (#5177) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index b8181eed59..6d682150a0 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -41,9 +41,9 @@ CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, osg::Group* parentNode, QWidget *parent) : EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent), mBrushTexture("L0#0"), - mBrushSize(0), + mBrushSize(1), mBrushShape(0), - mTextureBrushScenetool(0), + mTextureBrushScenetool(nullptr), mDragMode(InteractionType_None), mParentNode(parentNode), mIsEditing(false) @@ -82,7 +82,7 @@ void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) { toolbar->removeTool (mTextureBrushScenetool); delete mTextureBrushScenetool; - mTextureBrushScenetool = 0; + mTextureBrushScenetool = nullptr; } if (mTerrainTextureSelection) diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 0d670d725f..4176abefea 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -51,36 +51,37 @@ namespace CSVRender /// \brief Editmode for terrain texture grid TerrainTextureMode(WorldspaceWidget*, osg::Group* parentNode, QWidget* parent = nullptr); - void primaryOpenPressed (const WorldspaceHitResult& hit); + void primaryOpenPressed (const WorldspaceHitResult& hit) final; /// \brief Create single command for one-click texture editing - void primaryEditPressed (const WorldspaceHitResult& hit); + void primaryEditPressed (const WorldspaceHitResult& hit) final; /// \brief Open brush settings window - void primarySelectPressed(const WorldspaceHitResult&); + void primarySelectPressed(const WorldspaceHitResult&) final; - void secondarySelectPressed(const WorldspaceHitResult&); + void secondarySelectPressed(const WorldspaceHitResult&) final; - void activate(CSVWidget::SceneToolbar*); - void deactivate(CSVWidget::SceneToolbar*); + void activate(CSVWidget::SceneToolbar*) final; + void deactivate(CSVWidget::SceneToolbar*) final; /// \brief Start texture editing command macro - virtual bool primaryEditStartDrag (const QPoint& pos); + bool primaryEditStartDrag (const QPoint& pos) final; - virtual bool secondaryEditStartDrag (const QPoint& pos); - virtual bool primarySelectStartDrag (const QPoint& pos); - virtual bool secondarySelectStartDrag (const QPoint& pos); + bool secondaryEditStartDrag (const QPoint& pos) final; + bool primarySelectStartDrag (const QPoint& pos) final; + bool secondarySelectStartDrag (const QPoint& pos) final; /// \brief Handle texture edit behavior during dragging - virtual void drag (const QPoint& pos, int diffX, int diffY, double speedFactor); + void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) final; /// \brief End texture editing command macro - virtual void dragCompleted(const QPoint& pos); + void dragCompleted(const QPoint& pos) final; - virtual void dragAborted(); - virtual void dragWheel (int diff, double speedFactor); - virtual void dragMoveEvent (QDragMoveEvent *event); + void dragAborted() final; + void dragWheel (int diff, double speedFactor) final; + void dragMoveEvent (QDragMoveEvent *event) final; + private: /// \brief Handle brush mechanics, maths regarding worldspace hit etc. void editTerrainTextureGrid (const WorldspaceHitResult& hit); @@ -100,7 +101,6 @@ namespace CSVRender /// \brief Create new cell and land if needed bool allowLandTextureEditing(std::string textureFileName); - private: std::string mCellId; std::string mBrushTexture; int mBrushSize; @@ -113,7 +113,6 @@ namespace CSVRender std::unique_ptr mTerrainTextureSelection; const int cellSize {ESM::Land::REAL_SIZE}; - const int landSize {ESM::Land::LAND_SIZE}; const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE}; signals: diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index 2208f88a68..4081872795 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -33,19 +33,19 @@ CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent) - : QGroupBox(title, parent) + : QGroupBox(title, parent), + mLayoutSliderSize(new QHBoxLayout), + mBrushSizeSlider(new QSlider(Qt::Horizontal)), + mBrushSizeSpinBox(new QSpinBox) { - mBrushSizeSlider = new QSlider(Qt::Horizontal); mBrushSizeSlider->setTickPosition(QSlider::TicksBothSides); mBrushSizeSlider->setTickInterval(10); mBrushSizeSlider->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt()); mBrushSizeSlider->setSingleStep(1); - mBrushSizeSpinBox = new QSpinBox; mBrushSizeSpinBox->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt()); mBrushSizeSpinBox->setSingleStep(1); - mLayoutSliderSize = new QHBoxLayout; mLayoutSliderSize->addWidget(mBrushSizeSlider); mLayoutSliderSize->addWidget(mBrushSizeSpinBox); @@ -58,7 +58,7 @@ CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *p CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QWidget *parent) : QFrame(parent, Qt::Popup), mBrushShape(0), - mBrushSize(0), + mBrushSize(1), mBrushTexture("L0#0"), mDocument(document) { @@ -142,60 +142,61 @@ void CSVWidget::TextureBrushWindow::configureButtonInitialSettings(QPushButton * void CSVWidget::TextureBrushWindow::setBrushTexture(std::string brushTexture) { - mBrushTexture = brushTexture; + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + QUndoStack& undoStack = mDocument.getUndoStack(); CSMWorld::IdCollection& landtexturesCollection = mDocument.getData().getLandTextures(); - int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); - int columnModification = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Modification); - int index = landtexturesCollection.searchId(mBrushTexture); - // Check if texture exists in current plugin - if(landtexturesCollection.getData(index, columnModification).value() == 0) + int index = 0; + int pluginInDragged = 0; + CSMWorld::LandTexture::parseUniqueRecordId(brushTexture, pluginInDragged, index); + std::string newBrushTextureId = CSMWorld::LandTexture::createUniqueRecordId(0, index); + int rowInBase = landtexturesCollection.searchId(brushTexture); + int rowInNew = landtexturesCollection.searchId(newBrushTextureId); + + // Check if texture exists in current plugin, and clone if id found in base, otherwise reindex the texture + // TO-DO: Handle case when texture is not found in neither base or plugin properly (finding new index is not enough) + // TO-DO: Handle conflicting plugins properly + if (rowInNew == -1) { - CSMWorld::IdTable& ltexTable = dynamic_cast ( - *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); - - QUndoStack& undoStack = mDocument.getUndoStack(); - - QVariant textureFileNameVariant; - textureFileNameVariant.setValue(landtexturesCollection.getData(index, landTextureFilename).value()); - - std::size_t hashlocation = mBrushTexture.find("#"); - std::string mBrushTexturePlugin = "L0#" + mBrushTexture.substr (hashlocation+1); - int indexPlugin = landtexturesCollection.searchId(mBrushTexturePlugin); - - // Reindex texture if needed - if (indexPlugin != -1 && !landtexturesCollection.getRecord(indexPlugin).isDeleted()) + if (rowInBase == -1) { int counter=0; bool freeIndexFound = false; + const int maxCounter = std::numeric_limits::max() - 1; do { - const size_t maxCounter = std::numeric_limits::max() - 1; - mBrushTexturePlugin = CSMWorld::LandTexture::createUniqueRecordId(0, counter); - if (landtexturesCollection.searchId(mBrushTexturePlugin) != -1 && landtexturesCollection.getRecord(mBrushTexturePlugin).isDeleted() == 0) counter = (counter + 1) % maxCounter; + newBrushTextureId = CSMWorld::LandTexture::createUniqueRecordId(0, counter); + if (landtexturesCollection.searchId(brushTexture) != -1 && + landtexturesCollection.getRecord(brushTexture).isDeleted() == 0 && + landtexturesCollection.searchId(newBrushTextureId) != -1 && + landtexturesCollection.getRecord(newBrushTextureId).isDeleted() == 0) + counter = (counter + 1) % maxCounter; else freeIndexFound = true; - } while (freeIndexFound == false); + } while (freeIndexFound == false || counter < maxCounter); } undoStack.beginMacro ("Add land texture record"); - undoStack.push (new CSMWorld::CloneCommand (ltexTable, mBrushTexture, mBrushTexturePlugin, CSMWorld::UniversalId::Type_LandTexture)); + undoStack.push (new CSMWorld::CloneCommand (ltexTable, brushTexture, newBrushTextureId, CSMWorld::UniversalId::Type_LandTexture)); undoStack.endMacro(); - mBrushTexture = mBrushTexturePlugin; - emit passTextureId(mBrushTexture); } if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) { - mBrushTextureLabel = "Selected texture: " + mBrushTexture + " "; + mBrushTextureLabel = "Selected texture: " + newBrushTextureId + " "; mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel) + landtexturesCollection.getData(index, landTextureFilename).value()); } else { + newBrushTextureId = ""; mBrushTextureLabel = "No selected texture or invalid texture"; mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel)); } - emit passBrushShape(mBrushShape); // update icon + mBrushTexture = newBrushTextureId; + + emit passTextureId(mBrushTexture); + emit passBrushShape(mBrushShape); // updates the icon tooltip } void CSVWidget::TextureBrushWindow::setBrushSize(int brushSize)