Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setTerrain functionality to TileLayerEdit #3758

Merged
merged 18 commits into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/tiled/editabletilelayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@

#include "editabletilelayer.h"

#include "addremovetileset.h"
#include "changelayer.h"
#include "editablemanager.h"
#include "editablemap.h"
#include "painttilelayer.h"
#include "resizetilelayer.h"
#include "tilelayeredit.h"
#include "tilelayerwangedit.h"
#include "tilesetdocument.h"

namespace Tiled {
Expand All @@ -45,6 +48,8 @@ EditableTileLayer::~EditableTileLayer()
{
while (!mActiveEdits.isEmpty())
delete mActiveEdits.first();
while (!mActiveWangEdits.isEmpty())
delete mActiveWangEdits.first();
}

void EditableTileLayer::setSize(QSize size)
Expand Down Expand Up @@ -101,6 +106,51 @@ TileLayerEdit *EditableTileLayer::edit()
return new TileLayerEdit(this);
}

TileLayerWangEdit *EditableTileLayer::wangEdit(EditableWangSet *wangSet)
{
return new TileLayerWangEdit(this, wangSet);
}

void EditableTileLayer::applyChangesFrom(TileLayer *changes, bool mergeable)
a-morphous marked this conversation as resolved.
Show resolved Hide resolved
{
// Determine painted region and normalize the changes layer
auto paintedRegion = changes->region([] (const Cell &cell) { return cell.checked(); });

// If the painted region is empty there's nothing else to do
if (paintedRegion.isEmpty())
return;

auto rect = paintedRegion.boundingRect();
changes->resize(rect.size(), -rect.topLeft());
const auto tilesets = changes->usedTilesets();

if (mapDocument()) {
// Apply the change using an undo command
auto mapDocument = map()->mapDocument();
auto paint = new PaintTileLayer(mapDocument,
tileLayer(),
rect.x(), rect.y(),
changes,
paintedRegion);
paint->setMergeable(mergeable);

// Add any used tilesets that aren't yet part of the target map
const auto existingTilesets = mapDocument->map()->tilesets();
for (const SharedTileset &tileset : tilesets)
if (!existingTilesets.contains(tileset))
new AddTileset(mapDocument, tileset, paint);

map()->push(paint);
} else {
// Add any used tilesets that aren't yet part of the target map
if (auto map = tileLayer()->map())
map->addTilesets(tilesets);

// Apply the change directly
tileLayer()->setCells(rect.x(), rect.y(), changes, paintedRegion);
}
}

} // namespace Tiled

#include "moc_editabletilelayer.cpp"
7 changes: 7 additions & 0 deletions src/tiled/editabletilelayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
namespace Tiled {

class EditableTile;
class EditableWangSet;
class TileLayerEdit;
class TileLayerWangEdit;

class EditableTileLayer : public EditableLayer
{
Expand Down Expand Up @@ -64,13 +66,18 @@ class EditableTileLayer : public EditableLayer
Q_INVOKABLE Tiled::EditableTile *tileAt(int x, int y) const;

Q_INVOKABLE Tiled::TileLayerEdit *edit();
Q_INVOKABLE Tiled::TileLayerWangEdit *wangEdit(Tiled::EditableWangSet *wangSet);

TileLayer *tileLayer() const;

private:
friend TileLayerEdit;
friend TileLayerWangEdit;

QList<TileLayerEdit*> mActiveEdits;
QList<TileLayerWangEdit*> mActiveWangEdits;

void applyChangesFrom(TileLayer *changes, bool mergeable);
};


Expand Down
4 changes: 4 additions & 0 deletions src/tiled/libtilededitor.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@ DynamicLibrary {
"tilelayeredit.h",
"tilelayeritem.cpp",
"tilelayeritem.h",
"tilelayerwangedit.cpp",
"tilelayerwangedit.h",
"tilepainter.cpp",
"tilepainter.h",
"tileselectionitem.cpp",
Expand Down Expand Up @@ -561,6 +563,8 @@ DynamicLibrary {
"wangfiller.h",
"wangoverlay.cpp",
"wangoverlay.h",
"wangpainter.cpp",
"wangpainter.h",
"wangsetmodel.cpp",
"wangsetmodel.h",
"wangsetview.cpp",
Expand Down
39 changes: 1 addition & 38 deletions src/tiled/tilelayeredit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,44 +63,7 @@ void TileLayerEdit::apply()
// Applying an edit automatically makes it mergeable, so that further
// changes made through the same edit are merged by default.
bool mergeable = std::exchange(mMergeable, true);

// Determine painted region and normalize the changes layer
auto paintedRegion = mChanges.region([] (const Cell &cell) { return cell.checked(); });

// If the painted region is empty there's nothing else to do
if (paintedRegion.isEmpty())
return;

auto rect = paintedRegion.boundingRect();
mChanges.resize(rect.size(), -rect.topLeft());
const auto tilesets = mChanges.usedTilesets();

if (mTargetLayer->mapDocument()) {
// Apply the change using an undo command
auto mapDocument = mTargetLayer->map()->mapDocument();
auto paint = new PaintTileLayer(mapDocument,
mTargetLayer->tileLayer(),
rect.x(), rect.y(),
&mChanges,
paintedRegion);
paint->setMergeable(mergeable);

// Add any used tilesets that aren't yet part of the target map
const auto existingTilesets = mapDocument->map()->tilesets();
for (const SharedTileset &tileset : tilesets)
if (!existingTilesets.contains(tileset))
new AddTileset(mapDocument, tileset, paint);

mTargetLayer->map()->push(paint);
} else {
// Add any used tilesets that aren't yet part of the target map
if (auto map = mTargetLayer->tileLayer()->map())
map->addTilesets(tilesets);

// Apply the change directly
mTargetLayer->tileLayer()->setCells(rect.x(), rect.y(), &mChanges, paintedRegion);
}

mTargetLayer->applyChangesFrom(&mChanges, mergeable);
mChanges.clear();
}

Expand Down
44 changes: 44 additions & 0 deletions src/tiled/tilelayerwangedit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "tilelayerwangedit.h"

#include "addremovetileset.h"
#include "editablemap.h"
#include "editabletile.h"
#include "editabletilelayer.h"
#include "painttilelayer.h"
#include "scriptmanager.h"

namespace Tiled {

TileLayerWangEdit::TileLayerWangEdit(EditableTileLayer *tileLayer, EditableWangSet *wangSet, QObject *parent)
: QObject(parent)
, mTargetLayer(tileLayer)
{
mTargetLayer->mActiveWangEdits.append(this);
mWangPainter = new WangPainter();
mWangPainter->setWangSet(wangSet->wangSet());
}

TileLayerWangEdit::~TileLayerWangEdit()
{
mTargetLayer->mActiveWangEdits.removeOne(this);
}

void TileLayerWangEdit::setTerrain(int x, int y, int color, WangId::Index direction) {
mWangPainter->setTerrain(mTargetLayer->mapDocument(), color, QPoint(x, y), direction);
}

void TileLayerWangEdit::apply()
{
// apply terrain changes
mWangPainter->commit(mTargetLayer->mapDocument(), &mChanges);

// Applying an edit automatically makes it mergeable, so that further
// changes made through the same edit are merged by default.
bool mergeable = std::exchange(mMergeable, true);
mTargetLayer->applyChangesFrom(&mChanges, mergeable);
mChanges.clear();
}

} // namespace Tiled

#include "moc_tilelayerwangedit.cpp"
66 changes: 66 additions & 0 deletions src/tiled/tilelayerwangedit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#pragma once

#include "editablewangset.h"
#include "tilelayer.h"
#include "wangpainter.h"

#include <QObject>

namespace Tiled {

class EditableTileLayer;

class TileLayerWangEdit : public QObject
{
Q_OBJECT

Q_PROPERTY(Tiled::EditableTileLayer *target READ target)
Q_PROPERTY(bool mergeable READ isMergeable WRITE setMergeable)

public:
explicit TileLayerWangEdit(EditableTileLayer *tileLayer,
EditableWangSet *wangSet,
QObject *parent = nullptr);
~TileLayerWangEdit() override;

/**
* Sets whether this edit can be merged with a previous edit.
*
* Calling apply() automatically set this edit to be mergeable, so that
* edits are merged when this object is reused.
*/
void setMergeable(bool mergeable);
bool isMergeable() const;

EditableTileLayer *target() const;

public slots:
void setTerrain(int x, int y, int color, WangId::Index direction = WangId::Left);
void apply();

private:
EditableTileLayer *mTargetLayer;
TileLayer mChanges;
bool mMergeable = false;
WangPainter *mWangPainter = nullptr;
};


inline void TileLayerWangEdit::setMergeable(bool mergeable)
{
mMergeable = mergeable;
}

inline bool TileLayerWangEdit::isMergeable() const
{
return mMergeable;
}

inline EditableTileLayer *TileLayerWangEdit::target() const
{
return mTargetLayer;
}

} // namespace Tiled

Q_DECLARE_METATYPE(Tiled::TileLayerWangEdit*)
Loading