[nostalgia/core/studio/tilesheet] Add line drawing tool
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build / build (push) Successful in 3m36s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build / build (push) Successful in 3m36s
				
			This commit is contained in:
		@@ -2,10 +2,64 @@
 | 
				
			|||||||
 * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
 | 
					 * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "drawcommand.hpp"
 | 
					#include "drawcommand.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nostalgia::gfx {
 | 
					namespace nostalgia::gfx {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr void iterateLine(ox::Point const &a, ox::Point const &b, auto const &f) noexcept {
 | 
				
			||||||
 | 
						auto const rise = b.y - a.y;
 | 
				
			||||||
 | 
						auto const run = b.x - a.x;
 | 
				
			||||||
 | 
						auto const slope = static_cast<double>(rise) / static_cast<double>(run);
 | 
				
			||||||
 | 
						auto y = static_cast<double>(a.y);
 | 
				
			||||||
 | 
						auto const w = abs(run);
 | 
				
			||||||
 | 
						if (rise > 0) {
 | 
				
			||||||
 | 
							if (run > 0) {
 | 
				
			||||||
 | 
								auto constexpr xmod = 1;
 | 
				
			||||||
 | 
								for (int32_t i = 0; i < w; ++i) {
 | 
				
			||||||
 | 
									auto const climb = static_cast<int32_t>(ceil(y + slope - y));
 | 
				
			||||||
 | 
									f(a.x + i * xmod, static_cast<int32_t>(y), climb * xmod);
 | 
				
			||||||
 | 
									y += slope * xmod;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (run < 0) {
 | 
				
			||||||
 | 
								auto constexpr xmod = -1;
 | 
				
			||||||
 | 
								for (int32_t i = 0; i < w; ++i) {
 | 
				
			||||||
 | 
									auto const climb = static_cast<int32_t>(floor(y + slope - y));
 | 
				
			||||||
 | 
									f(a.x + i * xmod, static_cast<int32_t>(y), climb * xmod);
 | 
				
			||||||
 | 
									y += slope * xmod;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								f(a.x, a.y, rise);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (rise < 0) {
 | 
				
			||||||
 | 
							if (run > 0) {
 | 
				
			||||||
 | 
								auto constexpr xmod = 1;
 | 
				
			||||||
 | 
								for (int32_t i = 0; i < w; ++i) {
 | 
				
			||||||
 | 
									auto const climb = static_cast<int32_t>(floor(y + slope - y));
 | 
				
			||||||
 | 
									f(a.x + i * xmod, static_cast<int32_t>(y), climb * xmod);
 | 
				
			||||||
 | 
									y += slope * xmod;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (run < 0) {
 | 
				
			||||||
 | 
								auto constexpr xmod = -1;
 | 
				
			||||||
 | 
								for (int32_t i = 0; i < w; ++i) {
 | 
				
			||||||
 | 
									auto const climb = static_cast<int32_t>(ceil(y + slope - y));
 | 
				
			||||||
 | 
									f(a.x + i * xmod, static_cast<int32_t>(y), climb * xmod);
 | 
				
			||||||
 | 
									y += slope * xmod;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								f(a.x, a.y, rise - 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							auto const xmod = run > 0 ? 1 : -1;
 | 
				
			||||||
 | 
							for (int32_t i = 0; i < w; ++i) {
 | 
				
			||||||
 | 
								f(a.x + i * xmod, static_cast<int32_t>(y), 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DrawCommand::DrawCommand(
 | 
					DrawCommand::DrawCommand(
 | 
				
			||||||
		TileSheet &img,
 | 
							TileSheet &img,
 | 
				
			||||||
		TileSheet::SubSheetIdx subSheetIdx,
 | 
							TileSheet::SubSheetIdx subSheetIdx,
 | 
				
			||||||
@@ -21,7 +75,7 @@ DrawCommand::DrawCommand(
 | 
				
			|||||||
DrawCommand::DrawCommand(
 | 
					DrawCommand::DrawCommand(
 | 
				
			||||||
		TileSheet &img,
 | 
							TileSheet &img,
 | 
				
			||||||
		TileSheet::SubSheetIdx subSheetIdx,
 | 
							TileSheet::SubSheetIdx subSheetIdx,
 | 
				
			||||||
		ox::Vector<std::size_t> const&idxList,
 | 
							ox::SpanView<std::size_t> const&idxList,
 | 
				
			||||||
		int palIdx) noexcept:
 | 
							int palIdx) noexcept:
 | 
				
			||||||
		m_img(img),
 | 
							m_img(img),
 | 
				
			||||||
		m_subSheetIdx(std::move(subSheetIdx)),
 | 
							m_subSheetIdx(std::move(subSheetIdx)),
 | 
				
			||||||
@@ -32,11 +86,12 @@ DrawCommand::DrawCommand(
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool DrawCommand::append(std::size_t idx) noexcept {
 | 
					bool DrawCommand::append(std::size_t const idx) noexcept {
 | 
				
			||||||
	auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
 | 
						auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
 | 
				
			||||||
	if (m_changes.back().value->idx != idx && getPixel(subsheet, idx) != m_palIdx) {
 | 
						if (m_changes.back().value->idx != idx && getPixel(subsheet, idx) != m_palIdx) {
 | 
				
			||||||
		// duplicate entries are bad
 | 
							// duplicate entries are bad
 | 
				
			||||||
		auto existing = ox::find_if(m_changes.cbegin(), m_changes.cend(), [idx](auto const&c) {
 | 
							auto existing = find_if(
 | 
				
			||||||
 | 
								m_changes.cbegin(), m_changes.cend(), [idx](auto const&c) {
 | 
				
			||||||
			return c.idx == idx;
 | 
								return c.idx == idx;
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		if (existing == m_changes.cend()) {
 | 
							if (existing == m_changes.cend()) {
 | 
				
			||||||
@@ -48,7 +103,7 @@ bool DrawCommand::append(std::size_t idx) noexcept {
 | 
				
			|||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool DrawCommand::append(ox::Vector<std::size_t> const&idxList) noexcept {
 | 
					bool DrawCommand::append(ox::SpanView<std::size_t> const&idxList) noexcept {
 | 
				
			||||||
	auto out = false;
 | 
						auto out = false;
 | 
				
			||||||
	for (auto idx : idxList) {
 | 
						for (auto idx : idxList) {
 | 
				
			||||||
		out = append(idx) || out;
 | 
							out = append(idx) || out;
 | 
				
			||||||
@@ -56,6 +111,25 @@ bool DrawCommand::append(ox::Vector<std::size_t> const&idxList) noexcept {
 | 
				
			|||||||
	return out;
 | 
						return out;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void DrawCommand::lineUpdate(ox::Point a, ox::Point b) noexcept {
 | 
				
			||||||
 | 
						std::ignore = undo();
 | 
				
			||||||
 | 
						m_changes.clear();
 | 
				
			||||||
 | 
						auto &ss = getSubSheet(m_img, m_subSheetIdx);
 | 
				
			||||||
 | 
						if (a.x < b.x) { ++b.x; }
 | 
				
			||||||
 | 
						if (a.y < b.y) { ++b.y; }
 | 
				
			||||||
 | 
						if (a.x > b.x) { --b.x; }
 | 
				
			||||||
 | 
						iterateLine(a, b, [this, &ss](int32_t const x, int32_t const y, int32_t const h) {
 | 
				
			||||||
 | 
							int const mod = h < 0 ? -1 : 1;
 | 
				
			||||||
 | 
							for (int32_t i{}; i < abs(h); ++i) {
 | 
				
			||||||
 | 
								auto const idx = ptToIdx(x, y + i * mod, ss.columns * TileWidth);
 | 
				
			||||||
 | 
								if (idx < ss.pixels.size()) {
 | 
				
			||||||
 | 
									m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(ss, idx));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						std::ignore = redo();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ox::Error DrawCommand::redo() noexcept {
 | 
					ox::Error DrawCommand::redo() noexcept {
 | 
				
			||||||
	auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
 | 
						auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
 | 
				
			||||||
	for (auto const&c : m_changes) {
 | 
						for (auto const&c : m_changes) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,12 +33,14 @@ class DrawCommand: public TileSheetCommand {
 | 
				
			|||||||
		DrawCommand(
 | 
							DrawCommand(
 | 
				
			||||||
				TileSheet &img,
 | 
									TileSheet &img,
 | 
				
			||||||
				TileSheet::SubSheetIdx subSheetIdx,
 | 
									TileSheet::SubSheetIdx subSheetIdx,
 | 
				
			||||||
				ox::Vector<std::size_t> const&idxList,
 | 
									ox::SpanView<std::size_t> const&idxList,
 | 
				
			||||||
				int palIdx) noexcept;
 | 
									int palIdx) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool append(std::size_t idx) noexcept;
 | 
							bool append(std::size_t idx) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool append(ox::Vector<std::size_t> const&idxList) noexcept;
 | 
							bool append(ox::SpanView<std::size_t> const&idxList) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void lineUpdate(ox::Point a, ox::Point b) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ox::Error redo() noexcept final;
 | 
							ox::Error redo() noexcept final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -152,6 +152,12 @@ void TileSheetEditorImGui::keyStateChanged(turbine::Key const key, bool const do
 | 
				
			|||||||
			setCutEnabled(false);
 | 
								setCutEnabled(false);
 | 
				
			||||||
			setPasteEnabled(false);
 | 
								setPasteEnabled(false);
 | 
				
			||||||
			m_model.clearSelection();
 | 
								m_model.clearSelection();
 | 
				
			||||||
 | 
							} else if (key == turbine::Key::Alpha_E) {
 | 
				
			||||||
 | 
								m_tool = TileSheetTool::Line;
 | 
				
			||||||
 | 
								setCopyEnabled(false);
 | 
				
			||||||
 | 
								setCutEnabled(false);
 | 
				
			||||||
 | 
								setPasteEnabled(false);
 | 
				
			||||||
 | 
								m_model.clearSelection();
 | 
				
			||||||
		} else if (key == turbine::Key::Alpha_S) {
 | 
							} else if (key == turbine::Key::Alpha_S) {
 | 
				
			||||||
			m_tool = TileSheetTool::Select;
 | 
								m_tool = TileSheetTool::Select;
 | 
				
			||||||
			setCopyEnabled(true);
 | 
								setCopyEnabled(true);
 | 
				
			||||||
@@ -214,7 +220,7 @@ void TileSheetEditorImGui::draw(studio::StudioContext&) noexcept {
 | 
				
			|||||||
	ImGui::BeginChild("Controls", {s_palViewWidth - 8, paneSize.y}, true);
 | 
						ImGui::BeginChild("Controls", {s_palViewWidth - 8, paneSize.y}, true);
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto const controlsSize = ImGui::GetContentRegionAvail();
 | 
							auto const controlsSize = ImGui::GetContentRegionAvail();
 | 
				
			||||||
		ImGui::BeginChild("ToolBox", {168, 32}, true);
 | 
							ImGui::BeginChild("ToolBox", {0, 32}, true);
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			auto const btnSz = ImVec2{45, 14};
 | 
								auto const btnSz = ImVec2{45, 14};
 | 
				
			||||||
			if (ImGui::Selectable("Select", m_tool == TileSheetTool::Select, 0, btnSz)) {
 | 
								if (ImGui::Selectable("Select", m_tool == TileSheetTool::Select, 0, btnSz)) {
 | 
				
			||||||
@@ -230,9 +236,16 @@ void TileSheetEditorImGui::draw(studio::StudioContext&) noexcept {
 | 
				
			|||||||
				m_tool = TileSheetTool::Fill;
 | 
									m_tool = TileSheetTool::Fill;
 | 
				
			||||||
				m_model.clearSelection();
 | 
									m_model.clearSelection();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								ImGui::SameLine();
 | 
				
			||||||
 | 
								if (ImGui::Selectable("Line", m_tool == TileSheetTool::Line, 0, btnSz)) {
 | 
				
			||||||
 | 
									m_tool = TileSheetTool::Line;
 | 
				
			||||||
 | 
									m_model.clearSelection();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								//ImGui::SameLine();
 | 
				
			||||||
 | 
								//size_t i{};
 | 
				
			||||||
 | 
								//ig::ComboBox("##Operations", ox::Array<ox::CStringView, 1>{"Operations"}, i);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ImGui::EndChild();
 | 
							ImGui::EndChild();
 | 
				
			||||||
		ImGui::SameLine();
 | 
					 | 
				
			||||||
		ImGui::BeginChild("OperationsBox", {0, 32}, true);
 | 
							ImGui::BeginChild("OperationsBox", {0, 32}, true);
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			auto constexpr btnSz = ImVec2{55, 16};
 | 
								auto constexpr btnSz = ImVec2{55, 16};
 | 
				
			||||||
@@ -448,6 +461,9 @@ void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept {
 | 
				
			|||||||
				case TileSheetTool::Fill:
 | 
									case TileSheetTool::Fill:
 | 
				
			||||||
					m_view.clickFill(fbSize, clickPos(winPos, mousePos));
 | 
										m_view.clickFill(fbSize, clickPos(winPos, mousePos));
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
 | 
									case TileSheetTool::Line:
 | 
				
			||||||
 | 
										m_view.clickLine(fbSize, clickPos(winPos, mousePos));
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
				case TileSheetTool::Select:
 | 
									case TileSheetTool::Select:
 | 
				
			||||||
					m_view.clickSelect(fbSize, clickPos(winPos, mousePos));
 | 
										m_view.clickSelect(fbSize, clickPos(winPos, mousePos));
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -141,10 +141,14 @@ size_t TileSheetEditorModel::palettePage() const noexcept {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TileSheetEditorModel::drawCommand(ox::Point const &pt, std::size_t const palIdx) noexcept {
 | 
					void TileSheetEditorModel::drawCommand(ox::Point const &pt, std::size_t const palIdx) noexcept {
 | 
				
			||||||
 | 
						if (m_lastDrawUpdatePt == pt) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	auto const &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
 | 
						auto const &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
 | 
				
			||||||
	if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) {
 | 
						if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						m_lastDrawUpdatePt = pt;
 | 
				
			||||||
	auto const idx = gfx::idx(activeSubSheet, pt);
 | 
						auto const idx = gfx::idx(activeSubSheet, pt);
 | 
				
			||||||
	if (m_ongoingDrawCommand) {
 | 
						if (m_ongoingDrawCommand) {
 | 
				
			||||||
		m_updated = m_updated || m_ongoingDrawCommand->append(idx);
 | 
							m_updated = m_updated || m_ongoingDrawCommand->append(idx);
 | 
				
			||||||
@@ -154,6 +158,26 @@ void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t const pal
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TileSheetEditorModel::drawLineCommand(ox::Point const &pt, std::size_t const palIdx) noexcept {
 | 
				
			||||||
 | 
						if (m_lastDrawUpdatePt == pt) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						auto const &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
 | 
				
			||||||
 | 
						if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m_lastDrawUpdatePt = pt;
 | 
				
			||||||
 | 
						auto const idx = gfx::idx(activeSubSheet, pt);
 | 
				
			||||||
 | 
						if (m_ongoingDrawCommand) {
 | 
				
			||||||
 | 
							m_ongoingDrawCommand->lineUpdate(m_lineStartPt, pt);
 | 
				
			||||||
 | 
							m_updated = true;
 | 
				
			||||||
 | 
						} else if (getPixel(activeSubSheet, idx) != palIdx) {
 | 
				
			||||||
 | 
							std::ignore = pushCommand(ox::make<DrawCommand>(
 | 
				
			||||||
 | 
								m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx)));
 | 
				
			||||||
 | 
							m_lineStartPt = pt;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TileSheetEditorModel::endDrawCommand() noexcept {
 | 
					void TileSheetEditorModel::endDrawCommand() noexcept {
 | 
				
			||||||
	m_ongoingDrawCommand = nullptr;
 | 
						m_ongoingDrawCommand = nullptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,8 @@ class TileSheetEditorModel: public ox::SignalHandler {
 | 
				
			|||||||
		class DrawCommand *m_ongoingDrawCommand = nullptr;
 | 
							class DrawCommand *m_ongoingDrawCommand = nullptr;
 | 
				
			||||||
		studio::SelectionTracker m_selTracker;
 | 
							studio::SelectionTracker m_selTracker;
 | 
				
			||||||
		ox::Optional<studio::Selection> m_selection;
 | 
							ox::Optional<studio::Selection> m_selection;
 | 
				
			||||||
 | 
							ox::Point m_lineStartPt;
 | 
				
			||||||
 | 
							ox::Point m_lastDrawUpdatePt;
 | 
				
			||||||
		bool m_updated = false;
 | 
							bool m_updated = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
@@ -71,6 +73,8 @@ class TileSheetEditorModel: public ox::SignalHandler {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		void drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept;
 | 
							void drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void drawLineCommand(ox::Point const&pt, std::size_t palIdx) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void endDrawCommand() noexcept;
 | 
							void endDrawCommand() noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void addSubsheet(TileSheet::SubSheetIdx const&parentIdx) noexcept;
 | 
							void addSubsheet(TileSheet::SubSheetIdx const&parentIdx) noexcept;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace nostalgia::gfx {
 | 
					namespace nostalgia::gfx {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TileSheetEditorView::TileSheetEditorView(studio::StudioContext &sctx, ox::StringView path, studio::UndoStack &undoStack):
 | 
					TileSheetEditorView::TileSheetEditorView(
 | 
				
			||||||
 | 
							studio::StudioContext &sctx, ox::StringViewCR path, studio::UndoStack &undoStack):
 | 
				
			||||||
	m_model(sctx, path, undoStack),
 | 
						m_model(sctx, path, undoStack),
 | 
				
			||||||
	m_pixelsDrawer(m_model) {
 | 
						m_pixelsDrawer(m_model) {
 | 
				
			||||||
	glBindVertexArray(0);
 | 
						glBindVertexArray(0);
 | 
				
			||||||
@@ -76,6 +77,11 @@ void TileSheetEditorView::clickDraw(ox::Vec2 const&paneSize, ox::Vec2 const&clic
 | 
				
			|||||||
	m_model.drawCommand(pt, m_palIdx);
 | 
						m_model.drawCommand(pt, m_palIdx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TileSheetEditorView::clickLine(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
 | 
				
			||||||
 | 
						auto const pt = clickPoint(paneSize, clickPos);
 | 
				
			||||||
 | 
						m_model.drawLineCommand(pt, m_palIdx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TileSheetEditorView::clickSelect(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
 | 
					void TileSheetEditorView::clickSelect(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
 | 
				
			||||||
	auto const pt = clickPoint(paneSize, clickPos);
 | 
						auto const pt = clickPoint(paneSize, clickPos);
 | 
				
			||||||
	m_model.select(pt);
 | 
						m_model.select(pt);
 | 
				
			||||||
@@ -90,6 +96,7 @@ void TileSheetEditorView::releaseMouseButton(TileSheetTool tool) noexcept {
 | 
				
			|||||||
	switch (tool) {
 | 
						switch (tool) {
 | 
				
			||||||
		case TileSheetTool::Draw:
 | 
							case TileSheetTool::Draw:
 | 
				
			||||||
		case TileSheetTool::Fill:
 | 
							case TileSheetTool::Fill:
 | 
				
			||||||
 | 
							case TileSheetTool::Line:
 | 
				
			||||||
			m_model.endDrawCommand();
 | 
								m_model.endDrawCommand();
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case TileSheetTool::Select:
 | 
							case TileSheetTool::Select:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ enum class TileSheetTool {
 | 
				
			|||||||
	Select,
 | 
						Select,
 | 
				
			||||||
	Draw,
 | 
						Draw,
 | 
				
			||||||
	Fill,
 | 
						Fill,
 | 
				
			||||||
 | 
						Line,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[nodiscard]]
 | 
					[[nodiscard]]
 | 
				
			||||||
@@ -34,6 +35,8 @@ constexpr auto toString(TileSheetTool t) noexcept {
 | 
				
			|||||||
			return "Draw";
 | 
								return "Draw";
 | 
				
			||||||
		case TileSheetTool::Fill:
 | 
							case TileSheetTool::Fill:
 | 
				
			||||||
			return "Fill";
 | 
								return "Fill";
 | 
				
			||||||
 | 
							case TileSheetTool::Line:
 | 
				
			||||||
 | 
								return "Line";
 | 
				
			||||||
		case TileSheetTool::None:
 | 
							case TileSheetTool::None:
 | 
				
			||||||
			return "None";
 | 
								return "None";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -53,7 +56,7 @@ class TileSheetEditorView: public ox::SignalHandler {
 | 
				
			|||||||
		std::size_t m_palIdx = 0;
 | 
							std::size_t m_palIdx = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
		TileSheetEditorView(studio::StudioContext &sctx, ox::StringView path, studio::UndoStack &undoStack);
 | 
							TileSheetEditorView(studio::StudioContext &sctx, ox::StringViewCR path, studio::UndoStack &undoStack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		~TileSheetEditorView() override = default;
 | 
							~TileSheetEditorView() override = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,6 +68,8 @@ class TileSheetEditorView: public ox::SignalHandler {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		void clickDraw(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept;
 | 
							void clickDraw(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void clickLine(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void clickSelect(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept;
 | 
							void clickSelect(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void clickFill(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept;
 | 
							void clickFill(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user