From 2dca389a3b00dd32697bd16703c47e29074dea6d Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Fri, 30 Mar 2018 19:56:46 +0300 Subject: [PATCH 01/50] Extend magic resistance/weakness to all effects that can be resisted (fixes #4309) --- apps/openmw/mwmechanics/spellcasting.cpp | 78 +++++++++++------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index d864dc619..48ff64829 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -222,45 +222,42 @@ namespace MWMechanics magicEffects = effects; float resisted = 0; - if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful) - { - // Effects with no resistance attribute belonging to them can not be resisted - if (ESM::MagicEffect::getResistanceEffect(effectId) == -1) - return 0.f; + // Effects with no resistance attribute belonging to them can not be resisted + if (ESM::MagicEffect::getResistanceEffect(effectId) == -1) + return 0.f; - float resistance = getEffectResistanceAttribute(effectId, magicEffects); + float resistance = getEffectResistanceAttribute(effectId, magicEffects); - int willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified(); - float luck = static_cast(stats.getAttribute(ESM::Attribute::Luck).getModified()); - float x = (willpower + 0.1f * luck) * stats.getFatigueTerm(); + int willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified(); + float luck = static_cast(stats.getAttribute(ESM::Attribute::Luck).getModified()); + float x = (willpower + 0.1f * luck) * stats.getFatigueTerm(); - // This makes spells that are easy to cast harder to resist and vice versa - float castChance = 100.f; - if (spell != NULL && !caster.isEmpty() && caster.getClass().isActor()) - { - castChance = getSpellSuccessChance(spell, caster, NULL, false); // Uncapped casting chance - } - if (castChance > 0) - x *= 50 / castChance; + // This makes spells that are easy to cast harder to resist and vice versa + float castChance = 100.f; + if (spell != NULL && !caster.isEmpty() && caster.getClass().isActor()) + { + castChance = getSpellSuccessChance(spell, caster, NULL, false); // Uncapped casting chance + } + if (castChance > 0) + x *= 50 / castChance; - float roll = Misc::Rng::rollClosedProbability() * 100; - if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude) - roll -= resistance; + float roll = Misc::Rng::rollClosedProbability() * 100; + if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude) + roll -= resistance; - if (x <= roll) - x = 0; + if (x <= roll) + x = 0; + else + { + if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude) + x = 100; else - { - if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude) - x = 100; - else - x = roll / std::min(x, 100.f); - } + x = roll / std::min(x, 100.f); + } - x = std::min(x + resistance, 100.f); + x = std::min(x + resistance, 100.f); - resisted = x; - } + resisted = x; return resisted; } @@ -458,13 +455,11 @@ namespace MWMechanics } float magnitudeMult = 1; - if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful && target.getClass().isActor()) - { - if (absorbed) - continue; - // Try reflecting - if (!reflected && !caster.isEmpty() && caster != target && !(magicEffect->mData.mFlags & ESM::MagicEffect::Unreflectable)) + if (!absorbed) + { + // Reflect harmful effects + if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful && !reflected && !caster.isEmpty() && caster != target && !(magicEffect->mData.mFlags & ESM::MagicEffect::Unreflectable)) { float reflect = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::Reflect).getMagnitude(); bool isReflected = (Misc::Rng::roll0to99() < reflect); @@ -488,13 +483,14 @@ namespace MWMechanics else if (castByPlayer) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicTargetResisted}"); } - - // If player is attempting to cast a harmful spell, show the target's HP bar - if (castByPlayer && target != caster) + else if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful && castByPlayer && target != caster) + { + // If player is attempting to cast a harmful spell and it wasn't fully resisted, show the target's HP bar MWBase::Environment::get().getWindowManager()->setEnemy(target); + } // Notify the target actor they've been hit - if (target != caster && !caster.isEmpty()) + if (target != caster && !caster.isEmpty() && magicEffect->mData.mFlags & ESM::MagicEffect::Harmful) target.getClass().onHit(target, 0.0f, true, MWWorld::Ptr(), caster, osg::Vec3f(), true); } From 4ae75d1d20e6b3ef1de43cab5f9f29d281865af5 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 15 Apr 2018 14:47:31 +0300 Subject: [PATCH 02/50] Terrain texture brush frame --- apps/opencs/CMakeLists.txt | 2 +- .../view/render/pagedworldspacewidget.cpp | 3 +- .../opencs/view/render/terraintexturemode.cpp | 214 ++++++++++++++++++ .../opencs/view/render/terraintexturemode.hpp | 108 +++++++++ apps/opencs/view/render/worldspacewidget.cpp | 3 + apps/opencs/view/widget/scenetoolmode.cpp | 9 + apps/opencs/view/widget/scenetoolmode.hpp | 4 + files/opencs/resources.qrc | 8 +- 8 files changed, 347 insertions(+), 4 deletions(-) create mode 100644 apps/opencs/view/render/terraintexturemode.cpp create mode 100644 apps/opencs/view/render/terraintexturemode.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f07b518a9..f8dd1fe2d 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -88,7 +88,7 @@ opencs_units (view/render scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget previewwidget editmode instancemode instanceselectionmode instancemovemode orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller - cellwater + cellwater terraintexturemode ) opencs_units_noqt (view/render diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 4a745195b..1d1a7cd17 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -21,6 +21,7 @@ #include "mask.hpp" #include "cameracontroller.hpp" #include "cellarrow.hpp" +#include "terraintexturemode.hpp" bool CSVRender::PagedWorldspaceWidget::adjustCells() { @@ -136,7 +137,7 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons ( new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain shape editing"), "terrain-shape"); tool->addButton ( - new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain texture editing"), + new TerrainTextureMode (this, tool), "terrain-texture"); tool->addButton ( new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain vertex paint editing"), diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp new file mode 100644 index 000000000..346ba3136 --- /dev/null +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -0,0 +1,214 @@ +// To-do: Getting Texture Id and Texture Filenames to base class Terraintexturemode +// To-do: Better data handling options for mBrushTexture +// To-do: loading texture bitmaps from virtual file system (vfs) for texture overlay icon + +#include "terraintexturemode.hpp" +#include "editmode.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../widget/modebutton.hpp" +#include "../widget/scenetoolbar.hpp" + +#include "../../model/world/universalid.hpp" +#include "../../model/world/tablemimedata.hpp" + +#include "pagedworldspacewidget.hpp" + + +CSVRender::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent) + : QGroupBox(title, parent) +{ + brushSizeSlider = new QSlider(Qt::Horizontal); + brushSizeSlider->setTickPosition(QSlider::TicksBothSides); + brushSizeSlider->setTickInterval(10); + brushSizeSlider->setSingleStep(1); + + brushSizeSpinBox = new QSpinBox; + brushSizeSpinBox->setRange(1, 100); + brushSizeSpinBox->setSingleStep(1); + + layoutSliderSize = new QHBoxLayout; + layoutSliderSize->addWidget(brushSizeSlider); + layoutSliderSize->addWidget(brushSizeSpinBox); + + connect(brushSizeSlider, SIGNAL(valueChanged(int)), brushSizeSpinBox, SLOT(setValue(int))); + connect(brushSizeSpinBox, SIGNAL(valueChanged(int)), brushSizeSlider, SLOT(setValue(int))); + + setLayout(layoutSliderSize); +} + +CSVRender::TextureBrushButton::TextureBrushButton (const QIcon & icon, const QString & text, QWidget * parent) + : QPushButton(icon, text, parent) +{ +} + +CSVRender::TextureBrushWindow::TextureBrushWindow(WorldspaceWidget *worldspaceWidget, QWidget *parent) + : QFrame(parent, Qt::Popup), mWorldspaceWidget (worldspaceWidget) +{ + mBrushTextureLabel = "Brush: " + mBrushTexture; + selectedBrush = new QLabel(QString::fromUtf8(mBrushTextureLabel.c_str()), this); + + const std::string& iconPoint = ":scenetoolbar/brush-point"; + const std::string& iconSquare = ":scenetoolbar/brush-square"; + const std::string& iconCircle = ":scenetoolbar/brush-circle"; + const std::string& iconCustom = ":scenetoolbar/brush-custom"; + + TextureBrushButton *buttonPoint = new TextureBrushButton(QIcon (QPixmap (iconPoint.c_str())), "", this); + TextureBrushButton *buttonSquare = new TextureBrushButton(QIcon (QPixmap (iconSquare.c_str())), "", this); + TextureBrushButton *buttonCircle = new TextureBrushButton(QIcon (QPixmap (iconCircle.c_str())), "", this); + TextureBrushButton *buttonCustom = new TextureBrushButton(QIcon (QPixmap (iconCustom.c_str())), "", this); + + QVBoxLayout *layoutMain = new QVBoxLayout; + layoutMain->setSpacing(0); + + QHBoxLayout *layoutHorizontal = new QHBoxLayout; + layoutHorizontal->setContentsMargins (QMargins (0, 0, 0, 0)); + layoutHorizontal->setSpacing(0); + + configureButtonInitialSettings(buttonPoint); + configureButtonInitialSettings(buttonSquare); + configureButtonInitialSettings(buttonCircle); + configureButtonInitialSettings(buttonCustom); + + QButtonGroup* brushButtonGroup = new QButtonGroup(this); + brushButtonGroup->addButton(buttonPoint); + brushButtonGroup->addButton(buttonSquare); + brushButtonGroup->addButton(buttonCircle); + brushButtonGroup->addButton(buttonCustom); + + brushButtonGroup->setExclusive(true); + + layoutHorizontal->addWidget(buttonPoint); + layoutHorizontal->addWidget(buttonSquare); + layoutHorizontal->addWidget(buttonCircle); + layoutHorizontal->addWidget(buttonCustom); + + horizontalGroupBox = new QGroupBox(tr("")); + horizontalGroupBox->setLayout(layoutHorizontal); + + BrushSizeControls* sizeSliders = new BrushSizeControls(tr(""), this); + + layoutMain->addWidget(horizontalGroupBox); + layoutMain->addWidget(sizeSliders); + layoutMain->addWidget(selectedBrush); + + setLayout(layoutMain); + + connect(parent, SIGNAL(passBrushTexture(std::string)), this, SLOT(getBrushTexture(std::string))); +} + +void CSVRender::TextureBrushWindow::configureButtonInitialSettings(TextureBrushButton *button) +{ + button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); + button->setContentsMargins (QMargins (0, 0, 0, 0)); + button->setIconSize (QSize (48-6, 48-6)); + button->setFixedSize (48, 48); + button->setAcceptDrops(true); + button->setCheckable(true); +} + +void CSVRender::TextureBrushWindow::getBrushTexture(std::string brushTexture) +{ + mBrushTexture = brushTexture; + mBrushTextureLabel = "Brush:" + mBrushTexture; + selectedBrush->setText(QString::fromUtf8(mBrushTextureLabel.c_str())); +} + +CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) +: EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent) +, textureBrushWindow(new TextureBrushWindow(worldspaceWidget, this)) +{ + connect(parent, SIGNAL(passEvent(QDragEnterEvent*)), this, SLOT(handleDragEnterEvent(QDragEnterEvent*))); + connect(parent, SIGNAL(passEvent(QDropEvent*)), this, SLOT(handleDropEvent(QDropEvent*))); +} + +void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) +{ + EditMode::activate(toolbar); +} + +void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) +{ + EditMode::deactivate(toolbar); +} + +void CSVRender::TerrainTextureMode::primarySelectPressed(const WorldspaceHitResult& hit) +{ + QPoint position = QCursor::pos(); + textureBrushWindow->move (position); + textureBrushWindow->show(); +} + +void CSVRender::TerrainTextureMode::secondarySelectPressed(const WorldspaceHitResult& hit) +{ +} + +bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) +{ + return false; +} + +bool CSVRender::TerrainTextureMode::secondaryEditStartDrag (const QPoint& pos) +{ + return false; +} + +bool CSVRender::TerrainTextureMode::primarySelectStartDrag (const QPoint& pos) +{ + return false; +} + +bool CSVRender::TerrainTextureMode::secondarySelectStartDrag (const QPoint& pos) +{ + return false; +} + +void CSVRender::TerrainTextureMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor) { +} + +void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos) { +} + +void CSVRender::TerrainTextureMode::dragAborted() { +} + +void CSVRender::TerrainTextureMode::dragWheel (int diff, double speedFactor) {} + +void CSVRender::TerrainTextureMode::handleDragEnterEvent (QDragEnterEvent *event) { + event->accept(); +} + +void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) { + const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + + if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped + return; + + if (mime->holdsType (CSMWorld::UniversalId::Type_LandTexture)) + { + const std::vector ids = mime->getData(); + + for (const CSMWorld::UniversalId& uid : ids) + { + mBrushTexture = uid.getId(); + emit passBrushTexture(mBrushTexture); + } + } +} + +void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) { +} diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp new file mode 100644 index 000000000..809816047 --- /dev/null +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -0,0 +1,108 @@ +#ifndef CSV_RENDER_TERRAINTEXTUREMODE_H +#define CSV_RENDER_TERRAINTEXTUREMODE_H + +#include "editmode.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CSVWidget +{ + class SceneToolMode; +} + +namespace CSVRender +{ + class BrushSizeControls : public QGroupBox + { + Q_OBJECT + + public: + BrushSizeControls(const QString &title, QWidget *parent); + + private: + QSlider *brushSizeSlider; + QSpinBox *brushSizeSpinBox; + QHBoxLayout *layoutSliderSize; + }; + + class TextureBrushButton : public QPushButton + { + Q_OBJECT + + public: + TextureBrushButton (const QIcon& icon, const QString& tooltip = "", + QWidget *parent = 0); + }; + + class TextureBrushWindow : public QFrame + { + Q_OBJECT + + public: + TextureBrushWindow(WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); + void configureButtonInitialSettings(TextureBrushButton *button); + + private: + QLabel *selectedBrush; + QGroupBox *horizontalGroupBox; + int mButtonSize; + int mIconSize; + WorldspaceWidget *mWorldspaceWidget; + std::string mBrushTexture; + std::string mBrushTextureLabel; + + public slots: + void getBrushTexture(std::string brushTexture); + }; + + class TerrainTextureMode : public EditMode + { + Q_OBJECT + + public: + std::string mBrushTexture; + + TerrainTextureMode(WorldspaceWidget*, QWidget* parent = nullptr); + + void primarySelectPressed(const WorldspaceHitResult&); + void secondarySelectPressed(const WorldspaceHitResult&); + + void activate(CSVWidget::SceneToolbar*); + void deactivate(CSVWidget::SceneToolbar*); + + virtual bool primaryEditStartDrag (const QPoint& pos); + virtual bool secondaryEditStartDrag (const QPoint& pos); + virtual bool primarySelectStartDrag (const QPoint& pos); + virtual bool secondarySelectStartDrag (const QPoint& pos); + virtual void drag (const QPoint& pos, int diffX, int diffY, double speedFactor); + virtual void dragCompleted(const QPoint& pos); + virtual void dragAborted(); + virtual void dragWheel (int diff, double speedFactor); + virtual void dragMoveEvent (QDragMoveEvent *event); + + private: + TextureBrushWindow *textureBrushWindow; + + signals: + + void passBrushTexture(std::string brushTexture); + + public slots: + void handleDragEnterEvent (QDragEnterEvent *event); + void handleDropEvent(QDropEvent *event); + }; +} + + +#endif diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index af53c86f0..f3b781080 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -577,6 +577,9 @@ void CSVRender::WorldspaceWidget::debugProfileAboutToBeRemoved (const QModelInde void CSVRender::WorldspaceWidget::editModeChanged (const std::string& id) { dynamic_cast (*mEditMode->getCurrent()).setEditLock (mLocked); + if (mEditMode->getCurrentId() == "terrain-texture") mEditMode->setAcceptDrops(true); + else mEditMode->setAcceptDrops(false); + mDragging = false; mDragMode = InteractionType_None; } diff --git a/apps/opencs/view/widget/scenetoolmode.cpp b/apps/opencs/view/widget/scenetoolmode.cpp index 7b2ff64db..80104515b 100644 --- a/apps/opencs/view/widget/scenetoolmode.cpp +++ b/apps/opencs/view/widget/scenetoolmode.cpp @@ -144,6 +144,15 @@ bool CSVWidget::SceneToolMode::event(QEvent* event) return SceneTool::event(event); } +void CSVWidget::SceneToolMode::dragEnterEvent (QDragEnterEvent *event) +{ + emit passEvent(event); +} +void CSVWidget::SceneToolMode::dropEvent (QDropEvent *event) +{ + emit passEvent(event); +} + void CSVWidget::SceneToolMode::selected() { std::map::iterator iter = diff --git a/apps/opencs/view/widget/scenetoolmode.hpp b/apps/opencs/view/widget/scenetoolmode.hpp index 90f1dc419..84fcf59a7 100644 --- a/apps/opencs/view/widget/scenetoolmode.hpp +++ b/apps/opencs/view/widget/scenetoolmode.hpp @@ -47,6 +47,8 @@ namespace CSVWidget protected: bool event(QEvent* event); + void dragEnterEvent (QDragEnterEvent *event); + void dropEvent (QDropEvent *event); public: @@ -72,6 +74,8 @@ namespace CSVWidget signals: void modeChanged (const std::string& id); + void passEvent (QDragEnterEvent *event); + void passEvent (QDropEvent *event); private slots: diff --git a/files/opencs/resources.qrc b/files/opencs/resources.qrc index bfa256faf..0afd855f9 100644 --- a/files/opencs/resources.qrc +++ b/files/opencs/resources.qrc @@ -68,7 +68,7 @@ record-preview.png record-clone.png record-add.png - resources-icon.png + resources-icon.png resources-mesh.png resources-music.png resources-sound.png @@ -149,6 +149,10 @@ transform-scale.png selection-mode-cube.png selection-mode-cube-corner.png - selection-mode-cube-sphere.png + selection-mode-cube-sphere.png + brush-point.png + brush-square.png + brush-circle.png + brush-custom.png From 4649d1258c03dcc9f653e011e69859855409157b Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 15 Apr 2018 18:49:33 +0300 Subject: [PATCH 03/50] Direct data terrain editing --- .../opencs/view/render/terraintexturemode.cpp | 146 ++++++++++++++++-- .../opencs/view/render/terraintexturemode.hpp | 33 +++- 2 files changed, 166 insertions(+), 13 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 346ba3136..3d3175b8d 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -25,10 +25,35 @@ #include "../../model/world/universalid.hpp" #include "../../model/world/tablemimedata.hpp" +#include "../../model/world/idtable.hpp" #include "pagedworldspacewidget.hpp" +#include "../../model/doc/document.hpp" +#include "../../model/world/land.hpp" +#include "../../model/world/landtexture.hpp" +//#include "../../model/world/universalid.hpp" +//#include "../../model/world/tablemimedata.hpp" +//#include "../../model/world/idtable.hpp" + +#include "../../model/world/columnbase.hpp" +#include "../../model/world/resourcetable.hpp" +#include "../../model/world/commandmacro.hpp" +#include "../../model/world/data.hpp" +#include "../../model/world/commands.hpp" + +//#include +//#include + +//#include +#include +//#include +//#include +//#include + + + CSVRender::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent) : QGroupBox(title, parent) { @@ -62,16 +87,6 @@ CSVRender::TextureBrushWindow::TextureBrushWindow(WorldspaceWidget *worldspaceWi mBrushTextureLabel = "Brush: " + mBrushTexture; selectedBrush = new QLabel(QString::fromUtf8(mBrushTextureLabel.c_str()), this); - const std::string& iconPoint = ":scenetoolbar/brush-point"; - const std::string& iconSquare = ":scenetoolbar/brush-square"; - const std::string& iconCircle = ":scenetoolbar/brush-circle"; - const std::string& iconCustom = ":scenetoolbar/brush-custom"; - - TextureBrushButton *buttonPoint = new TextureBrushButton(QIcon (QPixmap (iconPoint.c_str())), "", this); - TextureBrushButton *buttonSquare = new TextureBrushButton(QIcon (QPixmap (iconSquare.c_str())), "", this); - TextureBrushButton *buttonCircle = new TextureBrushButton(QIcon (QPixmap (iconCircle.c_str())), "", this); - TextureBrushButton *buttonCustom = new TextureBrushButton(QIcon (QPixmap (iconCustom.c_str())), "", this); - QVBoxLayout *layoutMain = new QVBoxLayout; layoutMain->setSpacing(0); @@ -108,6 +123,13 @@ CSVRender::TextureBrushWindow::TextureBrushWindow(WorldspaceWidget *worldspaceWi setLayout(layoutMain); + connect(buttonPoint, SIGNAL(clicked()), this, SLOT(setBrushShape())); + connect(buttonSquare, SIGNAL(clicked()), this, SLOT(setBrushShape())); + connect(buttonCircle, SIGNAL(clicked()), this, SLOT(setBrushShape())); + connect(buttonCustom, SIGNAL(clicked()), this, SLOT(setBrushShape())); + + connect(sizeSliders->brushSizeSlider, SIGNAL(valueChanged(int)), parent, SLOT(setBrushSize(int))); + connect(parent, SIGNAL(passBrushTexture(std::string)), this, SLOT(getBrushTexture(std::string))); } @@ -128,12 +150,29 @@ void CSVRender::TextureBrushWindow::getBrushTexture(std::string brushTexture) selectedBrush->setText(QString::fromUtf8(mBrushTextureLabel.c_str())); } +void CSVRender::TextureBrushWindow::setBrushSize(int brushSize) +{ + mBrushSize = brushSize; + emit passBrushSize(mBrushSize); +} + +void CSVRender::TextureBrushWindow::setBrushShape() +{ + if(buttonPoint->isChecked()) mBrushShape = 0; + if(buttonSquare->isChecked()) mBrushShape = 1; + if(buttonCircle->isChecked()) mBrushShape = 2; + if(buttonCustom->isChecked()) mBrushShape = 3; + emit passBrushShape(mBrushShape); +} + CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) : EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent) , textureBrushWindow(new TextureBrushWindow(worldspaceWidget, this)) { connect(parent, SIGNAL(passEvent(QDragEnterEvent*)), this, SLOT(handleDragEnterEvent(QDragEnterEvent*))); connect(parent, SIGNAL(passEvent(QDropEvent*)), this, SLOT(handleDropEvent(QDropEvent*))); + connect(textureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int))); + connect(textureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); } void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) @@ -146,6 +185,83 @@ void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) EditMode::deactivate(toolbar); } +void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult& hit) // Apply changes here +{ + cellId = getWorldspaceWidget().getCellId (hit.worldPos); + std::string hash = "#"; + std::string space = " "; + std::size_t hashlocation = cellId.find(hash); + std::size_t spacelocation = cellId.find(space); + std::string slicedX = cellId.substr (hashlocation+1, spacelocation-hashlocation); + std::string slicedY = cellId.substr (spacelocation+1); + CSMWorld::CellCoordinates mCoordinates(stoi(slicedX), stoi(slicedY)); + + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( +*document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + /*CSMWorld::IdTable& ltexTable = dynamic_cast ( +*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));*/ + + int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex); + CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(cellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + + int xInCell {(hit.worldPos.x() - (stoi(slicedX)* cellSize)) * landTextureSize / cellSize}; + int yInCell {(hit.worldPos.y() - (stoi(slicedY)* cellSize)) * landTextureSize / cellSize}; + + hashlocation = mBrushTexture.find(hash); + std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1); + int brushInt = stoi(mBrushTexture.substr (hashlocation+1)); + + if (mBrushShape == 0) mNew[yInCell*landTextureSize+xInCell] = brushInt; + if (mBrushShape == 1) + { + for(int i=-mBrushSize/2;i= 0 && yInCell+j >= 0 && xInCell+i <= 15 && yInCell+j <= 15) + mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; + } + } + } + float distance = 0; + if (mBrushShape == 2) + { + float rf = mBrushSize/2; + int r = (mBrushSize/2)+1; + int r2 = r * r; + for(int i = -r; i < r; i++) + { + for(int j = -r; j < r; j++) + { + distance = std::round(sqrt(pow((xInCell+i)-xInCell, 2) + pow((yInCell+j)-yInCell, 2))); + if (xInCell+i >= 0 && yInCell+j >= 0 && xInCell+i <= 15 && yInCell+j <= 15 && distance <= rf) + mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; + } + } + } + if (mBrushShape == 3) + { + // Not implemented + } + + // Modify data, this should be done via command system! + QVariant variant; + variant.setValue(mNew); + landTable.setData(landTable.getModelIndex(cellId, textureColumn), variant); + + // Reference + /*CSMWorld::ModifyLandTexturesCommand::ModifyLandTexturesCommand(IdTable& landTable, + IdTable& ltexTable, QUndoCommand* parent)*/ + + // Reference + /*CSMWorld::DeleteCommand* command = new CSMWorld::DeleteCommand(referencesTable, + static_cast(iter->get())->mObject->getReferenceId()); + + getWorldspaceWidget().getDocument().getUndoStack().push(command);*/ +} + void CSVRender::TerrainTextureMode::primarySelectPressed(const WorldspaceHitResult& hit) { QPoint position = QCursor::pos(); @@ -212,3 +328,13 @@ void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) { void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) { } + +void CSVRender::TerrainTextureMode::setBrushSize(int brushSize) +{ + mBrushSize = brushSize; +} + +void CSVRender::TerrainTextureMode::setBrushShape(int brushShape) +{ + mBrushShape = brushShape; +} diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 809816047..fff5b7dae 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -16,6 +16,9 @@ #include #include +#include "../../model/world/data.hpp" +#include "../../model/world/land.hpp" + namespace CSVWidget { class SceneToolMode; @@ -29,9 +32,9 @@ namespace CSVRender public: BrushSizeControls(const QString &title, QWidget *parent); + QSlider *brushSizeSlider; private: - QSlider *brushSizeSlider; QSpinBox *brushSizeSpinBox; QHBoxLayout *layoutSliderSize; }; @@ -53,10 +56,17 @@ namespace CSVRender TextureBrushWindow(WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); void configureButtonInitialSettings(TextureBrushButton *button); + TextureBrushButton *buttonPoint = new TextureBrushButton(QIcon (QPixmap (":scenetoolbar/brush-point")), "", this); + TextureBrushButton *buttonSquare = new TextureBrushButton(QIcon (QPixmap (":scenetoolbar/brush-square")), "", this); + TextureBrushButton *buttonCircle = new TextureBrushButton(QIcon (QPixmap (":scenetoolbar/brush-circle")), "", this); + TextureBrushButton *buttonCustom = new TextureBrushButton(QIcon (QPixmap (":scenetoolbar/brush-custom")), "", this); + private: QLabel *selectedBrush; QGroupBox *horizontalGroupBox; int mButtonSize; + int mBrushSize = 0; + int mBrushShape = 0; int mIconSize; WorldspaceWidget *mWorldspaceWidget; std::string mBrushTexture; @@ -64,6 +74,12 @@ namespace CSVRender public slots: void getBrushTexture(std::string brushTexture); + void setBrushShape(); + void setBrushSize(int brushSize); + + signals: + void passBrushSize (int brushSize); + void passBrushShape(int brushShape); }; class TerrainTextureMode : public EditMode @@ -71,10 +87,11 @@ namespace CSVRender Q_OBJECT public: - std::string mBrushTexture; TerrainTextureMode(WorldspaceWidget*, QWidget* parent = nullptr); + void primaryEditPressed (const WorldspaceHitResult& hit); + void primarySelectPressed(const WorldspaceHitResult&); void secondarySelectPressed(const WorldspaceHitResult&); @@ -93,14 +110,24 @@ namespace CSVRender private: TextureBrushWindow *textureBrushWindow; + std::string cellId; + std::string mBrushTexture = "#0"; + int mBrushSize = 0; + int mBrushShape = 0; - signals: + const int cellSize {ESM::Land::REAL_SIZE}; + const int landSize {ESM::Land::LAND_SIZE}; + const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE}; + signals: void passBrushTexture(std::string brushTexture); public slots: void handleDragEnterEvent (QDragEnterEvent *event); void handleDropEvent(QDropEvent *event); + void setBrushSize(int brushSize); + void setBrushShape(int brushShape); + }; } From 316d05bdc4bd10a776b44e1d0cd14776ca175ac4 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 15 Apr 2018 22:17:38 +0300 Subject: [PATCH 04/50] {} to () --- apps/opencs/view/render/terraintexturemode.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 3d3175b8d..76f018177 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -206,8 +206,8 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(cellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - int xInCell {(hit.worldPos.x() - (stoi(slicedX)* cellSize)) * landTextureSize / cellSize}; - int yInCell {(hit.worldPos.y() - (stoi(slicedY)* cellSize)) * landTextureSize / cellSize}; + int xInCell ((hit.worldPos.x() - (stoi(slicedX)* cellSize)) * landTextureSize / cellSize); + int yInCell ((hit.worldPos.y() - (stoi(slicedY)* cellSize)) * landTextureSize / cellSize); hashlocation = mBrushTexture.find(hash); std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1); @@ -225,12 +225,11 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult } } } - float distance = 0; + float distance = 1; if (mBrushShape == 2) { float rf = mBrushSize/2; - int r = (mBrushSize/2)+1; - int r2 = r * r; + int r = (mBrushSize/2)+1; for(int i = -r; i < r; i++) { for(int j = -r; j < r; j++) From cc415526b0e2eec09f49564fea829ecea2ecb4c7 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Mon, 16 Apr 2018 11:42:55 +0300 Subject: [PATCH 05/50] fix texture index +1, better icons --- apps/opencs/view/render/terraintexturemode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 76f018177..1c331f1ec 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -211,7 +211,7 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult hashlocation = mBrushTexture.find(hash); std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1); - int brushInt = stoi(mBrushTexture.substr (hashlocation+1)); + int brushInt = stoi(mBrushTexture.substr (hashlocation+1))+1; // All indices are offset by +1 if (mBrushShape == 0) mNew[yInCell*landTextureSize+xInCell] = brushInt; if (mBrushShape == 1) @@ -225,7 +225,7 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult } } } - float distance = 1; + float distance = 0; if (mBrushShape == 2) { float rf = mBrushSize/2; From a54a1b994013a03633e2e04b479452dc6c59cea3 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Tue, 17 Apr 2018 17:11:43 +0300 Subject: [PATCH 06/50] Command system and undo --- .../opencs/view/render/terraintexturemode.cpp | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 1c331f1ec..8933b5038 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -199,8 +199,8 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult CSMDoc::Document& document = getWorldspaceWidget().getDocument(); CSMWorld::IdTable& landTable = dynamic_cast ( *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); - /*CSMWorld::IdTable& ltexTable = dynamic_cast ( -*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));*/ + CSMWorld::IdTable& ltexTable = dynamic_cast ( +*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex); CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(cellId, textureColumn)).value(); @@ -245,20 +245,16 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult // Not implemented } - // Modify data, this should be done via command system! QVariant variant; variant.setValue(mNew); - landTable.setData(landTable.getModelIndex(cellId, textureColumn), variant); - // Reference - /*CSMWorld::ModifyLandTexturesCommand::ModifyLandTexturesCommand(IdTable& landTable, - IdTable& ltexTable, QUndoCommand* parent)*/ + CSMWorld::CommandMacro macro (document.getUndoStack(), "Edit texture records"); + QModelIndex index(landTable.getModelIndex (cellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex))); - // Reference - /*CSMWorld::DeleteCommand* command = new CSMWorld::DeleteCommand(referencesTable, - static_cast(iter->get())->mObject->getReferenceId()); - - getWorldspaceWidget().getDocument().getUndoStack().push(command);*/ + CSMWorld::TouchLandCommand* ltexTouch = new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId); + CSMWorld::ModifyCommand* ltexModify = new CSMWorld::ModifyCommand(landTable, index, variant); + macro.push (ltexTouch); + macro.push (ltexModify); } void CSVRender::TerrainTextureMode::primarySelectPressed(const WorldspaceHitResult& hit) From 3327d6f7c47639fb951e3dc98b6cc9bec830bfe5 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Tue, 17 Apr 2018 20:48:58 +0300 Subject: [PATCH 07/50] Drag terrain painting, code cleanup --- .../opencs/view/render/terraintexturemode.cpp | 177 +++++++++--------- .../opencs/view/render/terraintexturemode.hpp | 4 +- 2 files changed, 88 insertions(+), 93 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 8933b5038..79973b806 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -1,7 +1,3 @@ -// To-do: Getting Texture Id and Texture Filenames to base class Terraintexturemode -// To-do: Better data handling options for mBrushTexture -// To-do: loading texture bitmaps from virtual file system (vfs) for texture overlay icon - #include "terraintexturemode.hpp" #include "editmode.hpp" @@ -23,35 +19,25 @@ #include "../widget/modebutton.hpp" #include "../widget/scenetoolbar.hpp" -#include "../../model/world/universalid.hpp" -#include "../../model/world/tablemimedata.hpp" -#include "../../model/world/idtable.hpp" - #include "pagedworldspacewidget.hpp" - +#include "mask.hpp" +#include "object.hpp" // Something small needed regarding pointers from here () +#include "worldspacewidget.hpp" #include "../../model/doc/document.hpp" -#include "../../model/world/land.hpp" -#include "../../model/world/landtexture.hpp" -//#include "../../model/world/universalid.hpp" -//#include "../../model/world/tablemimedata.hpp" -//#include "../../model/world/idtable.hpp" - #include "../../model/world/columnbase.hpp" -#include "../../model/world/resourcetable.hpp" #include "../../model/world/commandmacro.hpp" -#include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" +#include "../../model/world/data.hpp" +#include "../../model/world/idtable.hpp" +#include "../../model/world/land.hpp" +#include "../../model/world/landtexture.hpp" +#include "../../model/world/resourcetable.hpp" +#include "../../model/world/tablemimedata.hpp" +#include "../../model/world/universalid.hpp" -//#include -//#include -//#include #include -//#include -//#include -//#include - CSVRender::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent) @@ -187,74 +173,7 @@ void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult& hit) // Apply changes here { - cellId = getWorldspaceWidget().getCellId (hit.worldPos); - std::string hash = "#"; - std::string space = " "; - std::size_t hashlocation = cellId.find(hash); - std::size_t spacelocation = cellId.find(space); - std::string slicedX = cellId.substr (hashlocation+1, spacelocation-hashlocation); - std::string slicedY = cellId.substr (spacelocation+1); - CSMWorld::CellCoordinates mCoordinates(stoi(slicedX), stoi(slicedY)); - - CSMDoc::Document& document = getWorldspaceWidget().getDocument(); - CSMWorld::IdTable& landTable = dynamic_cast ( -*document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); - CSMWorld::IdTable& ltexTable = dynamic_cast ( -*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); - - int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex); - CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(cellId, textureColumn)).value(); - CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - - int xInCell ((hit.worldPos.x() - (stoi(slicedX)* cellSize)) * landTextureSize / cellSize); - int yInCell ((hit.worldPos.y() - (stoi(slicedY)* cellSize)) * landTextureSize / cellSize); - - hashlocation = mBrushTexture.find(hash); - std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1); - int brushInt = stoi(mBrushTexture.substr (hashlocation+1))+1; // All indices are offset by +1 - - if (mBrushShape == 0) mNew[yInCell*landTextureSize+xInCell] = brushInt; - if (mBrushShape == 1) - { - for(int i=-mBrushSize/2;i= 0 && yInCell+j >= 0 && xInCell+i <= 15 && yInCell+j <= 15) - mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; - } - } - } - float distance = 0; - if (mBrushShape == 2) - { - float rf = mBrushSize/2; - int r = (mBrushSize/2)+1; - for(int i = -r; i < r; i++) - { - for(int j = -r; j < r; j++) - { - distance = std::round(sqrt(pow((xInCell+i)-xInCell, 2) + pow((yInCell+j)-yInCell, 2))); - if (xInCell+i >= 0 && yInCell+j >= 0 && xInCell+i <= 15 && yInCell+j <= 15 && distance <= rf) - mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; - } - } - } - if (mBrushShape == 3) - { - // Not implemented - } - - QVariant variant; - variant.setValue(mNew); - - CSMWorld::CommandMacro macro (document.getUndoStack(), "Edit texture records"); - QModelIndex index(landTable.getModelIndex (cellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex))); - - CSMWorld::TouchLandCommand* ltexTouch = new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId); - CSMWorld::ModifyCommand* ltexModify = new CSMWorld::ModifyCommand(landTable, index, variant); - macro.push (ltexTouch); - macro.push (ltexModify); + editTerrainTextureGrid(hit); } void CSVRender::TerrainTextureMode::primarySelectPressed(const WorldspaceHitResult& hit) @@ -270,6 +189,8 @@ void CSVRender::TerrainTextureMode::secondarySelectPressed(const WorldspaceHitRe bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) { + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); + editTerrainTextureGrid(hit); return false; } @@ -321,6 +242,78 @@ void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) { } } +void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitResult& hit) +{ + mCellId = getWorldspaceWidget().getCellId (hit.worldPos); + std::string hash = "#"; + std::string space = " "; + std::size_t hashlocation = mCellId.find(hash); + std::size_t spacelocation = mCellId.find(space); + std::string slicedX = mCellId.substr (hashlocation+1, spacelocation-hashlocation); + std::string slicedY = mCellId.substr (spacelocation+1); + CSMWorld::CellCoordinates mCoordinates(stoi(slicedX), stoi(slicedY)); + + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + + int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex); + CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + + int xInCell ((hit.worldPos.x() - (stoi(slicedX)* cellSize)) * landTextureSize / cellSize); + int yInCell ((hit.worldPos.y() - (stoi(slicedY)* cellSize)) * landTextureSize / cellSize); + + hashlocation = mBrushTexture.find(hash); + std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1); + int brushInt = stoi(mBrushTexture.substr (hashlocation+1))+1; // All indices are offset by +1 + + if (mBrushShape == 0) mNew[yInCell*landTextureSize+xInCell] = brushInt; + if (mBrushShape == 1) + { + for(int i=-mBrushSize/2;i= 0 && yInCell+j >= 0 && xInCell+i <= 15 && yInCell+j <= 15) + mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; + } + } + } + float distance = 0; + if (mBrushShape == 2) + { + float rf = mBrushSize/2; + int r = (mBrushSize/2)+1; + for(int i = -r; i < r; i++) + { + for(int j = -r; j < r; j++) + { + distance = std::round(sqrt(pow((xInCell+i)-xInCell, 2) + pow((yInCell+j)-yInCell, 2))); + if (xInCell+i >= 0 && yInCell+j >= 0 && xInCell+i <= 15 && yInCell+j <= 15 && distance <= rf) + mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; + } + } + } + if (mBrushShape == 3) + { + // Not implemented + } + + QVariant changedLand; + changedLand.setValue(mNew); + + CSMWorld::CommandMacro macro (document.getUndoStack(), "Edit texture records"); + QModelIndex index(landTable.getModelIndex (mCellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex))); + + CSMWorld::TouchLandCommand* ltexTouch = new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId); + CSMWorld::ModifyCommand* ltexModify = new CSMWorld::ModifyCommand(landTable, index, changedLand); + macro.push (ltexTouch); + macro.push (ltexModify); +} + void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) { } diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index fff5b7dae..6b6eb6c63 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -108,9 +108,11 @@ namespace CSVRender virtual void dragWheel (int diff, double speedFactor); virtual void dragMoveEvent (QDragMoveEvent *event); + void editTerrainTextureGrid (const WorldspaceHitResult& hit); + private: TextureBrushWindow *textureBrushWindow; - std::string cellId; + std::string mCellId; std::string mBrushTexture = "#0"; int mBrushSize = 0; int mBrushShape = 0; From 1c113eca9cec97c691f3be36307e3fd2c53af018 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Tue, 17 Apr 2018 21:34:40 +0300 Subject: [PATCH 08/50] 15 to landTextureSize-1 --- apps/opencs/view/render/terraintexturemode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 79973b806..77d850861 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -277,7 +277,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe { for(int j=-mBrushSize/2;j= 0 && yInCell+j >= 0 && xInCell+i <= 15 && yInCell+j <= 15) + if (xInCell+i >= 0 && yInCell+j >= 0 && xInCell+i <= landTextureSize - 1 && yInCell+j <= landTextureSize - 1) mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; } } @@ -292,7 +292,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe for(int j = -r; j < r; j++) { distance = std::round(sqrt(pow((xInCell+i)-xInCell, 2) + pow((yInCell+j)-yInCell, 2))); - if (xInCell+i >= 0 && yInCell+j >= 0 && xInCell+i <= 15 && yInCell+j <= 15 && distance <= rf) + if (xInCell+i >= 0 && yInCell+j >= 0 && xInCell+i <= landTextureSize - 1 && yInCell+j <= landTextureSize - 1 && distance <= rf) mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; } } From 1ca2710a2ae9f78fdcaa56c2e63a4203f4cf3d0c Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Wed, 18 Apr 2018 13:12:11 +0300 Subject: [PATCH 09/50] Formatting, fixes --- .../opencs/view/render/terraintexturemode.cpp | 59 ++++++++++--------- .../opencs/view/render/terraintexturemode.hpp | 14 ++--- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 77d850861..0ce0bcd9b 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -1,7 +1,7 @@ #include "terraintexturemode.hpp" -#include "editmode.hpp" #include +#include #include #include @@ -16,14 +16,11 @@ #include #include +#include + #include "../widget/modebutton.hpp" #include "../widget/scenetoolbar.hpp" -#include "pagedworldspacewidget.hpp" -#include "mask.hpp" -#include "object.hpp" // Something small needed regarding pointers from here () -#include "worldspacewidget.hpp" - #include "../../model/doc/document.hpp" #include "../../model/world/columnbase.hpp" #include "../../model/world/commandmacro.hpp" @@ -36,8 +33,11 @@ #include "../../model/world/tablemimedata.hpp" #include "../../model/world/universalid.hpp" - -#include +#include "editmode.hpp" +#include "pagedworldspacewidget.hpp" +#include "mask.hpp" +#include "object.hpp" // Something small needed regarding pointers from here () +#include "worldspacewidget.hpp" CSVRender::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent) @@ -68,7 +68,10 @@ CSVRender::TextureBrushButton::TextureBrushButton (const QIcon & icon, const QSt } CSVRender::TextureBrushWindow::TextureBrushWindow(WorldspaceWidget *worldspaceWidget, QWidget *parent) - : QFrame(parent, Qt::Popup), mWorldspaceWidget (worldspaceWidget) + : QFrame(parent, Qt::Popup), + mWorldspaceWidget (worldspaceWidget), + mBrushSize(0), + mBrushShape(0) { mBrushTextureLabel = "Brush: " + mBrushTexture; selectedBrush = new QLabel(QString::fromUtf8(mBrushTextureLabel.c_str()), this); @@ -116,7 +119,7 @@ CSVRender::TextureBrushWindow::TextureBrushWindow(WorldspaceWidget *worldspaceWi connect(sizeSliders->brushSizeSlider, SIGNAL(valueChanged(int)), parent, SLOT(setBrushSize(int))); - connect(parent, SIGNAL(passBrushTexture(std::string)), this, SLOT(getBrushTexture(std::string))); + connect(parent, SIGNAL(passBrushTexture(std::string)), this, SLOT(setBrushTexture(std::string))); } void CSVRender::TextureBrushWindow::configureButtonInitialSettings(TextureBrushButton *button) @@ -129,7 +132,7 @@ void CSVRender::TextureBrushWindow::configureButtonInitialSettings(TextureBrushB button->setCheckable(true); } -void CSVRender::TextureBrushWindow::getBrushTexture(std::string brushTexture) +void CSVRender::TextureBrushWindow::setBrushTexture(std::string brushTexture) { mBrushTexture = brushTexture; mBrushTextureLabel = "Brush:" + mBrushTexture; @@ -152,8 +155,11 @@ void CSVRender::TextureBrushWindow::setBrushShape() } CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) -: EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent) -, textureBrushWindow(new TextureBrushWindow(worldspaceWidget, this)) +: EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent), + textureBrushWindow(new TextureBrushWindow(worldspaceWidget, this)), + mBrushTexture("#0"), + mBrushSize(0), + mBrushShape(0) { connect(parent, SIGNAL(passEvent(QDragEnterEvent*)), this, SLOT(handleDragEnterEvent(QDragEnterEvent*))); connect(parent, SIGNAL(passEvent(QDropEvent*)), this, SLOT(handleDropEvent(QDropEvent*))); @@ -245,13 +251,12 @@ void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) { void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitResult& hit) { mCellId = getWorldspaceWidget().getCellId (hit.worldPos); - std::string hash = "#"; - std::string space = " "; - std::size_t hashlocation = mCellId.find(hash); - std::size_t spacelocation = mCellId.find(space); - std::string slicedX = mCellId.substr (hashlocation+1, spacelocation-hashlocation); - std::string slicedY = mCellId.substr (spacelocation+1); - CSMWorld::CellCoordinates mCoordinates(stoi(slicedX), stoi(slicedY)); + + std::istringstream streamCoord (mCellId); + char ignore; + int cellX = 0; + int cellY = 0; + streamCoord >> ignore >> cellX >> cellY; CSMDoc::Document& document = getWorldspaceWidget().getDocument(); CSMWorld::IdTable& landTable = dynamic_cast ( @@ -263,10 +268,10 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - int xInCell ((hit.worldPos.x() - (stoi(slicedX)* cellSize)) * landTextureSize / cellSize); - int yInCell ((hit.worldPos.y() - (stoi(slicedY)* cellSize)) * landTextureSize / cellSize); + int xInCell ((hit.worldPos.x() - (cellX* cellSize)) * landTextureSize / cellSize); + int yInCell ((hit.worldPos.y() - (cellY* cellSize)) * landTextureSize / cellSize); - hashlocation = mBrushTexture.find(hash); + std::size_t hashlocation = mBrushTexture.find("#"); std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1); int brushInt = stoi(mBrushTexture.substr (hashlocation+1))+1; // All indices are offset by +1 @@ -307,11 +312,9 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe CSMWorld::CommandMacro macro (document.getUndoStack(), "Edit texture records"); QModelIndex index(landTable.getModelIndex (mCellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex))); - - CSMWorld::TouchLandCommand* ltexTouch = new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId); - CSMWorld::ModifyCommand* ltexModify = new CSMWorld::ModifyCommand(landTable, index, changedLand); - macro.push (ltexTouch); - macro.push (ltexModify); + + macro.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); + macro.push (new CSMWorld::ModifyCommand(landTable, index, changedLand)); } void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) { diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 6b6eb6c63..7e991a8f0 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -64,16 +64,14 @@ namespace CSVRender private: QLabel *selectedBrush; QGroupBox *horizontalGroupBox; - int mButtonSize; - int mBrushSize = 0; - int mBrushShape = 0; - int mIconSize; WorldspaceWidget *mWorldspaceWidget; + int mBrushSize; + int mBrushShape; std::string mBrushTexture; std::string mBrushTextureLabel; public slots: - void getBrushTexture(std::string brushTexture); + void setBrushTexture(std::string brushTexture); void setBrushShape(); void setBrushSize(int brushSize); @@ -113,9 +111,9 @@ namespace CSVRender private: TextureBrushWindow *textureBrushWindow; std::string mCellId; - std::string mBrushTexture = "#0"; - int mBrushSize = 0; - int mBrushShape = 0; + std::string mBrushTexture; + int mBrushSize; + int mBrushShape; const int cellSize {ESM::Land::REAL_SIZE}; const int landSize {ESM::Land::LAND_SIZE}; From 9f742d5b1fe68a340db13b128c393645d18df542 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Thu, 19 Apr 2018 18:00:47 +0300 Subject: [PATCH 10/50] Brush affects adjancent cells --- .../opencs/view/render/terraintexturemode.cpp | 147 ++++++++++++++---- .../opencs/view/render/terraintexturemode.hpp | 7 + 2 files changed, 127 insertions(+), 27 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 0ce0bcd9b..baaae55be 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -252,11 +252,16 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe { mCellId = getWorldspaceWidget().getCellId (hit.worldPos); - std::istringstream streamCoord (mCellId); - char ignore; - int cellX = 0; - int cellY = 0; - streamCoord >> ignore >> cellX >> cellY; + std::pair cellCoordinates_pair = CSMWorld::CellCoordinates::fromId (mCellId); + + int cellX = cellCoordinates_pair.first.getX(); + int cellY = cellCoordinates_pair.first.getY(); + + // The coordinates of hit in mCellId + int xHitInCell ((hit.worldPos.x() - (cellX* cellSize)) * landTextureSize / cellSize); + int yHitInCell ((hit.worldPos.y() - (cellY* cellSize)) * landTextureSize / cellSize); + + std::string iteratedCellId; CSMDoc::Document& document = getWorldspaceWidget().getDocument(); CSMWorld::IdTable& landTable = dynamic_cast ( @@ -265,40 +270,123 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe *document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex); - CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); - CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - - int xInCell ((hit.worldPos.x() - (cellX* cellSize)) * landTextureSize / cellSize); - int yInCell ((hit.worldPos.y() - (cellY* cellSize)) * landTextureSize / cellSize); std::size_t hashlocation = mBrushTexture.find("#"); std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1); int brushInt = stoi(mBrushTexture.substr (hashlocation+1))+1; // All indices are offset by +1 - if (mBrushShape == 0) mNew[yInCell*landTextureSize+xInCell] = brushInt; + float rf = mBrushSize/2; + int r = (mBrushSize/2)+1; + float distance = 0; + + if (mBrushShape == 0) + { + CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + mNew[yHitInCell*landTextureSize+xHitInCell] = brushInt; + pushEditToCommand(mNew, document, landTable, ltexTable, mCellId); + } + if (mBrushShape == 1) { - for(int i=-mBrushSize/2;i landTextureSize - 1) lowerrightCellX++; + if (yHitInCell + (r % landTextureSize) > landTextureSize - 1) lowerrightCellY++; + + for(int i_cell = upperLeftCellX; i_cell <= lowerrightCellX; i_cell++) { - for(int j=-mBrushSize/2;j= 0 && yInCell+j >= 0 && xInCell+i <= landTextureSize - 1 && yInCell+j <= landTextureSize - 1) - mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; + iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell); + CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + for(int i = 0; i < landTextureSize; i++) + { + for(int j = 0; j < landTextureSize; j++) + { + + if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + { + mNew[j*landTextureSize+i] = brushInt; + } + else + { + int distanceX(0); + int distanceY(0); + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize + i - 1; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize + j - 1; + if (i_cell == cellX) distanceX = abs(i-xHitInCell); + if (j_cell == cellY) distanceY = abs(j-yHitInCell); + if (distanceX < r && distanceY < r) mNew[j*landTextureSize+i] = brushInt; + } + } + } + pushEditToCommand(mNew, document, landTable, ltexTable, iteratedCellId); } } } - float distance = 0; + if (mBrushShape == 2) { - float rf = mBrushSize/2; - int r = (mBrushSize/2)+1; - for(int i = -r; i < r; i++) + int upperLeftCellX = cellX - std::floor(r / landTextureSize); + int upperLeftCellY = cellY - std::floor(r / landTextureSize); + if (xHitInCell - (r % landTextureSize) < 0) upperLeftCellX--; + if (yHitInCell - (r % landTextureSize) < 0) upperLeftCellY--; + + int lowerrightCellX = cellX + std::floor(r / landTextureSize); + int lowerrightCellY = cellY + std::floor(r / landTextureSize); + if (xHitInCell + (r % landTextureSize) > landTextureSize - 1) lowerrightCellX++; + if (yHitInCell + (r % landTextureSize) > landTextureSize - 1) lowerrightCellY++; + + for(int i_cell = upperLeftCellX; i_cell <= lowerrightCellX; i_cell++) { - for(int j = -r; j < r; j++) + for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++) { - distance = std::round(sqrt(pow((xInCell+i)-xInCell, 2) + pow((yInCell+j)-yInCell, 2))); - if (xInCell+i >= 0 && yInCell+j >= 0 && xInCell+i <= landTextureSize - 1 && yInCell+j <= landTextureSize - 1 && distance <= rf) - mNew[(yInCell+j)*landTextureSize+(xInCell+i)] = brushInt; + iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell); + CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + for(int i = 0; i < landTextureSize; i++) + { + for(int j = 0; j < landTextureSize; j++) + { + + if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + { + int distanceX(0); + int distanceY(0); + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize + i - 1; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize + j - 1; + if (i_cell == cellX) distanceX = abs(i-xHitInCell); + if (j_cell == cellY) distanceY = abs(j-yHitInCell); + distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); + if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + } + else + { + int distanceX(0); + int distanceY(0); + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize + i - 1; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize + j - 1; + if (i_cell == cellX) distanceX = abs(i-xHitInCell); + if (j_cell == cellY) distanceY = abs(j-yHitInCell); + distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); + if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + } + } + } + pushEditToCommand(mNew, document, landTable, ltexTable, iteratedCellId); } } } @@ -307,13 +395,18 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe // Not implemented } +} + +void CSVRender::TerrainTextureMode::pushEditToCommand(CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, + CSMWorld::IdTable& landTable, CSMWorld::IdTable& ltexTable, std::string cellId) +{ QVariant changedLand; - changedLand.setValue(mNew); + changedLand.setValue(newLandGrid); CSMWorld::CommandMacro macro (document.getUndoStack(), "Edit texture records"); - QModelIndex index(landTable.getModelIndex (mCellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex))); - - macro.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); + QModelIndex index(landTable.getModelIndex (cellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex))); + + macro.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId)); macro.push (new CSMWorld::ModifyCommand(landTable, index, changedLand)); } diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 7e991a8f0..48b9aeb59 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -19,6 +19,11 @@ #include "../../model/world/data.hpp" #include "../../model/world/land.hpp" +#include "../../model/doc/document.hpp" +#include "../../model/world/commands.hpp" +#include "../../model/world/idtable.hpp" +#include "../../model/world/landtexture.hpp" + namespace CSVWidget { class SceneToolMode; @@ -107,6 +112,8 @@ namespace CSVRender virtual void dragMoveEvent (QDragMoveEvent *event); void editTerrainTextureGrid (const WorldspaceHitResult& hit); + void pushEditToCommand (CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, + CSMWorld::IdTable& landTable, CSMWorld::IdTable& ltexTable, std::string cellId); private: TextureBrushWindow *textureBrushWindow; From cf7a0f715ea5f20ee5b3892fbf5ac0c888167566 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sat, 21 Apr 2018 13:46:06 +0300 Subject: [PATCH 11/50] Command macro for complete drag-editing operations. --- .../opencs/view/render/terraintexturemode.cpp | 38 +++++++++++++------ .../opencs/view/render/terraintexturemode.hpp | 2 +- apps/opencs/view/render/worldspacewidget.cpp | 6 +++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index baaae55be..f7f3b0631 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -196,8 +196,21 @@ void CSVRender::TerrainTextureMode::secondarySelectPressed(const WorldspaceHitRe bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) { WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); + + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + + mCellId = getWorldspaceWidget().getCellId (hit.worldPos); + + QUndoStack& undoStack = document.getUndoStack(); + undoStack.beginMacro ("Edit texture records"); + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); editTerrainTextureGrid(hit); - return false; + + return true; } bool CSVRender::TerrainTextureMode::secondaryEditStartDrag (const QPoint& pos) @@ -215,10 +228,16 @@ bool CSVRender::TerrainTextureMode::secondarySelectStartDrag (const QPoint& pos) return false; } -void CSVRender::TerrainTextureMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor) { +void CSVRender::TerrainTextureMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor) +{ + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); + editTerrainTextureGrid(hit); } void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos) { + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + QUndoStack& undoStack = document.getUndoStack(); + undoStack.endMacro(); } void CSVRender::TerrainTextureMode::dragAborted() { @@ -266,8 +285,6 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe CSMDoc::Document& document = getWorldspaceWidget().getDocument(); CSMWorld::IdTable& landTable = dynamic_cast ( *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); - CSMWorld::IdTable& ltexTable = dynamic_cast ( - *document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex); @@ -284,7 +301,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType mNew(mPointer); mNew[yHitInCell*landTextureSize+xHitInCell] = brushInt; - pushEditToCommand(mNew, document, landTable, ltexTable, mCellId); + pushEditToCommand(mNew, document, landTable, mCellId); } if (mBrushShape == 1) @@ -329,7 +346,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } } } - pushEditToCommand(mNew, document, landTable, ltexTable, iteratedCellId); + pushEditToCommand(mNew, document, landTable, iteratedCellId); } } } @@ -386,7 +403,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } } } - pushEditToCommand(mNew, document, landTable, ltexTable, iteratedCellId); + pushEditToCommand(mNew, document, landTable, iteratedCellId); } } } @@ -398,16 +415,15 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } void CSVRender::TerrainTextureMode::pushEditToCommand(CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, - CSMWorld::IdTable& landTable, CSMWorld::IdTable& ltexTable, std::string cellId) + CSMWorld::IdTable& landTable, std::string cellId) { QVariant changedLand; changedLand.setValue(newLandGrid); - CSMWorld::CommandMacro macro (document.getUndoStack(), "Edit texture records"); QModelIndex index(landTable.getModelIndex (cellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex))); - macro.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId)); - macro.push (new CSMWorld::ModifyCommand(landTable, index, changedLand)); + QUndoStack& undoStack = document.getUndoStack(); + undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLand)); } void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) { diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 48b9aeb59..d8d27d045 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -113,7 +113,7 @@ namespace CSVRender void editTerrainTextureGrid (const WorldspaceHitResult& hit); void pushEditToCommand (CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, - CSMWorld::IdTable& landTable, CSMWorld::IdTable& ltexTable, std::string cellId); + CSMWorld::IdTable& landTable, std::string cellId); private: TextureBrushWindow *textureBrushWindow; diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index f3b781080..c8ba16666 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -651,6 +651,12 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) mDragX = event->posF().x(); mDragY = height() - event->posF().y(); #endif + + if (mDragMode == InteractionType_PrimaryEdit) + { + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); + editMode.drag (event->pos(), mDragX, mDragY, mDragFactor); // note: terraintexturemode only uses pos + } } } else From 5f3c8b2b9937c2400f4a06a879fb13546fdead80 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sat, 21 Apr 2018 13:54:06 +0300 Subject: [PATCH 12/50] c_str -> fromStdString, remove TextureBrushButton class --- .../opencs/view/render/terraintexturemode.cpp | 11 +++-------- .../opencs/view/render/terraintexturemode.hpp | 19 +++++-------------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index f7f3b0631..40afd9b35 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -62,11 +62,6 @@ CSVRender::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *p setLayout(layoutSliderSize); } -CSVRender::TextureBrushButton::TextureBrushButton (const QIcon & icon, const QString & text, QWidget * parent) - : QPushButton(icon, text, parent) -{ -} - CSVRender::TextureBrushWindow::TextureBrushWindow(WorldspaceWidget *worldspaceWidget, QWidget *parent) : QFrame(parent, Qt::Popup), mWorldspaceWidget (worldspaceWidget), @@ -74,7 +69,7 @@ CSVRender::TextureBrushWindow::TextureBrushWindow(WorldspaceWidget *worldspaceWi mBrushShape(0) { mBrushTextureLabel = "Brush: " + mBrushTexture; - selectedBrush = new QLabel(QString::fromUtf8(mBrushTextureLabel.c_str()), this); + selectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel), this); QVBoxLayout *layoutMain = new QVBoxLayout; layoutMain->setSpacing(0); @@ -122,7 +117,7 @@ CSVRender::TextureBrushWindow::TextureBrushWindow(WorldspaceWidget *worldspaceWi connect(parent, SIGNAL(passBrushTexture(std::string)), this, SLOT(setBrushTexture(std::string))); } -void CSVRender::TextureBrushWindow::configureButtonInitialSettings(TextureBrushButton *button) +void CSVRender::TextureBrushWindow::configureButtonInitialSettings(QPushButton *button) { button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); button->setContentsMargins (QMargins (0, 0, 0, 0)); @@ -136,7 +131,7 @@ void CSVRender::TextureBrushWindow::setBrushTexture(std::string brushTexture) { mBrushTexture = brushTexture; mBrushTextureLabel = "Brush:" + mBrushTexture; - selectedBrush->setText(QString::fromUtf8(mBrushTextureLabel.c_str())); + selectedBrush->setText(QString::fromStdString(mBrushTextureLabel)); } void CSVRender::TextureBrushWindow::setBrushSize(int brushSize) diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index d8d27d045..4f20ccfc1 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -44,27 +44,18 @@ namespace CSVRender QHBoxLayout *layoutSliderSize; }; - class TextureBrushButton : public QPushButton - { - Q_OBJECT - - public: - TextureBrushButton (const QIcon& icon, const QString& tooltip = "", - QWidget *parent = 0); - }; - class TextureBrushWindow : public QFrame { Q_OBJECT public: TextureBrushWindow(WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); - void configureButtonInitialSettings(TextureBrushButton *button); + void configureButtonInitialSettings(QPushButton *button); - TextureBrushButton *buttonPoint = new TextureBrushButton(QIcon (QPixmap (":scenetoolbar/brush-point")), "", this); - TextureBrushButton *buttonSquare = new TextureBrushButton(QIcon (QPixmap (":scenetoolbar/brush-square")), "", this); - TextureBrushButton *buttonCircle = new TextureBrushButton(QIcon (QPixmap (":scenetoolbar/brush-circle")), "", this); - TextureBrushButton *buttonCustom = new TextureBrushButton(QIcon (QPixmap (":scenetoolbar/brush-custom")), "", this); + QPushButton *buttonPoint = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-point")), "", this); + QPushButton *buttonSquare = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-square")), "", this); + QPushButton *buttonCircle = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-circle")), "", this); + QPushButton *buttonCustom = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-custom")), "", this); private: QLabel *selectedBrush; From 20d1d8ac8912ec65a9f12b93d090fa06acb1a90c Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Mon, 23 Apr 2018 11:21:59 +0300 Subject: [PATCH 13/50] Fixed brush calculations, implement undostack macro when clicked. --- .../opencs/view/render/terraintexturemode.cpp | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 40afd9b35..00bbfa110 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -174,7 +174,19 @@ void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult& hit) // Apply changes here { + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + + mCellId = getWorldspaceWidget().getCellId (hit.worldPos); + + QUndoStack& undoStack = document.getUndoStack(); + undoStack.beginMacro ("Edit texture records"); + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); editTerrainTextureGrid(hit); + undoStack.endMacro(); } void CSVRender::TerrainTextureMode::primarySelectPressed(const WorldspaceHitResult& hit) @@ -331,10 +343,10 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe { int distanceX(0); int distanceY(0); - if (i_cell < cellX) distanceX = xHitInCell + landTextureSize - i; - if (j_cell < cellY) distanceY = yHitInCell + landTextureSize - j; - if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize + i - 1; - if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize + j - 1; + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; if (i_cell == cellX) distanceX = abs(i-xHitInCell); if (j_cell == cellY) distanceY = abs(j-yHitInCell); if (distanceX < r && distanceY < r) mNew[j*landTextureSize+i] = brushInt; @@ -374,10 +386,10 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe { int distanceX(0); int distanceY(0); - if (i_cell < cellX) distanceX = xHitInCell + landTextureSize - i; - if (j_cell < cellY) distanceY = yHitInCell + landTextureSize - j; - if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize + i - 1; - if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize + j - 1; + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize* abs(i_cell-cellX) + i; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; if (i_cell == cellX) distanceX = abs(i-xHitInCell); if (j_cell == cellY) distanceY = abs(j-yHitInCell); distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); @@ -387,10 +399,10 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe { int distanceX(0); int distanceY(0); - if (i_cell < cellX) distanceX = xHitInCell + landTextureSize - i; - if (j_cell < cellY) distanceY = yHitInCell + landTextureSize - j; - if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize + i - 1; - if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize + j - 1; + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; if (i_cell == cellX) distanceX = abs(i-xHitInCell); if (j_cell == cellY) distanceY = abs(j-yHitInCell); distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); From 71398895669beeb3262238b46a647a946669c1aa Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sat, 28 Apr 2018 16:05:15 +0300 Subject: [PATCH 14/50] Brush button window opens at modebutton, slider 1-50, doxygen comments --- .../opencs/view/render/terraintexturemode.cpp | 21 +++++++++++++++---- .../opencs/view/render/terraintexturemode.hpp | 19 +++++++++++++++++ apps/opencs/view/widget/scenetoolmode.cpp | 10 +++++++++ apps/opencs/view/widget/scenetoolmode.hpp | 3 +++ 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 00bbfa110..91672bbef 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -46,10 +46,11 @@ CSVRender::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *p brushSizeSlider = new QSlider(Qt::Horizontal); brushSizeSlider->setTickPosition(QSlider::TicksBothSides); brushSizeSlider->setTickInterval(10); + brushSizeSlider->setRange(1, 50); brushSizeSlider->setSingleStep(1); brushSizeSpinBox = new QSpinBox; - brushSizeSpinBox->setRange(1, 100); + brushSizeSpinBox->setRange(1, 50); brushSizeSpinBox->setSingleStep(1); layoutSliderSize = new QHBoxLayout; @@ -158,6 +159,7 @@ CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceW { connect(parent, SIGNAL(passEvent(QDragEnterEvent*)), this, SLOT(handleDragEnterEvent(QDragEnterEvent*))); connect(parent, SIGNAL(passEvent(QDropEvent*)), this, SLOT(handleDropEvent(QDropEvent*))); + connect(parent, SIGNAL(passEvent(QMouseEvent*)), this, SLOT(handleMouseEvent(QMouseEvent*))); connect(textureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int))); connect(textureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); } @@ -191,9 +193,6 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult void CSVRender::TerrainTextureMode::primarySelectPressed(const WorldspaceHitResult& hit) { - QPoint position = QCursor::pos(); - textureBrushWindow->move (position); - textureBrushWindow->show(); } void CSVRender::TerrainTextureMode::secondarySelectPressed(const WorldspaceHitResult& hit) @@ -274,6 +273,20 @@ void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) { } } +void CSVRender::TerrainTextureMode::handleMouseEvent (QMouseEvent *event) +{ + if (event->button()==Qt::MidButton) + { + QPoint position = QCursor::pos(); + textureBrushWindow->move (position); + textureBrushWindow->show(); + } + if (event->button()==Qt::LeftButton) PushButton::mouseReleaseEvent (event); +} + +void CSVRender::TerrainTextureMode::handlePrimarySelectOnModeButton () { +} + void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitResult& hit) { mCellId = getWorldspaceWidget().getCellId (hit.worldPos); diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 4f20ccfc1..60d6fd87b 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -31,6 +31,8 @@ namespace CSVWidget namespace CSVRender { + + /// \brief Layout-box for some brush button settings class BrushSizeControls : public QGroupBox { Q_OBJECT @@ -44,6 +46,7 @@ namespace CSVRender QHBoxLayout *layoutSliderSize; }; + /// \brief Brush settings window class TextureBrushWindow : public QFrame { Q_OBJECT @@ -82,27 +85,41 @@ namespace CSVRender public: + /// \brief Editmode for terrain texture grid TerrainTextureMode(WorldspaceWidget*, QWidget* parent = nullptr); + /// \brief Create single command for one-click texture editing void primaryEditPressed (const WorldspaceHitResult& hit); + /// \brief Open brush settings window void primarySelectPressed(const WorldspaceHitResult&); + void secondarySelectPressed(const WorldspaceHitResult&); void activate(CSVWidget::SceneToolbar*); void deactivate(CSVWidget::SceneToolbar*); + /// \brief Start texture editing command macro virtual bool primaryEditStartDrag (const QPoint& pos); + virtual bool secondaryEditStartDrag (const QPoint& pos); virtual bool primarySelectStartDrag (const QPoint& pos); virtual bool secondarySelectStartDrag (const QPoint& pos); + + /// \brief Handle texture edit behavior during dragging virtual void drag (const QPoint& pos, int diffX, int diffY, double speedFactor); + + /// \brief End texture editing command macro virtual void dragCompleted(const QPoint& pos); + virtual void dragAborted(); virtual void dragWheel (int diff, double speedFactor); virtual void dragMoveEvent (QDragMoveEvent *event); + /// \brief Handle brush mechanics, maths regarding worldspace hit etc. void editTerrainTextureGrid (const WorldspaceHitResult& hit); + + /// \brief Push texture edits to command macro void pushEditToCommand (CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, CSMWorld::IdTable& landTable, std::string cellId); @@ -123,6 +140,8 @@ namespace CSVRender public slots: void handleDragEnterEvent (QDragEnterEvent *event); void handleDropEvent(QDropEvent *event); + void handleMouseEvent (QMouseEvent *event); + void handlePrimarySelectOnModeButton(); void setBrushSize(int brushSize); void setBrushShape(int brushShape); diff --git a/apps/opencs/view/widget/scenetoolmode.cpp b/apps/opencs/view/widget/scenetoolmode.cpp index 80104515b..94435016f 100644 --- a/apps/opencs/view/widget/scenetoolmode.cpp +++ b/apps/opencs/view/widget/scenetoolmode.cpp @@ -134,6 +134,16 @@ void CSVWidget::SceneToolMode::setButton (const std::string& id) } } + +void CSVWidget::SceneToolMode::mouseReleaseEvent (QMouseEvent *event) +{ + if (event->button()==Qt::MidButton && getCurrentId() == "terrain-texture") emit passEvent(event); + if (getType()==Type_TopAction && event->button()==Qt::RightButton) + showPanel (parentWidget()->mapToGlobal (pos())); + else + PushButton::mouseReleaseEvent (event); +} + bool CSVWidget::SceneToolMode::event(QEvent* event) { if (event->type() == QEvent::ToolTip) diff --git a/apps/opencs/view/widget/scenetoolmode.hpp b/apps/opencs/view/widget/scenetoolmode.hpp index 84fcf59a7..7d0c8f70e 100644 --- a/apps/opencs/view/widget/scenetoolmode.hpp +++ b/apps/opencs/view/widget/scenetoolmode.hpp @@ -44,6 +44,8 @@ namespace CSVWidget void setButton (std::map::iterator iter); + void mouseReleaseEvent (QMouseEvent *event); + protected: bool event(QEvent* event); @@ -74,6 +76,7 @@ namespace CSVWidget signals: void modeChanged (const std::string& id); + void passEvent (QMouseEvent *event); void passEvent (QDragEnterEvent *event); void passEvent (QDropEvent *event); From e8a9bff85c0bd6a3cb6310bdb31b3674497f8ebb Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 29 Apr 2018 12:26:18 +0300 Subject: [PATCH 15/50] Drop textures to landtextures from assets (try-method) --- .../opencs/view/render/terraintexturemode.cpp | 52 +++++++++++++++++++ .../opencs/view/render/terraintexturemode.hpp | 3 ++ 2 files changed, 55 insertions(+) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 91672bbef..5e1b6afb8 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -271,6 +271,16 @@ void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) { emit passBrushTexture(mBrushTexture); } } + if (mime->holdsType (CSMWorld::UniversalId::Type_Texture)) + { + const std::vector ids = mime->getData(); + + for (const CSMWorld::UniversalId& uid : ids) + { + std::string textureFileName = uid.toString(); + createTexture(textureFileName); + } + } } void CSVRender::TerrainTextureMode::handleMouseEvent (QMouseEvent *event) @@ -446,6 +456,48 @@ void CSVRender::TerrainTextureMode::pushEditToCommand(CSMWorld::LandTexturesColu undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLand)); } +void CSVRender::TerrainTextureMode::createTexture(std::string textureFileName) +{ + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + + QUndoStack& undoStack = document.getUndoStack(); + + std::string newId; + + int counter=0; + bool freeIndexFound = false; + do { + const size_t maxCounter = std::numeric_limits::max() - 1; + try + { + newId = CSMWorld::LandTexture::createUniqueRecordId(0, counter); + if (ltexTable.getRecord(newId).isDeleted() == 0) counter = (counter + 1) % maxCounter; + } catch (const std::exception& e) + { + newId = CSMWorld::LandTexture::createUniqueRecordId(0, counter); + freeIndexFound = true; + } + } while (freeIndexFound == false); + + std::size_t idlocation = textureFileName.find("Texture: "); + textureFileName = textureFileName.substr (idlocation + 9); + + QVariant textureNameVariant; + + QVariant textureFileNameVariant; + textureFileNameVariant.setValue(QString::fromStdString(textureFileName)); + + undoStack.beginMacro ("Add land texture record"); + + undoStack.push (new CSMWorld::CreateCommand (ltexTable, newId)); + QModelIndex index(ltexTable.getModelIndex (newId, ltexTable.findColumnIndex (CSMWorld::Columns::ColumnId_Texture))); + undoStack.push (new CSMWorld::ModifyCommand(ltexTable, index, textureFileNameVariant)); + undoStack.endMacro(); +} + void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) { } diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 60d6fd87b..f6fde3544 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -123,6 +123,9 @@ namespace CSVRender void pushEditToCommand (CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, CSMWorld::IdTable& landTable, std::string cellId); + /// \brief Create new land texture record from texture asset + void createTexture(std::string textureFileName); + private: TextureBrushWindow *textureBrushWindow; std::string mCellId; From 24977fcc0f9d7358f07be1d6de6ec3ffd8903ceb Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 29 Apr 2018 13:33:00 +0300 Subject: [PATCH 16/50] improve hit calculation accuracy for texture editing --- apps/opencs/view/render/terraintexturemode.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 5e1b6afb8..97856c20c 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -307,8 +307,20 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe int cellY = cellCoordinates_pair.first.getY(); // The coordinates of hit in mCellId - int xHitInCell ((hit.worldPos.x() - (cellX* cellSize)) * landTextureSize / cellSize); - int yHitInCell ((hit.worldPos.y() - (cellY* cellSize)) * landTextureSize / cellSize); + int xHitInCell (float(((hit.worldPos.x() - (cellX* cellSize)) * landTextureSize / cellSize) - 0.5)); + int yHitInCell (float(((hit.worldPos.y() - (cellY* cellSize)) * landTextureSize / cellSize) + 0.5)); + if (xHitInCell < 0) + { + xHitInCell = xHitInCell + landTextureSize; + cellX = cellX - 1; + } + if (yHitInCell > 15) + { + yHitInCell = yHitInCell - landTextureSize; + cellY = cellY + 1; + } + + mCellId = "#" + std::to_string(cellX) + " " + std::to_string(cellY); std::string iteratedCellId; From baa707b5e3e8cf020c7717a1b681f7abaccb1f64 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 29 Apr 2018 15:17:06 +0300 Subject: [PATCH 17/50] User setting for selective cell editing or new land creation --- apps/opencs/model/prefs/state.cpp | 12 + .../opencs/view/render/terraintexturemode.cpp | 216 +++++++++++++----- .../opencs/view/render/terraintexturemode.hpp | 3 + 3 files changed, 171 insertions(+), 60 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 8a9dad7f3..6cbc33766 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -222,6 +222,14 @@ void CSMPrefs::State::declare() EnumValues insertOutsideVisibleCell; insertOutsideVisibleCell.add (showAndInsert).add (dontInsert).add (insertAnyway); + EnumValue createAndLandEdit ("Create cell and land, then edit"); + EnumValue showAndLandEdit ("Show cell and edit"); + EnumValue dontLandEdit ("Discard"); + EnumValues landeditOutsideCell; + landeditOutsideCell.add (createAndLandEdit).add (dontLandEdit); + EnumValues landeditOutsideVisibleCell; + landeditOutsideVisibleCell.add (showAndLandEdit).add (dontLandEdit); + declareCategory ("Scene Drops"); declareInt ("distance", "Drop Distance", 50). setTooltip ("If an instance drop can not be placed against another object at the " @@ -230,6 +238,10 @@ void CSMPrefs::State::declare() addValues (insertOutsideCell); declareEnum ("outside-visible-drop", "Handling drops outside of visible cells", showAndInsert). addValues (insertOutsideVisibleCell); + declareEnum ("outside-landedit", "Handling land edit outside of cells", createAndLandEdit). + addValues (landeditOutsideCell); + declareEnum ("outside-visible-landedit", "Handling land edit outside of visible cells", showAndLandEdit). + addValues (landeditOutsideVisibleCell); declareCategory ("Key Bindings"); diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 97856c20c..3468d4cd9 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -22,11 +22,13 @@ #include "../widget/scenetoolbar.hpp" #include "../../model/doc/document.hpp" +#include "../../model/prefs/state.hpp" #include "../../model/world/columnbase.hpp" #include "../../model/world/commandmacro.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/data.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/world/idtree.hpp" #include "../../model/world/land.hpp" #include "../../model/world/landtexture.hpp" #include "../../model/world/resourcetable.hpp" @@ -186,8 +188,11 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult QUndoStack& undoStack = document.getUndoStack(); undoStack.beginMacro ("Edit texture records"); - undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); - editTerrainTextureGrid(hit); + if(allowLandTextureEditing(mCellId)==true) + { + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); + editTerrainTextureGrid(hit); + } undoStack.endMacro(); } @@ -213,8 +218,11 @@ bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) QUndoStack& undoStack = document.getUndoStack(); undoStack.beginMacro ("Edit texture records"); - undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); - editTerrainTextureGrid(hit); + if(allowLandTextureEditing(mCellId)==true) + { + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); + editTerrainTextureGrid(hit); + } return true; } @@ -299,7 +307,12 @@ void CSVRender::TerrainTextureMode::handlePrimarySelectOnModeButton () { void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitResult& hit) { + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + mCellId = getWorldspaceWidget().getCellId (hit.worldPos); + if(allowLandTextureEditing(mCellId)==true) {} std::pair cellCoordinates_pair = CSMWorld::CellCoordinates::fromId (mCellId); @@ -321,13 +334,10 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } mCellId = "#" + std::to_string(cellX) + " " + std::to_string(cellY); + if(allowLandTextureEditing(mCellId)==true) {} std::string iteratedCellId; - CSMDoc::Document& document = getWorldspaceWidget().getDocument(); - CSMWorld::IdTable& landTable = dynamic_cast ( - *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); - int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex); std::size_t hashlocation = mBrushTexture.find("#"); @@ -342,8 +352,12 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe { CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - mNew[yHitInCell*landTextureSize+xHitInCell] = brushInt; - pushEditToCommand(mNew, document, landTable, mCellId); + + if(allowLandTextureEditing(mCellId)==true) + { + mNew[yHitInCell*landTextureSize+xHitInCell] = brushInt; + pushEditToCommand(mNew, document, landTable, mCellId); + } } if (mBrushShape == 1) @@ -363,32 +377,35 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++) { iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell); - CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); - CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - for(int i = 0; i < landTextureSize; i++) + if(allowLandTextureEditing(iteratedCellId)==true) { - for(int j = 0; j < landTextureSize; j++) + CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + for(int i = 0; i < landTextureSize; i++) { - - if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + for(int j = 0; j < landTextureSize; j++) { - mNew[j*landTextureSize+i] = brushInt; - } - else - { - int distanceX(0); - int distanceY(0); - if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; - if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; - if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; - if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; - if (i_cell == cellX) distanceX = abs(i-xHitInCell); - if (j_cell == cellY) distanceY = abs(j-yHitInCell); - if (distanceX < r && distanceY < r) mNew[j*landTextureSize+i] = brushInt; + + if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + { + mNew[j*landTextureSize+i] = brushInt; + } + else + { + int distanceX(0); + int distanceY(0); + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; + if (i_cell == cellX) distanceX = abs(i-xHitInCell); + if (j_cell == cellY) distanceY = abs(j-yHitInCell); + if (distanceX < r && distanceY < r) mNew[j*landTextureSize+i] = brushInt; + } } } + pushEditToCommand(mNew, document, landTable, iteratedCellId); } - pushEditToCommand(mNew, document, landTable, iteratedCellId); } } } @@ -410,45 +427,49 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++) { iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell); - CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); - CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - for(int i = 0; i < landTextureSize; i++) + if(allowLandTextureEditing(iteratedCellId)==true) { - for(int j = 0; j < landTextureSize; j++) + CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + for(int i = 0; i < landTextureSize; i++) { - - if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + for(int j = 0; j < landTextureSize; j++) { - int distanceX(0); - int distanceY(0); - if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; - if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; - if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize* abs(i_cell-cellX) + i; - if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; - if (i_cell == cellX) distanceX = abs(i-xHitInCell); - if (j_cell == cellY) distanceY = abs(j-yHitInCell); - distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); - if (distance < rf) mNew[j*landTextureSize+i] = brushInt; - } - else - { - int distanceX(0); - int distanceY(0); - if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; - if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; - if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; - if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; - if (i_cell == cellX) distanceX = abs(i-xHitInCell); - if (j_cell == cellY) distanceY = abs(j-yHitInCell); - distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); - if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + + if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + { + int distanceX(0); + int distanceY(0); + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize* abs(i_cell-cellX) + i; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; + if (i_cell == cellX) distanceX = abs(i-xHitInCell); + if (j_cell == cellY) distanceY = abs(j-yHitInCell); + distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); + if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + } + else + { + int distanceX(0); + int distanceY(0); + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; + if (i_cell == cellX) distanceX = abs(i-xHitInCell); + if (j_cell == cellY) distanceY = abs(j-yHitInCell); + distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); + if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + } } } + pushEditToCommand(mNew, document, landTable, iteratedCellId); } - pushEditToCommand(mNew, document, landTable, iteratedCellId); } } } + if (mBrushShape == 3) { // Not implemented @@ -510,6 +531,81 @@ void CSVRender::TerrainTextureMode::createTexture(std::string textureFileName) undoStack.endMacro(); } +bool CSVRender::TerrainTextureMode::allowLandTextureEditing(std::string cellId) +{ + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + CSMWorld::IdTree& cellTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); + + bool noCell = document.getData().getCells().searchId (cellId)==-1; + bool noLand = document.getData().getLand().searchId (cellId)==-1; + + if (noCell) + { + std::string mode = CSMPrefs::get()["Scene Drops"]["outside-landedit"].toString(); + + // target cell does not exist + if (mode=="Discard") + return false; + + if (mode=="Create cell and land, then edit") + { + std::unique_ptr createCommand ( + new CSMWorld::CreateCommand (cellTable, cellId)); + int parentIndex = cellTable.findColumnIndex (CSMWorld::Columns::ColumnId_Cell); + int index = cellTable.findNestedColumnIndex (parentIndex, CSMWorld::Columns::ColumnId_Interior); + createCommand->addNestedValue (parentIndex, index, false); + document.getUndoStack().push (createCommand.release()); + + if (CSVRender::PagedWorldspaceWidget *paged = + dynamic_cast (&getWorldspaceWidget())) + { + CSMWorld::CellSelection selection = paged->getCellSelection(); + selection.add (CSMWorld::CellCoordinates::fromId (cellId).first); + paged->setCellSelection (selection); + } + } + } + else if (CSVRender::PagedWorldspaceWidget *paged = + dynamic_cast (&getWorldspaceWidget())) + { + CSMWorld::CellSelection selection = paged->getCellSelection(); + if (!selection.has (CSMWorld::CellCoordinates::fromId (cellId).first)) + { + // target cell exists, but is not shown + std::string mode = + CSMPrefs::get()["Scene Drops"]["outside-visible-landedit"].toString(); + + if (mode=="Discard") + return false; + + if (mode=="Show cell and edit") + { + selection.add (CSMWorld::CellCoordinates::fromId (cellId).first); + paged->setCellSelection (selection); + } + } + } + + if (noLand) + { + std::string mode = CSMPrefs::get()["Scene Drops"]["outside-landedit"].toString(); + + // target cell does not exist + if (mode=="Discard") + return false; + + if (mode=="Create cell and land, then edit") + { + document.getUndoStack().push (new CSMWorld::CreateCommand (landTable, cellId)); + } + } + + return true; +} + void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) { } diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index f6fde3544..dcf16040e 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -126,6 +126,9 @@ namespace CSVRender /// \brief Create new land texture record from texture asset void createTexture(std::string textureFileName); + /// \brief Create new cell and land if needed + bool allowLandTextureEditing(std::string textureFileName); + private: TextureBrushWindow *textureBrushWindow; std::string mCellId; From 56567454455bd284da4d22d669688582690f7c8f Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 6 May 2018 18:02:18 +0300 Subject: [PATCH 18/50] Select dragged texture-assets, add brush settings widget-type, fixes. --- apps/opencs/CMakeLists.txt | 2 +- .../opencs/view/render/terraintexturemode.cpp | 162 +++------------- .../opencs/view/render/terraintexturemode.hpp | 54 +----- apps/opencs/view/render/worldspacewidget.cpp | 4 - apps/opencs/view/widget/scenetoolmode.cpp | 10 - apps/opencs/view/widget/scenetoolmode.hpp | 5 - .../view/widget/scenetooltexturebrush.cpp | 173 ++++++++++++++++++ .../view/widget/scenetooltexturebrush.hpp | 109 +++++++++++ 8 files changed, 310 insertions(+), 209 deletions(-) create mode 100644 apps/opencs/view/widget/scenetooltexturebrush.cpp create mode 100644 apps/opencs/view/widget/scenetooltexturebrush.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f8dd1fe2d..d1ebcde42 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -81,7 +81,7 @@ opencs_units_noqt (view/world opencs_units (view/widget scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton - scenetooltoggle2 completerpopup coloreditor colorpickerpopup droplineedit + scenetooltoggle2 scenetooltexturebrush completerpopup coloreditor colorpickerpopup droplineedit ) opencs_units (view/render diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 3468d4cd9..1c1c318d7 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -20,6 +20,7 @@ #include "../widget/modebutton.hpp" #include "../widget/scenetoolbar.hpp" +#include "../widget/scenetooltexturebrush.hpp" #include "../../model/doc/document.hpp" #include "../../model/prefs/state.hpp" @@ -41,138 +42,41 @@ #include "object.hpp" // Something small needed regarding pointers from here () #include "worldspacewidget.hpp" - -CSVRender::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent) - : QGroupBox(title, parent) -{ - brushSizeSlider = new QSlider(Qt::Horizontal); - brushSizeSlider->setTickPosition(QSlider::TicksBothSides); - brushSizeSlider->setTickInterval(10); - brushSizeSlider->setRange(1, 50); - brushSizeSlider->setSingleStep(1); - - brushSizeSpinBox = new QSpinBox; - brushSizeSpinBox->setRange(1, 50); - brushSizeSpinBox->setSingleStep(1); - - layoutSliderSize = new QHBoxLayout; - layoutSliderSize->addWidget(brushSizeSlider); - layoutSliderSize->addWidget(brushSizeSpinBox); - - connect(brushSizeSlider, SIGNAL(valueChanged(int)), brushSizeSpinBox, SLOT(setValue(int))); - connect(brushSizeSpinBox, SIGNAL(valueChanged(int)), brushSizeSlider, SLOT(setValue(int))); - - setLayout(layoutSliderSize); -} - -CSVRender::TextureBrushWindow::TextureBrushWindow(WorldspaceWidget *worldspaceWidget, QWidget *parent) - : QFrame(parent, Qt::Popup), - mWorldspaceWidget (worldspaceWidget), - mBrushSize(0), - mBrushShape(0) -{ - mBrushTextureLabel = "Brush: " + mBrushTexture; - selectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel), this); - - QVBoxLayout *layoutMain = new QVBoxLayout; - layoutMain->setSpacing(0); - - QHBoxLayout *layoutHorizontal = new QHBoxLayout; - layoutHorizontal->setContentsMargins (QMargins (0, 0, 0, 0)); - layoutHorizontal->setSpacing(0); - - configureButtonInitialSettings(buttonPoint); - configureButtonInitialSettings(buttonSquare); - configureButtonInitialSettings(buttonCircle); - configureButtonInitialSettings(buttonCustom); - - QButtonGroup* brushButtonGroup = new QButtonGroup(this); - brushButtonGroup->addButton(buttonPoint); - brushButtonGroup->addButton(buttonSquare); - brushButtonGroup->addButton(buttonCircle); - brushButtonGroup->addButton(buttonCustom); - - brushButtonGroup->setExclusive(true); - - layoutHorizontal->addWidget(buttonPoint); - layoutHorizontal->addWidget(buttonSquare); - layoutHorizontal->addWidget(buttonCircle); - layoutHorizontal->addWidget(buttonCustom); - - horizontalGroupBox = new QGroupBox(tr("")); - horizontalGroupBox->setLayout(layoutHorizontal); - - BrushSizeControls* sizeSliders = new BrushSizeControls(tr(""), this); - - layoutMain->addWidget(horizontalGroupBox); - layoutMain->addWidget(sizeSliders); - layoutMain->addWidget(selectedBrush); - - setLayout(layoutMain); - - connect(buttonPoint, SIGNAL(clicked()), this, SLOT(setBrushShape())); - connect(buttonSquare, SIGNAL(clicked()), this, SLOT(setBrushShape())); - connect(buttonCircle, SIGNAL(clicked()), this, SLOT(setBrushShape())); - connect(buttonCustom, SIGNAL(clicked()), this, SLOT(setBrushShape())); - - connect(sizeSliders->brushSizeSlider, SIGNAL(valueChanged(int)), parent, SLOT(setBrushSize(int))); - - connect(parent, SIGNAL(passBrushTexture(std::string)), this, SLOT(setBrushTexture(std::string))); -} - -void CSVRender::TextureBrushWindow::configureButtonInitialSettings(QPushButton *button) -{ - button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); - button->setContentsMargins (QMargins (0, 0, 0, 0)); - button->setIconSize (QSize (48-6, 48-6)); - button->setFixedSize (48, 48); - button->setAcceptDrops(true); - button->setCheckable(true); -} - -void CSVRender::TextureBrushWindow::setBrushTexture(std::string brushTexture) -{ - mBrushTexture = brushTexture; - mBrushTextureLabel = "Brush:" + mBrushTexture; - selectedBrush->setText(QString::fromStdString(mBrushTextureLabel)); -} - -void CSVRender::TextureBrushWindow::setBrushSize(int brushSize) -{ - mBrushSize = brushSize; - emit passBrushSize(mBrushSize); -} - -void CSVRender::TextureBrushWindow::setBrushShape() -{ - if(buttonPoint->isChecked()) mBrushShape = 0; - if(buttonSquare->isChecked()) mBrushShape = 1; - if(buttonCircle->isChecked()) mBrushShape = 2; - if(buttonCustom->isChecked()) mBrushShape = 3; - emit passBrushShape(mBrushShape); -} - CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) : EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent), - textureBrushWindow(new TextureBrushWindow(worldspaceWidget, this)), mBrushTexture("#0"), mBrushSize(0), - mBrushShape(0) + mBrushShape(0), + mTextureBrushScenetool(0) { - connect(parent, SIGNAL(passEvent(QDragEnterEvent*)), this, SLOT(handleDragEnterEvent(QDragEnterEvent*))); - connect(parent, SIGNAL(passEvent(QDropEvent*)), this, SLOT(handleDropEvent(QDropEvent*))); - connect(parent, SIGNAL(passEvent(QMouseEvent*)), this, SLOT(handleMouseEvent(QMouseEvent*))); - connect(textureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int))); - connect(textureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); } void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) { + if(!mTextureBrushScenetool) + { + mTextureBrushScenetool = new CSVWidget::SceneToolTextureBrush (toolbar, "scenetooltexturebrush"); + connect(mTextureBrushScenetool, SIGNAL (clicked()), mTextureBrushScenetool, SLOT (activate())); + connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int))); + connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); + connect(mTextureBrushScenetool->mTextureBrushWindow->mSizeSliders->mBrushSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrushSize(int))); + + connect(mTextureBrushScenetool, SIGNAL(passEvent(QDropEvent*)), this, SLOT(handleDropEvent(QDropEvent*))); + connect(this, SIGNAL(passBrushTexture(std::string)), mTextureBrushScenetool->mTextureBrushWindow, SLOT(setBrushTexture(std::string))); + } + EditMode::activate(toolbar); + toolbar->addTool (mTextureBrushScenetool); } void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) { + if(mTextureBrushScenetool) + { + toolbar->removeTool (mTextureBrushScenetool); + delete mTextureBrushScenetool; + mTextureBrushScenetool = 0; + } EditMode::deactivate(toolbar); } @@ -259,10 +163,6 @@ void CSVRender::TerrainTextureMode::dragAborted() { void CSVRender::TerrainTextureMode::dragWheel (int diff, double speedFactor) {} -void CSVRender::TerrainTextureMode::handleDragEnterEvent (QDragEnterEvent *event) { - event->accept(); -} - void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) { const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); @@ -287,24 +187,11 @@ void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) { { std::string textureFileName = uid.toString(); createTexture(textureFileName); + emit passBrushTexture(mBrushTexture); } } } -void CSVRender::TerrainTextureMode::handleMouseEvent (QMouseEvent *event) -{ - if (event->button()==Qt::MidButton) - { - QPoint position = QCursor::pos(); - textureBrushWindow->move (position); - textureBrushWindow->show(); - } - if (event->button()==Qt::LeftButton) PushButton::mouseReleaseEvent (event); -} - -void CSVRender::TerrainTextureMode::handlePrimarySelectOnModeButton () { -} - void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitResult& hit) { CSMDoc::Document& document = getWorldspaceWidget().getDocument(); @@ -529,6 +416,7 @@ void CSVRender::TerrainTextureMode::createTexture(std::string textureFileName) QModelIndex index(ltexTable.getModelIndex (newId, ltexTable.findColumnIndex (CSMWorld::Columns::ColumnId_Texture))); undoStack.push (new CSMWorld::ModifyCommand(ltexTable, index, textureFileNameVariant)); undoStack.endMacro(); + mBrushTexture = newId; } bool CSVRender::TerrainTextureMode::allowLandTextureEditing(std::string cellId) @@ -602,7 +490,7 @@ bool CSVRender::TerrainTextureMode::allowLandTextureEditing(std::string cellId) document.getUndoStack().push (new CSMWorld::CreateCommand (landTable, cellId)); } } - + return true; } diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index dcf16040e..212cff639 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -26,59 +26,12 @@ namespace CSVWidget { - class SceneToolMode; + class SceneToolTextureBrush; } namespace CSVRender { - /// \brief Layout-box for some brush button settings - class BrushSizeControls : public QGroupBox - { - Q_OBJECT - - public: - BrushSizeControls(const QString &title, QWidget *parent); - QSlider *brushSizeSlider; - - private: - QSpinBox *brushSizeSpinBox; - QHBoxLayout *layoutSliderSize; - }; - - /// \brief Brush settings window - class TextureBrushWindow : public QFrame - { - Q_OBJECT - - public: - TextureBrushWindow(WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); - void configureButtonInitialSettings(QPushButton *button); - - QPushButton *buttonPoint = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-point")), "", this); - QPushButton *buttonSquare = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-square")), "", this); - QPushButton *buttonCircle = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-circle")), "", this); - QPushButton *buttonCustom = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-custom")), "", this); - - private: - QLabel *selectedBrush; - QGroupBox *horizontalGroupBox; - WorldspaceWidget *mWorldspaceWidget; - int mBrushSize; - int mBrushShape; - std::string mBrushTexture; - std::string mBrushTextureLabel; - - public slots: - void setBrushTexture(std::string brushTexture); - void setBrushShape(); - void setBrushSize(int brushSize); - - signals: - void passBrushSize (int brushSize); - void passBrushShape(int brushShape); - }; - class TerrainTextureMode : public EditMode { Q_OBJECT @@ -130,11 +83,11 @@ namespace CSVRender bool allowLandTextureEditing(std::string textureFileName); private: - TextureBrushWindow *textureBrushWindow; std::string mCellId; std::string mBrushTexture; int mBrushSize; int mBrushShape; + CSVWidget::SceneToolTextureBrush *mTextureBrushScenetool; const int cellSize {ESM::Land::REAL_SIZE}; const int landSize {ESM::Land::LAND_SIZE}; @@ -144,10 +97,7 @@ namespace CSVRender void passBrushTexture(std::string brushTexture); public slots: - void handleDragEnterEvent (QDragEnterEvent *event); void handleDropEvent(QDropEvent *event); - void handleMouseEvent (QMouseEvent *event); - void handlePrimarySelectOnModeButton(); void setBrushSize(int brushSize); void setBrushShape(int brushShape); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index c8ba16666..9fb6aa02a 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -576,10 +576,6 @@ void CSVRender::WorldspaceWidget::debugProfileAboutToBeRemoved (const QModelInde void CSVRender::WorldspaceWidget::editModeChanged (const std::string& id) { - dynamic_cast (*mEditMode->getCurrent()).setEditLock (mLocked); - if (mEditMode->getCurrentId() == "terrain-texture") mEditMode->setAcceptDrops(true); - else mEditMode->setAcceptDrops(false); - mDragging = false; mDragMode = InteractionType_None; } diff --git a/apps/opencs/view/widget/scenetoolmode.cpp b/apps/opencs/view/widget/scenetoolmode.cpp index 94435016f..426bceb29 100644 --- a/apps/opencs/view/widget/scenetoolmode.cpp +++ b/apps/opencs/view/widget/scenetoolmode.cpp @@ -137,7 +137,6 @@ void CSVWidget::SceneToolMode::setButton (const std::string& id) void CSVWidget::SceneToolMode::mouseReleaseEvent (QMouseEvent *event) { - if (event->button()==Qt::MidButton && getCurrentId() == "terrain-texture") emit passEvent(event); if (getType()==Type_TopAction && event->button()==Qt::RightButton) showPanel (parentWidget()->mapToGlobal (pos())); else @@ -154,15 +153,6 @@ bool CSVWidget::SceneToolMode::event(QEvent* event) return SceneTool::event(event); } -void CSVWidget::SceneToolMode::dragEnterEvent (QDragEnterEvent *event) -{ - emit passEvent(event); -} -void CSVWidget::SceneToolMode::dropEvent (QDropEvent *event) -{ - emit passEvent(event); -} - void CSVWidget::SceneToolMode::selected() { std::map::iterator iter = diff --git a/apps/opencs/view/widget/scenetoolmode.hpp b/apps/opencs/view/widget/scenetoolmode.hpp index 7d0c8f70e..377357df6 100644 --- a/apps/opencs/view/widget/scenetoolmode.hpp +++ b/apps/opencs/view/widget/scenetoolmode.hpp @@ -49,8 +49,6 @@ namespace CSVWidget protected: bool event(QEvent* event); - void dragEnterEvent (QDragEnterEvent *event); - void dropEvent (QDropEvent *event); public: @@ -76,9 +74,6 @@ namespace CSVWidget signals: void modeChanged (const std::string& id); - void passEvent (QMouseEvent *event); - void passEvent (QDragEnterEvent *event); - void passEvent (QDropEvent *event); private slots: diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp new file mode 100644 index 000000000..abf65182c --- /dev/null +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -0,0 +1,173 @@ +#include "scenetooltexturebrush.hpp" + +#include + +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scenetool.hpp" + +CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent) + : QGroupBox(title, parent) +{ + mBrushSizeSlider = new QSlider(Qt::Horizontal); + mBrushSizeSlider->setTickPosition(QSlider::TicksBothSides); + mBrushSizeSlider->setTickInterval(10); + mBrushSizeSlider->setRange(1, 50); + mBrushSizeSlider->setSingleStep(1); + + mBrushSizeSpinBox = new QSpinBox; + mBrushSizeSpinBox->setRange(1, 50); + mBrushSizeSpinBox->setSingleStep(1); + + mLayoutSliderSize = new QHBoxLayout; + mLayoutSliderSize->addWidget(mBrushSizeSlider); + mLayoutSliderSize->addWidget(mBrushSizeSpinBox); + + connect(mBrushSizeSlider, SIGNAL(valueChanged(int)), mBrushSizeSpinBox, SLOT(setValue(int))); + connect(mBrushSizeSpinBox, SIGNAL(valueChanged(int)), mBrushSizeSlider, SLOT(setValue(int))); + + setLayout(mLayoutSliderSize); +} + +CSVWidget::TextureBrushWindow::TextureBrushWindow(QWidget *parent) + : QFrame(parent, Qt::Popup), + mBrushShape(0), + mBrushSize(0) + +{ + mBrushTextureLabel = "Brush: " + mBrushTexture; + mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel), this); + + QVBoxLayout *layoutMain = new QVBoxLayout; + layoutMain->setSpacing(0); + + QHBoxLayout *layoutHorizontal = new QHBoxLayout; + layoutHorizontal->setContentsMargins (QMargins (0, 0, 0, 0)); + layoutHorizontal->setSpacing(0); + + configureButtonInitialSettings(mButtonPoint); + configureButtonInitialSettings(mButtonSquare); + configureButtonInitialSettings(mButtonCircle); + configureButtonInitialSettings(mButtonCustom); + + QButtonGroup* brushButtonGroup = new QButtonGroup(this); + brushButtonGroup->addButton(mButtonPoint); + brushButtonGroup->addButton(mButtonSquare); + brushButtonGroup->addButton(mButtonCircle); + brushButtonGroup->addButton(mButtonCustom); + + brushButtonGroup->setExclusive(true); + + layoutHorizontal->addWidget(mButtonPoint); + layoutHorizontal->addWidget(mButtonSquare); + layoutHorizontal->addWidget(mButtonCircle); + layoutHorizontal->addWidget(mButtonCustom); + + mHorizontalGroupBox = new QGroupBox(tr("")); + mHorizontalGroupBox->setLayout(layoutHorizontal); + + layoutMain->addWidget(mHorizontalGroupBox); + layoutMain->addWidget(mSizeSliders); + layoutMain->addWidget(mSelectedBrush); + + setLayout(layoutMain); + + connect(mButtonPoint, SIGNAL(clicked()), this, SLOT(setBrushShape())); + connect(mButtonSquare, SIGNAL(clicked()), this, SLOT(setBrushShape())); + connect(mButtonCircle, SIGNAL(clicked()), this, SLOT(setBrushShape())); + connect(mButtonCustom, SIGNAL(clicked()), this, SLOT(setBrushShape())); +} + +void CSVWidget::TextureBrushWindow::configureButtonInitialSettings(QPushButton *button) +{ + button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); + button->setContentsMargins (QMargins (0, 0, 0, 0)); + button->setIconSize (QSize (48-6, 48-6)); + button->setFixedSize (48, 48); + button->setCheckable(true); +} + +void CSVWidget::TextureBrushWindow::setBrushTexture(std::string brushTexture) +{ + mBrushTexture = brushTexture; + mBrushTextureLabel = "Brush:" + mBrushTexture; + mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel)); +} + +void CSVWidget::TextureBrushWindow::setBrushSize(int brushSize) +{ + mBrushSize = brushSize; + emit passBrushSize(mBrushSize); +} + +void CSVWidget::TextureBrushWindow::setBrushShape() +{ + if(mButtonPoint->isChecked()) mBrushShape = 0; + if(mButtonSquare->isChecked()) mBrushShape = 1; + if(mButtonCircle->isChecked()) mBrushShape = 2; + if(mButtonCustom->isChecked()) mBrushShape = 3; + emit passBrushShape(mBrushShape); +} + +void CSVWidget::SceneToolTextureBrush::adjustToolTips() +{ +} + +CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip) +: SceneTool (parent), + mToolTip (toolTip), + mTextureBrushWindow(new TextureBrushWindow(this)) +{ + setAcceptDrops(true); + if(mTextureBrushWindow->mBrushShape == 0) setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); + if(mTextureBrushWindow->mBrushShape == 1) setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); + if(mTextureBrushWindow->mBrushShape == 2) setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); + if(mTextureBrushWindow->mBrushShape == 3) setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); + connect(mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setButtonIcon(int))); +} + +void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) +{ + if(brushShape == 0) setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); + if(brushShape == 1) setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); + if(brushShape == 2) setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); + if(brushShape == 3) setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); +} + +void CSVWidget::SceneToolTextureBrush::showPanel (const QPoint& position) +{ + +} + +void CSVWidget::SceneToolTextureBrush::activate () +{ + QPoint position = QCursor::pos(); + mTextureBrushWindow->move (position); + mTextureBrushWindow->show(); +} + +void CSVWidget::SceneToolTextureBrush::dragEnterEvent (QDragEnterEvent *event) +{ + emit passEvent(event); + event->accept(); +} +void CSVWidget::SceneToolTextureBrush::dropEvent (QDropEvent *event) +{ + emit passEvent(event); + event->accept(); +} diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp new file mode 100644 index 000000000..d9cc1e566 --- /dev/null +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -0,0 +1,109 @@ +#ifndef CSV_WIDGET_SCENETOOLTEXTUREBRUSH_H +#define CSV_WIDGET_SCENETOOLTEXTUREBRUSH_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scenetool.hpp" + +/*namespace CSVRender +{ + class TerrainTextureMode; +}*/ + +namespace CSVWidget +{ + /// \brief Layout-box for some brush button settings + class BrushSizeControls : public QGroupBox + { + Q_OBJECT + + public: + BrushSizeControls(const QString &title, QWidget *parent); + QSlider *mBrushSizeSlider; + + private: + QSpinBox *mBrushSizeSpinBox; + QHBoxLayout *mLayoutSliderSize; + }; + + /// \brief Brush settings window + class TextureBrushWindow : public QFrame + { + Q_OBJECT + + public: + TextureBrushWindow(QWidget *parent = 0); + void configureButtonInitialSettings(QPushButton *button); + + QPushButton *mButtonPoint = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-point")), "", this); + QPushButton *mButtonSquare = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-square")), "", this); + QPushButton *mButtonCircle = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-circle")), "", this); + QPushButton *mButtonCustom = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-custom")), "", this); + BrushSizeControls* mSizeSliders = new BrushSizeControls(tr(""), this); + int mBrushShape; + + private: + QLabel *mSelectedBrush; + QGroupBox *mHorizontalGroupBox; + int mBrushSize; + std::string mBrushTexture; + std::string mBrushTextureLabel; + + public slots: + void setBrushTexture(std::string brushTexture); + void setBrushShape(); + void setBrushSize(int brushSize); + + signals: + void passBrushSize (int brushSize); + void passBrushShape(int brushShape); + }; + + class SceneToolTextureBrush : public SceneTool + { + Q_OBJECT + + QString mToolTip; + + //CSVRender::TerrainTextureMode *mTerrainTextureMode; + //QIcon *mTextureBrushIcon; + + private: + + void adjustToolTips(); + + public: + + SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip); + + virtual void showPanel (const QPoint& position); + + TextureBrushWindow *mTextureBrushWindow; + //virtual void activate(); + + void dropEvent (QDropEvent *event); + void dragEnterEvent (QDragEnterEvent *event); + + public slots: + void setButtonIcon(int brushShape); + virtual void activate(); + //void clicked (); + + signals: + void passEvent(QDropEvent *event); + void passEvent(QDragEnterEvent *event); + }; +} + +#endif From d33c98c68d6b56ac4377d64b90140c1954b2f0b3 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 6 May 2018 18:13:15 +0300 Subject: [PATCH 19/50] Revert unintended changes --- apps/opencs/view/render/worldspacewidget.cpp | 1 + apps/opencs/view/widget/scenetoolmode.cpp | 9 --------- apps/opencs/view/widget/scenetoolmode.hpp | 2 -- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 9fb6aa02a..c2a6617c1 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -576,6 +576,7 @@ void CSVRender::WorldspaceWidget::debugProfileAboutToBeRemoved (const QModelInde void CSVRender::WorldspaceWidget::editModeChanged (const std::string& id) { + dynamic_cast (*mEditMode->getCurrent()).setEditLock (mLocked); mDragging = false; mDragMode = InteractionType_None; } diff --git a/apps/opencs/view/widget/scenetoolmode.cpp b/apps/opencs/view/widget/scenetoolmode.cpp index 426bceb29..7b2ff64db 100644 --- a/apps/opencs/view/widget/scenetoolmode.cpp +++ b/apps/opencs/view/widget/scenetoolmode.cpp @@ -134,15 +134,6 @@ void CSVWidget::SceneToolMode::setButton (const std::string& id) } } - -void CSVWidget::SceneToolMode::mouseReleaseEvent (QMouseEvent *event) -{ - if (getType()==Type_TopAction && event->button()==Qt::RightButton) - showPanel (parentWidget()->mapToGlobal (pos())); - else - PushButton::mouseReleaseEvent (event); -} - bool CSVWidget::SceneToolMode::event(QEvent* event) { if (event->type() == QEvent::ToolTip) diff --git a/apps/opencs/view/widget/scenetoolmode.hpp b/apps/opencs/view/widget/scenetoolmode.hpp index 377357df6..90f1dc419 100644 --- a/apps/opencs/view/widget/scenetoolmode.hpp +++ b/apps/opencs/view/widget/scenetoolmode.hpp @@ -44,8 +44,6 @@ namespace CSVWidget void setButton (std::map::iterator iter); - void mouseReleaseEvent (QMouseEvent *event); - protected: bool event(QEvent* event); From 62066f01bd417a8a513daa5a81f73ddb2bfe9e88 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 6 May 2018 18:51:58 +0300 Subject: [PATCH 20/50] clean-up --- apps/opencs/view/render/terraintexturemode.cpp | 6 ------ apps/opencs/view/render/terraintexturemode.hpp | 8 -------- apps/opencs/view/widget/scenetooltexturebrush.cpp | 4 ---- apps/opencs/view/widget/scenetooltexturebrush.hpp | 5 ----- 4 files changed, 23 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 1c1c318d7..33822291b 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -5,14 +5,8 @@ #include #include -#include -#include -#include #include #include -#include -#include -#include #include #include diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 212cff639..084f4c637 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -6,15 +6,7 @@ #include #include -#include -#include -#include -#include -#include -#include #include -#include -#include #include "../../model/world/data.hpp" #include "../../model/world/land.hpp" diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index abf65182c..ddc921729 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -1,13 +1,10 @@ #include "scenetooltexturebrush.hpp" -#include - #include #include #include #include - #include #include #include @@ -151,7 +148,6 @@ void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) void CSVWidget::SceneToolTextureBrush::showPanel (const QPoint& position) { - } void CSVWidget::SceneToolTextureBrush::activate () diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp index d9cc1e566..66d40ca53 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.hpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -76,9 +76,6 @@ namespace CSVWidget QString mToolTip; - //CSVRender::TerrainTextureMode *mTerrainTextureMode; - //QIcon *mTextureBrushIcon; - private: void adjustToolTips(); @@ -90,7 +87,6 @@ namespace CSVWidget virtual void showPanel (const QPoint& position); TextureBrushWindow *mTextureBrushWindow; - //virtual void activate(); void dropEvent (QDropEvent *event); void dragEnterEvent (QDragEnterEvent *event); @@ -98,7 +94,6 @@ namespace CSVWidget public slots: void setButtonIcon(int brushShape); virtual void activate(); - //void clicked (); signals: void passEvent(QDropEvent *event); From d2cf764a46e1358dda4bd8bcde036afc905d57cb Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Thu, 10 May 2018 15:01:53 +0300 Subject: [PATCH 21/50] Tooltips, fixes --- .../view/widget/scenetooltexturebrush.cpp | 58 +++++++++++++------ .../view/widget/scenetooltexturebrush.hpp | 10 +++- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index ddc921729..07682cbca 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -44,24 +44,30 @@ CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *p CSVWidget::TextureBrushWindow::TextureBrushWindow(QWidget *parent) : QFrame(parent, Qt::Popup), mBrushShape(0), - mBrushSize(0) - + mBrushSize(0), + mBrushTexture("L0#0") { - mBrushTextureLabel = "Brush: " + mBrushTexture; + mBrushTextureLabel = "Selected texture (id): " + mBrushTexture; mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel), this); QVBoxLayout *layoutMain = new QVBoxLayout; layoutMain->setSpacing(0); + layoutMain->setContentsMargins(4,0,4,4); QHBoxLayout *layoutHorizontal = new QHBoxLayout; - layoutHorizontal->setContentsMargins (QMargins (0, 0, 0, 0)); layoutHorizontal->setSpacing(0); + layoutHorizontal->setContentsMargins (QMargins (0, 0, 0, 0)); configureButtonInitialSettings(mButtonPoint); configureButtonInitialSettings(mButtonSquare); configureButtonInitialSettings(mButtonCircle); configureButtonInitialSettings(mButtonCustom); + mButtonPoint->setToolTip (toolTipPoint); + mButtonSquare->setToolTip (toolTipSquare); + mButtonCircle->setToolTip (toolTipCircle); + mButtonCustom->setToolTip (toolTipCustom); + QButtonGroup* brushButtonGroup = new QButtonGroup(this); brushButtonGroup->addButton(mButtonPoint); brushButtonGroup->addButton(mButtonSquare); @@ -70,10 +76,10 @@ CSVWidget::TextureBrushWindow::TextureBrushWindow(QWidget *parent) brushButtonGroup->setExclusive(true); - layoutHorizontal->addWidget(mButtonPoint); - layoutHorizontal->addWidget(mButtonSquare); - layoutHorizontal->addWidget(mButtonCircle); - layoutHorizontal->addWidget(mButtonCustom); + layoutHorizontal->addWidget(mButtonPoint, 0, Qt::AlignTop); + layoutHorizontal->addWidget(mButtonSquare, 0, Qt::AlignTop); + layoutHorizontal->addWidget(mButtonCircle, 0, Qt::AlignTop); + layoutHorizontal->addWidget(mButtonCustom, 0, Qt::AlignTop); mHorizontalGroupBox = new QGroupBox(tr("")); mHorizontalGroupBox->setLayout(layoutHorizontal); @@ -102,8 +108,9 @@ void CSVWidget::TextureBrushWindow::configureButtonInitialSettings(QPushButton * void CSVWidget::TextureBrushWindow::setBrushTexture(std::string brushTexture) { mBrushTexture = brushTexture; - mBrushTextureLabel = "Brush:" + mBrushTexture; + mBrushTextureLabel = "Selected texture (id): " + mBrushTexture; mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel)); + emit passBrushShape(mBrushShape); // update icon } void CSVWidget::TextureBrushWindow::setBrushSize(int brushSize) @@ -131,19 +138,36 @@ CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, c mTextureBrushWindow(new TextureBrushWindow(this)) { setAcceptDrops(true); - if(mTextureBrushWindow->mBrushShape == 0) setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); - if(mTextureBrushWindow->mBrushShape == 1) setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); - if(mTextureBrushWindow->mBrushShape == 2) setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); - if(mTextureBrushWindow->mBrushShape == 3) setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); connect(mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setButtonIcon(int))); + setButtonIcon(mTextureBrushWindow->mBrushShape); } void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) { - if(brushShape == 0) setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); - if(brushShape == 1) setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); - if(brushShape == 2) setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); - if(brushShape == 3) setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); + QString tooltip = "Brush settings

Currently selected: "; + if(brushShape == 0) + { + setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); + tooltip += dynamic_cast (mTextureBrushWindow->toolTipPoint); + } + if(brushShape == 1) + { + setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); + tooltip += dynamic_cast (mTextureBrushWindow->toolTipSquare); + } + if(brushShape == 2) + { + setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); + tooltip += dynamic_cast (mTextureBrushWindow->toolTipCircle); + } + if(brushShape == 3) + { + setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); + tooltip += dynamic_cast (mTextureBrushWindow->toolTipCustom); + } + tooltip += "

Selected texture: " + QString::fromStdString(mTextureBrushWindow->mBrushTexture); + tooltip += "
(drop texture here to change)"; + setToolTip (tooltip); } void CSVWidget::SceneToolTextureBrush::showPanel (const QPoint& position) diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp index 66d40ca53..1bf15ead9 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.hpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -50,14 +50,18 @@ namespace CSVWidget QPushButton *mButtonSquare = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-square")), "", this); QPushButton *mButtonCircle = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-circle")), "", this); QPushButton *mButtonCustom = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-custom")), "", this); - BrushSizeControls* mSizeSliders = new BrushSizeControls(tr(""), this); + QString toolTipPoint = "Paint single point"; + QString toolTipSquare = "Paint with square brush"; + QString toolTipCircle = "Paint with circle brush"; + QString toolTipCustom = "Paint custom selection (not implemented yet)"; + BrushSizeControls* mSizeSliders = new BrushSizeControls("Brush size", this); int mBrushShape; + int mBrushSize; + std::string mBrushTexture; private: QLabel *mSelectedBrush; QGroupBox *mHorizontalGroupBox; - int mBrushSize; - std::string mBrushTexture; std::string mBrushTextureLabel; public slots: From 1c79d5311c198f49ce3efea7f536daa85b424dfa Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Thu, 10 May 2018 21:58:36 +0300 Subject: [PATCH 22/50] Brush history menu --- .../opencs/view/render/terraintexturemode.cpp | 7 ++ .../opencs/view/render/terraintexturemode.hpp | 2 +- .../view/widget/scenetooltexturebrush.cpp | 72 ++++++++++++++++++- .../view/widget/scenetooltexturebrush.hpp | 12 ++-- 4 files changed, 87 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 33822291b..ea68cfa93 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -54,9 +54,11 @@ void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int))); connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); connect(mTextureBrushScenetool->mTextureBrushWindow->mSizeSliders->mBrushSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrushSize(int))); + connect(mTextureBrushScenetool, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string))); connect(mTextureBrushScenetool, SIGNAL(passEvent(QDropEvent*)), this, SLOT(handleDropEvent(QDropEvent*))); connect(this, SIGNAL(passBrushTexture(std::string)), mTextureBrushScenetool->mTextureBrushWindow, SLOT(setBrushTexture(std::string))); + connect(this, SIGNAL(passBrushTexture(std::string)), mTextureBrushScenetool, SLOT(updateBrushHistory(std::string))); } EditMode::activate(toolbar); @@ -500,3 +502,8 @@ void CSVRender::TerrainTextureMode::setBrushShape(int brushShape) { mBrushShape = brushShape; } + +void CSVRender::TerrainTextureMode::setBrushTexture(std::string brushTexture) +{ + mBrushTexture = brushTexture; +} diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 084f4c637..e1538e243 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -92,7 +92,7 @@ namespace CSVRender void handleDropEvent(QDropEvent *event); void setBrushSize(int brushSize); void setBrushShape(int brushShape); - + void setBrushTexture(std::string brushShape); }; } diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index 07682cbca..990963415 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -15,6 +15,10 @@ #include #include #include +#include +#include +#include +#include #include "scenetool.hpp" @@ -133,13 +137,40 @@ void CSVWidget::SceneToolTextureBrush::adjustToolTips() } CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip) -: SceneTool (parent), +: SceneTool (parent, Type_TopAction), mToolTip (toolTip), + mBrushHistory{"L0#0"}, mTextureBrushWindow(new TextureBrushWindow(this)) { setAcceptDrops(true); connect(mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setButtonIcon(int))); setButtonIcon(mTextureBrushWindow->mBrushShape); + + mPanel = new QFrame (this, Qt::Popup); + + QHBoxLayout *layout = new QHBoxLayout (mPanel); + + layout->setContentsMargins (QMargins (0, 0, 0, 0)); + + mTable = new QTableWidget (0, 2, this); + + mTable->setShowGrid (true); + mTable->verticalHeader()->hide(); + mTable->horizontalHeader()->hide(); +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + mTable->horizontalHeader()->setSectionResizeMode (0, QHeaderView::Stretch); + mTable->horizontalHeader()->setSectionResizeMode (1, QHeaderView::ResizeToContents); +#else + mTable->horizontalHeader()->setResizeMode (0, QHeaderView::Stretch); + mTable->horizontalHeader()->setResizeMode (1, QHeaderView::ResizeToContents); +#endif + mTable->setSelectionMode (QAbstractItemView::NoSelection); + + layout->addWidget (mTable); + + connect (mTable, SIGNAL (clicked (const QModelIndex&)), + this, SLOT (clicked (const QModelIndex&))); + } void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) @@ -172,6 +203,45 @@ void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) void CSVWidget::SceneToolTextureBrush::showPanel (const QPoint& position) { + updatePanel(); + mPanel->move (position); + mPanel->show(); +} + +void CSVWidget::SceneToolTextureBrush::updatePanel() +{ + mTable->setRowCount (mBrushHistory.size()); + + mTable->setItem (0, 1, new QTableWidgetItem ( + QApplication::style()->standardIcon (QStyle::SP_TitleBarCloseButton), "")); + + for (int i = mBrushHistory.size()-1; i >= 0; --i) + { + mTable->setItem (i, 0, new QTableWidgetItem (QString::fromStdString(mBrushHistory[i]))); + } +} + +void CSVWidget::SceneToolTextureBrush::updateBrushHistory (const std::string& brushTexture) +{ + mBrushHistory.insert(mBrushHistory.begin(), brushTexture); + if(mBrushHistory.size() > 5) mBrushHistory.pop_back(); +} + +void CSVWidget::SceneToolTextureBrush::clicked (const QModelIndex& index) +{ + if (index.column()==0) + { + std::string brushTexture = mBrushHistory[index.row()]; + std::swap(mBrushHistory[index.row()], mBrushHistory[0]); + mTextureBrushWindow->setBrushTexture(brushTexture); + emit passTextureId(brushTexture); + updatePanel(); + mPanel->hide(); + } + else if (index.column()==1) + { + mPanel->hide(); + } } void CSVWidget::SceneToolTextureBrush::activate () diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp index 1bf15ead9..982ccc3aa 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.hpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -16,10 +16,7 @@ #include "scenetool.hpp" -/*namespace CSVRender -{ - class TerrainTextureMode; -}*/ +class QTableWidget; namespace CSVWidget { @@ -79,6 +76,9 @@ namespace CSVWidget Q_OBJECT QString mToolTip; + QFrame *mPanel; + QTableWidget *mTable; + std::vector mBrushHistory; private: @@ -89,6 +89,7 @@ namespace CSVWidget SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip); virtual void showPanel (const QPoint& position); + void updatePanel (); TextureBrushWindow *mTextureBrushWindow; @@ -97,11 +98,14 @@ namespace CSVWidget public slots: void setButtonIcon(int brushShape); + void updateBrushHistory (const std::string& mBrushTexture); + void clicked (const QModelIndex& index); virtual void activate(); signals: void passEvent(QDropEvent *event); void passEvent(QDragEnterEvent *event); + void passTextureId(std::string brushTexture); }; } From 49ae5bc75c59b2c645267ea535f5753e13299188 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Thu, 10 May 2018 22:57:48 +0300 Subject: [PATCH 23/50] List initialization -> initialization in constructor --- apps/opencs/view/widget/scenetooltexturebrush.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index 990963415..2a41ce091 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -139,9 +139,11 @@ void CSVWidget::SceneToolTextureBrush::adjustToolTips() CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip) : SceneTool (parent, Type_TopAction), mToolTip (toolTip), - mBrushHistory{"L0#0"}, mTextureBrushWindow(new TextureBrushWindow(this)) { + mBrushHistory.resize(1); + mBrushHistory[0] = "L0#0"; + setAcceptDrops(true); connect(mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setButtonIcon(int))); setButtonIcon(mTextureBrushWindow->mBrushShape); From 758ccac75aace490d5d2d3877c2e03823117fc20 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Wed, 16 May 2018 11:34:58 +0300 Subject: [PATCH 24/50] Show texture id + filename --- .../opencs/view/render/terraintexturemode.cpp | 2 +- .../view/widget/scenetooltexturebrush.cpp | 62 +++++++++++++------ .../view/widget/scenetooltexturebrush.hpp | 8 ++- 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index ea68cfa93..2b5e9ca59 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -49,7 +49,7 @@ void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) { if(!mTextureBrushScenetool) { - mTextureBrushScenetool = new CSVWidget::SceneToolTextureBrush (toolbar, "scenetooltexturebrush"); + mTextureBrushScenetool = new CSVWidget::SceneToolTextureBrush (toolbar, "scenetooltexturebrush", getWorldspaceWidget().getDocument()); connect(mTextureBrushScenetool, SIGNAL (clicked()), mTextureBrushScenetool, SLOT (activate())); connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int))); connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index 2a41ce091..003ab12fd 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -21,6 +21,11 @@ #include #include "scenetool.hpp" +#include "../../model/doc/document.hpp" +#include "../../model/world/data.hpp" +#include "../../model/world/idtable.hpp" +#include "../../model/world/landtexture.hpp" + CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent) : QGroupBox(title, parent) @@ -45,14 +50,21 @@ CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *p setLayout(mLayoutSliderSize); } -CSVWidget::TextureBrushWindow::TextureBrushWindow(QWidget *parent) +CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QWidget *parent) : QFrame(parent, Qt::Popup), mBrushShape(0), mBrushSize(0), - mBrushTexture("L0#0") + mBrushTexture("L0#0"), + mDocument(document) { - mBrushTextureLabel = "Selected texture (id): " + mBrushTexture; - mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel), this); + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + + int landTextureFilename = ltexTable.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + + QModelIndex index = ltexTable.getModelIndex (mBrushTexture, landTextureFilename); + mBrushTextureLabel = "Selected texture: " + mBrushTexture + " "; + mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel) + ltexTable.data(index).value()); QVBoxLayout *layoutMain = new QVBoxLayout; layoutMain->setSpacing(0); @@ -111,10 +123,16 @@ void CSVWidget::TextureBrushWindow::configureButtonInitialSettings(QPushButton * void CSVWidget::TextureBrushWindow::setBrushTexture(std::string brushTexture) { + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + int landTextureFilename = ltexTable.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + mBrushTexture = brushTexture; - mBrushTextureLabel = "Selected texture (id): " + mBrushTexture; - mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel)); + mBrushTextureLabel = "Selected texture: " + mBrushTexture + " "; + QModelIndex index = ltexTable.getModelIndex (mBrushTexture, landTextureFilename); + mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel) + ltexTable.data(index).value()); emit passBrushShape(mBrushShape); // update icon + } void CSVWidget::TextureBrushWindow::setBrushSize(int brushSize) @@ -136,10 +154,11 @@ void CSVWidget::SceneToolTextureBrush::adjustToolTips() { } -CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip) +CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip, CSMDoc::Document& document) : SceneTool (parent, Type_TopAction), mToolTip (toolTip), - mTextureBrushWindow(new TextureBrushWindow(this)) + mDocument (document), + mTextureBrushWindow(new TextureBrushWindow(document, this)) { mBrushHistory.resize(1); mBrushHistory[0] = "L0#0"; @@ -161,10 +180,10 @@ CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, c mTable->horizontalHeader()->hide(); #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) mTable->horizontalHeader()->setSectionResizeMode (0, QHeaderView::Stretch); - mTable->horizontalHeader()->setSectionResizeMode (1, QHeaderView::ResizeToContents); + mTable->horizontalHeader()->setSectionResizeMode (1, QHeaderView::Stretch); #else mTable->horizontalHeader()->setResizeMode (0, QHeaderView::Stretch); - mTable->horizontalHeader()->setResizeMode (1, QHeaderView::ResizeToContents); + mTable->horizontalHeader()->setResizeMode (1, QHeaderView::Stretch); #endif mTable->setSelectionMode (QAbstractItemView::NoSelection); @@ -198,7 +217,14 @@ void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); tooltip += dynamic_cast (mTextureBrushWindow->toolTipCustom); } - tooltip += "

