Merge commit '09b4a705a9251d54e797eb75db1f3d4687829a24'
@ -183,8 +183,8 @@ ox::Error TileSheetV4ToTileSheetV5Converter::convert(
|
||||
keel::Context&,
|
||||
TileSheetV4 &src,
|
||||
TileSheetV5 &dst) const noexcept {
|
||||
dst.bpp = src.bpp;
|
||||
dst.idIt = src.idIt;
|
||||
dst.bpp = src.bpp;
|
||||
dst.idIt = src.idIt;
|
||||
OX_RETURN_ERROR(src.defaultPalette.getPath().moveTo(dst.defaultPalette));
|
||||
convertSubsheet(dst.bpp, src.subsheet, dst.subsheet);
|
||||
return {};
|
||||
|
@ -96,7 +96,7 @@ TileSheetEditorImGui::TileSheetEditorImGui(studio::StudioContext &sctx, ox::Stri
|
||||
m_model{m_view.model()} {
|
||||
// connect signal/slots
|
||||
m_subsheetEditor.inputSubmitted.connect(this, &TileSheetEditorImGui::updateActiveSubsheet);
|
||||
m_exportMenu.inputSubmitted.connect(this, &TileSheetEditorImGui::exportSubhseetToPng);
|
||||
m_exportMenu.inputSubmitted.connect(this, &TileSheetEditorImGui::exportSubsheetToPng);
|
||||
// load config
|
||||
auto const&config = studio::readConfig<TileSheetEditorConfig>(
|
||||
keelCtx(m_sctx), itemPath());
|
||||
@ -397,7 +397,7 @@ void TileSheetEditorImGui::showSubsheetEditor() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error TileSheetEditorImGui::exportSubhseetToPng(int const scale) const noexcept {
|
||||
ox::Error TileSheetEditorImGui::exportSubsheetToPng(int const scale) const noexcept {
|
||||
OX_REQUIRE(path, studio::saveFile({{"PNG", "png"}}));
|
||||
// subsheet to png
|
||||
auto const&s = m_model.activeSubSheet();
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <studio/editor.hpp>
|
||||
#include <studio/filepickerpopup.hpp>
|
||||
|
||||
#include "tilesheetpixelgrid.hpp"
|
||||
#include "tilesheetpixels.hpp"
|
||||
#include "tilesheeteditorview.hpp"
|
||||
|
||||
@ -91,7 +90,7 @@ class TileSheetEditorImGui: public studio::Editor {
|
||||
private:
|
||||
void showSubsheetEditor() noexcept;
|
||||
|
||||
ox::Error exportSubhseetToPng(int scale) const noexcept;
|
||||
ox::Error exportSubsheetToPng(int scale) const noexcept;
|
||||
|
||||
void drawTileSheet(ox::Vec2 const&fbSize) noexcept;
|
||||
|
||||
@ -99,8 +98,6 @@ class TileSheetEditorImGui: public studio::Editor {
|
||||
|
||||
ox::Error updateActiveSubsheet(ox::StringView const&name, int cols, int rows) noexcept;
|
||||
|
||||
// slots
|
||||
private:
|
||||
void setActiveSubsheet(TileSheet::SubSheetIdx path) noexcept;
|
||||
|
||||
};
|
||||
|
@ -120,7 +120,7 @@ bool TileSheetEditorModel::acceptsClipboardPayload() const noexcept {
|
||||
return cb.ok();
|
||||
}
|
||||
|
||||
ox::StringView TileSheetEditorModel::palPath() const noexcept {
|
||||
ox::String const &TileSheetEditorModel::palPath() const & noexcept {
|
||||
return m_palPath;
|
||||
}
|
||||
|
||||
@ -263,7 +263,13 @@ ox::Error TileSheetEditorModel::rotateRight() noexcept {
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept {
|
||||
m_selection.emplace(sel);
|
||||
auto const &ss = activeSubSheet();
|
||||
if (sel.a.x < ss.columns * TileWidth && sel.a.y < ss.rows * TileHeight) {
|
||||
m_selection.emplace(sel);
|
||||
} else {
|
||||
m_selTracker.finishSelection();
|
||||
m_selection.reset();
|
||||
}
|
||||
m_updated = true;
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
constexpr Palette const&pal() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::StringView palPath() const noexcept;
|
||||
ox::String const &palPath() const & noexcept;
|
||||
|
||||
ox::Error setPalette(ox::StringViewCR path) noexcept;
|
||||
|
||||
|
8
deps/nostalgia/src/nostalgia/player/app.cpp
vendored
@ -64,13 +64,10 @@ static void testKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool d
|
||||
|
||||
[[maybe_unused]]
|
||||
static ox::Error runTest(turbine::Context &tctx) {
|
||||
constexpr ox::StringView TileSheetAddr{"/TileSheets/Charset.nts"};
|
||||
constexpr ox::StringView PaletteAddr{"/Palettes/Chester.npal"};
|
||||
OX_REQUIRE_M(cctx, gfx::init(tctx));
|
||||
turbine::setApplicationData(tctx, cctx.get());
|
||||
OX_REQUIRE(tsStat, turbine::rom(tctx)->stat(PaletteAddr));
|
||||
OX_RETURN_ERROR(gfx::loadSpriteTileSheet(*cctx, TileSheetAddr));
|
||||
OX_RETURN_ERROR(gfx::loadSpritePalette(*cctx, PaletteAddr));
|
||||
OX_RETURN_ERROR(gfx::loadSpriteTileSheet(*cctx, "/TileSheets/Charset.nts"));
|
||||
OX_RETURN_ERROR(gfx::loadSpritePalette(*cctx, "/Palettes/Chester.npal"));
|
||||
OX_RETURN_ERROR(gfx::initConsole(*cctx));
|
||||
gfx::puts(*cctx, 10, 9, "DOPENESS!!!");
|
||||
turbine::setUpdateHandler(tctx, testUpdateHandler);
|
||||
@ -86,7 +83,6 @@ static ox::Error runTileSheetSetTest(turbine::Context &tctx) {
|
||||
constexpr ox::StringView PaletteAddr{"/Palettes/Charset.npal"};
|
||||
OX_REQUIRE_M(cctx, gfx::init(tctx));
|
||||
turbine::setApplicationData(tctx, cctx.get());
|
||||
OX_REQUIRE(tsStat, turbine::rom(tctx)->stat(PaletteAddr));
|
||||
gfx::TileSheetSet const set{
|
||||
.bpp = 4,
|
||||
.entries = {
|
||||
|
@ -1,4 +1,8 @@
|
||||
add_executable(NostalgiaStudio WIN32 MACOSX_BUNDLE)
|
||||
add_executable(
|
||||
NostalgiaStudio WIN32 MACOSX_BUNDLE
|
||||
ns.rc
|
||||
icondata.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
NostalgiaStudio
|
||||
|
1495
deps/nostalgia/src/nostalgia/studio/icondata.cpp
vendored
Normal file
1
deps/nostalgia/src/nostalgia/studio/ns.rc
vendored
Normal file
@ -0,0 +1 @@
|
||||
IDI_ICON1 ICON DISCARDABLE "ns_logo.ico"
|
BIN
deps/nostalgia/src/nostalgia/studio/ns_logo.ico
vendored
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
deps/nostalgia/src/nostalgia/studio/ns_logo1080.png
vendored
Normal file
After Width: | Height: | Size: 851 B |
BIN
deps/nostalgia/src/nostalgia/studio/ns_logo16.png
vendored
Normal file
After Width: | Height: | Size: 134 B |
BIN
deps/nostalgia/src/nostalgia/studio/ns_logo24.png
vendored
Normal file
After Width: | Height: | Size: 149 B |
BIN
deps/nostalgia/src/nostalgia/studio/ns_logo264.png
vendored
Normal file
After Width: | Height: | Size: 275 B |
BIN
deps/nostalgia/src/nostalgia/studio/ns_logo32.png
vendored
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
deps/nostalgia/src/nostalgia/studio/ns_logo40.png
vendored
Normal file
After Width: | Height: | Size: 334 B |
BIN
deps/nostalgia/src/nostalgia/studio/ns_logo48.png
vendored
Normal file
After Width: | Height: | Size: 163 B |
39
deps/nostalgia/src/nostalgia/studio/rsrc.json
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"cpp": "icondata.cpp",
|
||||
"namespace": "studio",
|
||||
"all_files": "WindowIcons",
|
||||
"files": [
|
||||
{
|
||||
"path": "ns_logo16.png",
|
||||
"cpp_name": "WindowIcon16"
|
||||
},
|
||||
{
|
||||
"path": "ns_logo24.png",
|
||||
"cpp_name": "WindowIcon24"
|
||||
},
|
||||
{
|
||||
"path": "ns_logo32.png",
|
||||
"cpp_name": "WindowIcon32"
|
||||
},
|
||||
{
|
||||
"path": "ns_logo40.png",
|
||||
"cpp_name": "WindowIcon40"
|
||||
},
|
||||
{
|
||||
"path": "ns_logo48.png",
|
||||
"cpp_name": "WindowIcon48"
|
||||
},
|
||||
{
|
||||
"path": "ns_logo128.png",
|
||||
"cpp_name": "WindowIcon128"
|
||||
},
|
||||
{
|
||||
"path": "ns_logo264.png",
|
||||
"cpp_name": "WindowIcon264"
|
||||
},
|
||||
{
|
||||
"path": "ns_logo1080.png",
|
||||
"cpp_name": "WindowIcon1080"
|
||||
}
|
||||
]
|
||||
}
|
@ -32,11 +32,15 @@ static void keyEventHandler(turbine::Context &ctx, turbine::Key key, bool down)
|
||||
sctx->ui.handleKeyEvent(key, down);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Vector<ox::SpanView<uint8_t>> WindowIcons() noexcept;
|
||||
|
||||
static ox::Error runApp(
|
||||
ox::StringViewCR appName,
|
||||
ox::StringViewCR projectDataDir,
|
||||
ox::UPtr<ox::FileSystem> &&fs) noexcept {
|
||||
OX_REQUIRE_M(ctx, turbine::init(std::move(fs), appName));
|
||||
oxLogError(turbine::setWindowIcon(*ctx, WindowIcons()));
|
||||
turbine::setWindowTitle(*ctx, keelCtx(*ctx).appName);
|
||||
turbine::setKeyEventHandler(*ctx, keyEventHandler);
|
||||
turbine::setRefreshWithin(*ctx, 0);
|
||||
|
@ -71,12 +71,6 @@ class SelectionTracker {
|
||||
return m_selectionOngoing;
|
||||
}
|
||||
|
||||
constexpr void startSelection(ox::Point cursor) noexcept {
|
||||
m_pointA = cursor;
|
||||
m_pointB = cursor;
|
||||
m_selectionOngoing = true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param cursor
|
||||
|
@ -26,20 +26,22 @@ void removeDrawer(Context &ctx, Drawer *cd) noexcept;
|
||||
|
||||
ox::Error initGfx(Context &ctx) noexcept;
|
||||
|
||||
ox::Error setWindowIcon(Context &ctx, ox::SpanView<ox::SpanView<uint8_t>> const &iconPngs) noexcept;
|
||||
|
||||
void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept;
|
||||
|
||||
void focusWindow(Context &ctx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
int getScreenWidth(Context &ctx) noexcept;
|
||||
int getScreenWidth(Context const &ctx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
int getScreenHeight(Context &ctx) noexcept;
|
||||
int getScreenHeight(Context const &ctx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Size getScreenSize(Context &ctx) noexcept;
|
||||
ox::Size getScreenSize(Context const &ctx) noexcept;
|
||||
|
||||
ox::Bounds getWindowBounds(Context &ctx) noexcept;
|
||||
ox::Bounds getWindowBounds(Context const &ctx) noexcept;
|
||||
|
||||
ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept;
|
||||
|
||||
|
@ -27,19 +27,19 @@ ox::Error initGfx(Context&) noexcept {
|
||||
void setWindowTitle(Context&, ox::StringViewCR) noexcept {
|
||||
}
|
||||
|
||||
int getScreenWidth(Context&) noexcept {
|
||||
int getScreenWidth(Context const&) noexcept {
|
||||
return 240;
|
||||
}
|
||||
|
||||
int getScreenHeight(Context&) noexcept {
|
||||
int getScreenHeight(Context const&) noexcept {
|
||||
return 160;
|
||||
}
|
||||
|
||||
ox::Size getScreenSize(Context&) noexcept {
|
||||
ox::Size getScreenSize(Context const&) noexcept {
|
||||
return {240, 160};
|
||||
}
|
||||
|
||||
ox::Bounds getWindowBounds(Context&) noexcept {
|
||||
ox::Bounds getWindowBounds(Context const&) noexcept {
|
||||
return {0, 0, 240, 160};
|
||||
}
|
||||
|
||||
|
@ -21,4 +21,5 @@ target_link_libraries(
|
||||
glad
|
||||
glfw
|
||||
imgui
|
||||
lodepng
|
||||
)
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <lodepng.h>
|
||||
#if TURBINE_USE_IMGUI
|
||||
#include <imgui_impl_glfw.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
@ -228,6 +229,39 @@ ox::Error initGfx(Context &ctx) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
struct IconData {
|
||||
std::vector<uint8_t> pixels;
|
||||
int w{}, h{};
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
static ox::Result<IconData> toGlfwImgPixels(ox::SpanView<uint8_t> const &iconPng) noexcept {
|
||||
ox::Result<IconData> out;
|
||||
unsigned w{}, h{};
|
||||
if (lodepng::decode(out.value.pixels, w, h, iconPng.data(), iconPng.size())) {
|
||||
return ox::Error{1, "unable to decode window icon PNG data"};
|
||||
}
|
||||
out.value.w = static_cast<int>(w);
|
||||
out.value.h = static_cast<int>(h);
|
||||
return out;
|
||||
}
|
||||
|
||||
ox::Error setWindowIcon(Context &ctx, ox::SpanView<ox::SpanView<uint8_t>> const &iconPngs) noexcept {
|
||||
ox::Vector<IconData, 8> src;
|
||||
ox::Vector<GLFWimage, 8> imgs;
|
||||
for (auto const &iconPng : iconPngs) {
|
||||
OX_RETURN_ERROR(toGlfwImgPixels(iconPng).moveTo(src.emplace_back()));
|
||||
auto &icon = *src.back().unwrap();
|
||||
imgs.emplace_back(GLFWimage{
|
||||
.width = icon.w,
|
||||
.height = icon.h,
|
||||
.pixels = icon.pixels.data(),
|
||||
});
|
||||
}
|
||||
glfwSetWindowIcon(ctx.window, static_cast<int>(imgs.size()), imgs.data());
|
||||
return {};
|
||||
}
|
||||
|
||||
void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept {
|
||||
auto cstr = ox_malloca(title.bytes() + 1, char);
|
||||
ox::strncpy(cstr.get(), title.data(), title.bytes());
|
||||
@ -238,25 +272,25 @@ void focusWindow(Context &ctx) noexcept {
|
||||
glfwFocusWindow(ctx.window);
|
||||
}
|
||||
|
||||
int getScreenWidth(Context &ctx) noexcept {
|
||||
int getScreenWidth(Context const &ctx) noexcept {
|
||||
int w = 0, h = 0;
|
||||
glfwGetFramebufferSize(ctx.window, &w, &h);
|
||||
return w;
|
||||
}
|
||||
|
||||
int getScreenHeight(Context &ctx) noexcept {
|
||||
int getScreenHeight(Context const &ctx) noexcept {
|
||||
int w = 0, h = 0;
|
||||
glfwGetFramebufferSize(ctx.window, &w, &h);
|
||||
return h;
|
||||
}
|
||||
|
||||
ox::Size getScreenSize(Context &ctx) noexcept {
|
||||
ox::Size getScreenSize(Context const &ctx) noexcept {
|
||||
int w = 0, h = 0;
|
||||
glfwGetFramebufferSize(ctx.window, &w, &h);
|
||||
return {w, h};
|
||||
}
|
||||
|
||||
ox::Bounds getWindowBounds(Context &ctx) noexcept {
|
||||
ox::Bounds getWindowBounds(Context const &ctx) noexcept {
|
||||
ox::Bounds bnds;
|
||||
glfwGetWindowPos(ctx.window, &bnds.x, &bnds.y);
|
||||
glfwGetWindowSize(ctx.window, &bnds.width, &bnds.height);
|
||||
|