104 lines
3.2 KiB
C++
104 lines
3.2 KiB
C++
/*
|
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
*/
|
|
|
|
#include <ox/claw/write.hpp>
|
|
|
|
#include <nostalgia/core/media.hpp>
|
|
|
|
#include "tilesheeteditormodel.hpp"
|
|
|
|
namespace nostalgia::core {
|
|
|
|
TileSheetEditorModel::TileSheetEditorModel(Context *ctx, const ox::String &path) {
|
|
m_ctx = ctx;
|
|
m_path = path;
|
|
oxRequireT(img, readObj<TileSheet>(ctx, path.c_str()));
|
|
m_img = *img;
|
|
oxThrowError(readObj<Palette>(ctx, m_img.defaultPalette).moveTo(&m_pal));
|
|
m_undoStack.changeTriggered.connect(this, &TileSheetEditorModel::markUpdated);
|
|
}
|
|
|
|
void TileSheetEditorModel::cut() {
|
|
}
|
|
|
|
void TileSheetEditorModel::copy() {
|
|
}
|
|
|
|
void TileSheetEditorModel::paste() {
|
|
}
|
|
|
|
void TileSheetEditorModel::drawCommand(const geo::Point &pt, std::size_t palIdx) noexcept {
|
|
if (m_ongoingDrawCommand) {
|
|
m_updated = m_updated || m_ongoingDrawCommand->append(ptToIdx(pt, m_img.columns()));
|
|
} else {
|
|
const auto idx = ptToIdx(pt, m_img.columns());
|
|
if (m_img.getPixel(idx) != palIdx) {
|
|
pushCommand(new DrawCommand(&m_img, idx, palIdx));
|
|
}
|
|
}
|
|
}
|
|
|
|
void TileSheetEditorModel::endDrawCommand() noexcept {
|
|
m_ongoingDrawCommand = nullptr;
|
|
}
|
|
|
|
bool TileSheetEditorModel::updated() const noexcept {
|
|
return m_updated;
|
|
}
|
|
|
|
ox::Error TileSheetEditorModel::markUpdated() noexcept {
|
|
m_updated = true;
|
|
return OxError(0);
|
|
}
|
|
|
|
void TileSheetEditorModel::ackUpdate() noexcept {
|
|
m_updated = false;
|
|
}
|
|
|
|
ox::Error TileSheetEditorModel::saveFile() noexcept {
|
|
auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
|
oxReturnError(sctx->project->writeObj(m_path, &m_img));
|
|
return m_ctx->assetManager.setAsset(m_path, m_img).error;
|
|
}
|
|
|
|
void TileSheetEditorModel::getFillPixels(bool *pixels, const geo::Point &pt, int oldColor) const noexcept {
|
|
const auto tileIdx = [this](const geo::Point &pt) noexcept {
|
|
return ptToIdx(pt, img().columns()) / PixelsPerTile;
|
|
};
|
|
// get points
|
|
const auto leftPt = pt + geo::Point(-1, 0);
|
|
const auto rightPt = pt + geo::Point(1, 0);
|
|
const auto topPt = pt + geo::Point(0, -1);
|
|
const auto bottomPt = pt + geo::Point(0, 1);
|
|
// calculate indices
|
|
const auto idx = ptToIdx(pt, m_img.columns());
|
|
const auto leftIdx = ptToIdx(leftPt, m_img.columns());
|
|
const auto rightIdx = ptToIdx(rightPt, m_img.columns());
|
|
const auto topIdx = ptToIdx(topPt, m_img.columns());
|
|
const auto bottomIdx = ptToIdx(bottomPt, m_img.columns());
|
|
const auto tile = tileIdx(pt);
|
|
// mark pixels to update
|
|
pixels[idx % PixelsPerTile] = true;
|
|
if (!pixels[leftIdx % PixelsPerTile] && tile == tileIdx(leftPt) && m_img.pixels[leftIdx] == oldColor) {
|
|
getFillPixels(pixels, leftPt, oldColor);
|
|
}
|
|
if (!pixels[rightIdx % PixelsPerTile] && tile == tileIdx(rightPt) && m_img.pixels[rightIdx] == oldColor) {
|
|
getFillPixels(pixels, rightPt, oldColor);
|
|
}
|
|
if (!pixels[topIdx % PixelsPerTile] && tile == tileIdx(topPt) && m_img.pixels[topIdx] == oldColor) {
|
|
getFillPixels(pixels, topPt, oldColor);
|
|
}
|
|
if (!pixels[bottomIdx % PixelsPerTile] && tile == tileIdx(bottomPt) && m_img.pixels[bottomIdx] == oldColor) {
|
|
getFillPixels(pixels, bottomPt, oldColor);
|
|
}
|
|
}
|
|
|
|
void TileSheetEditorModel::pushCommand(studio::UndoCommand *cmd) noexcept {
|
|
m_undoStack.push(cmd);
|
|
m_ongoingDrawCommand = dynamic_cast<DrawCommand*>(cmd);
|
|
m_updated = true;
|
|
}
|
|
|
|
}
|