Add support to TilemapMode::Tiles mode
When transforming slices in a tilemap layer while Tiles mode is active
This commit is contained in:
parent
f5baba389b
commit
ca75a98679
|
|
@ -32,47 +32,45 @@ ClearSlices::ClearSlices(const Site& site,
|
|||
: m_tilemapMode(site.tilemapMode())
|
||||
, m_tilesetMode(site.tilesetMode())
|
||||
{
|
||||
//Doc* doc = static_cast<Doc*>(cel->document());
|
||||
|
||||
if (layers.empty())
|
||||
return;
|
||||
|
||||
Doc* doc = static_cast<Doc*>((*layers.begin())->sprite()->document());
|
||||
|
||||
for (const auto& sk : slicesKeys) {
|
||||
m_mask.add(sk.bounds());
|
||||
}
|
||||
const gfx::Rect maskBounds = m_mask.bounds();
|
||||
|
||||
// gfx::Rect maskBounds;
|
||||
// if (image->pixelFormat() == IMAGE_TILEMAP) {
|
||||
// auto grid = cel->grid();
|
||||
// imageBounds = gfx::Rect(grid.canvasToTile(cel->position()),
|
||||
// cel->image()->size());
|
||||
// maskBounds = grid.canvasToTile(mask->bounds());
|
||||
// m_bgcolor = doc::notile; // TODO configurable empty tile
|
||||
// }
|
||||
// else {
|
||||
for (auto* layer : layers) {
|
||||
SlicesContent sc;
|
||||
for (const auto& sk : slicesKeys) {
|
||||
sc.mask.add(sk.bounds());
|
||||
}
|
||||
gfx::Rect maskBounds = sc.mask.bounds();
|
||||
|
||||
Cel* cel = layer->cel(frame);
|
||||
const gfx::Rect imageBounds = cel->bounds();
|
||||
Image* image = cel->image();
|
||||
assert(image);
|
||||
if (!image)
|
||||
continue;
|
||||
|
||||
gfx::Rect imageBounds = cel->bounds();
|
||||
|
||||
color_t bgcolor = doc->bgColor(layer);
|
||||
if (image->pixelFormat() == IMAGE_TILEMAP) {
|
||||
auto grid = cel->grid();
|
||||
imageBounds = gfx::Rect(grid.canvasToTile(cel->position()),
|
||||
cel->image()->size());
|
||||
maskBounds = grid.canvasToTile(maskBounds);
|
||||
bgcolor = doc::notile; // TODO configurable empty tile
|
||||
}
|
||||
|
||||
gfx::Rect cropBounds = (imageBounds & maskBounds);
|
||||
if (cropBounds.isEmpty())
|
||||
continue;
|
||||
|
||||
cropBounds.offset(-imageBounds.origin());
|
||||
|
||||
Image* image = cel->image();
|
||||
assert(image);
|
||||
if (!image)
|
||||
continue;
|
||||
|
||||
SlicesContent sc;
|
||||
sc.cel = cel;
|
||||
sc.cropPos = cropBounds.origin();
|
||||
sc.bgcolor = doc->bgColor(layer);
|
||||
sc.bgcolor = bgcolor;
|
||||
sc.copy.reset(crop_image(image, cropBounds, sc.bgcolor));
|
||||
|
||||
m_slicesContents.push_back(sc);
|
||||
}
|
||||
}
|
||||
|
|
@ -105,27 +103,19 @@ void ClearSlices::clear()
|
|||
if (sc.cel->layer()->isTilemap() && m_tilemapMode == TilemapMode::Pixels) {
|
||||
|
||||
Doc* doc = static_cast<Doc*>(sc.cel->document());
|
||||
/*
|
||||
// Simple case (there is no visible selection, so we remove the
|
||||
// whole cel)
|
||||
if (!doc->isMaskVisible()) {
|
||||
cmds->executeAndAdd(new cmd::ClearCel(cel));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
color_t bgcolor = doc->bgColor(sc.cel->layer());
|
||||
|
||||
modify_tilemap_cel_region(
|
||||
&m_seq, sc.cel, nullptr,
|
||||
gfx::Region(m_mask.bounds()),
|
||||
gfx::Region(sc.mask.bounds()),
|
||||
m_tilesetMode,
|
||||
[this, bgcolor](const doc::ImageRef& origTile,
|
||||
[sc, bgcolor](const doc::ImageRef& origTile,
|
||||
const gfx::Rect& tileBoundsInCanvas) -> doc::ImageRef {
|
||||
doc::ImageRef modified(doc::Image::createCopy(origTile.get()));
|
||||
doc::algorithm::fill_selection(
|
||||
modified.get(),
|
||||
tileBoundsInCanvas,
|
||||
&m_mask,
|
||||
&sc.mask,
|
||||
bgcolor,
|
||||
nullptr);
|
||||
return modified;
|
||||
|
|
@ -136,7 +126,7 @@ void ClearSlices::clear()
|
|||
doc::algorithm::fill_selection(
|
||||
sc.cel->image(),
|
||||
sc.cel->bounds(),
|
||||
&m_mask,
|
||||
&sc.mask,
|
||||
sc.bgcolor,
|
||||
(sc.cel->image()->isTilemap() ? &grid: nullptr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ namespace cmd {
|
|||
Cel* cel = nullptr;
|
||||
// Image having a copy of the content of each selected slice.
|
||||
ImageRef copy = nullptr;
|
||||
Mask mask;
|
||||
gfx::Point cropPos;
|
||||
color_t bgcolor;
|
||||
size_t memSize() const {
|
||||
|
|
@ -63,7 +64,6 @@ namespace cmd {
|
|||
void clear();
|
||||
void restore();
|
||||
|
||||
Mask m_mask;
|
||||
CmdSequence m_seq;
|
||||
// Slices content for each selected layer's cel
|
||||
std::vector<SlicesContent> m_slicesContents;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ MovingSliceState::MovingSliceState(Editor* editor,
|
|||
: m_frame(editor->frame())
|
||||
, m_hit(hit)
|
||||
, m_items(std::max<std::size_t>(1, selectedSlices.size()))
|
||||
//, m_reader(UIContext::instance())
|
||||
, m_tx(Tx::DontLockDoc, UIContext::instance(),
|
||||
UIContext::instance()->activeDocument(),
|
||||
(editor->slicesTransforms() ? "Slices Transformation" : "Slice Movement"))
|
||||
|
|
@ -95,6 +94,12 @@ void MovingSliceState::onEnterState(Editor* editor)
|
|||
{
|
||||
if (editor->slicesTransforms() && !m_items.empty()) {
|
||||
for (auto& item : m_items) {
|
||||
// Align slice origin to tiles origin under Tiles mode.
|
||||
if (m_site.tilemapMode() == TilemapMode::Tiles) {
|
||||
auto origin = m_site.grid().tileToCanvas(m_site.grid().canvasToTile(item.newKey.bounds().origin()));
|
||||
auto bounds = gfx::Rect(origin, item.newKey.bounds().size());
|
||||
item.newKey.setBounds(bounds);
|
||||
}
|
||||
item.imgs.reserve(m_selectedLayers.size());
|
||||
item.masks.reserve(m_selectedLayers.size());
|
||||
int i = 0;
|
||||
|
|
@ -106,7 +111,7 @@ void MovingSliceState::onEnterState(Editor* editor)
|
|||
if (layer &&
|
||||
layer->isTilemap() &&
|
||||
m_site.tilemapMode() == TilemapMode::Tiles) {
|
||||
//item.img.reset(new_tilemap_from_mask(m_site, item.mask.get()));
|
||||
item.imgs[i].reset(new_tilemap_from_mask(m_site, item.masks[i].get()));
|
||||
}
|
||||
else {
|
||||
item.imgs[i].reset(new_image_from_mask(
|
||||
|
|
@ -152,22 +157,13 @@ void MovingSliceState::onEnterState(Editor* editor)
|
|||
|
||||
clearSlices();
|
||||
|
||||
if (editor->slicesTransforms()) {
|
||||
drawSliceContents();
|
||||
drawSliceContents();
|
||||
|
||||
// Redraw the editor.
|
||||
editor->invalidate();
|
||||
}
|
||||
// Redraw the editor.
|
||||
editor->invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
EditorState::LeaveAction MovingSliceState::onLeaveState(Editor *editor, EditorState *newState)
|
||||
{
|
||||
//editor->document()->resetTransformation();
|
||||
|
||||
return StandbyState::onLeaveState(editor, newState);
|
||||
}
|
||||
|
||||
bool MovingSliceState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
{
|
||||
|
|
@ -211,7 +207,6 @@ void MovingSliceState::stampExtraCelImage()
|
|||
TiledMode::NONE, m_tx,
|
||||
ExpandCelCanvas::None);
|
||||
|
||||
|
||||
gfx::Point dstPt;
|
||||
gfx::Size canvasImageSize = image->size();
|
||||
if (m_site.tilemapMode() == TilemapMode::Tiles) {
|
||||
|
|
@ -308,16 +303,12 @@ void MovingSliceState::drawExtraCel(const gfx::Rect& bounds, DrawExtraCelContent
|
|||
if (m_site.tilemapMode() == TilemapMode::Tiles) {
|
||||
dst->setMaskColor(doc::notile);
|
||||
dst->clear(dst->maskColor());
|
||||
/*
|
||||
TODO: Fix this when the TilemapMode::Pixels mode works
|
||||
if (m_site.cel()) {
|
||||
doc::Grid grid = m_site.grid();
|
||||
dst->copy(m_site.cel()->image(),
|
||||
gfx::Clip(0, 0, grid.canvasToTile(bounds)));
|
||||
//dst->copy(item.img.get(),
|
||||
// gfx::Clip(0, 0, grid.canvasToTile(bounds)));
|
||||
}
|
||||
*/
|
||||
|
||||
if (m_site.cel()) {
|
||||
doc::Grid grid = m_site.grid();
|
||||
dst->copy(m_site.cel()->image(),
|
||||
gfx::Clip(0, 0, grid.canvasToTile(bounds)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
dst->setMaskColor(m_site.sprite()->transparentColor());
|
||||
|
|
@ -345,13 +336,14 @@ void MovingSliceState::drawImage(doc::Image* dst,
|
|||
if (!src) return;
|
||||
|
||||
if (m_site.tilemapMode() == TilemapMode::Tiles) {
|
||||
|
||||
/* TODO: Finish this when TilemapMode::Pixels works
|
||||
drawTransformedTilemap(
|
||||
transformation,
|
||||
dst, m_originalImage.get(),
|
||||
m_initialMask.get());
|
||||
*/
|
||||
gfx::Rect tilesBounds = m_site.grid().canvasToTile(bounds);
|
||||
doc::algorithm::parallelogram(
|
||||
dst, src, nullptr,
|
||||
tilesBounds.x , tilesBounds.y,
|
||||
tilesBounds.x+tilesBounds.w, tilesBounds.y,
|
||||
tilesBounds.x+tilesBounds.w, tilesBounds.y+tilesBounds.h,
|
||||
tilesBounds.x , tilesBounds.y+tilesBounds.h
|
||||
);
|
||||
}
|
||||
else {
|
||||
doc::algorithm::parallelogram(
|
||||
|
|
@ -370,6 +362,11 @@ bool MovingSliceState::onMouseMove(Editor* editor, MouseMessage* msg)
|
|||
gfx::Point delta = newCursorPos - m_mouseStart;
|
||||
gfx::Rect totalBounds = selectedSlicesBounds();
|
||||
|
||||
// Move by tile size under Tiles mode.
|
||||
if (editor->slicesTransforms() && m_site.tilemapMode() == TilemapMode::Tiles) {
|
||||
delta = m_site.grid().tileToCanvas(m_site.grid().canvasToTile(delta));
|
||||
}
|
||||
|
||||
ASSERT(totalBounds.w > 0);
|
||||
ASSERT(totalBounds.h > 0);
|
||||
|
||||
|
|
@ -447,6 +444,11 @@ bool MovingSliceState::onMouseMove(Editor* editor, MouseMessage* msg)
|
|||
}
|
||||
}
|
||||
|
||||
// Align slice origin to tiles origin under Tiles mode.
|
||||
if (editor->slicesTransforms() && m_site.tilemapMode() == TilemapMode::Tiles) {
|
||||
rc.setOrigin(m_site.grid().tileToCanvas(m_site.grid().canvasToTile(rc.origin())));
|
||||
}
|
||||
|
||||
if (m_hit.type() == EditorHit::SliceCenter)
|
||||
key.setCenter(rc);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ namespace app {
|
|||
const doc::SelectedObjects& selectedSlices);
|
||||
|
||||
void onEnterState(Editor* editor) override;
|
||||
LeaveAction onLeaveState(Editor *editor, EditorState *newState) override;
|
||||
bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override;
|
||||
bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;
|
||||
bool onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos) override;
|
||||
|
|
|
|||
|
|
@ -314,6 +314,25 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class TilemapDelegate : public GenericDelegate<TilemapTraits> {
|
||||
public:
|
||||
TilemapDelegate(color_t mask_color) :
|
||||
m_mask_color(mask_color) {
|
||||
}
|
||||
|
||||
void putPixel(const Image* spr, int spr_x, int spr_y) {
|
||||
ASSERT(m_it != m_end);
|
||||
|
||||
color_t c = get_pixel_fast<TilemapTraits>(spr, spr_x, spr_y);
|
||||
if (c != m_mask_color)
|
||||
*m_it = c;
|
||||
}
|
||||
|
||||
private:
|
||||
color_t m_mask_color;
|
||||
};
|
||||
|
||||
|
||||
/* _parallelogram_map:
|
||||
* Worker routine for drawing rotated and/or scaled and/or flipped sprites:
|
||||
* It actually maps the sprite to any parallelogram-shaped area of the
|
||||
|
|
@ -773,6 +792,12 @@ static void ase_parallelogram_map_standard(
|
|||
ase_parallelogram_map<BitmapTraits, BitmapDelegate>(bmp, sprite, mask, xs, ys, false, delegate);
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_TILEMAP: {
|
||||
TilemapDelegate delegate(sprite->maskColor());
|
||||
ase_parallelogram_map<TilemapTraits, TilemapDelegate>(bmp, sprite, mask, xs, ys, false, delegate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue