[nostalgia/studio] Add export option to tilesheet editor
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include <imgui.h>
|
||||
#include <lodepng.h>
|
||||
|
||||
#include <nostalgia/core/media.hpp>
|
||||
#include <nostalgia/geo/point.hpp>
|
||||
@@ -11,10 +12,29 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
static ox::Error toPngFile(const ox::String &path, const TileSheet::SubSheet &s, const Palette &pal, int8_t bpp) noexcept {
|
||||
ox::Vector<uint8_t> pixels;
|
||||
s.readPixelsTo(&pixels, bpp);
|
||||
const unsigned rows = s.rows == -1 ? pixels.size() / PixelsPerTile : static_cast<unsigned>(s.rows);
|
||||
const unsigned cols = s.columns == -1 ? 1 : static_cast<unsigned>(s.columns);
|
||||
const auto width = cols * TileWidth;
|
||||
const auto height = rows * TileHeight;
|
||||
ox::Vector<unsigned char> outData(pixels.size() * 3);
|
||||
for (auto idx = 0; const auto colorIdx : pixels) {
|
||||
const auto pt = idxToPt(idx, static_cast<int>(cols));
|
||||
const auto i = static_cast<unsigned>(pt.y * static_cast<int>(width) + pt.x) * 3;
|
||||
const auto c = pal.colors[colorIdx];
|
||||
outData[i + 0] = (red32(c));
|
||||
outData[i + 1] = (green32(c));
|
||||
outData[i + 2] = (blue32(c));
|
||||
++idx;
|
||||
}
|
||||
return OxError(lodepng_encode24_file(path.c_str(), outData.data(), width, height));
|
||||
}
|
||||
TileSheetEditorImGui::TileSheetEditorImGui(Context *ctx, const ox::String &path): m_tileSheetEditor(ctx, path) {
|
||||
m_ctx = ctx;
|
||||
m_itemPath = path;
|
||||
const auto lastSlash = std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset();
|
||||
const auto lastSlash = ox::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset();
|
||||
m_itemName = m_itemPath.substr(lastSlash + 1);
|
||||
// init palette idx
|
||||
const auto &palPath = model()->palPath();
|
||||
@@ -41,6 +61,7 @@ const ox::String &TileSheetEditorImGui::itemDisplayName() const noexcept {
|
||||
}
|
||||
|
||||
void TileSheetEditorImGui::exportFile() {
|
||||
exportSubhseetToPng();
|
||||
}
|
||||
|
||||
void TileSheetEditorImGui::cut() {
|
||||
@@ -125,9 +146,13 @@ void TileSheetEditorImGui::draw(core::Context*) noexcept {
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Edit", ImVec2(36, btnHeight))) {
|
||||
if (ImGui::Button("Edit", ImVec2(51, btnHeight))) {
|
||||
showSubsheetEditor();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Export", ImVec2(51, btnHeight))) {
|
||||
exportSubhseetToPng();
|
||||
}
|
||||
TileSheet::SubSheetIdx path;
|
||||
static constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
||||
if (ImGui::BeginTable("Subsheets", 3, flags)) {
|
||||
@@ -214,6 +239,21 @@ void TileSheetEditorImGui::showSubsheetEditor() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void TileSheetEditorImGui::exportSubhseetToPng() noexcept {
|
||||
auto [path, err] = studio::saveFile({{"PNG", "png"}});
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
// subsheet to png
|
||||
const auto &img = model()->img();
|
||||
const auto &s = *model()->activeSubSheet();
|
||||
const auto &pal = model()->pal();
|
||||
err = toPngFile(path, s, pal, img.bpp);
|
||||
if (err) {
|
||||
oxErrorf("Tilesheet export failed: {}", toStr(err));
|
||||
}
|
||||
}
|
||||
|
||||
void TileSheetEditorImGui::drawTileSheet(const geo::Vec2 &fbSize) noexcept {
|
||||
const auto winPos = ImGui::GetWindowPos();
|
||||
const auto fbSizei = geo::Size(static_cast<int>(fbSize.x), static_cast<int>(fbSize.y));
|
||||
@@ -230,10 +270,10 @@ void TileSheetEditorImGui::drawTileSheet(const geo::Vec2 &fbSize) noexcept {
|
||||
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));
|
||||
reinterpret_cast<void*>(m_framebuffer.color.id),
|
||||
static_cast<ImVec2>(fbSize),
|
||||
ImVec2(0, 1),
|
||||
ImVec2(1, 0));
|
||||
// handle input, this must come after drawing
|
||||
const auto &io = ImGui::GetIO();
|
||||
const auto mousePos = geo::Vec2(io.MousePos);
|
||||
@@ -242,7 +282,7 @@ void TileSheetEditorImGui::drawTileSheet(const geo::Vec2 &fbSize) noexcept {
|
||||
const auto wheelh = io.MouseWheelH;
|
||||
if (wheel != 0) {
|
||||
const auto zoomMod = ox::defines::OS == ox::OS::Darwin ?
|
||||
io.KeySuper : core::buttonDown(m_ctx, core::Key::Mod_Ctrl);
|
||||
io.KeySuper : core::buttonDown(m_ctx, core::Key::Mod_Ctrl);
|
||||
m_tileSheetEditor.scrollV(fbSize, wheel, zoomMod);
|
||||
}
|
||||
if (wheelh != 0) {
|
||||
|
||||
Reference in New Issue
Block a user