Selected texture: " + QString::fromStdString(mTextureBrushWindow->mBrushTexture); + tooltip += "

Selected texture: " + QString::fromStdString(mTextureBrushWindow->mBrushTexture) + " "; + + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + int landTextureFilename = ltexTable.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + QModelIndex index = ltexTable.getModelIndex (mTextureBrushWindow->mBrushTexture, landTextureFilename); + tooltip += ltexTable.data(index).value(); + tooltip += "
(drop texture here to change)"; setToolTip (tooltip); } @@ -214,11 +240,13 @@ void CSVWidget::SceneToolTextureBrush::updatePanel() { mTable->setRowCount (mBrushHistory.size()); - mTable->setItem (0, 1, new QTableWidgetItem ( - QApplication::style()->standardIcon (QStyle::SP_TitleBarCloseButton), "")); - for (int i = mBrushHistory.size()-1; i >= 0; --i) { + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + int landTextureFilename = ltexTable.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + QModelIndex index = ltexTable.getModelIndex (mBrushHistory[i], landTextureFilename); + mTable->setItem (i, 1, new QTableWidgetItem (ltexTable.data(index).value())); mTable->setItem (i, 0, new QTableWidgetItem (QString::fromStdString(mBrushHistory[i]))); } } @@ -231,7 +259,7 @@ void CSVWidget::SceneToolTextureBrush::updateBrushHistory (const std::string& br void CSVWidget::SceneToolTextureBrush::clicked (const QModelIndex& index) { - if (index.column()==0) + if (index.column()==0 || index.column()==1) { std::string brushTexture = mBrushHistory[index.row()]; std::swap(mBrushHistory[index.row()], mBrushHistory[0]); @@ -240,10 +268,6 @@ void CSVWidget::SceneToolTextureBrush::clicked (const QModelIndex& index) updatePanel(); mPanel->hide(); } - else if (index.column()==1) - { - mPanel->hide(); - } } void CSVWidget::SceneToolTextureBrush::activate () diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp index 982ccc3aa..1c0e0a334 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.hpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -16,6 +16,8 @@ #include "scenetool.hpp" +#include "../../model/doc/document.hpp" + class QTableWidget; namespace CSVWidget @@ -40,7 +42,7 @@ namespace CSVWidget Q_OBJECT public: - TextureBrushWindow(QWidget *parent = 0); + TextureBrushWindow(CSMDoc::Document& document, QWidget *parent = 0); void configureButtonInitialSettings(QPushButton *button); QPushButton *mButtonPoint = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-point")), "", this); @@ -57,6 +59,7 @@ namespace CSVWidget std::string mBrushTexture; private: + CSMDoc::Document& mDocument; QLabel *mSelectedBrush; QGroupBox *mHorizontalGroupBox; std::string mBrushTextureLabel; @@ -76,6 +79,7 @@ namespace CSVWidget Q_OBJECT QString mToolTip; + CSMDoc::Document& mDocument; QFrame *mPanel; QTableWidget *mTable; std::vector mBrushHistory; @@ -86,7 +90,7 @@ namespace CSVWidget public: - SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip); + SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip, CSMDoc::Document& document); virtual void showPanel (const QPoint& position); void updatePanel (); From 17e01ca336ae232114666866b92f949c5278ad71 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Wed, 16 May 2018 11:41:37 +0300 Subject: [PATCH 25/50] Setting "Scene Drops" rename "3D Scene Editing" --- apps/opencs/model/prefs/state.cpp | 2 +- apps/opencs/view/render/instancemode.cpp | 4 ++-- apps/opencs/view/render/terraintexturemode.cpp | 6 +++--- apps/opencs/view/render/worldspacewidget.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 6cbc33766..99cbd98db 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -230,7 +230,7 @@ void CSMPrefs::State::declare() EnumValues landeditOutsideVisibleCell; landeditOutsideVisibleCell.add (showAndLandEdit).add (dontLandEdit); - declareCategory ("Scene Drops"); + declareCategory ("3D Scene Editing"); declareInt ("distance", "Drop Distance", 50). setTooltip ("If an instance drop can not be placed against another object at the " "insert point, it will be placed by this distance from the insert point instead"); diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index ee3e18d71..4b14e29bf 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -551,7 +551,7 @@ void CSVRender::InstanceMode::dropEvent (QDropEvent* event) if (noCell) { - std::string mode = CSMPrefs::get()["Scene Drops"]["outside-drop"].toString(); + std::string mode = CSMPrefs::get()["3D Scene Editing"]["outside-drop"].toString(); // target cell does not exist if (mode=="Discard") @@ -585,7 +585,7 @@ void CSVRender::InstanceMode::dropEvent (QDropEvent* event) { // target cell exists, but is not shown std::string mode = - CSMPrefs::get()["Scene Drops"]["outside-visible-drop"].toString(); + CSMPrefs::get()["3D Scene Editing"]["outside-visible-drop"].toString(); if (mode=="Discard") return; diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 2b5e9ca59..c7ffe6b38 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -428,7 +428,7 @@ bool CSVRender::TerrainTextureMode::allowLandTextureEditing(std::string cellId) if (noCell) { - std::string mode = CSMPrefs::get()["Scene Drops"]["outside-landedit"].toString(); + std::string mode = CSMPrefs::get()["3D Scene Editing"]["outside-landedit"].toString(); // target cell does not exist if (mode=="Discard") @@ -460,7 +460,7 @@ bool CSVRender::TerrainTextureMode::allowLandTextureEditing(std::string cellId) { // target cell exists, but is not shown std::string mode = - CSMPrefs::get()["Scene Drops"]["outside-visible-landedit"].toString(); + CSMPrefs::get()["3D Scene Editing"]["outside-visible-landedit"].toString(); if (mode=="Discard") return false; @@ -475,7 +475,7 @@ bool CSVRender::TerrainTextureMode::allowLandTextureEditing(std::string cellId) if (noLand) { - std::string mode = CSMPrefs::get()["Scene Drops"]["outside-landedit"].toString(); + std::string mode = CSMPrefs::get()["3D Scene Editing"]["outside-landedit"].toString(); // target cell does not exist if (mode=="Discard") diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index c2a6617c1..084fb87e6 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -445,7 +445,7 @@ CSVRender::WorldspaceHitResult CSVRender::WorldspaceWidget::mousePick (const QPo // Default placement direction.normalize(); - direction *= CSMPrefs::get()["Scene Drops"]["distance"].toInt(); + direction *= CSMPrefs::get()["3D Scene Editing"]["distance"].toInt(); WorldspaceHitResult hit = { false, 0, 0, 0, 0, start + direction }; return hit; From c2cddc91e42768b67f93be0a51f5d9c1491248fd Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Fri, 18 May 2018 11:32:42 +0300 Subject: [PATCH 26/50] Brush maximum size to a custom setting --- apps/opencs/model/prefs/state.cpp | 2 ++ apps/opencs/view/widget/scenetooltexturebrush.cpp | 8 ++++++-- apps/opencs/view/widget/scenetooltexturebrush.hpp | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 99cbd98db..6f64da72e 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -242,6 +242,8 @@ void CSMPrefs::State::declare() addValues (landeditOutsideCell); declareEnum ("outside-visible-landedit", "Handling land edit outside of visible cells", showAndLandEdit). addValues (landeditOutsideVisibleCell); + declareInt ("texturebrush-maximumsize", "Maximum texture brush size", 50). + setMin (1); declareCategory ("Key Bindings"); diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index 003ab12fd..76727a7a9 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -21,7 +21,9 @@ #include #include "scenetool.hpp" + #include "../../model/doc/document.hpp" +#include "../../model/prefs/state.hpp" #include "../../model/world/data.hpp" #include "../../model/world/idtable.hpp" #include "../../model/world/landtexture.hpp" @@ -33,11 +35,11 @@ CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *p mBrushSizeSlider = new QSlider(Qt::Horizontal); mBrushSizeSlider->setTickPosition(QSlider::TicksBothSides); mBrushSizeSlider->setTickInterval(10); - mBrushSizeSlider->setRange(1, 50); + mBrushSizeSlider->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt()); mBrushSizeSlider->setSingleStep(1); mBrushSizeSpinBox = new QSpinBox; - mBrushSizeSpinBox->setRange(1, 50); + mBrushSizeSpinBox->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt()); mBrushSizeSpinBox->setSingleStep(1); mLayoutSliderSize = new QHBoxLayout; @@ -273,6 +275,8 @@ void CSVWidget::SceneToolTextureBrush::clicked (const QModelIndex& index) void CSVWidget::SceneToolTextureBrush::activate () { QPoint position = QCursor::pos(); + mTextureBrushWindow->mSizeSliders->mBrushSizeSlider->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt()); + mTextureBrushWindow->mSizeSliders->mBrushSizeSpinBox->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt()); mTextureBrushWindow->move (position); mTextureBrushWindow->show(); } diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp index 1c0e0a334..33a6dc2de 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.hpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -30,9 +30,9 @@ namespace CSVWidget public: BrushSizeControls(const QString &title, QWidget *parent); QSlider *mBrushSizeSlider; + QSpinBox *mBrushSizeSpinBox; private: - QSpinBox *mBrushSizeSpinBox; QHBoxLayout *mLayoutSliderSize; }; From 21e8d08e69bbf9968ffea15104569153084eb79a Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 20 May 2018 21:20:40 +0300 Subject: [PATCH 27/50] Handle invalid texture id's --- .../opencs/view/render/terraintexturemode.cpp | 52 +++++++++--- .../view/widget/scenetooltexturebrush.cpp | 81 +++++++++++++------ 2 files changed, 96 insertions(+), 37 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index c7ffe6b38..dac744ae6 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -38,7 +38,7 @@ CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) : EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent), - mBrushTexture("#0"), + mBrushTexture("L0#0"), mBrushSize(0), mBrushShape(0), mTextureBrushScenetool(0) @@ -87,13 +87,19 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult mCellId = getWorldspaceWidget().getCellId (hit.worldPos); QUndoStack& undoStack = document.getUndoStack(); - undoStack.beginMacro ("Edit texture records"); - if(allowLandTextureEditing(mCellId)==true) + CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); + int index = landtexturesCollection.searchId(mBrushTexture); + + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) { - undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); - editTerrainTextureGrid(hit); + undoStack.beginMacro ("Edit texture records"); + if(allowLandTextureEditing(mCellId)==true) + { + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); + editTerrainTextureGrid(hit); + } + undoStack.endMacro(); } - undoStack.endMacro(); } void CSVRender::TerrainTextureMode::primarySelectPressed(const WorldspaceHitResult& hit) @@ -117,11 +123,18 @@ bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) mCellId = getWorldspaceWidget().getCellId (hit.worldPos); QUndoStack& undoStack = document.getUndoStack(); - undoStack.beginMacro ("Edit texture records"); - if(allowLandTextureEditing(mCellId)==true) + + CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); + int index = landtexturesCollection.searchId(mBrushTexture); + + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) { - undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); - editTerrainTextureGrid(hit); + undoStack.beginMacro ("Edit texture records"); + if(allowLandTextureEditing(mCellId)==true) + { + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); + editTerrainTextureGrid(hit); + } } return true; @@ -145,13 +158,28 @@ bool CSVRender::TerrainTextureMode::secondarySelectStartDrag (const QPoint& pos) void CSVRender::TerrainTextureMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor) { WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); - editTerrainTextureGrid(hit); + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + + CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); + int index = landtexturesCollection.searchId(mBrushTexture); + + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + { + editTerrainTextureGrid(hit); + } } void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos) { CSMDoc::Document& document = getWorldspaceWidget().getDocument(); QUndoStack& undoStack = document.getUndoStack(); - undoStack.endMacro(); + + CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); + int index = landtexturesCollection.searchId(mBrushTexture); + + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + { + undoStack.endMacro(); + } } void CSVRender::TerrainTextureMode::dragAborted() { diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index 76727a7a9..a58b98bdd 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -25,8 +25,10 @@ #include "../../model/doc/document.hpp" #include "../../model/prefs/state.hpp" #include "../../model/world/data.hpp" +#include "../../model/world/idcollection.hpp" #include "../../model/world/idtable.hpp" #include "../../model/world/landtexture.hpp" +#include "../../model/world/universalid.hpp" CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent) @@ -59,14 +61,21 @@ CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QW mBrushTexture("L0#0"), mDocument(document) { - CSMWorld::IdTable& ltexTable = dynamic_cast ( - *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + mBrushTextureLabel = "Selected texture: " + mBrushTexture + " "; - int landTextureFilename = ltexTable.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + CSMWorld::IdCollection& landtexturesCollection = mDocument.getData().getLandTextures(); - QModelIndex index = ltexTable.getModelIndex (mBrushTexture, landTextureFilename); - mBrushTextureLabel = "Selected texture: " + mBrushTexture + " "; - mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel) + ltexTable.data(index).value()); + int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + int index = landtexturesCollection.searchId(mBrushTexture); + + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + { + mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel) + landtexturesCollection.getData(index, landTextureFilename).value()); + } else + { + mBrushTextureLabel = "No selected texture or invalid texture"; + mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel)); + } QVBoxLayout *layoutMain = new QVBoxLayout; layoutMain->setSpacing(0); @@ -125,16 +134,22 @@ void CSVWidget::TextureBrushWindow::configureButtonInitialSettings(QPushButton * void CSVWidget::TextureBrushWindow::setBrushTexture(std::string brushTexture) { - CSMWorld::IdTable& ltexTable = dynamic_cast ( - *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); - int landTextureFilename = ltexTable.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + CSMWorld::IdCollection& landtexturesCollection = mDocument.getData().getLandTextures(); + int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + int index = landtexturesCollection.searchId(mBrushTexture); mBrushTexture = brushTexture; - mBrushTextureLabel = "Selected texture: " + mBrushTexture + " "; - QModelIndex index = ltexTable.getModelIndex (mBrushTexture, landTextureFilename); - mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel) + ltexTable.data(index).value()); - emit passBrushShape(mBrushShape); // update icon + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + { + mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel) + landtexturesCollection.getData(index, landTextureFilename).value()); + } else + { + mBrushTextureLabel = "No selected texture or invalid texture"; + mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel)); + } + + emit passBrushShape(mBrushShape); // update icon } void CSVWidget::TextureBrushWindow::setBrushSize(int brushSize) @@ -219,13 +234,22 @@ void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); tooltip += dynamic_cast (mTextureBrushWindow->toolTipCustom); } - tooltip += "

Selected texture: " + QString::fromStdString(mTextureBrushWindow->mBrushTexture) + " "; - CSMWorld::IdTable& ltexTable = dynamic_cast ( - *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); - int landTextureFilename = ltexTable.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); - QModelIndex index = ltexTable.getModelIndex (mTextureBrushWindow->mBrushTexture, landTextureFilename); - tooltip += ltexTable.data(index).value(); + CSMWorld::IdCollection& landtexturesCollection = mDocument.getData().getLandTextures(); + + int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + int index = landtexturesCollection.searchId(mTextureBrushWindow->mBrushTexture); + + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + { + //QModelIndex qIndex = landtexturesCollection.getModelIndex (mBrushTexture, landTextureFilename); + tooltip += "

Selected texture: " + QString::fromStdString(mTextureBrushWindow->mBrushTexture) + " "; + + tooltip += landtexturesCollection.getData(index, landTextureFilename).value(); + } else + { + tooltip += "No selected texture or invalid texture"; + } tooltip += "
(drop texture here to change)"; setToolTip (tooltip); @@ -244,12 +268,19 @@ void CSVWidget::SceneToolTextureBrush::updatePanel() for (int i = mBrushHistory.size()-1; i >= 0; --i) { - CSMWorld::IdTable& ltexTable = dynamic_cast ( - *mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); - int landTextureFilename = ltexTable.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); - QModelIndex index = ltexTable.getModelIndex (mBrushHistory[i], landTextureFilename); - mTable->setItem (i, 1, new QTableWidgetItem (ltexTable.data(index).value())); - mTable->setItem (i, 0, new QTableWidgetItem (QString::fromStdString(mBrushHistory[i]))); + CSMWorld::IdCollection& landtexturesCollection = mDocument.getData().getLandTextures(); + int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); + int index = landtexturesCollection.searchId(mBrushHistory[i]); + + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + { + mTable->setItem (i, 1, new QTableWidgetItem (landtexturesCollection.getData(index, landTextureFilename).value())); + mTable->setItem (i, 0, new QTableWidgetItem (QString::fromStdString(mBrushHistory[i]))); + } else + { + mTable->setItem (i, 1, new QTableWidgetItem ("Invalid/deleted texture")); + mTable->setItem (i, 0, new QTableWidgetItem (QString::fromStdString(mBrushHistory[i]))); + } } } From 8ae46519cf3df1ea4a136c49532218f6938351a7 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 20 May 2018 21:58:40 +0300 Subject: [PATCH 28/50] Fix missed worldspacehits, add linebreak to tooltip --- apps/opencs/view/render/terraintexturemode.cpp | 6 +++--- apps/opencs/view/widget/scenetooltexturebrush.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index dac744ae6..d312c28d9 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -90,7 +90,7 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); int index = landtexturesCollection.searchId(mBrushTexture); - if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit == true) { undoStack.beginMacro ("Edit texture records"); if(allowLandTextureEditing(mCellId)==true) @@ -130,7 +130,7 @@ bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) { undoStack.beginMacro ("Edit texture records"); - if(allowLandTextureEditing(mCellId)==true) + if(allowLandTextureEditing(mCellId)==true && hit.hit == true) { undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); editTerrainTextureGrid(hit); @@ -163,7 +163,7 @@ void CSVRender::TerrainTextureMode::drag (const QPoint& pos, int diffX, int diff CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); int index = landtexturesCollection.searchId(mBrushTexture); - if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit == true) { editTerrainTextureGrid(hit); } diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index a58b98bdd..d8d4600e5 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -248,7 +248,7 @@ void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) tooltip += landtexturesCollection.getData(index, landTextureFilename).value(); } else { - tooltip += "No selected texture or invalid texture"; + tooltip += "

No selected texture or invalid texture"; } tooltip += "
(drop texture here to change)"; From 825c3317644eefb073553a96fa5c268046c616e5 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Tue, 22 May 2018 14:55:09 +0300 Subject: [PATCH 29/50] Remove texture filtering, better ltex importing, reindexing duplicates --- .../world/landtexturetableproxymodel.cpp | 5 -- .../opencs/view/render/terraintexturemode.cpp | 5 ++ .../view/widget/scenetooltexturebrush.cpp | 46 +++++++++++++++++-- .../view/widget/scenetooltexturebrush.hpp | 1 + 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/apps/opencs/model/world/landtexturetableproxymodel.cpp b/apps/opencs/model/world/landtexturetableproxymodel.cpp index cf33fab9e..e064bbe8a 100644 --- a/apps/opencs/model/world/landtexturetableproxymodel.cpp +++ b/apps/opencs/model/world/landtexturetableproxymodel.cpp @@ -11,11 +11,6 @@ namespace CSMWorld bool LandTextureTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const { - int columnIndex = mSourceModel->findColumnIndex(Columns::ColumnId_Modification); - QModelIndex index = mSourceModel->index(sourceRow, columnIndex); - if (mSourceModel->data(index).toInt() != RecordBase::State_ModifiedOnly) - return false; - return IdTableProxyModel::filterAcceptsRow(sourceRow, sourceParent); } } diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index d312c28d9..376258c5e 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -55,6 +55,7 @@ void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); connect(mTextureBrushScenetool->mTextureBrushWindow->mSizeSliders->mBrushSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrushSize(int))); connect(mTextureBrushScenetool, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string))); + connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string))); connect(mTextureBrushScenetool, SIGNAL(passEvent(QDropEvent*)), this, SLOT(handleDropEvent(QDropEvent*))); connect(this, SIGNAL(passBrushTexture(std::string)), mTextureBrushScenetool->mTextureBrushWindow, SLOT(setBrushTexture(std::string))); @@ -391,12 +392,16 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe void CSVRender::TerrainTextureMode::pushEditToCommand(CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, CSMWorld::IdTable& landTable, std::string cellId) { + CSMWorld::IdTable& ltexTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); + QVariant changedLand; changedLand.setValue(newLandGrid); QModelIndex index(landTable.getModelIndex (cellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex))); QUndoStack& undoStack = document.getUndoStack(); + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId)); undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLand)); } diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index d8d4600e5..d6df4e9f9 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -24,6 +24,7 @@ #include "../../model/doc/document.hpp" #include "../../model/prefs/state.hpp" +#include "../../model/world/commands.hpp" #include "../../model/world/data.hpp" #include "../../model/world/idcollection.hpp" #include "../../model/world/idtable.hpp" @@ -134,19 +135,57 @@ void CSVWidget::TextureBrushWindow::configureButtonInitialSettings(QPushButton * void CSVWidget::TextureBrushWindow::setBrushTexture(std::string brushTexture) { + mBrushTexture = brushTexture; + 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); - mBrushTexture = brushTexture; + + // Check if texture exists in current plugin + if(landtexturesCollection.getData(index, columnModification).value() == 0) + { + 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()) + { + int counter=0; + bool freeIndexFound = false; + 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; + else freeIndexFound = true; + } while (freeIndexFound == false); + } + + undoStack.beginMacro ("Add land texture record"); + undoStack.push (new CSMWorld::CloneCommand (ltexTable, mBrushTexture, mBrushTexturePlugin, CSMWorld::UniversalId::Type_LandTexture)); + undoStack.endMacro(); + mBrushTexture = mBrushTexturePlugin; + emit passTextureId(mBrushTexture); + } if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) { - mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel) + landtexturesCollection.getData(index, landTextureFilename).value()); + mBrushTextureLabel = "Selected texture: " + mBrushTexture + " "; + mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel) + landtexturesCollection.getData(index, landTextureFilename).value()); } else { mBrushTextureLabel = "No selected texture or invalid texture"; - mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel)); + mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel)); } emit passBrushShape(mBrushShape); // update icon @@ -242,7 +281,6 @@ void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) { - //QModelIndex qIndex = landtexturesCollection.getModelIndex (mBrushTexture, landTextureFilename); tooltip += "

Selected texture: " + QString::fromStdString(mTextureBrushWindow->mBrushTexture) + " "; tooltip += landtexturesCollection.getData(index, landTextureFilename).value(); diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp index 33a6dc2de..d40132d42 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.hpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -72,6 +72,7 @@ namespace CSVWidget signals: void passBrushSize (int brushSize); void passBrushShape(int brushShape); + void passTextureId(std::string brushTexture); }; class SceneToolTextureBrush : public SceneTool From 9ac752ea70d32901c25144a057272a6f4383bb56 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 24 May 2018 10:48:46 +0400 Subject: [PATCH 30/50] Implement filtering in the spells window --- apps/openmw/mwgui/keyboardnavigation.cpp | 3 +++ apps/openmw/mwgui/spellmodel.cpp | 20 +++++++++++++++++--- apps/openmw/mwgui/spellmodel.hpp | 3 +++ apps/openmw/mwgui/spellwindow.cpp | 19 +++++++++++++++++-- apps/openmw/mwgui/spellwindow.hpp | 2 ++ files/mygui/openmw_spell_window.layout | 6 +++++- 6 files changed, 47 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/keyboardnavigation.cpp b/apps/openmw/mwgui/keyboardnavigation.cpp index 1374ef93d..cde8a17cc 100644 --- a/apps/openmw/mwgui/keyboardnavigation.cpp +++ b/apps/openmw/mwgui/keyboardnavigation.cpp @@ -14,6 +14,9 @@ namespace MWGui bool shouldAcceptKeyFocus(MyGUI::Widget* w) { + if (w && w->getUserString("IgnoreTabKey") == "y") + return false; + return w && !w->castType(false) && w->getInheritedEnabled() && w->getInheritedVisible() && w->getVisible() && w->getEnabled(); } diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index f83b72096..ba661093f 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -32,10 +32,14 @@ namespace namespace MWGui { + SpellModel::SpellModel(const MWWorld::Ptr &actor, const std::string& filter) + : mActor(actor), mFilter(filter) + { + } + SpellModel::SpellModel(const MWWorld::Ptr &actor) : mActor(actor) { - } void SpellModel::update() @@ -54,8 +58,13 @@ namespace MWGui if (spell->mData.mType != ESM::Spell::ST_Power && spell->mData.mType != ESM::Spell::ST_Spell) continue; + std::string name = spell->mName; + + if (name.find(mFilter) == std::string::npos) + continue; + Spell newSpell; - newSpell.mName = spell->mName; + newSpell.mName = name; if (spell->mData.mType == ESM::Spell::ST_Spell) { newSpell.mType = Spell::Type_Spell; @@ -89,10 +98,15 @@ namespace MWGui if (enchant->mData.mType != ESM::Enchantment::WhenUsed && enchant->mData.mType != ESM::Enchantment::CastOnce) continue; + std::string name = item.getClass().getName(item); + + if (name.find(mFilter) == std::string::npos) + continue; + Spell newSpell; newSpell.mItem = item; newSpell.mId = item.getCellRef().getRefId(); - newSpell.mName = item.getClass().getName(item); + newSpell.mName = name; newSpell.mType = Spell::Type_EnchantedItem; newSpell.mSelected = invStore.getSelectedEnchantItem() == it; diff --git a/apps/openmw/mwgui/spellmodel.hpp b/apps/openmw/mwgui/spellmodel.hpp index 21fbc9a6e..6b10f7127 100644 --- a/apps/openmw/mwgui/spellmodel.hpp +++ b/apps/openmw/mwgui/spellmodel.hpp @@ -35,6 +35,7 @@ namespace MWGui class SpellModel { public: + SpellModel(const MWWorld::Ptr& actor, const std::string& filter); SpellModel(const MWWorld::Ptr& actor); typedef int ModelIndex; @@ -50,6 +51,8 @@ namespace MWGui MWWorld::Ptr mActor; std::vector mSpells; + + std::string mFilter; }; } diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 601204aa1..10b4598ee 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -2,6 +2,7 @@ #include +#include #include #include @@ -38,8 +39,12 @@ namespace MWGui getWidget(mSpellView, "SpellView"); getWidget(mEffectBox, "EffectsBox"); + getWidget(mFilterEdit, "FilterEdit"); + + mFilterEdit->setUserString("IgnoreTabKey", "y"); mSpellView->eventSpellClicked += MyGUI::newDelegate(this, &SpellWindow::onModelIndexSelected); + mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &SpellWindow::onFilterChanged); setCoord(498, 300, 302, 300); } @@ -64,6 +69,11 @@ namespace MWGui void SpellWindow::onOpen() { + // Reset the filter focus when opening the window + MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); + if (focus == mFilterEdit) + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(NULL); + updateSpells(); } @@ -82,7 +92,7 @@ namespace MWGui { mSpellIcons->updateWidgets(mEffectBox, false); - mSpellView->setModel(new SpellModel(MWMechanics::getPlayer())); + mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), mFilterEdit->getCaption())); } void SpellWindow::onEnchantedItemSelected(MWWorld::Ptr item, bool alreadyEquipped) @@ -167,6 +177,11 @@ namespace MWGui } } + void SpellWindow::onFilterChanged(MyGUI::EditBox *sender) + { + mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), sender->getCaption())); + } + void SpellWindow::onSpellSelected(const std::string& spellId) { MWWorld::Ptr player = MWMechanics::getPlayer(); @@ -202,7 +217,7 @@ namespace MWGui if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery()) return; - mSpellView->setModel(new SpellModel(MWMechanics::getPlayer())); + mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), mFilterEdit->getCaption())); SpellModel::ModelIndex selected = 0; for (SpellModel::ModelIndex i = 0; igetModel()->getItemCount()); ++i) diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index f8fead9ea..ce10770f5 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -32,6 +32,7 @@ namespace MWGui void onEnchantedItemSelected(MWWorld::Ptr item, bool alreadyEquipped); void onSpellSelected(const std::string& spellId); void onModelIndexSelected(SpellModel::ModelIndex index); + void onFilterChanged(MyGUI::EditBox *sender); void onDeleteSpellAccept(); void askDeleteSpell(const std::string& spellId); @@ -41,6 +42,7 @@ namespace MWGui SpellView* mSpellView; SpellIcons* mSpellIcons; + MyGUI::EditBox* mFilterEdit; private: float mUpdateTimer; diff --git a/files/mygui/openmw_spell_window.layout b/files/mygui/openmw_spell_window.layout index 21bf74267..8a98c47b2 100644 --- a/files/mygui/openmw_spell_window.layout +++ b/files/mygui/openmw_spell_window.layout @@ -10,7 +10,11 @@ - + + + + + From b5374029e5af3d4b9756ddb41b0c5e9cb65930c4 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 24 May 2018 12:39:00 +0400 Subject: [PATCH 31/50] Implement case-insensitive search in spell window --- apps/openmw/mwgui/spellmodel.cpp | 12 +++--- apps/openmw/mwgui/spellwindow.cpp | 2 +- components/misc/stringops.hpp | 66 +++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index ba661093f..d1db582d2 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -52,19 +52,21 @@ namespace MWGui const MWWorld::ESMStore &esmStore = MWBase::Environment::get().getWorld()->getStore(); + std::string filter = Misc::StringUtils::lowerCaseUtf8(mFilter); + for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it) { const ESM::Spell* spell = it->first; if (spell->mData.mType != ESM::Spell::ST_Power && spell->mData.mType != ESM::Spell::ST_Spell) continue; - std::string name = spell->mName; + std::string name = Misc::StringUtils::lowerCaseUtf8(spell->mName); - if (name.find(mFilter) == std::string::npos) + if (name.find(filter) == std::string::npos) continue; Spell newSpell; - newSpell.mName = name; + newSpell.mName = spell->mName; if (spell->mData.mType == ESM::Spell::ST_Spell) { newSpell.mType = Spell::Type_Spell; @@ -98,9 +100,9 @@ namespace MWGui if (enchant->mData.mType != ESM::Enchantment::WhenUsed && enchant->mData.mType != ESM::Enchantment::CastOnce) continue; - std::string name = item.getClass().getName(item); + std::string name = Misc::StringUtils::lowerCaseUtf8(item.getClass().getName(item)); - if (name.find(mFilter) == std::string::npos) + if (name.find(filter) == std::string::npos) continue; Spell newSpell; diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 10b4598ee..3fe171e4e 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -217,7 +217,7 @@ namespace MWGui if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery()) return; - mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), mFilterEdit->getCaption())); + mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), "")); SpellModel::ModelIndex selected = 0; for (SpellModel::ModelIndex i = 0; igetModel()->getItemCount()); ++i) diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index 9f4931d72..0fde1c96c 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -6,6 +6,8 @@ #include #include +#include "utf8stream.hpp" + namespace Misc { class StringUtils @@ -56,6 +58,70 @@ public: }; } + static Utf8Stream::UnicodeChar toLowerUtf8(Utf8Stream::UnicodeChar ch) + { + // Russian alphabet + if (ch >= 0x0410 && ch < 0x0430) + return ch += 0x20; + + // Cyrillic IO character + if (ch == 0x0401) + return ch += 0x50; + + // Latin alphabet + if (ch >= 0x41 && ch < 0x60) + return ch += 0x20; + + // Deutch characters + if (ch == 0xc4 || ch == 0xd6 || ch == 0xdc) + return ch += 0x20; + if (ch == 0x1e9e) + return 0xdf; + + // TODO: probably we will need to support characters from other languages + + return ch; + } + + static std::string lowerCaseUtf8(const std::string str) + { + if (str.empty()) + return str; + + // Decode string as utf8 characters, convert to lower case and pack them to string + std::string out; + Utf8Stream stream (str.c_str()); + while (!stream.eof ()) + { + Utf8Stream::UnicodeChar character = toLowerUtf8(stream.peek()); + + if (character <= 0x7f) + out.append(1, static_cast(character)); + else if (character <= 0x7ff) + { + out.append(1, static_cast(0xc0 | ((character >> 6) & 0x1f))); + out.append(1, static_cast(0x80 | (character & 0x3f))); + } + else if (character <= 0xffff) + { + out.append(1, static_cast(0xe0 | ((character >> 12) & 0x0f))); + out.append(1, static_cast(0x80 | ((character >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (character & 0x3f))); + } + else + { + out.append(1, static_cast(0xf0 | ((character >> 18) & 0x07))); + out.append(1, static_cast(0x80 | ((character >> 12) & 0x3f))); + out.append(1, static_cast(0x80 | ((character >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (character & 0x3f))); + } + + stream.consume(); + } + + return out; + } + static bool ciLess(const std::string &x, const std::string &y) { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci()); } From afae398b5c7f557c272c3b61f2129ccf9f8aedf0 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 24 May 2018 12:53:06 +0400 Subject: [PATCH 32/50] Use utf8 lowercase function for journal index to avoid code duplication --- apps/openmw/mwgui/journalbooks.cpp | 4 ++-- apps/openmw/mwgui/journalviewmodel.cpp | 24 +++--------------------- apps/openmw/mwgui/journalviewmodel.hpp | 4 +++- components/misc/utf8stream.hpp | 1 + 4 files changed, 9 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwgui/journalbooks.cpp b/apps/openmw/mwgui/journalbooks.cpp index e8aa23158..1075239fa 100644 --- a/apps/openmw/mwgui/journalbooks.cpp +++ b/apps/openmw/mwgui/journalbooks.cpp @@ -244,7 +244,7 @@ BookTypesetter::Ptr JournalBooks::createLatinJournalIndex () const MWGui::TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours(); BookTypesetter::Style* style = typesetter->createHotStyle (body, textColours.journalTopic, textColours.journalTopicOver, - textColours.journalTopicPressed, (uint32_t) ch); + textColours.journalTopicPressed, (Utf8Stream::UnicodeChar) ch); if (i == 13) typesetter->sectionBreak (); @@ -274,7 +274,7 @@ BookTypesetter::Ptr JournalBooks::createCyrillicJournalIndex () sprintf(buffer, "( %c%c )", ch[0], ch[1]); Utf8Stream stream ((char*) ch); - uint32_t first = stream.peek(); + Utf8Stream::UnicodeChar first = stream.peek(); const MWGui::TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours(); BookTypesetter::Style* style = typesetter->createHotStyle (body, textColours.journalTopic, diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 6ff68c9c5..63b48eab1 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -7,7 +7,6 @@ #include #include -#include #include "../mwbase/world.hpp" #include "../mwbase/journal.hpp" @@ -307,39 +306,22 @@ struct JournalViewModelImpl : JournalViewModel visitor (toUtf8Span (topic.getName())); } - void visitTopicNamesStartingWith (uint32_t character, std::function < void (const std::string&) > visitor) const + void visitTopicNamesStartingWith (Utf8Stream::UnicodeChar character, std::function < void (const std::string&) > visitor) const { MWBase::Journal * journal = MWBase::Environment::get().getJournal(); for (MWBase::Journal::TTopicIter i = journal->topicBegin (); i != journal->topicEnd (); ++i) { Utf8Stream stream (i->first.c_str()); - uint32_t first = toUpper(stream.peek()); + Utf8Stream::UnicodeChar first = Misc::StringUtils::toLowerUtf8(stream.peek()); - if (first != character) + if (first != Misc::StringUtils::toLowerUtf8(character)) continue; visitor (i->second.getName()); } } - static uint32_t toUpper(uint32_t ch) - { - // Russian alphabet - if (ch >= 0x0430 && ch < 0x0450) - ch -= 0x20; - - // Cyrillic IO character - if (ch == 0x0451) - ch -= 0x50; - - // Latin alphabet - if (ch >= 0x61 && ch < 0x80) - ch -= 0x20; - - return ch; - } - struct TopicEntryImpl : BaseEntry { MWDialogue::Topic const & mTopic; diff --git a/apps/openmw/mwgui/journalviewmodel.hpp b/apps/openmw/mwgui/journalviewmodel.hpp index 01dcb49de..fa4090225 100644 --- a/apps/openmw/mwgui/journalviewmodel.hpp +++ b/apps/openmw/mwgui/journalviewmodel.hpp @@ -6,6 +6,8 @@ #include #include +#include + namespace MWGui { /// View-Model for the journal GUI @@ -76,7 +78,7 @@ namespace MWGui virtual void visitTopicName (TopicId topicId, std::function visitor) const = 0; /// walks over the topics whose names start with the character - virtual void visitTopicNamesStartingWith (uint32_t character, std::function < void (const std::string&) > visitor) const = 0; + virtual void visitTopicNamesStartingWith (Utf8Stream::UnicodeChar character, std::function < void (const std::string&) > visitor) const = 0; /// walks over the topic entries for the topic specified by its identifier virtual void visitTopicEntries (TopicId topicId, std::function visitor) const = 0; diff --git a/components/misc/utf8stream.hpp b/components/misc/utf8stream.hpp index 368374a64..e499d15e6 100644 --- a/components/misc/utf8stream.hpp +++ b/components/misc/utf8stream.hpp @@ -1,6 +1,7 @@ #ifndef MISC_UTF8ITER_HPP #define MISC_UTF8ITER_HPP +#include #include class Utf8Stream From 1abff5365bb31378047bab5692608fc787125947 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 24 May 2018 12:57:29 +0400 Subject: [PATCH 33/50] Capitalize enchanted items names again in spells window --- apps/openmw/mwgui/spellmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index d1db582d2..a73d343f9 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -108,7 +108,7 @@ namespace MWGui Spell newSpell; newSpell.mItem = item; newSpell.mId = item.getCellRef().getRefId(); - newSpell.mName = name; + newSpell.mName = item.getClass().getName(item); newSpell.mType = Spell::Type_EnchantedItem; newSpell.mSelected = invStore.getSelectedEnchantItem() == it; From 8c9567635224cc1d9997e050a8b33e5e43de416b Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 24 May 2018 22:49:53 +0400 Subject: [PATCH 34/50] Preserve AppVeyor builds --- appveyor.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index eae4bd5b1..ede57d890 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -55,6 +55,10 @@ build_script: - cmd: if %PLATFORM%==x64 set build=MSVC%msvc%_64 - cmd: msbuild %build%\OpenMW.sln /t:Build /p:Configuration=%configuration% /m:2 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" +after_build: + - cmd: if %PLATFORM%==x64 7z a OpenMW_MSVC%msvc%_x64.zip %APPVEYOR_BUILD_FOLDER%\MSVC%msvc%_64\Debug\ -xr"!*.pdb" + - cmd: if %PLATFORM%==x64 7z a OpenMW_MSVC%msvc%_x64_pdb.zip %APPVEYOR_BUILD_FOLDER%\MSVC%msvc%_64\Debug\*.pdb + test: off #notifications: @@ -63,3 +67,9 @@ test: off # - # on_build_failure: true # on_build_status_changed: true + +artifacts: + - path: OpenMW_MSVC%msvc%_x64.zip + name: OpenMW_MSVC%msvc%_x64 + - path: OpenMW_MSVC%msvc%_x64_pdb.zip + name: OpenMW_MSVC%msvc%_x64_pdb From 77c5e85e8db8748a89fe286bc212c37986c3b73f Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 24 May 2018 22:51:25 +0400 Subject: [PATCH 35/50] Enable release builds --- appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ede57d890..21fb7e1d6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,8 +18,8 @@ platform: - x64 configuration: - - Debug -# - Release +# - Debug + - Release # For the Qt, Boost, CMake, etc installs #os: Visual Studio 2017 @@ -56,8 +56,8 @@ build_script: - cmd: msbuild %build%\OpenMW.sln /t:Build /p:Configuration=%configuration% /m:2 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" after_build: - - cmd: if %PLATFORM%==x64 7z a OpenMW_MSVC%msvc%_x64.zip %APPVEYOR_BUILD_FOLDER%\MSVC%msvc%_64\Debug\ -xr"!*.pdb" - - cmd: if %PLATFORM%==x64 7z a OpenMW_MSVC%msvc%_x64_pdb.zip %APPVEYOR_BUILD_FOLDER%\MSVC%msvc%_64\Debug\*.pdb + - cmd: if %PLATFORM%==x64 7z a OpenMW_MSVC%msvc%_x64.zip %APPVEYOR_BUILD_FOLDER%\MSVC%msvc%_64\Release\ -xr"!*.pdb" + - cmd: if %PLATFORM%==x64 7z a OpenMW_MSVC%msvc%_x64_pdb.zip %APPVEYOR_BUILD_FOLDER%\MSVC%msvc%_64\Release\*.pdb test: off From ba3a02ad055a2713f53aafe1d5a6c3bb69a957bc Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Thu, 24 May 2018 23:00:59 +0200 Subject: [PATCH 36/50] [macOS, CI] Do not upload a nightly if there's already one of the same commit --- CI/deploy.osx.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CI/deploy.osx.sh b/CI/deploy.osx.sh index 53bfa18b5..5fa2b70a3 100755 --- a/CI/deploy.osx.sh +++ b/CI/deploy.osx.sh @@ -6,4 +6,6 @@ DATE=`date +'%d%m%Y'` SHORT_COMMIT=`git rev-parse --short ${TRAVIS_COMMIT}` TARGET_FILENAME="OpenMW-${DATE}-${SHORT_COMMIT}.dmg" -curl --ssl --ftp-create-dirs -T *.dmg -u $OSX_FTP_USER:$OSX_FTP_PASSWORD "${OSX_FTP_URL}${TARGET_FILENAME}" +if ! curl --ssl -u $OSX_FTP_USER:$OSX_FTP_PASSWORD "${OSX_FTP_URL}" --silent | grep $SHORT_COMMIT > /dev/null; then + curl --ssl --ftp-create-dirs -T *.dmg -u $OSX_FTP_USER:$OSX_FTP_PASSWORD "${OSX_FTP_URL}${TARGET_FILENAME}" +fi From 2edb511a0bdb0478df5f59fbee12a276913a38af Mon Sep 17 00:00:00 2001 From: David Cernat Date: Fri, 25 May 2018 07:08:51 +0300 Subject: [PATCH 37/50] [Client] Remove unnecessary condition from WorldTime processor --- .../worldstate/ProcessorWorldTime.hpp | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwmp/processors/worldstate/ProcessorWorldTime.hpp b/apps/openmw/mwmp/processors/worldstate/ProcessorWorldTime.hpp index ef1c20487..46ff93d11 100644 --- a/apps/openmw/mwmp/processors/worldstate/ProcessorWorldTime.hpp +++ b/apps/openmw/mwmp/processors/worldstate/ProcessorWorldTime.hpp @@ -18,28 +18,25 @@ namespace mwmp virtual void Do(WorldstatePacket &packet, BaseWorldstate &worldstate) { - if (isLocal()) - { - MWBase::World *world = MWBase::Environment::get().getWorld(); - - if (worldstate.hour != -1) - world->setHour(worldstate.hour); - - if (worldstate.day != -1) - world->setDay(worldstate.day); - - if (worldstate.month != -1) - world->setMonth(worldstate.month); - - if (worldstate.year != -1) - world->setYear(worldstate.year); - - if (worldstate.daysPassed != -1) - world->setDaysPassed(worldstate.daysPassed); - - if (worldstate.timeScale != -1) - world->setTimeScale(worldstate.timeScale); - } + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (worldstate.hour != -1) + world->setHour(worldstate.hour); + + if (worldstate.day != -1) + world->setDay(worldstate.day); + + if (worldstate.month != -1) + world->setMonth(worldstate.month); + + if (worldstate.year != -1) + world->setYear(worldstate.year); + + if (worldstate.daysPassed != -1) + world->setDaysPassed(worldstate.daysPassed); + + if (worldstate.timeScale != -1) + world->setTimeScale(worldstate.timeScale); } }; } From 416ee776397efc5ae58748f6ffc3337a4ba79982 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Fri, 25 May 2018 07:09:32 +0300 Subject: [PATCH 38/50] [General] Add placeholder for WorldCollisionOverride packet --- apps/openmw/CMakeLists.txt | 14 +++++----- .../mwmp/processors/ProcessorInitializer.cpp | 2 ++ .../ProcessorWorldCollisionOverride.hpp | 28 +++++++++++++++++++ components/CMakeLists.txt | 2 +- .../WorldstatePacketController.cpp | 2 ++ components/openmw-mp/NetworkMessages.hpp | 8 ++++-- .../PacketWorldCollisionOverride.cpp | 17 +++++++++++ .../PacketWorldCollisionOverride.hpp | 17 +++++++++++ 8 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 apps/openmw/mwmp/processors/worldstate/ProcessorWorldCollisionOverride.hpp create mode 100644 components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.cpp create mode 100644 components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 8258b9c06..1a93b0a96 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -124,15 +124,15 @@ add_openmw_dir (mwmp/processors/player ProcessorChatMessage ProcessorGUIMessageB ProcessorPlayerSkill ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic ) -add_openmw_dir (mwmp/processors/object BaseObjectProcessor ProcessorConsoleCommand ProcessorContainer ProcessorDoorDestination - ProcessorDoorState ProcessorMusicPlay ProcessorVideoPlay ProcessorObjectAnimPlay ProcessorObjectAttach - ProcessorObjectCollision ProcessorObjectDelete ProcessorObjectLock ProcessorObjectMove ProcessorObjectPlace - ProcessorObjectReset ProcessorObjectRotate ProcessorObjectScale ProcessorObjectSpawn ProcessorObjectState - ProcessorObjectTrap ProcessorScriptLocalShort ProcessorScriptLocalFloat ProcessorScriptMemberShort - ProcessorScriptMemberFloat ProcessorScriptGlobalShort ProcessorScriptGlobalFloat +add_openmw_dir (mwmp/processors/object BaseObjectProcessor ProcessorConsoleCommand ProcessorContainer + ProcessorDoorDestination ProcessorDoorState ProcessorMusicPlay ProcessorVideoPlay ProcessorObjectAnimPlay + ProcessorObjectAttach ProcessorObjectCollision ProcessorObjectDelete ProcessorObjectLock ProcessorObjectMove + ProcessorObjectPlace ProcessorObjectReset ProcessorObjectRotate ProcessorObjectScale ProcessorObjectSpawn + ProcessorObjectState ProcessorObjectTrap ProcessorScriptLocalShort ProcessorScriptLocalFloat + ProcessorScriptMemberShort ProcessorScriptMemberFloat ProcessorScriptGlobalShort ProcessorScriptGlobalFloat ) -add_openmw_dir (mwmp/processors/worldstate ProcessorRecordDynamic ProcessorWorldTime +add_openmw_dir (mwmp/processors/worldstate ProcessorRecordDynamic ProcessorWorldCollisionOverride ProcessorWorldTime ) # Main executable diff --git a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp index 7f12e4629..c437b4381 100644 --- a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp +++ b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp @@ -91,6 +91,7 @@ #include "WorldstateProcessor.hpp" #include "worldstate/ProcessorRecordDynamic.hpp" +#include "worldstate/ProcessorWorldCollisionOverride.hpp" #include "worldstate/ProcessorWorldTime.hpp" using namespace mwmp; @@ -184,5 +185,6 @@ void ProcessorInitializer() ActorProcessor::AddProcessor(new ProcessorActorTest()); WorldstateProcessor::AddProcessor(new ProcessorRecordDynamic()); + WorldstateProcessor::AddProcessor(new ProcessorWorldCollisionOverride()); WorldstateProcessor::AddProcessor(new ProcessorWorldTime()); } diff --git a/apps/openmw/mwmp/processors/worldstate/ProcessorWorldCollisionOverride.hpp b/apps/openmw/mwmp/processors/worldstate/ProcessorWorldCollisionOverride.hpp new file mode 100644 index 000000000..e918e7d09 --- /dev/null +++ b/apps/openmw/mwmp/processors/worldstate/ProcessorWorldCollisionOverride.hpp @@ -0,0 +1,28 @@ +#ifndef OPENMW_PROCESSORWORLDCOLLISIONOVERRIDE_HPP +#define OPENMW_PROCESSORWORLDCOLLISIONOVERRIDE_HPP + + +#include +#include +#include "../WorldstateProcessor.hpp" + +namespace mwmp +{ + class ProcessorWorldCollisionOverride : public WorldstateProcessor + { + public: + ProcessorWorldCollisionOverride() + { + BPP_INIT(ID_WORLD_COLLISION_OVERRIDE) + } + + virtual void Do(WorldstatePacket &packet, BaseWorldstate &worldstate) + { + // Placeholder + } + }; +} + + + +#endif //OPENMW_PROCESSORWORLDCOLLISIONOVERRIDE_HPP diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 9fcec629f..72b79adf8 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -202,7 +202,7 @@ add_component_dir (openmw-mp/Packets/Object add_component_dir (openmw-mp/Packets/Worldstate WorldstatePacket - PacketRecordDynamic PacketWorldTime + PacketRecordDynamic PacketWorldCollisionOverride PacketWorldTime ) add_component_dir (fallback diff --git a/components/openmw-mp/Controllers/WorldstatePacketController.cpp b/components/openmw-mp/Controllers/WorldstatePacketController.cpp index 802c45cef..991029439 100644 --- a/components/openmw-mp/Controllers/WorldstatePacketController.cpp +++ b/components/openmw-mp/Controllers/WorldstatePacketController.cpp @@ -1,4 +1,5 @@ #include "../Packets/Worldstate/PacketRecordDynamic.hpp" +#include "../Packets/Worldstate/PacketWorldCollisionOverride.hpp" #include "../Packets/Worldstate/PacketWorldTime.hpp" #include "WorldstatePacketController.hpp" @@ -14,6 +15,7 @@ inline void AddPacket(mwmp::WorldstatePacketController::packets_t *packets, RakN mwmp::WorldstatePacketController::WorldstatePacketController(RakNet::RakPeerInterface *peer) { AddPacket(&packets, peer); + AddPacket(&packets, peer); AddPacket(&packets, peer); } diff --git a/components/openmw-mp/NetworkMessages.hpp b/components/openmw-mp/NetworkMessages.hpp index 143553a7f..b66786f71 100644 --- a/components/openmw-mp/NetworkMessages.hpp +++ b/components/openmw-mp/NetworkMessages.hpp @@ -18,7 +18,6 @@ enum GameMessages ID_LOADED, ID_GUI_MESSAGEBOX, - ID_WORLD_TIME, ID_GAME_WEATHER, ID_PLAYER_BASEINFO, @@ -90,7 +89,6 @@ enum GameMessages ID_OBJECT_TRAP, ID_CELL_CREATE, - ID_RECORD_DYNAMIC, ID_CONSOLE_COMMAND, ID_CONTAINER, @@ -107,7 +105,11 @@ enum GameMessages ID_SCRIPT_GLOBAL_FLOAT, ID_GAME_SETTINGS, - ID_GAME_PREINIT + ID_GAME_PREINIT, + + ID_RECORD_DYNAMIC, + ID_WORLD_COLLISION_OVERRIDE, + ID_WORLD_TIME, }; enum OrderingChannel diff --git a/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.cpp b/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.cpp new file mode 100644 index 000000000..b2b482b92 --- /dev/null +++ b/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.cpp @@ -0,0 +1,17 @@ +#include "PacketWorldCollisionOverride.hpp" +#include + +using namespace mwmp; + +PacketWorldCollisionOverride::PacketWorldCollisionOverride(RakNet::RakPeerInterface *peer) : WorldstatePacket(peer) +{ + packetID = ID_WORLD_COLLISION_OVERRIDE; + orderChannel = CHANNEL_WORLDSTATE; +} + +void PacketWorldCollisionOverride::Packet(RakNet::BitStream *bs, bool send) +{ + WorldstatePacket::Packet(bs, send); + + // Placeholder +} diff --git a/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.hpp b/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.hpp new file mode 100644 index 000000000..2698ae0f7 --- /dev/null +++ b/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.hpp @@ -0,0 +1,17 @@ +#ifndef OPENMW_PACKETWORLDCOLLISIONOVERRIDE_HPP +#define OPENMW_PACKETWORLDCOLLISIONOVERRIDE_HPP + +#include + +namespace mwmp +{ + class PacketWorldCollisionOverride : public WorldstatePacket + { + public: + PacketWorldCollisionOverride(RakNet::RakPeerInterface *peer); + + virtual void Packet(RakNet::BitStream *bs, bool send); + }; +} + +#endif //OPENMW_PACKETWORLDCOLLISIONOVERRIDE_HPP From 48e15dabc3c70a5bfcc35c1277d188818759c42b Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 25 May 2018 12:16:13 +0400 Subject: [PATCH 39/50] Try to generate PDB for release builds --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd809b58c..bfef2d328 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -360,6 +360,8 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-parameter") endif() elseif (MSVC) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /Zi /bigobj") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO") # Enable link-time code generation globally for all linking if (OPENMW_LTO_BUILD) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") From c8ec77875c6e5a56232aa9fdb640bc6ae88f880f Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sat, 26 May 2018 05:11:41 +0300 Subject: [PATCH 40/50] [Client] Update old comments for changes made by tes3mp --- apps/openmw/mwscript/interpretercontext.cpp | 19 +++++++++--- apps/openmw/mwworld/worldimp.cpp | 34 +++++++++++++++------ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 9a810e0e3..fd5ffae00 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -270,12 +270,16 @@ namespace MWScript bool InterpreterContext::menuMode() { - /* Disabled by tes3mp, because being in a menu should not pause scripts in it + /* + Start of tes3mp change (major) - return MWBase::Environment::get().getWindowManager()->isGuiMode(); + Being in a menu should not pause scripts in multiplayer, so always return false */ - + //return MWBase::Environment::get().getWindowManager()->isGuiMode(); return false; + /* + End of tes3mp change (major) + */ } int InterpreterContext::getGlobalShort (const std::string& name) const @@ -672,10 +676,17 @@ namespace MWScript Locals& locals = getMemberLocals (scriptId, global); - // Added by tes3mp so it can be reused by it + /* + Start of tes3mp change (minor) + + Declare an integer so it can be reused below for multiplayer script sync purposes + */ int index = findLocalVariableIndex(scriptId, name, 's'); locals.mShorts[index] = value; + /* + End of tes3mp change (minor) + */ /* Start of tes3mp addition diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 423b16d3a..b75a0da58 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -278,10 +278,11 @@ namespace MWWorld { ESM::Position pos; - // Major change made by tes3mp - // - // If Pelagiad exists, spawn there; otherwise, spawn at 0,0 + /* + Start of tes3mp change (major) + If Pelagiad exists, spawn there; otherwise, spawn at 0 ,0 + */ if (findExteriorPosition("Pelagiad", pos)) { changeToExteriorCell(pos, true); @@ -298,6 +299,9 @@ namespace MWWorld pos.rot[2] = 0; mWorldScene->changeToExteriorCell(pos, true); } + /* + End of tes3mp change (major) + */ } } @@ -2557,10 +2561,16 @@ namespace MWWorld void World::hurtStandingActors(const ConstPtr &object, float healthPerSecond) { - /* Disabled by tes3mp, because being in a menu should not pause the game in it + /* + Start of tes3mp change (major) - if (MWBase::Environment::get().getWindowManager()->isGuiMode()) - return; + Being in a menu should not prevent actors from being hurt in multiplayer, + so that check has been commented out + */ + //if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + // return; + /* + End of tes3mp change (major) */ std::vector actors; @@ -2594,10 +2604,16 @@ namespace MWWorld void World::hurtCollidingActors(const ConstPtr &object, float healthPerSecond) { - /* Disabled by tes3mp, because being in a menu should not pause the game in it + /* + Start of tes3mp change (major) - if (MWBase::Environment::get().getWindowManager()->isGuiMode()) - return; + Being in a menu should not prevent actors from being hurt in multiplayer, + so that check has been commented out + */ + //if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + // return; + /* + End of tes3mp change (major) */ std::vector actors; From f7a084c8247fedc188451bd3c0cca97b68f63ac2 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sat, 26 May 2018 08:13:26 +0300 Subject: [PATCH 41/50] [Client] Use faster check for whether actors are DedicatedPlayers --- apps/openmw/mwmp/PlayerList.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmp/PlayerList.cpp b/apps/openmw/mwmp/PlayerList.cpp index 24e392511..e07c16b07 100644 --- a/apps/openmw/mwmp/PlayerList.cpp +++ b/apps/openmw/mwmp/PlayerList.cpp @@ -71,8 +71,10 @@ DedicatedPlayer *PlayerList::getPlayer(const MWWorld::Ptr &ptr) { if (p.second == 0 || p.second->getPtr().mRef == 0) continue; - string refid = ptr.getCellRef().getRefId(); - if (p.second->getPtr().getCellRef().getRefId() == refid) + + string refId = ptr.getCellRef().getRefId(); + + if (p.second->getPtr().getCellRef().getRefId() == refId) return p.second; } return 0; @@ -83,6 +85,10 @@ bool PlayerList::isDedicatedPlayer(const MWWorld::Ptr &ptr) if (ptr.mRef == nullptr) return false; + // Players always have 0 as their refNumIndex and mpNum + if (ptr.getCellRef().getRefNum().mIndex != 0 || ptr.getCellRef().getMpNum() != 0) + return false; + return (getPlayer(ptr) != 0); } From e76df5f4d39afe5a2f0bfa7db2da400d4061900e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 May 2018 11:53:08 +0200 Subject: [PATCH 42/50] minor tooltip fixes --- .../view/widget/scenetooltexturebrush.cpp | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index d6df4e9f9..dab6a2850 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -252,28 +252,38 @@ CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, c void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) { - QString tooltip = "Brush settings

Currently selected: "; - if(brushShape == 0) - { - setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); - tooltip += dynamic_cast (mTextureBrushWindow->toolTipPoint); - } - if(brushShape == 1) - { - setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); - tooltip += dynamic_cast (mTextureBrushWindow->toolTipSquare); - } - if(brushShape == 2) - { - setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); - tooltip += dynamic_cast (mTextureBrushWindow->toolTipCircle); - } - if(brushShape == 3) + QString tooltip = "Change brush settings

Currently selected: "; + + switch (brushShape) { - setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); - tooltip += dynamic_cast (mTextureBrushWindow->toolTipCustom); + case 0: + + setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); + tooltip += mTextureBrushWindow->toolTipPoint; + break; + + case 1: + + setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); + tooltip += mTextureBrushWindow->toolTipSquare; + break; + + case 2: + + setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); + tooltip += mTextureBrushWindow->toolTipCircle; + break; + + case 3: + + setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); + tooltip += mTextureBrushWindow->toolTipCustom; + break; } + tooltip += "

(right click to access of previously used brush settings)"; + + CSMWorld::IdCollection& landtexturesCollection = mDocument.getData().getLandTextures(); int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture); From bbc337a0af8618e6c0b6f3f5c2816b113d07c44c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 May 2018 12:16:02 +0200 Subject: [PATCH 43/50] code cleanup --- .../view/widget/scenetooltexturebrush.cpp | 7 +++ .../view/widget/scenetooltexturebrush.hpp | 46 +++++++++++++------ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index dab6a2850..2208f88a6 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -78,6 +78,13 @@ CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QW mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel)); } + mButtonPoint = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-point")), "", this); + mButtonSquare = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-square")), "", this); + mButtonCircle = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-circle")), "", this); + mButtonCustom = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-custom")), "", this); + + mSizeSliders = new BrushSizeControls("Brush size", this); + QVBoxLayout *layoutMain = new QVBoxLayout; layoutMain->setSpacing(0); layoutMain->setContentsMargins(4,0,4,4); diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp index d40132d42..4669f432e 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.hpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -20,8 +20,15 @@ class QTableWidget; +namespace CSVRender +{ + class TerrainTextureMode; +} + namespace CSVWidget { + class SceneToolTextureBrush; + /// \brief Layout-box for some brush button settings class BrushSizeControls : public QGroupBox { @@ -29,13 +36,18 @@ namespace CSVWidget public: BrushSizeControls(const QString &title, QWidget *parent); - QSlider *mBrushSizeSlider; - QSpinBox *mBrushSizeSpinBox; private: QHBoxLayout *mLayoutSliderSize; + QSlider *mBrushSizeSlider; + QSpinBox *mBrushSizeSpinBox; + + friend class SceneToolTextureBrush; + friend class CSVRender::TerrainTextureMode; }; + class SceneToolTextureBrush; + /// \brief Brush settings window class TextureBrushWindow : public QFrame { @@ -45,24 +57,27 @@ namespace CSVWidget TextureBrushWindow(CSMDoc::Document& document, QWidget *parent = 0); void configureButtonInitialSettings(QPushButton *button); - QPushButton *mButtonPoint = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-point")), "", this); - QPushButton *mButtonSquare = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-square")), "", this); - QPushButton *mButtonCircle = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-circle")), "", this); - QPushButton *mButtonCustom = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-custom")), "", this); - QString toolTipPoint = "Paint single point"; - QString toolTipSquare = "Paint with square brush"; - QString toolTipCircle = "Paint with circle brush"; - QString toolTipCustom = "Paint custom selection (not implemented yet)"; - BrushSizeControls* mSizeSliders = new BrushSizeControls("Brush size", this); + const QString toolTipPoint = "Paint single point"; + const QString toolTipSquare = "Paint with square brush"; + const QString toolTipCircle = "Paint with circle brush"; + const QString toolTipCustom = "Paint custom selection (not implemented yet)"; + + private: int mBrushShape; int mBrushSize; std::string mBrushTexture; - - private: CSMDoc::Document& mDocument; QLabel *mSelectedBrush; QGroupBox *mHorizontalGroupBox; std::string mBrushTextureLabel; + QPushButton *mButtonPoint; + QPushButton *mButtonSquare; + QPushButton *mButtonCircle; + QPushButton *mButtonCustom; + BrushSizeControls* mSizeSliders; + + friend class SceneToolTextureBrush; + friend class CSVRender::TerrainTextureMode; public slots: void setBrushTexture(std::string brushTexture); @@ -84,6 +99,7 @@ namespace CSVWidget QFrame *mPanel; QTableWidget *mTable; std::vector mBrushHistory; + TextureBrushWindow *mTextureBrushWindow; private: @@ -96,11 +112,11 @@ namespace CSVWidget virtual void showPanel (const QPoint& position); void updatePanel (); - TextureBrushWindow *mTextureBrushWindow; - void dropEvent (QDropEvent *event); void dragEnterEvent (QDragEnterEvent *event); + friend class CSVRender::TerrainTextureMode; + public slots: void setButtonIcon(int brushShape); void updateBrushHistory (const std::string& mBrushTexture); From 99ffaafe3068d9727acaf76d054f9329f4eac879 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sat, 26 May 2018 11:35:48 +0000 Subject: [PATCH 44/50] Revert "Merge pull request #1701 from akortunov/standfix" This reverts commit da47fc79f540c65ccc2d7276f560d3d3a1e105a3, reversing changes made to 7324bd368f103a5dc3c029dfd1c7024e90200cdf. --- apps/openmw/mwbase/world.hpp | 1 - apps/openmw/mwmechanics/aiwander.cpp | 3 ++- apps/openmw/mwmechanics/character.cpp | 3 +-- apps/openmw/mwphysics/actor.cpp | 7 +----- apps/openmw/mwphysics/actor.hpp | 8 ------- apps/openmw/mwphysics/physicssystem.cpp | 31 +------------------------ apps/openmw/mwphysics/physicssystem.hpp | 3 --- apps/openmw/mwscript/miscextensions.cpp | 2 -- apps/openmw/mwstate/statemanagerimp.cpp | 5 +--- apps/openmw/mwworld/worldimp.cpp | 7 ++---- apps/openmw/mwworld/worldimp.hpp | 1 - 11 files changed, 8 insertions(+), 63 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 086e81678..68d4ac85d 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -391,7 +391,6 @@ namespace MWBase virtual bool isUnderwater(const MWWorld::ConstPtr &object, const float heightRatio) const = 0; virtual bool isWaterWalkingCastableOnTarget(const MWWorld::ConstPtr &target) const = 0; virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0; - virtual bool isIdle(const MWWorld::Ptr &ptr) const = 0; virtual osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const = 0; diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 511a47a49..8199170dc 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -866,7 +866,8 @@ namespace MWMechanics } // place above to prevent moving inside objects, e.g. stairs, because a vector between pathgrids can be underground. - dest.mZ += 80; + // Adding 20 in adjustPosition() is not enough. + dest.mZ += 60; ToWorldCoordinates(dest, actor.getCell()->getCell()); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 1ba5cc0d5..29a6d5e3b 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -2036,8 +2036,7 @@ void CharacterController::update(float duration) moved.z() = 1.0; // Update movement - // We should not apply movement for standing actors - if(mMovementAnimationControlled && mPtr.getClass().isActor() && (movement.length2() > 0.f || !world->isIdle(mPtr))) + if(mMovementAnimationControlled && mPtr.getClass().isActor()) world->queueMovement(mPtr, moved); mSkipAnim = false; diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index 6de0d1984..79c6dcabf 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -18,7 +18,7 @@ namespace MWPhysics Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr shape, btCollisionWorld* world) : mCanWaterWalk(false), mWalkingOnWater(false) - , mCollisionObject(nullptr), mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false), mIdle(true) + , mCollisionObject(nullptr), mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false) , mInternalCollisionMode(true) , mExternalCollisionMode(true) , mCollisionWorld(world) @@ -195,11 +195,6 @@ void Actor::setOnSlope(bool slope) mOnSlope = slope; } -void Actor::setIdle(bool idle) -{ - mIdle = idle; -} - bool Actor::isWalkingOnWater() const { return mWalkingOnWater; diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index bdafc1235..8ec94200f 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -139,13 +139,6 @@ namespace MWPhysics return mInternalCollisionMode && mOnSlope; } - void setIdle(bool idle); - - bool getIdle() const - { - return mIdle; - } - btCollisionObject* getCollisionObject() const { return mCollisionObject.get(); @@ -186,7 +179,6 @@ namespace MWPhysics osg::Vec3f mForce; bool mOnGround; bool mOnSlope; - bool mIdle; bool mInternalCollisionMode; bool mExternalCollisionMode; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 412e5e5b3..f3c34bc4e 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -249,7 +249,7 @@ namespace MWPhysics // Check if we actually found a valid spawn point (use an infinitely thin ray this time). // Required for some broken door destinations in Morrowind.esm, where the spawn point // intersects with other geometry if the actor's base is taken into account - btVector3 from = toBullet(position + offset); + btVector3 from = toBullet(position); btVector3 to = from - btVector3(0,0,maxHeight); btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); @@ -683,7 +683,6 @@ namespace MWPhysics , mWaterEnabled(false) , mParentNode(parentNode) , mPhysicsDt(1.f / 60.f) - , mIdleUpdateTimer(0) { mResourceSystem->addResourceManager(mShapeManager.get()); @@ -740,18 +739,6 @@ namespace MWPhysics delete mBroadphase; } - void PhysicsSystem::updateIdle() - { - for (ActorMap::iterator it = mActors.begin(); it != mActors.end(); ++it) - { - osg::Vec3f pos(it->second->getCollisionObjectPosition()); - - RayResult result = castRay(pos, pos - osg::Vec3f(0, 0, it->second->getHalfExtents().z() + 2), it->second->getPtr(), std::vector(), CollisionType_World|CollisionType_HeightMap|CollisionType_Door); - - it->second->setIdle(result.mHit); - } - } - void PhysicsSystem::setUnrefQueue(SceneUtil::UnrefQueue *unrefQueue) { mUnrefQueue = unrefQueue; @@ -1058,11 +1045,6 @@ namespace MWPhysics return physactor && physactor->getOnGround(); } - bool PhysicsSystem::isIdle(const MWWorld::Ptr &actor) - { - Actor* physactor = getActor(actor); - return physactor && physactor->getIdle(); - } bool PhysicsSystem::canMoveToWaterSurface(const MWWorld::ConstPtr &actor, const float waterlevel) { const Actor* physicActor = getActor(actor); @@ -1355,10 +1337,6 @@ namespace MWPhysics cmode = !cmode; found->second->enableCollisionMode(cmode); found->second->enableCollisionBody(cmode); - - if (cmode) - queueObjectMovement(MWMechanics::getPlayer(), osg::Vec3f(0, 0, -0.1f)); - return cmode; } @@ -1478,13 +1456,6 @@ namespace MWPhysics for (std::set::iterator it = mAnimatedObjects.begin(); it != mAnimatedObjects.end(); ++it) (*it)->animateCollisionShapes(mCollisionWorld); - mIdleUpdateTimer -= dt; - if (mIdleUpdateTimer <= 0.f) - { - mIdleUpdateTimer = 0.5f; - updateIdle(); - } - #ifndef BT_NO_PROFILE CProfileManager::Reset(); CProfileManager::Increment_Frame_Counter(); diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index fe2433ce0..3ef9990f5 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -124,7 +124,6 @@ namespace MWPhysics bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const; bool isOnGround (const MWWorld::Ptr& actor); - bool isIdle (const MWWorld::Ptr& actor); bool canMoveToWaterSurface (const MWWorld::ConstPtr &actor, const float waterlevel); @@ -174,7 +173,6 @@ namespace MWPhysics private: void updateWater(); - void updateIdle(); osg::ref_ptr mUnrefQueue; @@ -223,7 +221,6 @@ namespace MWPhysics osg::ref_ptr mParentNode; float mPhysicsDt; - float mIdleUpdateTimer; PhysicsSystem (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index fd27fe54b..243ba7b7e 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -701,8 +701,6 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWWorld::Ptr ptr = R()(runtime); - MWBase::Environment::get().getWorld()->queueMovement(ptr, osg::Vec3f(0, 0, -0.1f)); } }; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 911e0ebdc..c1bb589e8 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -506,7 +506,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str if (firstPersonCam != MWBase::Environment::get().getWorld()->isFirstPerson()) MWBase::Environment::get().getWorld()->togglePOV(); - const MWWorld::Ptr ptr = MWMechanics::getPlayer(); + MWWorld::ConstPtr ptr = MWMechanics::getPlayer(); if (ptr.isInCell()) { @@ -538,9 +538,6 @@ void MWState::StateManager::loadGame (const Character *character, const std::str // Since we passed "changeEvent=false" to changeCell, we shouldn't have triggered the cell change flag. // But make sure the flag is cleared anyway in case it was set from an earlier game. MWBase::Environment::get().getWorld()->markCellAsUnchanged(); - - // Workaround to fix camera position upon game load - MWBase::Environment::get().getWorld()->queueMovement(ptr, osg::Vec3f(0, 0, 0)); } catch (const std::exception& e) { diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 1179e1a9b..bbca8a46e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1314,6 +1314,8 @@ namespace MWWorld if (pos.z() < terrainHeight) pos.z() = terrainHeight; + pos.z() += 20; // place slightly above. will snap down to ground with code below + if (force || !isFlying(ptr)) { osg::Vec3f traced = mPhysics->traceDown(ptr, pos, 500); @@ -2160,11 +2162,6 @@ namespace MWWorld return mPhysics->isOnGround(ptr); } - bool World::isIdle(const MWWorld::Ptr &ptr) const - { - return mPhysics->isIdle(ptr); - } - void World::togglePOV() { mRendering->togglePOV(); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 25fc473dc..023d91bca 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -489,7 +489,6 @@ namespace MWWorld bool isWading(const MWWorld::ConstPtr &object) const override; bool isWaterWalkingCastableOnTarget(const MWWorld::ConstPtr &target) const override; bool isOnGround(const MWWorld::Ptr &ptr) const override; - bool isIdle(const MWWorld::Ptr &ptr) const override; osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const override; From cfdf99f601a36a6c5fb816311f41dc08ba264f89 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sat, 26 May 2018 11:39:30 +0000 Subject: [PATCH 45/50] Revert "Merged pull request #1573" This reverts commit 7324bd368f103a5dc3c029dfd1c7024e90200cdf, reversing changes made to 810e4416f68cd564a9d189e88c15b1cae29e663e. --- apps/openmw/mwbase/world.hpp | 7 +- apps/openmw/mwmechanics/character.cpp | 9 --- apps/openmw/mwmechanics/spellcasting.cpp | 83 +++-------------------- apps/openmw/mwrender/animation.cpp | 14 ++-- apps/openmw/mwrender/animation.hpp | 3 +- apps/openmw/mwrender/effectmanager.cpp | 9 +-- apps/openmw/mwrender/effectmanager.hpp | 1 - apps/openmw/mwrender/objects.cpp | 8 --- apps/openmw/mwrender/objects.hpp | 2 - apps/openmw/mwrender/renderingmanager.cpp | 13 +--- apps/openmw/mwrender/renderingmanager.hpp | 2 - apps/openmw/mwscript/miscextensions.cpp | 2 - apps/openmw/mwworld/worldimp.cpp | 9 +-- apps/openmw/mwworld/worldimp.hpp | 4 +- 14 files changed, 23 insertions(+), 143 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 68d4ac85d..47502fd71 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -5,9 +5,6 @@ #include #include -#include -#include - #include #include "../mwworld/ptr.hpp" @@ -537,7 +534,7 @@ namespace MWBase /// Spawn a blood effect for \a ptr at \a worldPosition virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) = 0; - virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true) = 0; + virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos) = 0; virtual void explodeSpell(const osg::Vec3f& origin, const ESM::EffectList& effects, const MWWorld::Ptr& caster, const MWWorld::Ptr& ignore, ESM::RangeType rangeType, const std::string& id, @@ -579,8 +576,6 @@ namespace MWBase /// Preload VFX associated with this effect list virtual void preloadEffects(const ESM::EffectList* effectList) = 0; - - virtual osg::ref_ptr getInstance (const std::string& modelName) = 0; }; } diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 29a6d5e3b..68dc17915 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -833,7 +833,6 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim refreshCurrentAnims(mIdleState, mMovementState, mJumpState, true); mAnimation->runAnimation(0.f); - mAnimation->updateEffects(0.f); unpersistAnimationState(); } @@ -1997,13 +1996,6 @@ void CharacterController::update(float duration) } osg::Vec3f moved = mAnimation->runAnimation(mSkipAnim ? 0.f : duration); - - // treat player specifically since he is not in rendering mObjects - if (mPtr == getPlayer()) - { - mAnimation->updateEffects(mSkipAnim ? 0.f : duration); - } - if(duration > 0.0f) moved /= duration; else @@ -2199,7 +2191,6 @@ void CharacterController::forceStateUpdate() } mAnimation->runAnimation(0.f); - mAnimation->updateEffects(0.f); } CharacterController::KillResult CharacterController::kill() diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index cdadd3b15..1f78e296f 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -6,12 +6,8 @@ #include -#include -#include - #include #include -#include #include "../mwbase/windowmanager.hpp" #include "../mwbase/soundmanager.hpp" @@ -28,7 +24,6 @@ #include "../mwworld/inventorystore.hpp" #include "../mwrender/animation.hpp" -#include "../mwrender/vismask.hpp" #include "npcstats.hpp" #include "actorutil.hpp" @@ -997,13 +992,11 @@ namespace MWMechanics return true; } - void CastSpell::playSpellCastingEffects(const std::string &spellid) - { + void CastSpell::playSpellCastingEffects(const std::string &spellid){ + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Spell *spell = store.get().find(spellid); - std::vector addedEffects; - for (std::vector::const_iterator iter = spell->mEffects.mList.begin(); iter != spell->mEffects.mList.end(); ++iter) { @@ -1012,72 +1005,18 @@ namespace MWMechanics MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(mCaster); - const ESM::Static* castStatic; - - if (!effect->mCasting.empty()) - castStatic = store.get().find (effect->mCasting); - else - castStatic = store.get().find ("VFX_DefaultCast"); - - // check if the effect was already added - if (std::find(addedEffects.begin(), addedEffects.end(), "meshes\\" + castStatic->mModel) != addedEffects.end()) - continue; - - std::string texture = effect->mParticle; - - float scale = 1.0f; - osg::Vec3f pos (mCaster.getRefData().getPosition().asVec3()); - - if (animation && mCaster.getClass().isNpc()) + if (animation && mCaster.getClass().isActor()) // TODO: Non-actors should also create a spell cast vfx even if they are disabled (animation == NULL) { - // For NOC we should take race height as scaling factor - const ESM::NPC *npc = mCaster.get()->mBase; - const MWWorld::ESMStore &esmStore = - MWBase::Environment::get().getWorld()->getStore(); - - const ESM::Race *race = - esmStore.get().find(npc->mRace); + const ESM::Static* castStatic; - scale = npc->isMale() ? race->mData.mHeight.mMale : race->mData.mHeight.mFemale; - } - else - { - std::string casterModel = mCaster.getClass().getModel(mCaster); - osg::ref_ptr model = MWBase::Environment::get().getWorld()->getInstance(casterModel); - - osg::ComputeBoundsVisitor computeBoundsVisitor; - computeBoundsVisitor.setTraversalMask(~(MWRender::Mask_ParticleSystem|MWRender::Mask_Effect)); - model->accept(computeBoundsVisitor); - osg::BoundingBox bounds = computeBoundsVisitor.getBoundingBox(); - - if (bounds.valid()) - { - float meshSizeX = std::abs(bounds.xMax() - bounds.xMin()); - float meshSizeY = std::abs(bounds.yMax() - bounds.yMin()); - float meshSizeZ = std::abs(bounds.zMax() - bounds.zMin()); - - // TODO: take a size of particle or NPC with height and weight = 1.0 as scale = 1.0 - float scaleX = meshSizeX/60.f; - float scaleY = meshSizeY/60.f; - float scaleZ = meshSizeZ/120.f; + if (!effect->mCasting.empty()) + castStatic = store.get().find (effect->mCasting); + else + castStatic = store.get().find ("VFX_DefaultCast"); - scale = std::max({ scaleX, scaleY, scaleZ }); + std::string texture = effect->mParticle; - //pos = bounds.center(); - //pos[2] = bounds.zMin(); - } - } - - // If the caster has no animation, add the effect directly to the effectManager - if (animation) - { - animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex, false, "", texture, scale); - } - else - { - // We should set scale for effect manager manually - float meshScale = !mCaster.getClass().isActor() ? mCaster.getCellRef().getScale() : 1.0f; - MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + castStatic->mModel, effect->mParticle, pos, scale * meshScale); + animation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex, false, "", texture); } if (animation && !mCaster.getClass().isActor()) @@ -1087,8 +1026,6 @@ namespace MWMechanics "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" }; - addedEffects.push_back("meshes\\" + castStatic->mModel); - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); if(!effect->mCastSound.empty()) sndMgr->playSound3D(mCaster, effect->mCastSound, 1.0f, 1.0f); diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 1b508e593..1bd839ead 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -8,8 +8,6 @@ #include #include #include -#include -#include #include #include @@ -1117,6 +1115,8 @@ namespace MWRender ++stateiter; } + updateEffects(duration); + if (mHeadController) { const float epsilon = 0.001f; @@ -1366,7 +1366,7 @@ namespace MWRender useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue); } - void Animation::addEffect (const std::string& model, int effectId, bool loop, const std::string& bonename, const std::string& texture, float scale) + void Animation::addEffect (const std::string& model, int effectId, bool loop, const std::string& bonename, const std::string& texture) { if (!mObjectRoot.get()) return; @@ -1417,13 +1417,7 @@ namespace MWRender overrideFirstRootTexture(texture, mResourceSystem, node); - osg::Vec3f scale3f (scale, scale, scale); - - osg::ref_ptr trans = new osg::PositionAttitudeTransform; - trans->setScale(scale3f); - trans->addChild(node); - parentNode->removeChild(node); - parentNode->addChild(trans); + // TODO: in vanilla morrowind the effect is scaled based on the host object's bounding box. mEffects.push_back(params); } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 74224c6bd..cff98a4b7 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -364,7 +364,7 @@ public: * @param texture override the texture specified in the model's materials - if empty, do not override * @note Will not add an effect twice. */ - void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", const std::string& texture = "", float scale = 1.0f); + void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", const std::string& texture = ""); void removeEffect (int effectId); void getLoopingEffects (std::vector& out) const; @@ -446,6 +446,7 @@ public: void setLoopingEnabled(const std::string &groupname, bool enabled); + /// This is typically called as part of runAnimation, but may be called manually if needed. void updateEffects(float duration); /// Return a node with the specified name, or NULL if not existing. diff --git a/apps/openmw/mwrender/effectmanager.cpp b/apps/openmw/mwrender/effectmanager.cpp index c44c5428a..3e785a769 100644 --- a/apps/openmw/mwrender/effectmanager.cpp +++ b/apps/openmw/mwrender/effectmanager.cpp @@ -26,13 +26,6 @@ EffectManager::~EffectManager() } void EffectManager::addEffect(const std::string &model, const std::string& textureOverride, const osg::Vec3f &worldPosition, float scale, bool isMagicVFX) -{ - osg::Vec3f scale3f (scale, scale, scale); - - addEffect(model, textureOverride, worldPosition, scale3f, isMagicVFX); -} - -void EffectManager::addEffect(const std::string &model, const std::string& textureOverride, const osg::Vec3f &worldPosition, const osg::Vec3f &scale, bool isMagicVFX) { osg::ref_ptr node = mResourceSystem->getSceneManager()->getInstance(model); @@ -47,7 +40,7 @@ void EffectManager::addEffect(const std::string &model, const std::string& textu osg::ref_ptr trans = new osg::PositionAttitudeTransform; trans->setPosition(worldPosition); - trans->setScale(scale); + trans->setScale(osg::Vec3f(scale, scale, scale)); trans->addChild(node); SceneUtil::AssignControllerSourcesVisitor assignVisitor(effect.mAnimTime); diff --git a/apps/openmw/mwrender/effectmanager.hpp b/apps/openmw/mwrender/effectmanager.hpp index cc1c1b42e..5873c00dd 100644 --- a/apps/openmw/mwrender/effectmanager.hpp +++ b/apps/openmw/mwrender/effectmanager.hpp @@ -33,7 +33,6 @@ namespace MWRender /// Add an effect. When it's finished playing, it will be removed automatically. void addEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPosition, float scale, bool isMagicVFX = true); - void addEffect (const std::string &model, const std::string& textureOverride, const osg::Vec3f &worldPosition, const osg::Vec3f &scale3f, bool isMagicVFX); void update(float dt); diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 523f1774c..f0a3d2e38 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -138,14 +138,6 @@ bool Objects::removeObject (const MWWorld::Ptr& ptr) return false; } -void Objects::updateEffects(float duration) -{ - for(PtrAnimationMap::iterator iter = mObjects.begin();iter != mObjects.end();) - { - iter->second->updateEffects(duration); - ++iter; - } -} void Objects::removeCell(const MWWorld::CellStore* store) { diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index e97395213..659853763 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -88,8 +88,6 @@ public: bool removeObject (const MWWorld::Ptr& ptr); ///< \return found? - void updateEffects(float duration); - void removeCell(const MWWorld::CellStore* store); /// Updates containing cell for object rendering data diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index e5933a72a..6f0ddba3a 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -557,7 +557,6 @@ namespace MWRender mEffectManager->update(dt); mSky->update(dt); mWater->update(dt); - mObjects->updateEffects(dt); } mCamera->update(dt, paused); @@ -842,11 +841,9 @@ namespace MWRender mObjects->updatePtr(old, updated); } - void RenderingManager::spawnEffect(const std::string &model, const std::string& texture, const osg::Vec3f &worldPosition, float scale, bool isMagicVFX) + void RenderingManager::spawnEffect(const std::string &model, const std::string &texture, const osg::Vec3f &worldPosition, float scale, bool isMagicVFX) { - osg::Vec3f scale3f (scale, scale, scale); - - mEffectManager->addEffect(model, texture, worldPosition, scale3f, isMagicVFX); + mEffectManager->addEffect(model, texture, worldPosition, scale, isMagicVFX); } void RenderingManager::notifyWorldSpaceChanged() @@ -1125,12 +1122,6 @@ namespace MWRender updateProjectionMatrix(); } } - - osg::ref_ptr RenderingManager::getInstance(const std::string& modelName) - { - return mResourceSystem->getSceneManager()->getInstance(modelName); - } - void RenderingManager::exportSceneGraph(const MWWorld::Ptr &ptr, const std::string &filename, const std::string &format) { osg::Node* node = mViewer->getSceneData(); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 7a570f249..1c689d29f 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -205,8 +205,6 @@ namespace MWRender LandManager* getLandManager() const; - osg::ref_ptr getInstance(const std::string& modelName); - private: void updateProjectionMatrix(); void updateTextureFiltering(); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 243ba7b7e..59f2cc9c6 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -14,7 +14,6 @@ #include #include "../mwbase/environment.hpp" -#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/scriptmanager.hpp" #include "../mwbase/world.hpp" @@ -1052,7 +1051,6 @@ namespace MWScript MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr (targetId, false); MWMechanics::CastSpell cast(ptr, target); - cast.playSpellCastingEffects(spell); cast.mHitPosition = target.getRefData().getPosition().asVec3(); cast.mAlwaysSucceed = true; cast.cast(spell); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index bbca8a46e..6cf1ead87 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1535,11 +1535,6 @@ namespace MWWorld } } - osg::ref_ptr World::getInstance (const std::string& modelName) - { - return mRendering->getInstance(modelName); - } - const ESM::Potion *World::createRecord (const ESM::Potion& record) { return mStore.insert(record); @@ -3329,9 +3324,9 @@ namespace MWWorld mRendering->spawnEffect(model, texture, worldPosition, 1.0f, false); } - void World::spawnEffect(const std::string &model, const std::string &textureOverride, const osg::Vec3f &worldPos, float scale, bool isMagicVFX) + void World::spawnEffect(const std::string &model, const std::string &textureOverride, const osg::Vec3f &worldPos) { - mRendering->spawnEffect(model, textureOverride, worldPos, scale, isMagicVFX); + mRendering->spawnEffect(model, textureOverride, worldPos); } void World::explodeSpell(const osg::Vec3f& origin, const ESM::EffectList& effects, const Ptr& caster, const Ptr& ignore, ESM::RangeType rangeType, diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 023d91bca..0d168c912 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -640,7 +640,7 @@ namespace MWWorld /// Spawn a blood effect for \a ptr at \a worldPosition void spawnBloodEffect (const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) override; - void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true) override; + void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos) override; void explodeSpell(const osg::Vec3f& origin, const ESM::EffectList& effects, const MWWorld::Ptr& caster, const MWWorld::Ptr& ignore, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName, @@ -680,8 +680,6 @@ namespace MWWorld /// Preload VFX associated with this effect list void preloadEffects(const ESM::EffectList* effectList) override; - - osg::ref_ptr getInstance (const std::string& modelName); }; } From 7e38bb8513fd4841e57810d65910adb674dc5c9d Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 26 May 2018 22:17:27 +0300 Subject: [PATCH 46/50] Verifier: improve handling of class name and description --- apps/opencs/model/tools/classcheck.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/classcheck.cpp b/apps/opencs/model/tools/classcheck.cpp index 316fc0ce5..79cb704bf 100644 --- a/apps/opencs/model/tools/classcheck.cpp +++ b/apps/opencs/model/tools/classcheck.cpp @@ -28,9 +28,13 @@ void CSMTools::ClassCheckStage::perform (int stage, CSMDoc::Messages& messages) CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Class, class_.mId); - // test for empty name and description + // A class should have a name if (class_.mName.empty()) - messages.push_back (std::make_pair (id, class_.mId + " has an empty name")); + messages.push_back (std::make_pair (id, class_.mId + " doesn't have a name")); + + // A playable class should have a description + if (class_.mData.mIsPlayable != 0 && class_.mDescription.empty()) + messages.push_back (std::make_pair (id, class_.mId + " doesn't have a description and it's playable")); // test for invalid attributes for (int i=0; i<2; ++i) From 31ea7c8edde6745031df2d72da0050315a6ddee2 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 27 May 2018 10:43:31 +0000 Subject: [PATCH 47/50] Revert "set rebalance soul gem values to true by default" This reverts commit 2963524a013e679f2c48d0929ac8065a3840aedc. --- files/settings-default.cfg | 2 +- files/ui/advancedpage.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 4483e3d9d..b10b91eb1 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -217,7 +217,7 @@ followers attack on sight = false can loot during death animation = true # Makes the value of filled soul gems dependent only on soul magnitude (with formula from the Morrowind Code Patch) -rebalance soul gem values = true +rebalance soul gem values = false [General] diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 4e0234e2e..f436b4db3 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -112,7 +112,7 @@ - <html><head/><body><p>If this setting is true, the value of filled soul gems is dependent only on soul magnitude.</p><p>The default value is true.</p></body></html> + <html><head/><body><p>If this setting is true, the value of filled soul gems is dependent only on soul magnitude.</p><p>The default value is false.</p></body></html> Rebalance soul gem values From e8ec031a81b8315b23d36babc04fe1575ca25196 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 27 May 2018 15:57:47 +0300 Subject: [PATCH 48/50] [Client] Create Worldstate class that inherits BaseWorldstate --- apps/openmw/mwmp/Networking.cpp | 6 +----- apps/openmw/mwmp/Networking.hpp | 14 ++++++-------- apps/openmw/mwmp/Worldstate.cpp | 21 +++++++++++++++++++++ apps/openmw/mwmp/Worldstate.hpp | 22 ++++++++++++++++++++++ 4 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 apps/openmw/mwmp/Worldstate.cpp create mode 100644 apps/openmw/mwmp/Worldstate.hpp diff --git a/apps/openmw/mwmp/Networking.cpp b/apps/openmw/mwmp/Networking.cpp index 0d13ce95f..b5779cc21 100644 --- a/apps/openmw/mwmp/Networking.cpp +++ b/apps/openmw/mwmp/Networking.cpp @@ -1,7 +1,3 @@ -// -// Created by koncord on 04.01.16. -// - #include #include #include @@ -477,7 +473,7 @@ ObjectList *Networking::getObjectList() return &objectList; } -BaseWorldstate *Networking::getWorldstate() +Worldstate *Networking::getWorldstate() { return &worldstate; } diff --git a/apps/openmw/mwmp/Networking.hpp b/apps/openmw/mwmp/Networking.hpp index fa8a83be8..0f0ce93ec 100644 --- a/apps/openmw/mwmp/Networking.hpp +++ b/apps/openmw/mwmp/Networking.hpp @@ -1,7 +1,3 @@ -// -// Created by koncord on 04.01.16. -// - #ifndef OPENMW_NETWORKING_HPP #define OPENMW_NETWORKING_HPP @@ -9,8 +5,6 @@ #include #include -#include "ActorList.hpp" -#include "ObjectList.hpp" #include #include @@ -20,6 +14,10 @@ #include +#include "ActorList.hpp" +#include "ObjectList.hpp" +#include "Worldstate.hpp" + namespace mwmp { class LocalPlayer; @@ -47,7 +45,7 @@ namespace mwmp LocalPlayer *getLocalPlayer(); ActorList *getActorList(); ObjectList *getObjectList(); - BaseWorldstate *getWorldstate(); + Worldstate *getWorldstate(); private: bool connected; @@ -62,7 +60,7 @@ namespace mwmp ActorList actorList; ObjectList objectList; - BaseWorldstate worldstate; + Worldstate worldstate; void receiveMessage(RakNet::Packet *packet); diff --git a/apps/openmw/mwmp/Worldstate.cpp b/apps/openmw/mwmp/Worldstate.cpp new file mode 100644 index 000000000..19b171417 --- /dev/null +++ b/apps/openmw/mwmp/Worldstate.cpp @@ -0,0 +1,21 @@ +#include "Worldstate.hpp" +#include "Main.hpp" +#include "Networking.hpp" + +using namespace mwmp; +using namespace std; + +Worldstate::Worldstate() +{ + +} + +Worldstate::~Worldstate() +{ + +} + +Networking *Worldstate::getNetworking() +{ + return mwmp::Main::get().getNetworking(); +} diff --git a/apps/openmw/mwmp/Worldstate.hpp b/apps/openmw/mwmp/Worldstate.hpp new file mode 100644 index 000000000..97b89375d --- /dev/null +++ b/apps/openmw/mwmp/Worldstate.hpp @@ -0,0 +1,22 @@ +#ifndef OPENMW_WORLDSTATE_HPP +#define OPENMW_WORLDSTATE_HPP + +#include + +namespace mwmp +{ + class Networking; + class Worldstate : public BaseWorldstate + { + public: + + Worldstate(); + virtual ~Worldstate(); + + private: + Networking *getNetworking(); + + }; +} + +#endif //OPENMW_WORLDSTATE_HPP From 5d30a884ba174137a165816e44e04967b499f16f Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 27 May 2018 16:00:14 +0300 Subject: [PATCH 49/50] [Client] Add Worldstate to CMakeLists --- apps/openmw/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 1a93b0a96..0fd44261a 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -98,7 +98,7 @@ add_openmw_dir (mwbase ) add_openmw_dir (mwmp Main Networking LocalPlayer DedicatedPlayer PlayerList LocalActor DedicatedActor ActorList ObjectList - Cell CellController MechanicsHelper RecordHelper GUIController + Worldstate Cell CellController MechanicsHelper RecordHelper GUIController ) add_openmw_dir (mwmp/GUI GUIChat GUILogin PlayerMarkerCollection GUIDialogList TextInputDialog From 3efe05a88e3baeb8d6b37bb241e5a4c25655ed3b Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 27 May 2018 16:05:40 +0300 Subject: [PATCH 50/50] [General] Implement WorldCollisionOverride packet --- .../openmw-mp/Script/Functions/Worldstate.cpp | 35 +++++++++++ .../openmw-mp/Script/Functions/Worldstate.hpp | 62 ++++++++++++++++--- apps/openmw/mwclass/apparatus.cpp | 32 ++++++++++ apps/openmw/mwclass/armor.cpp | 32 ++++++++++ apps/openmw/mwclass/book.cpp | 32 ++++++++++ apps/openmw/mwclass/clothing.cpp | 32 ++++++++++ apps/openmw/mwclass/ingredient.cpp | 32 ++++++++++ apps/openmw/mwclass/misc.cpp | 32 ++++++++++ apps/openmw/mwclass/potion.cpp | 32 ++++++++++ apps/openmw/mwclass/repair.cpp | 32 ++++++++++ apps/openmw/mwclass/weapon.cpp | 32 ++++++++++ apps/openmw/mwmp/Worldstate.cpp | 5 +- apps/openmw/mwphysics/actor.cpp | 34 ++++++++++ components/openmw-mp/Base/BasePlayer.hpp | 4 -- components/openmw-mp/Base/BaseWorldstate.hpp | 5 ++ .../PacketWorldCollisionOverride.cpp | 5 +- 16 files changed, 425 insertions(+), 13 deletions(-) diff --git a/apps/openmw-mp/Script/Functions/Worldstate.cpp b/apps/openmw-mp/Script/Functions/Worldstate.cpp index 3793e034a..2210d4a6c 100644 --- a/apps/openmw-mp/Script/Functions/Worldstate.cpp +++ b/apps/openmw-mp/Script/Functions/Worldstate.cpp @@ -41,6 +41,27 @@ void WorldstateFunctions::SetTimeScale(double timeScale) noexcept { writeWorldstate.timeScale = timeScale; } + +void WorldstateFunctions::SetPlayerCollisionState(bool state) noexcept +{ + writeWorldstate.hasPlayerCollision = state; +} + +void WorldstateFunctions::SetActorCollisionState(bool state) noexcept +{ + writeWorldstate.hasActorCollision = state; +} + +void WorldstateFunctions::SetPlacedObjectCollisionState(bool state) noexcept +{ + writeWorldstate.hasPlacedObjectCollision = state; +} + +void WorldstateFunctions::UseActorCollisionForPlacedObjects(bool useActorCollision) noexcept +{ + writeWorldstate.useActorCollisionForPlacedObjects = useActorCollision; +} + void WorldstateFunctions::SendWorldTime(unsigned short pid, bool toOthers) noexcept { Player *player; @@ -54,3 +75,17 @@ void WorldstateFunctions::SendWorldTime(unsigned short pid, bool toOthers) noexc if (toOthers) mwmp::Networking::get().getWorldstatePacketController()->GetPacket(ID_WORLD_TIME)->Send(true); } + +void WorldstateFunctions::SendWorldCollisionOverride(unsigned short pid, bool toOthers) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + writeWorldstate.guid = player->guid; + + mwmp::Networking::get().getWorldstatePacketController()->GetPacket(ID_WORLD_COLLISION_OVERRIDE)->setWorldstate(&writeWorldstate); + mwmp::Networking::get().getWorldstatePacketController()->GetPacket(ID_WORLD_COLLISION_OVERRIDE)->Send(false); + + if (toOthers) + mwmp::Networking::get().getWorldstatePacketController()->GetPacket(ID_WORLD_COLLISION_OVERRIDE)->Send(true); +} diff --git a/apps/openmw-mp/Script/Functions/Worldstate.hpp b/apps/openmw-mp/Script/Functions/Worldstate.hpp index ff60047df..bbc82e3ea 100644 --- a/apps/openmw-mp/Script/Functions/Worldstate.hpp +++ b/apps/openmw-mp/Script/Functions/Worldstate.hpp @@ -4,15 +4,20 @@ #include "../Types.hpp" #define WORLDSTATEAPI \ - {"SetHour", WorldstateFunctions::SetHour},\ - {"SetDay", WorldstateFunctions::SetDay},\ - {"SetMonth", WorldstateFunctions::SetMonth},\ - {"SetYear", WorldstateFunctions::SetYear},\ + {"SetHour", WorldstateFunctions::SetHour},\ + {"SetDay", WorldstateFunctions::SetDay},\ + {"SetMonth", WorldstateFunctions::SetMonth},\ + {"SetYear", WorldstateFunctions::SetYear},\ + {"SetDaysPassed", WorldstateFunctions::SetDaysPassed},\ + {"SetTimeScale", WorldstateFunctions::SetTimeScale},\ \ - {"SetDaysPassed", WorldstateFunctions::SetDaysPassed},\ - {"SetTimeScale", WorldstateFunctions::SetTimeScale},\ + {"SetPlayerCollisionState", WorldstateFunctions::SetPlayerCollisionState},\ + {"SetActorCollisionState", WorldstateFunctions::SetActorCollisionState},\ + {"SetPlacedObjectCollisionState", WorldstateFunctions::SetPlacedObjectCollisionState},\ + {"UseActorCollisionForPlacedObjects", WorldstateFunctions::UseActorCollisionForPlacedObjects},\ \ - {"SendWorldTime", WorldstateFunctions::SendWorldTime} + {"SendWorldTime", WorldstateFunctions::SendWorldTime},\ + {"SendWorldCollisionOverride", WorldstateFunctions::SendWorldCollisionOverride} class WorldstateFunctions { @@ -67,6 +72,40 @@ public: */ static void SetTimeScale(double timeScale) noexcept; + /** + * \brief Set the collision state for other players. + * + * \param state The collision state. + * \return void + */ + static void SetPlayerCollisionState(bool state) noexcept; + + /** + * \brief Set the collision state for actors. + * + * \param state The collision state. + * \return void + */ + static void SetActorCollisionState(bool state) noexcept; + + /** + * \brief Set the collision state for placed objects. + * + * \param state The collision state. + * \return void + */ + static void SetPlacedObjectCollisionState(bool state) noexcept; + + /** + * \brief Whether placed objects with collision turned on should use + * actor collision, i.e. whether they should be slippery + * and prevent players from standing on them. + * + * \param useActorCollision Whether to use actor collision. + * \return void + */ + static void UseActorCollisionForPlacedObjects(bool useActorCollision) noexcept; + /** * \brief Send a WorldTime packet with the current time and time scale * to a specific player or to all players. @@ -76,6 +115,15 @@ public: */ static void SendWorldTime(unsigned short pid, bool toOthers = false) noexcept; + /** + * \brief Send a WorldCollisionOverride packet with the current collision overrides + * to a specific player or to all players. + * + * \param pid The player ID. + * \return void + */ + static void SendWorldCollisionOverride(unsigned short pid, bool toOthers = false) noexcept; + }; #endif //OPENMW_WORLDSTATEAPI_HPP diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index a271dc5e9..ae16b289a 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -1,5 +1,16 @@ #include "apparatus.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +/* + End of tes3mp addition +*/ + #include #include "../mwbase/environment.hpp" @@ -31,6 +42,27 @@ namespace MWClass void Apparatus::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const { // TODO: add option somewhere to enable collision for placeable objects + + /* + Start of tes3mp addition + + Make it possible to enable collision for this object class from a packet + */ + if (!model.empty()) + { + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (worldstate->hasPlacedObjectCollision) + { + if (worldstate->useActorCollisionForPlacedObjects) + physics.addObject(ptr, model, MWPhysics::CollisionType_Actor); + else + physics.addObject(ptr, model, MWPhysics::CollisionType_World); + } + } + /* + End of tes3mp addition + */ } std::string Apparatus::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 460cd517a..6220c79d5 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -1,5 +1,16 @@ #include "armor.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +/* + End of tes3mp addition +*/ + #include #include #include @@ -37,6 +48,27 @@ namespace MWClass void Armor::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const { // TODO: add option somewhere to enable collision for placeable objects + + /* + Start of tes3mp addition + + Make it possible to enable collision for this object class from a packet + */ + if (!model.empty()) + { + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (worldstate->hasPlacedObjectCollision) + { + if (worldstate->useActorCollisionForPlacedObjects) + physics.addObject(ptr, model, MWPhysics::CollisionType_Actor); + else + physics.addObject(ptr, model, MWPhysics::CollisionType_World); + } + } + /* + End of tes3mp addition + */ } std::string Armor::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 3d6455dc6..e16a99398 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -1,5 +1,16 @@ #include "book.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +/* + End of tes3mp addition +*/ + #include #include "../mwbase/environment.hpp" @@ -34,6 +45,27 @@ namespace MWClass void Book::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const { // TODO: add option somewhere to enable collision for placeable objects + + /* + Start of tes3mp addition + + Make it possible to enable collision for this object class from a packet + */ + if (!model.empty()) + { + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (worldstate->hasPlacedObjectCollision) + { + if (worldstate->useActorCollisionForPlacedObjects) + physics.addObject(ptr, model, MWPhysics::CollisionType_Actor); + else + physics.addObject(ptr, model, MWPhysics::CollisionType_World); + } + } + /* + End of tes3mp addition + */ } std::string Book::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index b37d1e90b..2f790e559 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -1,5 +1,16 @@ #include "clothing.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +/* + End of tes3mp addition +*/ + #include #include "../mwbase/environment.hpp" @@ -33,6 +44,27 @@ namespace MWClass void Clothing::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const { // TODO: add option somewhere to enable collision for placeable objects + + /* + Start of tes3mp addition + + Make it possible to enable collision for this object class from a packet + */ + if (!model.empty()) + { + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (worldstate->hasPlacedObjectCollision) + { + if (worldstate->useActorCollisionForPlacedObjects) + physics.addObject(ptr, model, MWPhysics::CollisionType_Actor); + else + physics.addObject(ptr, model, MWPhysics::CollisionType_World); + } + } + /* + End of tes3mp addition + */ } std::string Clothing::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 09d149331..6c03f31ef 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -1,5 +1,16 @@ #include "ingredient.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +/* + End of tes3mp addition +*/ + #include #include "../mwbase/environment.hpp" @@ -34,6 +45,27 @@ namespace MWClass void Ingredient::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const { // TODO: add option somewhere to enable collision for placeable objects + + /* + Start of tes3mp addition + + Make it possible to enable collision for this object class from a packet + */ + if (!model.empty()) + { + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (worldstate->hasPlacedObjectCollision) + { + if (worldstate->useActorCollisionForPlacedObjects) + physics.addObject(ptr, model, MWPhysics::CollisionType_Actor); + else + physics.addObject(ptr, model, MWPhysics::CollisionType_World); + } + } + /* + End of tes3mp addition + */ } std::string Ingredient::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 62b15bc86..0625dfdd6 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -1,5 +1,16 @@ #include "misc.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +/* + End of tes3mp addition +*/ + #include #include @@ -41,6 +52,27 @@ namespace MWClass void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const { // TODO: add option somewhere to enable collision for placeable objects + + /* + Start of tes3mp addition + + Make it possible to enable collision for this object class from a packet + */ + if (!model.empty()) + { + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (worldstate->hasPlacedObjectCollision) + { + if (worldstate->useActorCollisionForPlacedObjects) + physics.addObject(ptr, model, MWPhysics::CollisionType_Actor); + else + physics.addObject(ptr, model, MWPhysics::CollisionType_World); + } + } + /* + End of tes3mp addition + */ } std::string Miscellaneous::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index ffdccf438..475b4ef50 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -1,5 +1,16 @@ #include "potion.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +/* + End of tes3mp addition +*/ + #include #include "../mwbase/environment.hpp" @@ -35,6 +46,27 @@ namespace MWClass void Potion::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const { // TODO: add option somewhere to enable collision for placeable objects + + /* + Start of tes3mp addition + + Make it possible to enable collision for this object class from a packet + */ + if (!model.empty()) + { + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (worldstate->hasPlacedObjectCollision) + { + if (worldstate->useActorCollisionForPlacedObjects) + physics.addObject(ptr, model, MWPhysics::CollisionType_Actor); + else + physics.addObject(ptr, model, MWPhysics::CollisionType_World); + } + } + /* + End of tes3mp addition + */ } std::string Potion::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 566d16106..ec84bb803 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -1,5 +1,16 @@ #include "repair.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +/* + End of tes3mp addition +*/ + #include #include "../mwbase/environment.hpp" @@ -31,6 +42,27 @@ namespace MWClass void Repair::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const { // TODO: add option somewhere to enable collision for placeable objects + + /* + Start of tes3mp addition + + Make it possible to enable collision for this object class from a packet + */ + if (!model.empty()) + { + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (worldstate->hasPlacedObjectCollision) + { + if (worldstate->useActorCollisionForPlacedObjects) + physics.addObject(ptr, model, MWPhysics::CollisionType_Actor); + else + physics.addObject(ptr, model, MWPhysics::CollisionType_World); + } + } + /* + End of tes3mp addition + */ } std::string Repair::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index e59567aac..4d0b7411b 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -1,5 +1,16 @@ #include "weapon.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +/* + End of tes3mp addition +*/ + #include #include @@ -35,6 +46,27 @@ namespace MWClass void Weapon::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const { // TODO: add option somewhere to enable collision for placeable objects + + /* + Start of tes3mp addition + + Make it possible to enable collision for this object class from a packet + */ + if (!model.empty()) + { + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (worldstate->hasPlacedObjectCollision) + { + if (worldstate->useActorCollisionForPlacedObjects) + physics.addObject(ptr, model, MWPhysics::CollisionType_Actor); + else + physics.addObject(ptr, model, MWPhysics::CollisionType_World); + } + } + /* + End of tes3mp addition + */ } std::string Weapon::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwmp/Worldstate.cpp b/apps/openmw/mwmp/Worldstate.cpp index 19b171417..e3c487445 100644 --- a/apps/openmw/mwmp/Worldstate.cpp +++ b/apps/openmw/mwmp/Worldstate.cpp @@ -7,7 +7,10 @@ using namespace std; Worldstate::Worldstate() { - + hasPlayerCollision = true; + hasActorCollision = true; + hasPlacedObjectCollision = false; + useActorCollisionForPlacedObjects = false; } Worldstate::~Worldstate() diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index 6de0d1984..7376a794d 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -1,5 +1,18 @@ #include "actor.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include +#include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" +#include "../mwmp/PlayerList.hpp" +/* + End of tes3mp addition +*/ + #include #include #include @@ -53,6 +66,27 @@ Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr updatePosition(); addCollisionMask(getCollisionMask()); + + /* + Start of tes3mp addition + + Make it possible to disable collision for players or regular actors from a packet + */ + mwmp::BaseWorldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (mwmp::PlayerList::isDedicatedPlayer(ptr)) + { + if (!worldstate->hasPlayerCollision) + enableCollisionBody(false); + } + else + { + if (!worldstate->hasActorCollision) + enableCollisionBody(false); + } + /* + End of tes3mp addition + */ } Actor::~Actor() diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 9cc13c71f..30d62a73d 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -1,7 +1,3 @@ -// -// Created by koncord on 07.01.16. -// - #ifndef OPENMW_BASEPLAYER_HPP #define OPENMW_BASEPLAYER_HPP diff --git a/components/openmw-mp/Base/BaseWorldstate.hpp b/components/openmw-mp/Base/BaseWorldstate.hpp index f8549b74e..6e2518c0f 100644 --- a/components/openmw-mp/Base/BaseWorldstate.hpp +++ b/components/openmw-mp/Base/BaseWorldstate.hpp @@ -32,6 +32,11 @@ namespace mwmp int daysPassed; float timeScale; + bool hasPlayerCollision; + bool hasActorCollision; + bool hasPlacedObjectCollision; + bool useActorCollisionForPlacedObjects; + bool isValid; }; } diff --git a/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.cpp b/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.cpp index b2b482b92..ee9720600 100644 --- a/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.cpp +++ b/components/openmw-mp/Packets/Worldstate/PacketWorldCollisionOverride.cpp @@ -13,5 +13,8 @@ void PacketWorldCollisionOverride::Packet(RakNet::BitStream *bs, bool send) { WorldstatePacket::Packet(bs, send); - // Placeholder + RW(worldstate->hasPlayerCollision, send); + RW(worldstate->hasActorCollision, send); + RW(worldstate->hasPlacedObjectCollision, send); + RW(worldstate->useActorCollisionForPlacedObjects, send); }