[nostalgia/core/studio] Decouple core TileSheetEditor from ImGui
This commit is contained in:
parent
7370b23c9d
commit
0aa71f1dbb
@ -5,8 +5,9 @@ add_library(
|
|||||||
#new_tilesheet_wizard.cpp
|
#new_tilesheet_wizard.cpp
|
||||||
#newpalettewizard.cpp
|
#newpalettewizard.cpp
|
||||||
#paletteeditor.cpp
|
#paletteeditor.cpp
|
||||||
|
tilesheeteditor-imgui.cpp
|
||||||
tilesheeteditor.cpp
|
tilesheeteditor.cpp
|
||||||
tilesheetpixelgrid.cpp
|
tilesheetpixelgrid.cpp
|
||||||
tilesheetpixels.cpp
|
tilesheetpixels.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tilesheeteditor.hpp"
|
#include "tilesheeteditor-imgui.hpp"
|
||||||
|
|
||||||
#include "module.hpp"
|
#include "module.hpp"
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ ox::Vector<studio::EditorMaker> Module::editors(core::Context *ctx) {
|
|||||||
{
|
{
|
||||||
{"ng"},
|
{"ng"},
|
||||||
[ctx](const ox::String &path) {
|
[ctx](const ox::String &path) {
|
||||||
return new TileSheetEditor(ctx, path);
|
return new TileSheetEditorImGui(ctx, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
115
src/nostalgia/core/studio/tilesheeteditor-imgui.cpp
Normal file
115
src/nostalgia/core/studio/tilesheeteditor-imgui.cpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include <nostalgia/common/point.hpp>
|
||||||
|
#include <nostalgia/core/media.hpp>
|
||||||
|
|
||||||
|
#include "tilesheeteditor-imgui.hpp"
|
||||||
|
|
||||||
|
namespace nostalgia::core {
|
||||||
|
|
||||||
|
TileSheetEditorImGui::TileSheetEditorImGui(Context *ctx, const ox::String &path): m_tileSheetEditor(ctx, path) {
|
||||||
|
m_itemPath = path;
|
||||||
|
const auto lastSlash = std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset();
|
||||||
|
m_itemName = m_itemPath.substr(lastSlash + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::String TileSheetEditorImGui::itemName() const noexcept {
|
||||||
|
return m_itemPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::String TileSheetEditorImGui::itemDisplayName() const noexcept {
|
||||||
|
return m_itemName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditorImGui::exportFile() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditorImGui::cut() {
|
||||||
|
m_tileSheetEditor.cut();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditorImGui::copy() {
|
||||||
|
m_tileSheetEditor.copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditorImGui::paste() {
|
||||||
|
m_tileSheetEditor.paste();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditorImGui::draw(core::Context*) noexcept {
|
||||||
|
const auto paneSize = ImGui::GetContentRegionAvail();
|
||||||
|
const auto tileSheetParentSize = ImVec2(paneSize.x - m_palViewWidth, paneSize.y);
|
||||||
|
const auto fbSize = common::Vec2(tileSheetParentSize.x - 16, tileSheetParentSize.y - 16);
|
||||||
|
ImGui::BeginChild("child1", ImVec2(tileSheetParentSize.x, tileSheetParentSize.y), true);
|
||||||
|
drawTileSheet(fbSize);
|
||||||
|
ImGui::EndChild();
|
||||||
|
ImGui::SameLine();
|
||||||
|
// draw palette/color picker
|
||||||
|
ImGui::BeginChild("child2", ImVec2(m_palViewWidth - 8, paneSize.y), true);
|
||||||
|
drawPalettePicker();
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditorImGui::saveItem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditorImGui::drawTileSheet(const common::Vec2 &fbSize) noexcept {
|
||||||
|
const auto fbSizei = common::Size(static_cast<int>(fbSize.x), static_cast<int>(fbSize.y));
|
||||||
|
if (m_framebuffer.width != fbSizei.width || m_framebuffer.height != fbSizei.height) {
|
||||||
|
m_framebuffer = glutils::generateFrameBuffer(fbSizei.width, fbSizei.height);
|
||||||
|
m_tileSheetEditor.resize(fbSize);
|
||||||
|
} else if (m_tileSheetEditor.updated()) {
|
||||||
|
m_tileSheetEditor.resize(fbSize);
|
||||||
|
m_tileSheetEditor.ackUpdate();
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
||||||
|
// clear screen and draw
|
||||||
|
glViewport(0, 0, fbSizei.width, fbSizei.height);
|
||||||
|
m_tileSheetEditor.draw();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
ImGui::Image(reinterpret_cast<void*>(m_framebuffer.color.id), static_cast<ImVec2>(fbSize), ImVec2(0, 1), ImVec2(1, 0));
|
||||||
|
// handle input, this must come after drawing
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
const auto &io = ImGui::GetIO();
|
||||||
|
const auto wheel = io.MouseWheel;
|
||||||
|
const auto wheelh = io.MouseWheelH;
|
||||||
|
if (wheel != 0) {
|
||||||
|
const auto zoomMod = ox::defines::OS == ox::OS::Darwin ? io.KeySuper : io.KeyCtrl;
|
||||||
|
m_tileSheetEditor.scrollV(fbSize, wheel, zoomMod);
|
||||||
|
}
|
||||||
|
if (wheelh != 0) {
|
||||||
|
m_tileSheetEditor.scrollH(fbSize, wheelh);
|
||||||
|
}
|
||||||
|
if (io.MouseDown[0]) {
|
||||||
|
auto clickPos = common::Vec2(io.MousePos);
|
||||||
|
const auto &winPos = ImGui::GetWindowPos();
|
||||||
|
clickPos.x -= winPos.x + 10;
|
||||||
|
clickPos.y -= winPos.y + 10;
|
||||||
|
m_tileSheetEditor.clickPixel(fbSize, clickPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditorImGui::drawPalettePicker() noexcept {
|
||||||
|
// header
|
||||||
|
ImGui::BeginTable("PaletteTable", 2);
|
||||||
|
ImGui::TableSetupColumn("No.", 0, 0.35);
|
||||||
|
ImGui::TableSetupColumn("Color16", 0, 3);
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
for (auto i = 1; auto c : m_tileSheetEditor.pal().colors) {
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%d", i);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("(%d, %d, %d)", red16(c), green16(c), blue16(c));
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
81
src/nostalgia/core/studio/tilesheeteditor-imgui.hpp
Normal file
81
src/nostalgia/core/studio/tilesheeteditor-imgui.hpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ox/model/def.hpp>
|
||||||
|
|
||||||
|
#include <nostalgia/common/bounds.hpp>
|
||||||
|
#include <nostalgia/common/vec.hpp>
|
||||||
|
#include <nostalgia/core/gfx.hpp>
|
||||||
|
#include <nostalgia/glutils/glutils.hpp>
|
||||||
|
#include <nostalgia/studio/studio.hpp>
|
||||||
|
|
||||||
|
#include "tilesheetpixelgrid.hpp"
|
||||||
|
#include "tilesheetpixels.hpp"
|
||||||
|
#include "tilesheeteditor.hpp"
|
||||||
|
|
||||||
|
namespace nostalgia::core {
|
||||||
|
|
||||||
|
class TileSheetEditorImGui: public studio::Editor {
|
||||||
|
|
||||||
|
private:
|
||||||
|
ox::String m_itemPath;
|
||||||
|
ox::String m_itemName;
|
||||||
|
glutils::FrameBuffer m_framebuffer;
|
||||||
|
TileSheetEditor m_tileSheetEditor;
|
||||||
|
float m_palViewWidth = 200;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TileSheetEditorImGui(Context *ctx, const ox::String &path);
|
||||||
|
|
||||||
|
~TileSheetEditorImGui() override = default;
|
||||||
|
|
||||||
|
ox::String itemName() const noexcept override;
|
||||||
|
|
||||||
|
ox::String itemDisplayName() const noexcept override;
|
||||||
|
|
||||||
|
void exportFile() override;
|
||||||
|
|
||||||
|
void cut() override;
|
||||||
|
|
||||||
|
void copy() override;
|
||||||
|
|
||||||
|
void paste() override;
|
||||||
|
|
||||||
|
void draw(core::Context*) noexcept override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void saveItem() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setPalette();
|
||||||
|
|
||||||
|
void saveState();
|
||||||
|
|
||||||
|
void restoreState();
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
ox::String paletteName(const ox::String &palettePath) const;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
ox::String palettePath(const ox::String &palettePath) const;
|
||||||
|
|
||||||
|
void drawTileSheet(const common::Vec2 &fbSize) noexcept;
|
||||||
|
|
||||||
|
void drawPalettePicker() noexcept;
|
||||||
|
|
||||||
|
// slots
|
||||||
|
public:
|
||||||
|
ox::Error colorSelected() noexcept;
|
||||||
|
|
||||||
|
ox::Error setColorTable() noexcept;
|
||||||
|
|
||||||
|
// slots
|
||||||
|
private:
|
||||||
|
ox::Error updateAfterClicked() noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
#include <nostalgia/common/point.hpp>
|
#include <nostalgia/common/point.hpp>
|
||||||
#include <nostalgia/core/consts.hpp>
|
#include <nostalgia/core/consts.hpp>
|
||||||
#include <nostalgia/core/media.hpp>
|
#include <nostalgia/core/media.hpp>
|
||||||
@ -16,28 +14,14 @@
|
|||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
TileSheetEditor::TileSheetEditor(Context *ctx, const ox::String &path) {
|
TileSheetEditor::TileSheetEditor(Context *ctx, const ox::String &path) {
|
||||||
m_itemPath = path;
|
|
||||||
const auto lastSlash = std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset();
|
|
||||||
m_itemName = m_itemPath.substr(lastSlash + 1);
|
|
||||||
// build shaders
|
// build shaders
|
||||||
oxThrowError(m_pixelsDrawer.buildShader());
|
oxThrowError(m_pixelsDrawer.buildShader());
|
||||||
oxThrowError(m_pixelGridDrawer.buildShader());
|
oxThrowError(m_pixelGridDrawer.buildShader());
|
||||||
oxRequireT(img, readObj<NostalgiaGraphic>(ctx, m_itemPath.c_str()));
|
oxRequireT(img, readObj<NostalgiaGraphic>(ctx, path.c_str()));
|
||||||
m_img = std::move(*img);
|
m_img = std::move(*img);
|
||||||
oxThrowError(readObj<NostalgiaPalette>(ctx, m_img.defaultPalette).moveTo(&m_pal));
|
oxThrowError(readObj<NostalgiaPalette>(ctx, m_img.defaultPalette).moveTo(&m_pal));
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::String TileSheetEditor::itemName() const noexcept {
|
|
||||||
return m_itemPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::String TileSheetEditor::itemDisplayName() const noexcept {
|
|
||||||
return m_itemName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileSheetEditor::exportFile() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileSheetEditor::cut() {
|
void TileSheetEditor::cut() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,29 +31,74 @@ void TileSheetEditor::copy() {
|
|||||||
void TileSheetEditor::paste() {
|
void TileSheetEditor::paste() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditor::draw(core::Context*) noexcept {
|
void TileSheetEditor::draw() noexcept {
|
||||||
const auto paneSize = ImGui::GetContentRegionAvail();
|
|
||||||
const auto tileSheetParentSize = ImVec2(paneSize.x - m_palViewWidth, paneSize.y);
|
|
||||||
const auto fbSize = common::Vec2(tileSheetParentSize.x - 16, tileSheetParentSize.y - 16);
|
|
||||||
ImGui::BeginChild("child1", ImVec2(tileSheetParentSize.x, tileSheetParentSize.y), true);
|
|
||||||
drawTileSheet(fbSize);
|
|
||||||
ImGui::EndChild();
|
|
||||||
ImGui::SameLine();
|
|
||||||
// draw palette/color picker
|
|
||||||
ImGui::BeginChild("child2", ImVec2(m_palViewWidth - 8, paneSize.y), true);
|
|
||||||
drawPalettePicker();
|
|
||||||
ImGui::EndChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileSheetEditor::glDraw() noexcept {
|
|
||||||
// clear screen
|
|
||||||
constexpr Color32 bgColor = 0x717d7e;
|
constexpr Color32 bgColor = 0x717d7e;
|
||||||
glClearColor(redf(bgColor), greenf(bgColor), bluef(bgColor), 1.f);
|
glClearColor(redf(bgColor), greenf(bgColor), bluef(bgColor), 1.f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
m_pixelsDrawer.draw(m_updated, m_scrollOffset);
|
m_pixelsDrawer.draw(m_updated, m_scrollOffset);
|
||||||
m_pixelGridDrawer.draw(m_updated, m_scrollOffset);
|
m_pixelGridDrawer.draw(m_updated, m_scrollOffset);
|
||||||
m_updated = false;
|
m_updated = false;
|
||||||
//oxAssert(glGetError() == 0, "There was an OpenGL error");
|
}
|
||||||
|
|
||||||
|
void TileSheetEditor::scrollV(const common::Vec2 paneSz, float wheel, bool zoomMod) noexcept {
|
||||||
|
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
||||||
|
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(m_img.columns) * TileWidth,
|
||||||
|
pixelSize.y * static_cast<float>(m_img.rows) * TileHeight);
|
||||||
|
if (zoomMod) {
|
||||||
|
m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel * 0.02f, 0.55f, 2.f);
|
||||||
|
m_pixelsDrawer.setPixelSizeMod(m_pixelSizeMod);
|
||||||
|
m_pixelGridDrawer.setPixelSizeMod(m_pixelSizeMod);
|
||||||
|
m_updated = true;
|
||||||
|
} else {
|
||||||
|
m_scrollOffset.y -= wheel * 0.1f;
|
||||||
|
}
|
||||||
|
// adjust scroll offset in both cases because the image can be zoomed
|
||||||
|
// or scrolled off screen
|
||||||
|
m_scrollOffset.y = ox::clamp(m_scrollOffset.y, 0.f, sheetSize.y / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditor::scrollH(const common::Vec2 paneSz, float wheelh) noexcept {
|
||||||
|
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz);
|
||||||
|
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(m_img.columns) * TileWidth,
|
||||||
|
pixelSize.y * static_cast<float>(m_img.rows) * TileHeight);
|
||||||
|
m_scrollOffset.x += wheelh * 0.1f;
|
||||||
|
m_scrollOffset.x = ox::clamp(m_scrollOffset.x, -(sheetSize.x / 2), 0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditor::clickPixel(const common::Vec2 &paneSize, const common::Vec2 &clickPos) noexcept {
|
||||||
|
auto [x, y] = clickPos;
|
||||||
|
const auto pixDrawSz = m_pixelsDrawer.pixelSize(paneSize);
|
||||||
|
x /= paneSize.x;
|
||||||
|
y /= paneSize.y;
|
||||||
|
x += -m_scrollOffset.x / 2;
|
||||||
|
y += m_scrollOffset.y / 2;
|
||||||
|
x /= pixDrawSz.x;
|
||||||
|
y /= pixDrawSz.y;
|
||||||
|
const auto pt = common::Point(static_cast<int>(x * 2), static_cast<int>(y * 2));
|
||||||
|
const uint8_t palIdx = 0;
|
||||||
|
m_img.setPixel(pt, palIdx);
|
||||||
|
m_updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditor::resize(const common::Vec2 &sz) noexcept {
|
||||||
|
m_pixelsDrawer.initBufferSet(sz, m_img, *m_pal);
|
||||||
|
m_pixelGridDrawer.initBufferSet(sz, m_img);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NostalgiaGraphic &TileSheetEditor::img() const {
|
||||||
|
return m_img;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NostalgiaPalette &TileSheetEditor::pal() const {
|
||||||
|
return *m_pal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TileSheetEditor::updated() const noexcept {
|
||||||
|
return m_updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditor::ackUpdate() noexcept {
|
||||||
|
m_updated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditor::saveItem() {
|
void TileSheetEditor::saveItem() {
|
||||||
@ -107,89 +136,4 @@ void TileSheetEditor::getFillPixels(bool *pixels, common::Point pt, int oldColor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditor::drawTileSheet(const common::Vec2 &fbSize) noexcept {
|
|
||||||
const auto fbSizei = common::Size(static_cast<int>(fbSize.x), static_cast<int>(fbSize.y));
|
|
||||||
if (m_framebuffer.width != fbSizei.width || m_framebuffer.height != fbSizei.height) {
|
|
||||||
m_framebuffer = glutils::generateFrameBuffer(fbSizei.width, fbSizei.height);
|
|
||||||
m_pixelsDrawer.initBufferSet(common::Vec2(fbSize), m_img, *m_pal);
|
|
||||||
m_pixelGridDrawer.initBufferSet(common::Vec2(fbSize), m_img);
|
|
||||||
} else if (m_updated) {
|
|
||||||
m_pixelsDrawer.initBufferSet(common::Vec2(fbSize), m_img, *m_pal);
|
|
||||||
m_pixelGridDrawer.initBufferSet(common::Vec2(fbSize), m_img);
|
|
||||||
}
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
|
||||||
glViewport(0, 0, fbSizei.width, fbSizei.height);
|
|
||||||
glDraw();
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
ImGui::Image(reinterpret_cast<void*>(m_framebuffer.color.id), static_cast<ImVec2>(fbSize), ImVec2(0, 1), ImVec2(1, 0));
|
|
||||||
// handle input, this must come after drawing
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
const auto &io = ImGui::GetIO();
|
|
||||||
const auto wheel = io.MouseWheel;
|
|
||||||
const auto wheelh = io.MouseWheelH;
|
|
||||||
if (wheel != 0) {
|
|
||||||
const auto zoomMod = ox::defines::OS == ox::OS::Darwin ? io.KeySuper : io.KeyCtrl;
|
|
||||||
const auto pixelSize = m_pixelsDrawer.pixelSize(common::Vec2(fbSize));
|
|
||||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(m_img.columns) * TileWidth,
|
|
||||||
pixelSize.y * static_cast<float>(m_img.rows) * TileHeight);
|
|
||||||
if (zoomMod) {
|
|
||||||
m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel * 0.02f, 0.55f, 2.f);
|
|
||||||
m_pixelsDrawer.setPixelSizeMod(m_pixelSizeMod);
|
|
||||||
m_pixelGridDrawer.setPixelSizeMod(m_pixelSizeMod);
|
|
||||||
m_updated = true;
|
|
||||||
} else {
|
|
||||||
m_scrollOffset.y -= wheel * 0.1f;
|
|
||||||
}
|
|
||||||
// adjust scroll offset in both cases because the image can be zoomed
|
|
||||||
// or scrolled off screen
|
|
||||||
m_scrollOffset.y = ox::clamp(m_scrollOffset.y, 0.f, sheetSize.y / 2);
|
|
||||||
}
|
|
||||||
if (wheelh != 0) {
|
|
||||||
const auto pixelSize = m_pixelsDrawer.pixelSize(common::Vec2(fbSize));
|
|
||||||
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(m_img.columns) * TileWidth,
|
|
||||||
pixelSize.y * static_cast<float>(m_img.rows) * TileHeight);
|
|
||||||
m_scrollOffset.x += wheelh * 0.1f;
|
|
||||||
m_scrollOffset.x = ox::clamp(m_scrollOffset.x, -(sheetSize.x / 2), 0.f);
|
|
||||||
}
|
|
||||||
if (io.MouseDown[0]) {
|
|
||||||
auto clickPos = common::Vec2(io.MousePos);
|
|
||||||
const auto &winPos = ImGui::GetWindowPos();
|
|
||||||
clickPos.x -= winPos.x + 10;
|
|
||||||
clickPos.y -= winPos.y + 10;
|
|
||||||
clickPixel(fbSize, clickPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileSheetEditor::drawPalettePicker() noexcept {
|
|
||||||
// header
|
|
||||||
ImGui::BeginTable("PaletteTable", 2);
|
|
||||||
ImGui::TableSetupColumn("No.", 0, 0.35);
|
|
||||||
ImGui::TableSetupColumn("Color16", 0, 3);
|
|
||||||
ImGui::TableHeadersRow();
|
|
||||||
for (auto i = 1; auto c : m_pal->colors) {
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%d", i);
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("(%d, %d, %d)", red16(c), green16(c), blue16(c));
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
ImGui::EndTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileSheetEditor::clickPixel(const common::Vec2 &paneSize, const common::Vec2 &clickPos) noexcept {
|
|
||||||
auto [x, y] = clickPos;
|
|
||||||
const auto pixDrawSz = m_pixelsDrawer.pixelSize(paneSize);
|
|
||||||
x /= paneSize.x;
|
|
||||||
y /= paneSize.y;
|
|
||||||
x += -m_scrollOffset.x / 2;
|
|
||||||
y += m_scrollOffset.y / 2;
|
|
||||||
x /= pixDrawSz.x;
|
|
||||||
y /= pixDrawSz.y;
|
|
||||||
const auto pt = common::Point(static_cast<int>(x * 2), static_cast<int>(y * 2));
|
|
||||||
const uint8_t palIdx = 0;
|
|
||||||
m_img.setPixel(pt, palIdx);
|
|
||||||
m_updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -95,12 +95,9 @@ constexpr ox::Error model(T *io, TileSheetClipboard *b) noexcept {
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
class TileSheetEditor: public studio::Editor {
|
class TileSheetEditor {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ox::String m_itemPath;
|
|
||||||
ox::String m_itemName;
|
|
||||||
glutils::FrameBuffer m_framebuffer;
|
|
||||||
TileSheetGrid m_pixelGridDrawer;
|
TileSheetGrid m_pixelGridDrawer;
|
||||||
TileSheetPixels m_pixelsDrawer;
|
TileSheetPixels m_pixelsDrawer;
|
||||||
bool m_updated = false;
|
bool m_updated = false;
|
||||||
@ -108,31 +105,38 @@ class TileSheetEditor: public studio::Editor {
|
|||||||
AssetRef<NostalgiaPalette> m_pal;
|
AssetRef<NostalgiaPalette> m_pal;
|
||||||
float m_pixelSizeMod = 1;
|
float m_pixelSizeMod = 1;
|
||||||
common::Vec2 m_scrollOffset;
|
common::Vec2 m_scrollOffset;
|
||||||
float m_palViewWidth = 200;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TileSheetEditor(Context *ctx, const ox::String &path);
|
TileSheetEditor(Context *ctx, const ox::String &path);
|
||||||
|
|
||||||
~TileSheetEditor() override = default;
|
~TileSheetEditor() = default;
|
||||||
|
|
||||||
ox::String itemName() const noexcept override;
|
void cut();
|
||||||
|
|
||||||
ox::String itemDisplayName() const noexcept override;
|
void copy();
|
||||||
|
|
||||||
void exportFile() override;
|
void paste();
|
||||||
|
|
||||||
void cut() override;
|
void draw() noexcept;
|
||||||
|
|
||||||
void copy() override;
|
void clickPixel(const common::Vec2 &paneSize, const common::Vec2 &clickPos) noexcept;
|
||||||
|
|
||||||
void paste() override;
|
void scrollV(const common::Vec2 paneSz, float wheel, bool zoomMod) noexcept;
|
||||||
|
|
||||||
void draw(core::Context*) noexcept override;
|
void scrollH(const common::Vec2 paneSz, float wheel) noexcept;
|
||||||
|
|
||||||
void glDraw() noexcept;
|
void resize(const common::Vec2 &sz) noexcept;
|
||||||
|
|
||||||
|
const NostalgiaGraphic &img() const;
|
||||||
|
|
||||||
|
const NostalgiaPalette &pal() const;
|
||||||
|
|
||||||
|
bool updated() const noexcept;
|
||||||
|
|
||||||
|
void ackUpdate() noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void saveItem() override;
|
void saveItem();
|
||||||
|
|
||||||
void getFillPixels(bool *pixels, common::Point pt, int oldColor) const;
|
void getFillPixels(bool *pixels, common::Point pt, int oldColor) const;
|
||||||
|
|
||||||
@ -149,22 +153,12 @@ class TileSheetEditor: public studio::Editor {
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::String palettePath(const ox::String &palettePath) const;
|
ox::String palettePath(const ox::String &palettePath) const;
|
||||||
|
|
||||||
void drawTileSheet(const common::Vec2 &fbSize) noexcept;
|
|
||||||
|
|
||||||
void drawPalettePicker() noexcept;
|
|
||||||
|
|
||||||
void clickPixel(const common::Vec2 &paneSize, const common::Vec2 &clickPos) noexcept;
|
|
||||||
|
|
||||||
// slots
|
// slots
|
||||||
public:
|
public:
|
||||||
ox::Error colorSelected() noexcept;
|
ox::Error colorSelected() noexcept;
|
||||||
|
|
||||||
ox::Error setColorTable() noexcept;
|
ox::Error setColorTable() noexcept;
|
||||||
|
|
||||||
// slots
|
|
||||||
private:
|
|
||||||
ox::Error updateAfterClicked() noexcept;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user