This commit is contained in:
parent
e367575974
commit
7ba66787f8
@ -113,7 +113,7 @@ void TileSheetEditorImGui::keyStateChanged(turbine::Key key, bool down) {
|
|||||||
auto const popupOpen = m_subsheetEditor.isOpen() && m_exportMenu.isOpen();
|
auto const popupOpen = m_subsheetEditor.isOpen() && m_exportMenu.isOpen();
|
||||||
auto const pal = m_model.pal();
|
auto const pal = m_model.pal();
|
||||||
if (!popupOpen) {
|
if (!popupOpen) {
|
||||||
const auto colorCnt = pal.pages[m_model.palettePage()].size();
|
auto const colorCnt = pal.pages[m_model.palettePage()].size();
|
||||||
if (key == turbine::Key::Alpha_D) {
|
if (key == turbine::Key::Alpha_D) {
|
||||||
m_tool = Tool::Draw;
|
m_tool = Tool::Draw;
|
||||||
setCopyEnabled(false);
|
setCopyEnabled(false);
|
||||||
@ -137,7 +137,7 @@ void TileSheetEditorImGui::keyStateChanged(turbine::Key key, bool down) {
|
|||||||
static_cast<uint32_t>(key - turbine::Key::Num_1), m_model.pal().pages.size() - 1);
|
static_cast<uint32_t>(key - turbine::Key::Num_1), m_model.pal().pages.size() - 1);
|
||||||
m_model.setPalettePage(idx);
|
m_model.setPalettePage(idx);
|
||||||
} else if (key <= turbine::Key::Num_0 + colorCnt) {
|
} else if (key <= turbine::Key::Num_0 + colorCnt) {
|
||||||
auto idx = ox::min<std::size_t>(static_cast<uint32_t>(key - turbine::Key::Num_1), colorCnt - 1);
|
auto const idx = ox::min<std::size_t>(static_cast<uint32_t>(key - turbine::Key::Num_1), colorCnt - 1);
|
||||||
m_view.setPalIdx(idx);
|
m_view.setPalIdx(idx);
|
||||||
}
|
}
|
||||||
} else if (key == turbine::Key::Num_0) {
|
} else if (key == turbine::Key::Num_0) {
|
||||||
@ -146,7 +146,7 @@ void TileSheetEditorImGui::keyStateChanged(turbine::Key key, bool down) {
|
|||||||
static_cast<uint32_t>(key - turbine::Key::Num_1 + 9), m_model.pal().pages.size() - 1);
|
static_cast<uint32_t>(key - turbine::Key::Num_1 + 9), m_model.pal().pages.size() - 1);
|
||||||
m_model.setPalettePage(idx);
|
m_model.setPalettePage(idx);
|
||||||
} else if (colorCnt >= 10) {
|
} else if (colorCnt >= 10) {
|
||||||
auto idx = ox::min<std::size_t>(
|
auto const idx = ox::min<std::size_t>(
|
||||||
static_cast<uint32_t>(key - turbine::Key::Num_1 + 9), colorCnt - 1);
|
static_cast<uint32_t>(key - turbine::Key::Num_1 + 9), colorCnt - 1);
|
||||||
m_view.setPalIdx(idx);
|
m_view.setPalIdx(idx);
|
||||||
}
|
}
|
||||||
@ -155,9 +155,9 @@ void TileSheetEditorImGui::keyStateChanged(turbine::Key key, bool down) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorImGui::draw(turbine::Context&) noexcept {
|
void TileSheetEditorImGui::draw(turbine::Context&) noexcept {
|
||||||
const auto paneSize = ImGui::GetContentRegionAvail();
|
auto const paneSize = ImGui::GetContentRegionAvail();
|
||||||
const auto tileSheetParentSize = ImVec2(paneSize.x - m_palViewWidth, paneSize.y);
|
auto const tileSheetParentSize = ImVec2(paneSize.x - m_palViewWidth, paneSize.y);
|
||||||
const auto fbSize = ox::Vec2(tileSheetParentSize.x - 16, tileSheetParentSize.y - 16);
|
auto const fbSize = ox::Vec2(tileSheetParentSize.x - 16, tileSheetParentSize.y - 16);
|
||||||
ImGui::BeginChild("TileSheetView", tileSheetParentSize, true);
|
ImGui::BeginChild("TileSheetView", tileSheetParentSize, true);
|
||||||
{
|
{
|
||||||
drawTileSheet(fbSize);
|
drawTileSheet(fbSize);
|
||||||
@ -166,10 +166,10 @@ void TileSheetEditorImGui::draw(turbine::Context&) noexcept {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::BeginChild("Controls", ImVec2(m_palViewWidth - 8, paneSize.y), true);
|
ImGui::BeginChild("Controls", ImVec2(m_palViewWidth - 8, paneSize.y), true);
|
||||||
{
|
{
|
||||||
const auto controlsSize = ImGui::GetContentRegionAvail();
|
auto const controlsSize = ImGui::GetContentRegionAvail();
|
||||||
ImGui::BeginChild("ToolBox", ImVec2(m_palViewWidth - 24, 30), true);
|
ImGui::BeginChild("ToolBox", ImVec2(m_palViewWidth - 24, 30), true);
|
||||||
{
|
{
|
||||||
const auto btnSz = ImVec2(45, 14);
|
auto const btnSz = ImVec2(45, 14);
|
||||||
if (ImGui::Selectable("Select", m_tool == Tool::Select, 0, btnSz)) {
|
if (ImGui::Selectable("Select", m_tool == Tool::Select, 0, btnSz)) {
|
||||||
m_tool = Tool::Select;
|
m_tool = Tool::Select;
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ void TileSheetEditorImGui::draw(turbine::Context&) noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
const auto ySize = controlsSize.y - 38;
|
auto const ySize = controlsSize.y - 38;
|
||||||
// draw palette/color picker
|
// draw palette/color picker
|
||||||
ImGui::BeginChild("Palette", ImVec2(m_palViewWidth - 24, ySize / 2.f), true);
|
ImGui::BeginChild("Palette", ImVec2(m_palViewWidth - 24, ySize / 2.f), true);
|
||||||
{
|
{
|
||||||
@ -195,17 +195,17 @@ void TileSheetEditorImGui::draw(turbine::Context&) noexcept {
|
|||||||
ImGui::BeginChild("SubSheets", ImVec2(m_palViewWidth - 24, ySize / 2.f), true);
|
ImGui::BeginChild("SubSheets", ImVec2(m_palViewWidth - 24, ySize / 2.f), true);
|
||||||
{
|
{
|
||||||
static constexpr auto btnHeight = 18;
|
static constexpr auto btnHeight = 18;
|
||||||
const auto btnSize = ImVec2(18, btnHeight);
|
auto const btnSize = ImVec2(18, btnHeight);
|
||||||
if (ImGui::Button("+", btnSize)) {
|
if (ImGui::Button("+", btnSize)) {
|
||||||
auto insertOnIdx = m_model.activeSubSheetIdx();
|
auto insertOnIdx = m_model.activeSubSheetIdx();
|
||||||
const auto &parent = *m_model.activeSubSheet();
|
auto const&parent = m_model.activeSubSheet();
|
||||||
m_model.addSubsheet(insertOnIdx);
|
m_model.addSubsheet(insertOnIdx);
|
||||||
insertOnIdx.emplace_back(parent.subsheets.size() - 1);
|
insertOnIdx.emplace_back(parent.subsheets.size() - 1);
|
||||||
m_model.setActiveSubsheet(insertOnIdx);
|
m_model.setActiveSubsheet(insertOnIdx);
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("-", btnSize)) {
|
if (ImGui::Button("-", btnSize)) {
|
||||||
const auto &activeSubsheetIdx = m_model.activeSubSheetIdx();
|
auto const&activeSubsheetIdx = m_model.activeSubSheetIdx();
|
||||||
if (!activeSubsheetIdx.empty()) {
|
if (!activeSubsheetIdx.empty()) {
|
||||||
m_model.rmSubsheet(activeSubsheetIdx);
|
m_model.rmSubsheet(activeSubsheetIdx);
|
||||||
}
|
}
|
||||||
@ -243,14 +243,14 @@ void TileSheetEditorImGui::drawSubsheetSelector(TileSheet::SubSheet &subsheet, T
|
|||||||
using Str = ox::BasicString<100>;
|
using Str = ox::BasicString<100>;
|
||||||
auto pathStr = ox::join<Str>("##", path).value;
|
auto pathStr = ox::join<Str>("##", path).value;
|
||||||
auto lbl = ox::sfmt<Str>("{}##{}", subsheet.name, pathStr);
|
auto lbl = ox::sfmt<Str>("{}##{}", subsheet.name, pathStr);
|
||||||
const auto rowSelected = path == m_model.activeSubSheetIdx();
|
auto const rowSelected = path == m_model.activeSubSheetIdx();
|
||||||
const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
|
auto const flags = ImGuiTreeNodeFlags_SpanFullWidth
|
||||||
| ImGuiTreeNodeFlags_OpenOnArrow
|
| ImGuiTreeNodeFlags_OpenOnArrow
|
||||||
| ImGuiTreeNodeFlags_DefaultOpen
|
| ImGuiTreeNodeFlags_DefaultOpen
|
||||||
| (subsheet.subsheets.empty() ? ImGuiTreeNodeFlags_Leaf : 0)
|
| (subsheet.subsheets.empty() ? ImGuiTreeNodeFlags_Leaf : 0)
|
||||||
| (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
|
| (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
|
auto const open = ImGui::TreeNodeEx(lbl.c_str(), flags);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::IsItemClicked()) {
|
if (ImGui::IsItemClicked()) {
|
||||||
m_model.setActiveSubsheet(path);
|
m_model.setActiveSubsheet(path);
|
||||||
@ -298,11 +298,11 @@ ox::Error TileSheetEditorImGui::saveItem() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorImGui::showSubsheetEditor() noexcept {
|
void TileSheetEditorImGui::showSubsheetEditor() noexcept {
|
||||||
const auto sheet = m_model.activeSubSheet();
|
auto const&sheet = m_model.activeSubSheet();
|
||||||
if (!sheet->subsheets.empty()) {
|
if (!sheet.subsheets.empty()) {
|
||||||
m_subsheetEditor.show(sheet->name, -1, -1);
|
m_subsheetEditor.show(sheet.name, -1, -1);
|
||||||
} else {
|
} else {
|
||||||
m_subsheetEditor.show(sheet->name, sheet->columns, sheet->rows);
|
m_subsheetEditor.show(sheet.name, sheet.columns, sheet.rows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ ox::Error TileSheetEditorImGui::exportSubhseetToPng(int scale) noexcept {
|
|||||||
oxRequire(path, studio::saveFile({{"PNG", "png"}}));
|
oxRequire(path, studio::saveFile({{"PNG", "png"}}));
|
||||||
// subsheet to png
|
// subsheet to png
|
||||||
auto const&img = m_model.img();
|
auto const&img = m_model.img();
|
||||||
auto const&s = *m_model.activeSubSheet();
|
auto const&s = m_model.activeSubSheet();
|
||||||
auto const&pal = m_model.pal();
|
auto const&pal = m_model.pal();
|
||||||
auto const width = s.columns * TileWidth;
|
auto const width = s.columns * TileWidth;
|
||||||
auto const height = s.rows * TileHeight;
|
auto const height = s.rows * TileHeight;
|
||||||
@ -423,7 +423,7 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
|||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - comboWidthSub);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - comboWidthSub);
|
||||||
if (ImGui::BeginCombo("Page", numStr.data(), 0)) {
|
if (ImGui::BeginCombo("Page", numStr.data(), 0)) {
|
||||||
for (auto n = 0u; n < pages; ++n) {
|
for (auto n = 0u; n < pages; ++n) {
|
||||||
const auto selected = (m_model.palettePage() == n);
|
auto const selected = (m_model.palettePage() == n);
|
||||||
ox_itoa(n + 1, numStr.data());
|
ox_itoa(n + 1, numStr.data());
|
||||||
if (ImGui::Selectable(numStr.data(), selected) && m_model.palettePage() != n) {
|
if (ImGui::Selectable(numStr.data(), selected) && m_model.palettePage() != n) {
|
||||||
m_model.setPalettePage(n);
|
m_model.setPalettePage(n);
|
||||||
@ -448,8 +448,8 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
|||||||
ImGui::PushID(static_cast<int>(i));
|
ImGui::PushID(static_cast<int>(i));
|
||||||
// Column: color idx
|
// Column: color idx
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
const auto label = ox::BString<8>() + (i + 1);
|
auto const label = ox::BString<8>() + (i + 1);
|
||||||
const auto rowSelected = i == m_view.palIdx();
|
auto const rowSelected = i == m_view.palIdx();
|
||||||
if (ImGui::Selectable(label.c_str(), rowSelected, ImGuiSelectableFlags_SpanAllColumns)) {
|
if (ImGui::Selectable(label.c_str(), rowSelected, ImGuiSelectableFlags_SpanAllColumns)) {
|
||||||
m_view.setPalIdx(i);
|
m_view.setPalIdx(i);
|
||||||
}
|
}
|
||||||
@ -473,10 +473,10 @@ ox::Error TileSheetEditorImGui::updateActiveSubsheet(ox::StringView const&name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Error TileSheetEditorImGui::setPaletteSelection() noexcept {
|
ox::Error TileSheetEditorImGui::setPaletteSelection() noexcept {
|
||||||
const auto &palPath = m_model.palPath();
|
auto const&palPath = m_model.palPath();
|
||||||
auto &sctx = *applicationData<studio::StudioContext>(m_ctx);
|
auto &sctx = *applicationData<studio::StudioContext>(m_ctx);
|
||||||
const auto &palList = sctx.project->fileList(core::FileExt_npal);
|
auto const&palList = sctx.project->fileList(core::FileExt_npal);
|
||||||
for (std::size_t i = 0; const auto &pal : palList) {
|
for (std::size_t i = 0; auto const&pal : palList) {
|
||||||
if (palPath == pal) {
|
if (palPath == pal) {
|
||||||
m_selectedPaletteIdx = i;
|
m_selectedPaletteIdx = i;
|
||||||
break;
|
break;
|
||||||
@ -498,8 +498,8 @@ void TileSheetEditorImGui::SubSheetEditor::draw() noexcept {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ImGui::OpenPopup(popupName);
|
ImGui::OpenPopup(popupName);
|
||||||
const auto modSize = m_cols > 0;
|
auto const modSize = m_cols > 0;
|
||||||
const auto popupHeight = modSize ? 125.f : 80.f;
|
auto const popupHeight = modSize ? 125.f : 80.f;
|
||||||
ImGui::SetNextWindowSize(ImVec2(235, popupHeight));
|
ImGui::SetNextWindowSize(ImVec2(235, popupHeight));
|
||||||
if (ImGui::BeginPopupModal(popupName, &m_show, modalFlags)) {
|
if (ImGui::BeginPopupModal(popupName, &m_show, modalFlags)) {
|
||||||
ImGui::InputText("Name", m_name.data(), m_name.cap());
|
ImGui::InputText("Name", m_name.data(), m_name.cap());
|
||||||
|
@ -27,6 +27,7 @@ class TileSheetEditorImGui: public studio::Editor {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
class SubSheetEditor {
|
class SubSheetEditor {
|
||||||
|
private:
|
||||||
ox::BString<100> m_name;
|
ox::BString<100> m_name;
|
||||||
int m_cols = 0;
|
int m_cols = 0;
|
||||||
int m_rows = 0;
|
int m_rows = 0;
|
||||||
@ -45,8 +46,9 @@ class TileSheetEditorImGui: public studio::Editor {
|
|||||||
inline bool isOpen() const noexcept { return m_show; }
|
inline bool isOpen() const noexcept { return m_show; }
|
||||||
};
|
};
|
||||||
class ExportMenu {
|
class ExportMenu {
|
||||||
int m_scale = 0;
|
private:
|
||||||
bool m_show = false;
|
int m_scale = 0;
|
||||||
|
bool m_show = false;
|
||||||
public:
|
public:
|
||||||
ox::Signal<ox::Error(int scale)> inputSubmitted;
|
ox::Signal<ox::Error(int scale)> inputSubmitted;
|
||||||
constexpr void show() noexcept {
|
constexpr void show() noexcept {
|
||||||
|
@ -44,12 +44,12 @@ TileSheetEditorModel::TileSheetEditorModel(turbine::Context &ctx, ox::StringView
|
|||||||
void TileSheetEditorModel::cut() {
|
void TileSheetEditorModel::cut() {
|
||||||
TileSheetClipboard blankCb;
|
TileSheetClipboard blankCb;
|
||||||
auto cb = ox::make_unique<TileSheetClipboard>();
|
auto cb = ox::make_unique<TileSheetClipboard>();
|
||||||
const auto s = activeSubSheet();
|
const auto &s = activeSubSheet();
|
||||||
for (int y = m_selectionBounds.y; y <= m_selectionBounds.y2(); ++y) {
|
for (int y = m_selectionBounds.y; y <= m_selectionBounds.y2(); ++y) {
|
||||||
for (int x = m_selectionBounds.x; x <= m_selectionBounds.x2(); ++x) {
|
for (int x = m_selectionBounds.x; x <= m_selectionBounds.x2(); ++x) {
|
||||||
auto pt = ox::Point(x, y);
|
auto pt = ox::Point(x, y);
|
||||||
const auto idx = core::idx(*s, pt);
|
const auto idx = core::idx(s, pt);
|
||||||
const auto c = getPixel(*s, m_img.bpp, idx);
|
const auto c = getPixel(s, m_img.bpp, idx);
|
||||||
pt.x -= m_selectionBounds.x;
|
pt.x -= m_selectionBounds.x;
|
||||||
pt.y -= m_selectionBounds.y;
|
pt.y -= m_selectionBounds.y;
|
||||||
cb->addPixel(pt, c);
|
cb->addPixel(pt, c);
|
||||||
@ -57,7 +57,7 @@ void TileSheetEditorModel::cut() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto pt1 = m_selectionOrigin == ox::Point(-1, -1) ? ox::Point(0, 0) : m_selectionOrigin;
|
const auto pt1 = m_selectionOrigin == ox::Point(-1, -1) ? ox::Point(0, 0) : m_selectionOrigin;
|
||||||
const auto pt2 = ox::Point(s->columns * TileWidth, s->rows * TileHeight);
|
const auto pt2 = ox::Point(s.columns * TileWidth, s.rows * TileHeight);
|
||||||
turbine::setClipboardObject(m_ctx, std::move(cb));
|
turbine::setClipboardObject(m_ctx, 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));
|
||||||
}
|
}
|
||||||
@ -67,9 +67,9 @@ void TileSheetEditorModel::copy() {
|
|||||||
for (int y = m_selectionBounds.y; y <= m_selectionBounds.y2(); ++y) {
|
for (int y = m_selectionBounds.y; y <= m_selectionBounds.y2(); ++y) {
|
||||||
for (int x = m_selectionBounds.x; x <= m_selectionBounds.x2(); ++x) {
|
for (int x = m_selectionBounds.x; x <= m_selectionBounds.x2(); ++x) {
|
||||||
auto pt = ox::Point(x, y);
|
auto pt = ox::Point(x, y);
|
||||||
const auto s = activeSubSheet();
|
const auto &s = activeSubSheet();
|
||||||
const auto idx = core::idx(*s, pt);
|
const auto idx = core::idx(s, pt);
|
||||||
const auto c = getPixel(*s, m_img.bpp, idx);
|
const auto c = getPixel(s, m_img.bpp, idx);
|
||||||
pt.x -= m_selectionBounds.x;
|
pt.x -= m_selectionBounds.x;
|
||||||
pt.y -= m_selectionBounds.y;
|
pt.y -= m_selectionBounds.y;
|
||||||
cb->addPixel(pt, c);
|
cb->addPixel(pt, c);
|
||||||
@ -85,9 +85,9 @@ void TileSheetEditorModel::paste() {
|
|||||||
oxErrf("Could not read clipboard: {}", toStr(err));
|
oxErrf("Could not read clipboard: {}", toStr(err));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto s = activeSubSheet();
|
const auto &s = activeSubSheet();
|
||||||
const auto pt1 = m_selectionOrigin == ox::Point(-1, -1) ? ox::Point(0, 0) : m_selectionOrigin;
|
const auto pt1 = m_selectionOrigin == ox::Point(-1, -1) ? ox::Point(0, 0) : m_selectionOrigin;
|
||||||
const auto pt2 = ox::Point(s->columns * TileWidth, s->rows * TileHeight);
|
const auto 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,10 +206,10 @@ void TileSheetEditorModel::select(ox::Point const&pt) noexcept {
|
|||||||
|
|
||||||
void TileSheetEditorModel::completeSelection() noexcept {
|
void TileSheetEditorModel::completeSelection() noexcept {
|
||||||
m_selectionOngoing = false;
|
m_selectionOngoing = false;
|
||||||
auto s = activeSubSheet();
|
auto &s = activeSubSheet();
|
||||||
auto pt = m_selectionBounds.pt2();
|
auto pt = m_selectionBounds.pt2();
|
||||||
pt.x = ox::min(s->columns * TileWidth, pt.x);
|
pt.x = ox::min(s.columns * TileWidth, pt.x);
|
||||||
pt.y = ox::min(s->rows * TileHeight, pt.y);
|
pt.y = ox::min(s.rows * TileHeight, pt.y);
|
||||||
m_selectionBounds.setPt2(pt);
|
m_selectionBounds.setPt2(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,13 +254,13 @@ ox::Error TileSheetEditorModel::saveFile() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TileSheetEditorModel::pixelSelected(std::size_t idx) const noexcept {
|
bool TileSheetEditorModel::pixelSelected(std::size_t idx) const noexcept {
|
||||||
const auto s = activeSubSheet();
|
const auto &s = activeSubSheet();
|
||||||
const auto pt = idxToPt(static_cast<int>(idx), s->columns);
|
const auto pt = idxToPt(static_cast<int>(idx), s.columns);
|
||||||
return m_selectionBounds.contains(pt);
|
return m_selectionBounds.contains(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorModel::getFillPixels(bool *pixels, ox::Point const&pt, int oldColor) const noexcept {
|
void TileSheetEditorModel::getFillPixels(bool *pixels, ox::Point const&pt, int oldColor) const noexcept {
|
||||||
const auto &activeSubSheet = *this->activeSubSheet();
|
const auto &activeSubSheet = this->activeSubSheet();
|
||||||
const auto tileIdx = [activeSubSheet](const ox::Point &pt) noexcept {
|
const auto tileIdx = [activeSubSheet](const ox::Point &pt) noexcept {
|
||||||
return ptToIdx(pt, activeSubSheet.columns) / PixelsPerTile;
|
return ptToIdx(pt, activeSubSheet.columns) / PixelsPerTile;
|
||||||
};
|
};
|
||||||
|
@ -84,15 +84,13 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
|||||||
void setActiveSubsheet(TileSheet::SubSheetIdx const&) noexcept;
|
void setActiveSubsheet(TileSheet::SubSheetIdx const&) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
const TileSheet::SubSheet *activeSubSheet() const noexcept {
|
TileSheet::SubSheet const&activeSubSheet() const noexcept {
|
||||||
auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
|
return getSubSheet(m_img, m_activeSubsSheetIdx);
|
||||||
return &activeSubSheet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
TileSheet::SubSheet *activeSubSheet() noexcept {
|
TileSheet::SubSheet &activeSubSheet() noexcept {
|
||||||
auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
|
return getSubSheet(m_img, m_activeSubsSheetIdx);
|
||||||
return &activeSubSheet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
|
@ -28,9 +28,10 @@ void TileSheetEditorView::draw() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorView::scrollV(ox::Vec2 const&paneSz, float wheel, bool zoomMod) noexcept {
|
void TileSheetEditorView::scrollV(ox::Vec2 const&paneSz, float wheel, bool zoomMod) noexcept {
|
||||||
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
auto const&s = m_model.activeSubSheet();
|
||||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(m_model.activeSubSheet()->columns) * TileWidth,
|
auto const pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
||||||
pixelSize.y * static_cast<float>(m_model.activeSubSheet()->rows) * TileHeight);
|
ImVec2 const sheetSize(pixelSize.x * static_cast<float>(s.columns) * TileWidth,
|
||||||
|
pixelSize.y * static_cast<float>(s.rows) * TileHeight);
|
||||||
if (zoomMod) {
|
if (zoomMod) {
|
||||||
m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel * 0.02f, 0.55f, 2.f);
|
m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel * 0.02f, 0.55f, 2.f);
|
||||||
m_pixelsDrawer.setPixelSizeMod(m_pixelSizeMod);
|
m_pixelsDrawer.setPixelSizeMod(m_pixelSizeMod);
|
||||||
@ -45,39 +46,40 @@ void TileSheetEditorView::scrollV(ox::Vec2 const&paneSz, float wheel, bool zoomM
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorView::scrollH(ox::Vec2 const&paneSz, float wheelh) noexcept {
|
void TileSheetEditorView::scrollH(ox::Vec2 const&paneSz, float wheelh) noexcept {
|
||||||
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
auto const&s = m_model.activeSubSheet();
|
||||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(m_model.activeSubSheet()->columns) * TileWidth,
|
auto const pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
||||||
pixelSize.y * static_cast<float>(m_model.activeSubSheet()->rows) * TileHeight);
|
ImVec2 const sheetSize(pixelSize.x * static_cast<float>(s.columns) * TileWidth,
|
||||||
|
pixelSize.y * static_cast<float>(s.rows) * TileHeight);
|
||||||
m_scrollOffset.x += wheelh * 0.1f;
|
m_scrollOffset.x += wheelh * 0.1f;
|
||||||
m_scrollOffset.x = ox::clamp(m_scrollOffset.x, -(sheetSize.x / 2), 0.f);
|
m_scrollOffset.x = ox::clamp(m_scrollOffset.x, -(sheetSize.x / 2), 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorView::insertTile(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
|
void TileSheetEditorView::insertTile(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
|
||||||
const auto pt = clickPoint(paneSize, clickPos);
|
auto const pt = clickPoint(paneSize, clickPos);
|
||||||
const auto s = m_model.activeSubSheet();
|
auto const&s = m_model.activeSubSheet();
|
||||||
const auto tileIdx = ptToIdx(pt, s->columns) / PixelsPerTile;
|
auto const tileIdx = ptToIdx(pt, s.columns) / PixelsPerTile;
|
||||||
m_model.insertTiles(m_model.activeSubSheetIdx(), tileIdx, 1);
|
m_model.insertTiles(m_model.activeSubSheetIdx(), tileIdx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorView::deleteTile(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
|
void TileSheetEditorView::deleteTile(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
|
||||||
const auto pt = clickPoint(paneSize, clickPos);
|
auto const pt = clickPoint(paneSize, clickPos);
|
||||||
const auto s = m_model.activeSubSheet();
|
auto const&s = m_model.activeSubSheet();
|
||||||
const auto tileIdx = ptToIdx(pt, s->columns) / PixelsPerTile;
|
auto const tileIdx = ptToIdx(pt, s.columns) / PixelsPerTile;
|
||||||
m_model.deleteTiles(m_model.activeSubSheetIdx(), tileIdx, 1);
|
m_model.deleteTiles(m_model.activeSubSheetIdx(), tileIdx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorView::clickDraw(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
|
void TileSheetEditorView::clickDraw(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
|
||||||
const auto pt = clickPoint(paneSize, clickPos);
|
auto const pt = clickPoint(paneSize, clickPos);
|
||||||
m_model.drawCommand(pt, m_palIdx);
|
m_model.drawCommand(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 {
|
||||||
const auto pt = clickPoint(paneSize, clickPos);
|
auto const pt = clickPoint(paneSize, clickPos);
|
||||||
m_model.select(pt);
|
m_model.select(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorView::clickFill(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
|
void TileSheetEditorView::clickFill(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
|
||||||
const auto pt = clickPoint(paneSize, clickPos);
|
auto const pt = clickPoint(paneSize, clickPos);
|
||||||
m_model.fill(pt, static_cast<int>(m_palIdx));
|
m_model.fill(pt, static_cast<int>(m_palIdx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,13 +105,13 @@ ox::Error TileSheetEditorView::markUpdated() noexcept {
|
|||||||
void TileSheetEditorView::ackUpdate() noexcept {
|
void TileSheetEditorView::ackUpdate() noexcept {
|
||||||
m_updated = false;
|
m_updated = false;
|
||||||
m_pixelsDrawer.update(m_viewSize);
|
m_pixelsDrawer.update(m_viewSize);
|
||||||
m_pixelGridDrawer.update(m_viewSize, *m_model.activeSubSheet());
|
m_pixelGridDrawer.update(m_viewSize, m_model.activeSubSheet());
|
||||||
m_model.ackUpdate();
|
m_model.ackUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorView::initView() noexcept {
|
void TileSheetEditorView::initView() noexcept {
|
||||||
m_pixelsDrawer.initBufferSet(m_viewSize);
|
m_pixelsDrawer.initBufferSet(m_viewSize);
|
||||||
m_pixelGridDrawer.initBufferSet(m_viewSize, *m_model.activeSubSheet());
|
m_pixelGridDrawer.initBufferSet(m_viewSize, m_model.activeSubSheet());
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Point TileSheetEditorView::clickPoint(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) const noexcept {
|
ox::Point TileSheetEditorView::clickPoint(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) const noexcept {
|
||||||
|
@ -15,9 +15,9 @@ void TileSheetGrid::setPixelSizeMod(float sm) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Error TileSheetGrid::buildShader() noexcept {
|
ox::Error TileSheetGrid::buildShader() noexcept {
|
||||||
const auto pixelLineVshad = ox::sfmt(VShad, gl::GlslVersion);
|
auto const pixelLineVshad = ox::sfmt(VShad, gl::GlslVersion);
|
||||||
const auto pixelLineFshad = ox::sfmt(FShad, gl::GlslVersion);
|
auto const pixelLineFshad = ox::sfmt(FShad, gl::GlslVersion);
|
||||||
const auto pixelLineGshad = ox::sfmt(GShad, gl::GlslVersion);
|
auto const pixelLineGshad = ox::sfmt(GShad, gl::GlslVersion);
|
||||||
return glutils::buildShaderProgram(pixelLineVshad, pixelLineFshad, pixelLineGshad).moveTo(m_shader);
|
return glutils::buildShaderProgram(pixelLineVshad, pixelLineFshad, pixelLineGshad).moveTo(m_shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ void TileSheetGrid::draw(bool update, ox::Vec2 const&scroll) noexcept {
|
|||||||
if (update) {
|
if (update) {
|
||||||
glutils::sendVbo(m_bufferSet);
|
glutils::sendVbo(m_bufferSet);
|
||||||
}
|
}
|
||||||
const auto uniformScroll = glGetUniformLocation(m_shader, "gScroll");
|
auto const uniformScroll = glGetUniformLocation(m_shader, "gScroll");
|
||||||
glUniform2f(uniformScroll, scroll.x, scroll.y);
|
glUniform2f(uniformScroll, scroll.x, scroll.y);
|
||||||
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(m_bufferSet.vertices.size() / VertexVboRowLength));
|
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(m_bufferSet.vertices.size() / VertexVboRowLength));
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
@ -44,14 +44,14 @@ void TileSheetGrid::initBufferSet(ox::Vec2 const&paneSize, TileSheet::SubSheet c
|
|||||||
setBufferObjects(paneSize, subsheet);
|
setBufferObjects(paneSize, subsheet);
|
||||||
glutils::sendVbo(m_bufferSet);
|
glutils::sendVbo(m_bufferSet);
|
||||||
// vbo layout
|
// vbo layout
|
||||||
const auto pt1Attr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vPt1"));
|
auto const pt1Attr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vPt1"));
|
||||||
glEnableVertexAttribArray(pt1Attr);
|
glEnableVertexAttribArray(pt1Attr);
|
||||||
glVertexAttribPointer(pt1Attr, 2, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float), nullptr);
|
glVertexAttribPointer(pt1Attr, 2, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float), nullptr);
|
||||||
const auto pt2Attr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vPt2"));
|
auto const pt2Attr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vPt2"));
|
||||||
glEnableVertexAttribArray(pt2Attr);
|
glEnableVertexAttribArray(pt2Attr);
|
||||||
glVertexAttribPointer(pt2Attr, 2, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float),
|
glVertexAttribPointer(pt2Attr, 2, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float),
|
||||||
std::bit_cast<void*>(uintptr_t{2 * sizeof(float)}));
|
std::bit_cast<void*>(uintptr_t{2 * sizeof(float)}));
|
||||||
const auto colorAttr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vColor"));
|
auto const colorAttr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vColor"));
|
||||||
glEnableVertexAttribArray(colorAttr);
|
glEnableVertexAttribArray(colorAttr);
|
||||||
glVertexAttribPointer(colorAttr, 3, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float),
|
glVertexAttribPointer(colorAttr, 3, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float),
|
||||||
std::bit_cast<void*>(uintptr_t{4 * sizeof(float)}));
|
std::bit_cast<void*>(uintptr_t{4 * sizeof(float)}));
|
||||||
@ -64,27 +64,32 @@ void TileSheetGrid::update(ox::Vec2 const&paneSize, TileSheet::SubSheet const&su
|
|||||||
glutils::sendEbo(m_bufferSet);
|
glutils::sendEbo(m_bufferSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetGrid::setBufferObject(ox::Point pt1, ox::Point pt2, Color32 c, float *vbo, ox::Vec2 const&pixSize) noexcept {
|
void TileSheetGrid::setBufferObject(
|
||||||
const auto x1 = static_cast<float>(pt1.x) * pixSize.x - 1.f;
|
ox::Point pt1,
|
||||||
const auto y1 = 1.f - static_cast<float>(pt1.y) * pixSize.y;
|
ox::Point pt2,
|
||||||
const auto x2 = static_cast<float>(pt2.x) * pixSize.x - 1.f;
|
Color32 c,
|
||||||
const auto y2 = 1.f - static_cast<float>(pt2.y) * pixSize.y;
|
float *vbo,
|
||||||
|
ox::Vec2 const&pixSize) noexcept {
|
||||||
|
auto const x1 = static_cast<float>(pt1.x) * pixSize.x - 1.f;
|
||||||
|
auto const y1 = 1.f - static_cast<float>(pt1.y) * pixSize.y;
|
||||||
|
auto const x2 = static_cast<float>(pt2.x) * pixSize.x - 1.f;
|
||||||
|
auto const y2 = 1.f - static_cast<float>(pt2.y) * pixSize.y;
|
||||||
// don't worry, this memcpy gets optimized to something much more ideal
|
// don't worry, this memcpy gets optimized to something much more ideal
|
||||||
const ox::Array<float, VertexVboLength> vertices = {x1, y1, x2, y2, redf(c), greenf(c), bluef(c)};
|
ox::Array<float, VertexVboLength> const vertices = {x1, y1, x2, y2, redf(c), greenf(c), bluef(c)};
|
||||||
memcpy(vbo, vertices.data(), sizeof(vertices));
|
memcpy(vbo, vertices.data(), sizeof(vertices));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetGrid::setBufferObjects(ox::Vec2 const&paneSize, TileSheet::SubSheet const&subsheet) noexcept {
|
void TileSheetGrid::setBufferObjects(ox::Vec2 const&paneSize, TileSheet::SubSheet const&subsheet) noexcept {
|
||||||
const auto pixSize = pixelSize(paneSize);
|
auto const pixSize = pixelSize(paneSize);
|
||||||
const auto set = [&](std::size_t i, ox::Point pt1, ox::Point pt2, Color32 c) {
|
auto const set = [&](std::size_t i, ox::Point pt1, ox::Point pt2, Color32 c) {
|
||||||
const auto vbo = &m_bufferSet.vertices[i * VertexVboLength];
|
auto const vbo = &m_bufferSet.vertices[i * VertexVboLength];
|
||||||
setBufferObject(pt1, pt2, c, vbo, pixSize);
|
setBufferObject(pt1, pt2, c, vbo, pixSize);
|
||||||
};
|
};
|
||||||
// set buffer length
|
// set buffer length
|
||||||
const auto width = subsheet.columns * TileWidth;
|
auto const width = subsheet.columns * TileWidth;
|
||||||
const auto height = subsheet.rows * TileHeight;
|
auto const height = subsheet.rows * TileHeight;
|
||||||
const auto tileCnt = static_cast<unsigned>(subsheet.columns + subsheet.rows);
|
auto const tileCnt = static_cast<unsigned>(subsheet.columns + subsheet.rows);
|
||||||
const auto pixelCnt = static_cast<unsigned>(width + height);
|
auto const pixelCnt = static_cast<unsigned>(width + height);
|
||||||
m_bufferSet.vertices.resize(static_cast<std::size_t>(tileCnt + pixelCnt + 4) * VertexVboLength);
|
m_bufferSet.vertices.resize(static_cast<std::size_t>(tileCnt + pixelCnt + 4) * VertexVboLength);
|
||||||
// set buffer
|
// set buffer
|
||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
@ -111,9 +116,9 @@ void TileSheetGrid::setBufferObjects(ox::Vec2 const&paneSize, TileSheet::SubShee
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Vec2 TileSheetGrid::pixelSize(ox::Vec2 const&paneSize) const noexcept {
|
ox::Vec2 TileSheetGrid::pixelSize(ox::Vec2 const&paneSize) const noexcept {
|
||||||
const auto [sw, sh] = paneSize;
|
auto const [sw, sh] = paneSize;
|
||||||
constexpr float ymod = 0.35f / 10.0f;
|
constexpr float ymod = 0.35f / 10.0f;
|
||||||
const auto xmod = ymod * sh / sw;
|
auto const xmod = ymod * sh / sw;
|
||||||
return {xmod * m_pixelSizeMod, ymod * m_pixelSizeMod};
|
return {xmod * m_pixelSizeMod, ymod * m_pixelSizeMod};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,17 +94,17 @@ void TileSheetPixels::setPixelBufferObject(
|
|||||||
|
|
||||||
void TileSheetPixels::setBufferObjects(ox::Vec2 const&paneSize) noexcept {
|
void TileSheetPixels::setBufferObjects(ox::Vec2 const&paneSize) noexcept {
|
||||||
// set buffer lengths
|
// set buffer lengths
|
||||||
auto const subSheet = m_model.activeSubSheet();
|
auto const&subSheet = m_model.activeSubSheet();
|
||||||
auto const&pal = m_model.pal();
|
auto const&pal = m_model.pal();
|
||||||
auto const width = subSheet->columns * TileWidth;
|
auto const width = subSheet.columns * TileWidth;
|
||||||
auto const height = subSheet->rows * TileHeight;
|
auto const height = subSheet.rows * TileHeight;
|
||||||
auto const pixels = static_cast<size_t>(width) * static_cast<size_t>(height);
|
auto const pixels = static_cast<size_t>(width) * static_cast<size_t>(height);
|
||||||
m_bufferSet.vertices.resize(pixels * VertexVboLength);
|
m_bufferSet.vertices.resize(pixels * VertexVboLength);
|
||||||
m_bufferSet.elements.resize(pixels * VertexEboLength);
|
m_bufferSet.elements.resize(pixels * VertexEboLength);
|
||||||
// set pixels
|
// set pixels
|
||||||
walkPixels(*subSheet, m_model.img().bpp, [&](std::size_t i, uint8_t p) {
|
walkPixels(subSheet, m_model.img().bpp, [&](std::size_t i, uint8_t p) {
|
||||||
auto color = core::color(pal, m_model.palettePage(), p);
|
auto color = core::color(pal, m_model.palettePage(), p);
|
||||||
auto const pt = idxToPt(static_cast<int>(i), subSheet->columns);
|
auto const pt = idxToPt(static_cast<int>(i), subSheet.columns);
|
||||||
auto const fx = static_cast<float>(pt.x);
|
auto const fx = static_cast<float>(pt.x);
|
||||||
auto const fy = static_cast<float>(pt.y);
|
auto const fy = static_cast<float>(pt.y);
|
||||||
auto const vbo = &m_bufferSet.vertices[i * VertexVboLength];
|
auto const vbo = &m_bufferSet.vertices[i * VertexVboLength];
|
||||||
|
Loading…
Reference in New Issue
Block a user