|  |  |  | @@ -26,11 +26,6 @@ | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | namespace nostalgia::core { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | Palette const TileSheetEditorModel::s_defaultPalette = { | 
		
	
		
			
				|  |  |  |  | 	.colorNames = {ox::Vector<ox::String>{{}}}, | 
		
	
		
			
				|  |  |  |  | 	.pages = {{"Page 1", ox::Vector<Color16>(128)}}, | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // delete pixels of all non-leaf nodes | 
		
	
		
			
				|  |  |  |  | static void normalizeSubsheets(TileSheet::SubSheet &ss) noexcept { | 
		
	
		
			
				|  |  |  |  | 	if (ss.subsheets.empty()) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -42,7 +37,14 @@ static void normalizeSubsheets(TileSheet::SubSheet &ss) noexcept { | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | TileSheetEditorModel::TileSheetEditorModel(studio::StudioContext &sctx, ox::StringView path, studio::UndoStack &undoStack): | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | Palette const TileSheetEditorModel::s_defaultPalette = { | 
		
	
		
			
				|  |  |  |  | 	.colorNames = {ox::Vector<ox::String>{{}}}, | 
		
	
		
			
				|  |  |  |  | 	.pages = {{"Page 1", ox::Vector<Color16>(128)}}, | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | TileSheetEditorModel::TileSheetEditorModel( | 
		
	
		
			
				|  |  |  |  | 		studio::StudioContext &sctx, ox::StringViewCR path, studio::UndoStack &undoStack): | 
		
	
		
			
				|  |  |  |  | 	m_sctx(sctx), | 
		
	
		
			
				|  |  |  |  | 	m_tctx(m_sctx.tctx), | 
		
	
		
			
				|  |  |  |  | 	m_path(path), | 
		
	
	
		
			
				
					
					|  |  |  | @@ -62,7 +64,7 @@ void TileSheetEditorModel::cut() { | 
		
	
		
			
				|  |  |  |  | 	TileSheetClipboard blankCb; | 
		
	
		
			
				|  |  |  |  | 	auto cb = ox::make_unique<TileSheetClipboard>(); | 
		
	
		
			
				|  |  |  |  | 	auto const&s = activeSubSheet(); | 
		
	
		
			
				|  |  |  |  | 	iterateSelectionRows(*m_selection, [&](int x, int y) { | 
		
	
		
			
				|  |  |  |  | 	iterateSelectionRows(*m_selection, [&](int const x, int const y) { | 
		
	
		
			
				|  |  |  |  | 		auto pt = ox::Point{x, y}; | 
		
	
		
			
				|  |  |  |  | 		auto const idx = core::idx(s, pt); | 
		
	
		
			
				|  |  |  |  | 		auto const c = getPixel(s, m_img.bpp, idx); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -73,7 +75,8 @@ void TileSheetEditorModel::cut() { | 
		
	
		
			
				|  |  |  |  | 	auto const pt1 = m_selection->a; | 
		
	
		
			
				|  |  |  |  | 	auto const pt2 = ox::Point{s.columns * TileWidth, s.rows * TileHeight}; | 
		
	
		
			
				|  |  |  |  | 	turbine::setClipboardObject(m_tctx, std::move(cb)); | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<CutPasteCommand>(CommandId::Cut, m_img, m_activeSubsSheetIdx, pt1, pt2, blankCb)); | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<CutPasteCommand>( | 
		
	
		
			
				|  |  |  |  | 		CommandId::Cut, m_img, m_activeSubsSheetIdx, pt1, pt2, blankCb)); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::copy() { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -81,7 +84,7 @@ void TileSheetEditorModel::copy() { | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	auto cb = ox::make_unique<TileSheetClipboard>(); | 
		
	
		
			
				|  |  |  |  | 	iterateSelectionRows(*m_selection, [&](int x, int y) { | 
		
	
		
			
				|  |  |  |  | 	iterateSelectionRows(*m_selection, [&](int const x, int const y) { | 
		
	
		
			
				|  |  |  |  | 		auto pt = ox::Point{x, y}; | 
		
	
		
			
				|  |  |  |  | 		const auto&s = activeSubSheet(); | 
		
	
		
			
				|  |  |  |  | 		const auto idx = core::idx(s, pt); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -105,7 +108,8 @@ void TileSheetEditorModel::paste() { | 
		
	
		
			
				|  |  |  |  | 	auto const&s = activeSubSheet(); | 
		
	
		
			
				|  |  |  |  | 	auto const pt1 = m_selection->a; | 
		
	
		
			
				|  |  |  |  | 	auto const pt2 = ox::Point{s.columns * TileWidth, s.rows * TileHeight}; | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<CutPasteCommand>(CommandId::Paste, m_img, m_activeSubsSheetIdx, pt1, pt2, *cb)); | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<CutPasteCommand>( | 
		
	
		
			
				|  |  |  |  | 		CommandId::Paste, m_img, m_activeSubsSheetIdx, pt1, pt2, *cb)); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | bool TileSheetEditorModel::acceptsClipboardPayload() const noexcept { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -120,8 +124,8 @@ ox::StringView TileSheetEditorModel::palPath() const noexcept { | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	constexpr ox::StringView uuidPrefix = "uuid://"; | 
		
	
		
			
				|  |  |  |  | 	if (ox::beginsWith(path, uuidPrefix)) { | 
		
	
		
			
				|  |  |  |  | 		auto uuid = ox::StringView(&path[uuidPrefix.bytes()], path.bytes() - uuidPrefix.bytes()); | 
		
	
		
			
				|  |  |  |  | 		auto out = keelCtx(m_tctx).uuidToPath.at(uuid); | 
		
	
		
			
				|  |  |  |  | 		auto const uuid = ox::StringView(&path[uuidPrefix.bytes()], path.bytes() - uuidPrefix.bytes()); | 
		
	
		
			
				|  |  |  |  | 		auto const out = keelCtx(m_tctx).uuidToPath.at(uuid); | 
		
	
		
			
				|  |  |  |  | 		if (out.error) { | 
		
	
		
			
				|  |  |  |  | 			return {}; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -131,13 +135,14 @@ ox::StringView TileSheetEditorModel::palPath() const noexcept { | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ox::Error TileSheetEditorModel::setPalette(ox::StringView path) noexcept { | 
		
	
		
			
				|  |  |  |  | ox::Error TileSheetEditorModel::setPalette(ox::StringViewCR path) noexcept { | 
		
	
		
			
				|  |  |  |  | 	OX_REQUIRE(uuid, keelCtx(m_tctx).pathToUuid.at(path)); | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<PaletteChangeCommand>(activeSubSheetIdx(), m_img, uuid->toString())); | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<PaletteChangeCommand>( | 
		
	
		
			
				|  |  |  |  | 		activeSubSheetIdx(), m_img, uuid->toString())); | 
		
	
		
			
				|  |  |  |  | 	return {}; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::setPalettePage(size_t pg) noexcept { | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::setPalettePage(size_t const pg) noexcept { | 
		
	
		
			
				|  |  |  |  | 	m_palettePage = ox::clamp<size_t>(pg, 0, m_pal->pages.size() - 1); | 
		
	
		
			
				|  |  |  |  | 	m_updated = true; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -146,7 +151,7 @@ size_t TileSheetEditorModel::palettePage() const noexcept { | 
		
	
		
			
				|  |  |  |  | 	return m_palettePage; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept { | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t const palIdx) noexcept { | 
		
	
		
			
				|  |  |  |  | 	const auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx); | 
		
	
		
			
				|  |  |  |  | 	if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) { | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -155,7 +160,8 @@ void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t palIdx) n | 
		
	
		
			
				|  |  |  |  | 	if (m_ongoingDrawCommand) { | 
		
	
		
			
				|  |  |  |  | 		m_updated = m_updated || m_ongoingDrawCommand->append(idx); | 
		
	
		
			
				|  |  |  |  | 	} else if (getPixel(activeSubSheet, m_img.bpp, idx) != palIdx) { | 
		
	
		
			
				|  |  |  |  | 		pushCommand(ox::make<DrawCommand>(m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx))); | 
		
	
		
			
				|  |  |  |  | 		pushCommand(ox::make<DrawCommand>( | 
		
	
		
			
				|  |  |  |  | 			m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx))); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -171,16 +177,20 @@ void TileSheetEditorModel::rmSubsheet(TileSheet::SubSheetIdx const&idx) noexcept | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<RmSubSheetCommand>(m_img, idx)); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::insertTiles(TileSheet::SubSheetIdx const&idx, std::size_t tileIdx, std::size_t tileCnt) noexcept { | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::insertTiles( | 
		
	
		
			
				|  |  |  |  | 	TileSheet::SubSheetIdx const&idx, std::size_t const tileIdx, std::size_t const tileCnt) noexcept { | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<InsertTilesCommand>(m_img, idx, tileIdx, tileCnt)); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::deleteTiles(TileSheet::SubSheetIdx const&idx, std::size_t tileIdx, std::size_t tileCnt) noexcept { | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::deleteTiles( | 
		
	
		
			
				|  |  |  |  | 	TileSheet::SubSheetIdx const&idx, std::size_t const tileIdx, std::size_t const tileCnt) noexcept { | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<DeleteTilesCommand>(m_img, idx, tileIdx, tileCnt)); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | ox::Error TileSheetEditorModel::updateSubsheet(TileSheet::SubSheetIdx const&idx, ox::StringView const&name, int cols, int rows) noexcept { | 
		
	
		
			
				|  |  |  |  | 	pushCommand(ox::make<UpdateSubSheetCommand>(m_img, idx, ox::String(name), cols, rows)); | 
		
	
		
			
				|  |  |  |  | ox::Error TileSheetEditorModel::updateSubsheet( | 
		
	
		
			
				|  |  |  |  | 	TileSheet::SubSheetIdx const&idx, ox::StringViewCR name, int const cols, int const rows) noexcept { | 
		
	
		
			
				|  |  |  |  | 	OX_REQUIRE(cmd, ox::makeCatch<UpdateSubSheetCommand>(m_img, idx, name, cols, rows)); | 
		
	
		
			
				|  |  |  |  | 	pushCommand(cmd); | 
		
	
		
			
				|  |  |  |  | 	return {}; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -189,7 +199,7 @@ void TileSheetEditorModel::setActiveSubsheet(TileSheet::SubSheetIdx const&idx) n | 
		
	
		
			
				|  |  |  |  | 	this->activeSubsheetChanged.emit(m_activeSubsSheetIdx); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::fill(ox::Point const&pt, int palIdx) noexcept { | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept { | 
		
	
		
			
				|  |  |  |  | 	auto const&activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx); | 
		
	
		
			
				|  |  |  |  | 	// build idx list | 
		
	
		
			
				|  |  |  |  | 	if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -197,10 +207,10 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int palIdx) noexcept { | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	ox::Array<bool, PixelsPerTile> updateMap = {}; | 
		
	
		
			
				|  |  |  |  | 	auto const oldColor = getPixel(activeSubSheet, m_img.bpp, pt); | 
		
	
		
			
				|  |  |  |  | 	getFillPixels(updateMap, pt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	getFillPixels(activeSubSheet, updateMap, pt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	ox::Vector<std::size_t> idxList; | 
		
	
		
			
				|  |  |  |  | 	auto i = core::idx(activeSubSheet, pt) / PixelsPerTile * PixelsPerTile; | 
		
	
		
			
				|  |  |  |  | 	for (auto u : updateMap) { | 
		
	
		
			
				|  |  |  |  | 	for (auto const u : updateMap) { | 
		
	
		
			
				|  |  |  |  | 		if (u) { | 
		
	
		
			
				|  |  |  |  | 			idxList.emplace_back(i); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -230,7 +240,7 @@ void TileSheetEditorModel::completeSelection() noexcept { | 
		
	
		
			
				|  |  |  |  | 		m_selTracker.finishSelection(); | 
		
	
		
			
				|  |  |  |  | 		m_selection.emplace(m_selTracker.selection()); | 
		
	
		
			
				|  |  |  |  | 		auto&pt = m_selection->b; | 
		
	
		
			
				|  |  |  |  | 		auto&s = activeSubSheet(); | 
		
	
		
			
				|  |  |  |  | 		auto const&s = activeSubSheet(); | 
		
	
		
			
				|  |  |  |  | 		pt.x = ox::min(s.columns * TileWidth - 1, pt.x); | 
		
	
		
			
				|  |  |  |  | 		pt.y = ox::min(s.rows * TileHeight - 1, pt.y); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -275,47 +285,44 @@ ox::Error TileSheetEditorModel::saveFile() noexcept { | 
		
	
		
			
				|  |  |  |  | 	return m_sctx.project->writeObj(m_path, m_img, ox::ClawFormat::Metal); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | bool TileSheetEditorModel::pixelSelected(std::size_t idx) const noexcept { | 
		
	
		
			
				|  |  |  |  | bool TileSheetEditorModel::pixelSelected(std::size_t const idx) const noexcept { | 
		
	
		
			
				|  |  |  |  | 	auto const&s = activeSubSheet(); | 
		
	
		
			
				|  |  |  |  | 	auto const pt = idxToPt(static_cast<int>(idx), s.columns); | 
		
	
		
			
				|  |  |  |  | 	return m_selection && m_selection->contains(pt); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::getFillPixels(ox::Span<bool> pixels, ox::Point const&pt, int oldColor) const noexcept { | 
		
	
		
			
				|  |  |  |  | 	const auto &activeSubSheet = this->activeSubSheet(); | 
		
	
		
			
				|  |  |  |  | 	const auto tileIdx = [activeSubSheet](const ox::Point &pt) noexcept { | 
		
	
		
			
				|  |  |  |  | 		return ptToIdx(pt, activeSubSheet.columns) / PixelsPerTile; | 
		
	
		
			
				|  |  |  |  | 	}; | 
		
	
		
			
				|  |  |  |  | 	// get points | 
		
	
		
			
				|  |  |  |  | 	const auto leftPt = pt + ox::Point(-1, 0); | 
		
	
		
			
				|  |  |  |  | 	const auto rightPt = pt + ox::Point(1, 0); | 
		
	
		
			
				|  |  |  |  | 	const auto topPt = pt + ox::Point(0, -1); | 
		
	
		
			
				|  |  |  |  | 	const auto bottomPt = pt + ox::Point(0, 1); | 
		
	
		
			
				|  |  |  |  | 	// calculate indices | 
		
	
		
			
				|  |  |  |  | 	const auto idx = ptToIdx(pt, activeSubSheet.columns); | 
		
	
		
			
				|  |  |  |  | 	const auto leftIdx = ptToIdx(leftPt, activeSubSheet.columns); | 
		
	
		
			
				|  |  |  |  | 	const auto rightIdx = ptToIdx(rightPt, activeSubSheet.columns); | 
		
	
		
			
				|  |  |  |  | 	const auto topIdx = ptToIdx(topPt, activeSubSheet.columns); | 
		
	
		
			
				|  |  |  |  | 	const auto bottomIdx = ptToIdx(bottomPt, activeSubSheet.columns); | 
		
	
		
			
				|  |  |  |  | 	const auto tile = tileIdx(pt); | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::getFillPixels( | 
		
	
		
			
				|  |  |  |  | 		TileSheet::SubSheet const&activeSubSheet, | 
		
	
		
			
				|  |  |  |  | 		ox::Span<bool> pixels, | 
		
	
		
			
				|  |  |  |  | 		ox::Point const&pt, | 
		
	
		
			
				|  |  |  |  | 		int const oldColor) const noexcept { | 
		
	
		
			
				|  |  |  |  | 	auto const idx = ptToIdx(pt, activeSubSheet.columns); | 
		
	
		
			
				|  |  |  |  | 	auto const relIdx = idx % PixelsPerTile; | 
		
	
		
			
				|  |  |  |  | 	if (pixels[relIdx] || getPixel(activeSubSheet, m_img.bpp, idx) != oldColor) { | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	// mark pixels to update | 
		
	
		
			
				|  |  |  |  | 	pixels[idx % PixelsPerTile] = true; | 
		
	
		
			
				|  |  |  |  | 	if (!pixels[leftIdx % PixelsPerTile] && tile == tileIdx(leftPt) && getPixel(activeSubSheet, m_img.bpp, leftIdx) == oldColor) { | 
		
	
		
			
				|  |  |  |  | 		getFillPixels(pixels, leftPt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	pixels[relIdx] = true; | 
		
	
		
			
				|  |  |  |  | 	if (pt.x % TileWidth != 0) { | 
		
	
		
			
				|  |  |  |  | 		auto const leftPt = pt + ox::Point{-1, 0}; | 
		
	
		
			
				|  |  |  |  | 		getFillPixels(activeSubSheet, pixels, leftPt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	if (!pixels[rightIdx % PixelsPerTile] && tile == tileIdx(rightPt) && getPixel(activeSubSheet, m_img.bpp, rightIdx) == oldColor) { | 
		
	
		
			
				|  |  |  |  | 		getFillPixels(pixels, rightPt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	if (pt.x % TileWidth != TileWidth - 1) { | 
		
	
		
			
				|  |  |  |  | 		auto const rightPt = pt + ox::Point{1, 0}; | 
		
	
		
			
				|  |  |  |  | 		getFillPixels(activeSubSheet, pixels, rightPt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	if (!pixels[topIdx % PixelsPerTile] && tile == tileIdx(topPt) && getPixel(activeSubSheet, m_img.bpp, topIdx) == oldColor) { | 
		
	
		
			
				|  |  |  |  | 		getFillPixels(pixels, topPt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	if (pt.y % TileHeight != 0) { | 
		
	
		
			
				|  |  |  |  | 		auto const topPt = pt + ox::Point{0, -1}; | 
		
	
		
			
				|  |  |  |  | 		getFillPixels(activeSubSheet, pixels, topPt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	if (!pixels[bottomIdx % PixelsPerTile] && tile == tileIdx(bottomPt) && getPixel(activeSubSheet, m_img.bpp, bottomIdx) == oldColor) { | 
		
	
		
			
				|  |  |  |  | 		getFillPixels(pixels, bottomPt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	if (pt.y % TileHeight != TileHeight - 1) { | 
		
	
		
			
				|  |  |  |  | 		auto const bottomPt = pt + ox::Point{0, 1}; | 
		
	
		
			
				|  |  |  |  | 		getFillPixels(activeSubSheet, pixels, bottomPt, oldColor); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void TileSheetEditorModel::pushCommand(studio::UndoCommand *cmd) noexcept { | 
		
	
		
			
				|  |  |  |  | 	std::ignore = m_undoStack.push(ox::UPtr<studio::UndoCommand>(cmd)); | 
		
	
		
			
				|  |  |  |  | 	std::ignore = m_undoStack.push(ox::UPtr<studio::UndoCommand>{cmd}); | 
		
	
		
			
				|  |  |  |  | 	m_ongoingDrawCommand = dynamic_cast<DrawCommand*>(cmd); | 
		
	
		
			
				|  |  |  |  | 	m_updated = true; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  |   |