Compare commits
1 Commits
ac1e34d4cd
...
release-d2
Author | SHA1 | Date | |
---|---|---|---|
13e256b3a9 |
10
Makefile
@ -15,11 +15,7 @@ PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}
|
|||||||
|
|
||||||
.PHONY: pkg-gba
|
.PHONY: pkg-gba
|
||||||
pkg-gba: build
|
pkg-gba: build
|
||||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME_CAP}
|
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
|
||||||
|
|
||||||
.PHONY: generate-studio-rsrc
|
|
||||||
generate-studio-rsrc:
|
|
||||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/nostalgia/studio/rsrc.json
|
|
||||||
|
|
||||||
.PHONY: build-player
|
.PHONY: build-player
|
||||||
build-player:
|
build-player:
|
||||||
@ -32,10 +28,10 @@ run-studio: build
|
|||||||
${PROJECT_STUDIO}
|
${PROJECT_STUDIO}
|
||||||
.PHONY: gba-run
|
.PHONY: gba-run
|
||||||
gba-run: pkg-gba
|
gba-run: pkg-gba
|
||||||
${MGBA} ${BC_VAR_PROJECT_NAME_CAP}.gba
|
${MGBA} ${BC_VAR_PROJECT_NAME}.gba
|
||||||
.PHONY: debug
|
.PHONY: debug
|
||||||
debug: build
|
debug: build
|
||||||
${BC_CMD_HOST_DEBUGGER} ${PROJECT_PLAYER} sample_project
|
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
|
||||||
.PHONY: debug-studio
|
.PHONY: debug-studio
|
||||||
debug-studio: build
|
debug-studio: build
|
||||||
${BC_CMD_HOST_DEBUGGER} ${PROJECT_STUDIO}
|
${BC_CMD_HOST_DEBUGGER} ${PROJECT_STUDIO}
|
||||||
|
@ -433,14 +433,14 @@ Error FileStoreTemplate<size_t>::resize() {
|
|||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
|
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
|
||||||
if (m_buffer->size() > size) {
|
if (m_buffer->size() > size) {
|
||||||
return ox::Error{1, "new buffer is too small for existing data"};
|
return ox::Error(1);
|
||||||
}
|
}
|
||||||
m_buffSize = static_cast<size_t>(size);
|
m_buffSize = static_cast<size_t>(size);
|
||||||
if (newBuff) {
|
if (newBuff) {
|
||||||
m_buffer = static_cast<Buffer*>(newBuff);
|
m_buffer = reinterpret_cast<Buffer*>(newBuff);
|
||||||
OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size)));
|
OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size)));
|
||||||
}
|
}
|
||||||
return {};
|
return ox::Error(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
|
27
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
@ -20,7 +20,7 @@
|
|||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
inline void fsBuffFree(char *buff) noexcept {
|
static inline void fsBuffFree(char *buff) noexcept {
|
||||||
safeDelete(buff);
|
safeDelete(buff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,11 +49,11 @@ class FileSystem {
|
|||||||
|
|
||||||
Result<Buffer> read(StringViewCR path) noexcept;
|
Result<Buffer> read(StringViewCR path) noexcept;
|
||||||
|
|
||||||
Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
|
inline Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
|
||||||
return readFilePath(path, buffer, buffSize);
|
return readFilePath(path, buffer, buffSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
|
inline Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
|
||||||
return readFileInode(inode, buffer, buffSize);
|
return readFileInode(inode, buffer, buffSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +69,8 @@ class FileSystem {
|
|||||||
* @param path
|
* @param path
|
||||||
* @param readStart
|
* @param readStart
|
||||||
* @param readSize
|
* @param readSize
|
||||||
* @param buff
|
* @param buffer
|
||||||
|
* @param size
|
||||||
* @return error or number of bytes read
|
* @return error or number of bytes read
|
||||||
*/
|
*/
|
||||||
Result<size_t> read(
|
Result<size_t> read(
|
||||||
@ -101,36 +102,36 @@ class FileSystem {
|
|||||||
|
|
||||||
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
|
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
|
||||||
|
|
||||||
Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
inline Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||||
return writeFilePath(path, buffer, size, fileType);
|
return writeFilePath(path, buffer, size, fileType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
inline Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
|
||||||
return writeFileInode(inode, buffer, size, fileType);
|
return writeFileInode(inode, buffer, size, fileType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<FileStat> stat(uint64_t inode) const noexcept {
|
inline Result<FileStat> stat(uint64_t inode) const noexcept {
|
||||||
return statInode(inode);
|
return statInode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<FileStat> stat(StringViewCR path) const noexcept {
|
inline Result<FileStat> stat(StringViewCR path) const noexcept {
|
||||||
return statPath(path);
|
return statPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<FileStat> stat(const FileAddress &addr) const noexcept;
|
Result<FileStat> stat(const FileAddress &addr) const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool exists(uint64_t inode) const noexcept {
|
inline bool exists(uint64_t inode) const noexcept {
|
||||||
return statInode(inode).ok();
|
return statInode(inode).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool exists(ox::StringView path) const noexcept {
|
inline bool exists(ox::StringView path) const noexcept {
|
||||||
return statPath(path).ok();
|
return statPath(path).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool exists(FileAddress const&addr) const noexcept {
|
inline bool exists(FileAddress const&addr) const noexcept {
|
||||||
return stat(addr).ok();
|
return stat(addr).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,11 +178,11 @@ class MemFS: public FileSystem {
|
|||||||
public:
|
public:
|
||||||
Result<const char*> directAccess(const FileAddress &addr) const noexcept;
|
Result<const char*> directAccess(const FileAddress &addr) const noexcept;
|
||||||
|
|
||||||
Result<const char*> directAccess(StringViewCR path) const noexcept {
|
inline Result<const char*> directAccess(StringViewCR path) const noexcept {
|
||||||
return directAccessPath(path);
|
return directAccessPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<const char*> directAccess(uint64_t inode) const noexcept {
|
inline Result<const char*> directAccess(uint64_t inode) const noexcept {
|
||||||
return directAccessInode(inode);
|
return directAccessInode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,4 @@
|
|||||||
# d2025.04.0
|
# d2025.02
|
||||||
|
|
||||||
* Add app icon for both window and file
|
|
||||||
* Fix selection clearing in TileSheet editor to work when clicking outside
|
|
||||||
image.
|
|
||||||
|
|
||||||
# d2025.02.1
|
|
||||||
|
|
||||||
* Fix closing tab with unsaved changes (a44c5acc4b)
|
|
||||||
|
|
||||||
# d2025.02.0
|
|
||||||
|
|
||||||
* Rename core namespace to gfx.
|
* Rename core namespace to gfx.
|
||||||
* Add PaletteV5 to accommodate namespace change.
|
* Add PaletteV5 to accommodate namespace change.
|
||||||
|
@ -1,269 +0,0 @@
|
|||||||
K1;e7ae945e-d6c5-4444-5738-be95b4e5937a;O1;net.drinkingtea.nostalgia.gfx.TileSheet;5;{
|
|
||||||
"bpp" : 4,
|
|
||||||
"defaultPalette" : "uuid://c79f21e2-f74f-4ad9-90ed-32b0ef7da6ed",
|
|
||||||
"subsheet" :
|
|
||||||
{
|
|
||||||
"columns" : 2,
|
|
||||||
"name" : "Root",
|
|
||||||
"pixels" :
|
|
||||||
[
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
3,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
],
|
|
||||||
"rows" : 2
|
|
||||||
}
|
|
||||||
}
|
|
@ -183,8 +183,8 @@ ox::Error TileSheetV4ToTileSheetV5Converter::convert(
|
|||||||
keel::Context&,
|
keel::Context&,
|
||||||
TileSheetV4 &src,
|
TileSheetV4 &src,
|
||||||
TileSheetV5 &dst) const noexcept {
|
TileSheetV5 &dst) const noexcept {
|
||||||
dst.bpp = src.bpp;
|
dst.bpp = src.bpp;
|
||||||
dst.idIt = src.idIt;
|
dst.idIt = src.idIt;
|
||||||
OX_RETURN_ERROR(src.defaultPalette.getPath().moveTo(dst.defaultPalette));
|
OX_RETURN_ERROR(src.defaultPalette.getPath().moveTo(dst.defaultPalette));
|
||||||
convertSubsheet(dst.bpp, src.subsheet, dst.subsheet);
|
convertSubsheet(dst.bpp, src.subsheet, dst.subsheet);
|
||||||
return {};
|
return {};
|
||||||
|
@ -96,7 +96,7 @@ TileSheetEditorImGui::TileSheetEditorImGui(studio::StudioContext &sctx, ox::Stri
|
|||||||
m_model{m_view.model()} {
|
m_model{m_view.model()} {
|
||||||
// connect signal/slots
|
// connect signal/slots
|
||||||
m_subsheetEditor.inputSubmitted.connect(this, &TileSheetEditorImGui::updateActiveSubsheet);
|
m_subsheetEditor.inputSubmitted.connect(this, &TileSheetEditorImGui::updateActiveSubsheet);
|
||||||
m_exportMenu.inputSubmitted.connect(this, &TileSheetEditorImGui::exportSubsheetToPng);
|
m_exportMenu.inputSubmitted.connect(this, &TileSheetEditorImGui::exportSubhseetToPng);
|
||||||
// load config
|
// load config
|
||||||
auto const&config = studio::readConfig<TileSheetEditorConfig>(
|
auto const&config = studio::readConfig<TileSheetEditorConfig>(
|
||||||
keelCtx(m_sctx), itemPath());
|
keelCtx(m_sctx), itemPath());
|
||||||
@ -397,7 +397,7 @@ void TileSheetEditorImGui::showSubsheetEditor() noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error TileSheetEditorImGui::exportSubsheetToPng(int const scale) const noexcept {
|
ox::Error TileSheetEditorImGui::exportSubhseetToPng(int const scale) const noexcept {
|
||||||
OX_REQUIRE(path, studio::saveFile({{"PNG", "png"}}));
|
OX_REQUIRE(path, studio::saveFile({{"PNG", "png"}}));
|
||||||
// subsheet to png
|
// subsheet to png
|
||||||
auto const&s = m_model.activeSubSheet();
|
auto const&s = m_model.activeSubSheet();
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <studio/editor.hpp>
|
#include <studio/editor.hpp>
|
||||||
#include <studio/filepickerpopup.hpp>
|
#include <studio/filepickerpopup.hpp>
|
||||||
|
|
||||||
|
#include "tilesheetpixelgrid.hpp"
|
||||||
#include "tilesheetpixels.hpp"
|
#include "tilesheetpixels.hpp"
|
||||||
#include "tilesheeteditorview.hpp"
|
#include "tilesheeteditorview.hpp"
|
||||||
|
|
||||||
@ -90,7 +91,7 @@ class TileSheetEditorImGui: public studio::Editor {
|
|||||||
private:
|
private:
|
||||||
void showSubsheetEditor() noexcept;
|
void showSubsheetEditor() noexcept;
|
||||||
|
|
||||||
ox::Error exportSubsheetToPng(int scale) const noexcept;
|
ox::Error exportSubhseetToPng(int scale) const noexcept;
|
||||||
|
|
||||||
void drawTileSheet(ox::Vec2 const&fbSize) noexcept;
|
void drawTileSheet(ox::Vec2 const&fbSize) noexcept;
|
||||||
|
|
||||||
|
@ -263,13 +263,7 @@ ox::Error TileSheetEditorModel::rotateRight() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept {
|
void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept {
|
||||||
auto const &ss = activeSubSheet();
|
m_selection.emplace(sel);
|
||||||
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;
|
m_updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +134,7 @@ ox::Error run(
|
|||||||
return ox::Error{1, "Please provide path to project directory or OxFS file."};
|
return ox::Error{1, "Please provide path to project directory or OxFS file."};
|
||||||
}
|
}
|
||||||
auto const path = args[1];
|
auto const path = args[1];
|
||||||
OX_REQUIRE_M(tctx, turbine::init(path, project));
|
OX_REQUIRE_M(fs, keel::loadRomFs(path));
|
||||||
|
OX_REQUIRE_M(tctx, turbine::init(std::move(fs), project));
|
||||||
return runTileSheetSetTest(*tctx);
|
return runTileSheetSetTest(*tctx);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
add_executable(
|
add_executable(NostalgiaStudio WIN32 MACOSX_BUNDLE)
|
||||||
NostalgiaStudio WIN32 MACOSX_BUNDLE
|
|
||||||
ns.rc
|
|
||||||
icondata.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
NostalgiaStudio
|
NostalgiaStudio
|
||||||
@ -15,7 +11,7 @@ target_link_libraries(
|
|||||||
|
|
||||||
target_compile_definitions(
|
target_compile_definitions(
|
||||||
NostalgiaStudio PUBLIC
|
NostalgiaStudio PUBLIC
|
||||||
OLYMPIC_APP_VERSION="dev build"
|
OLYMPIC_APP_VERSION="d2025.02.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
|
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>dev build</string>
|
<string>d2025.02.0</string>
|
||||||
|
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>12.0.0</string>
|
<string>12.0.0</string>
|
||||||
|
@ -1 +0,0 @@
|
|||||||
IDI_ICON1 ICON DISCARDABLE "ns_logo.ico"
|
|
Before Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 851 B |
Before Width: | Height: | Size: 134 B |
Before Width: | Height: | Size: 149 B |
Before Width: | Height: | Size: 275 B |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 334 B |
Before Width: | Height: | Size: 163 B |
@ -1,39 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -68,7 +68,7 @@ constexpr auto makeLoader(Context &ctx) {
|
|||||||
if (!beginsWith(assetId, "/")) {
|
if (!beginsWith(assetId, "/")) {
|
||||||
auto const p = ctx.uuidToPath.at(assetId);
|
auto const p = ctx.uuidToPath.at(assetId);
|
||||||
if (p.error) {
|
if (p.error) {
|
||||||
oxErrf("Could not find asset: {}\n", assetId);
|
oxErrf("Could not find asset: {}", assetId);
|
||||||
return ox::Error{1, "Asset ID not found"};
|
return ox::Error{1, "Asset ID not found"};
|
||||||
}
|
}
|
||||||
assetId = *p.value;
|
assetId = *p.value;
|
||||||
|
@ -32,15 +32,11 @@ static void keyEventHandler(turbine::Context &ctx, turbine::Key key, bool down)
|
|||||||
sctx->ui.handleKeyEvent(key, down);
|
sctx->ui.handleKeyEvent(key, down);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
ox::Vector<ox::SpanView<uint8_t>> WindowIcons() noexcept;
|
|
||||||
|
|
||||||
static ox::Error runApp(
|
static ox::Error runApp(
|
||||||
ox::StringViewCR appName,
|
ox::StringViewCR appName,
|
||||||
ox::StringViewCR projectDataDir,
|
ox::StringViewCR projectDataDir,
|
||||||
ox::UPtr<ox::FileSystem> &&fs) noexcept {
|
ox::UPtr<ox::FileSystem> &&fs) noexcept {
|
||||||
OX_REQUIRE_M(ctx, turbine::init(std::move(fs), appName));
|
OX_REQUIRE_M(ctx, turbine::init(std::move(fs), appName));
|
||||||
oxLogError(turbine::setWindowIcon(*ctx, WindowIcons()));
|
|
||||||
turbine::setWindowTitle(*ctx, keelCtx(*ctx).appName);
|
turbine::setWindowTitle(*ctx, keelCtx(*ctx).appName);
|
||||||
turbine::setKeyEventHandler(*ctx, keyEventHandler);
|
turbine::setKeyEventHandler(*ctx, keyEventHandler);
|
||||||
turbine::setRefreshWithin(*ctx, 0);
|
turbine::setRefreshWithin(*ctx, 0);
|
||||||
|
@ -254,7 +254,6 @@ void StudioUI::drawTabs() noexcept {
|
|||||||
if (!open) {
|
if (!open) {
|
||||||
if (e->unsavedChanges()) {
|
if (e->unsavedChanges()) {
|
||||||
m_closeFileConfirm.open();
|
m_closeFileConfirm.open();
|
||||||
++it;
|
|
||||||
} else {
|
} else {
|
||||||
e->close();
|
e->close();
|
||||||
if (m_activeEditor == (*it).get()) {
|
if (m_activeEditor == (*it).get()) {
|
||||||
|
@ -26,22 +26,20 @@ void removeDrawer(Context &ctx, Drawer *cd) noexcept;
|
|||||||
|
|
||||||
ox::Error initGfx(Context &ctx) 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 setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept;
|
||||||
|
|
||||||
void focusWindow(Context &ctx) noexcept;
|
void focusWindow(Context &ctx) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
int getScreenWidth(Context const &ctx) noexcept;
|
int getScreenWidth(Context &ctx) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
int getScreenHeight(Context const &ctx) noexcept;
|
int getScreenHeight(Context &ctx) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::Size getScreenSize(Context const &ctx) noexcept;
|
ox::Size getScreenSize(Context &ctx) noexcept;
|
||||||
|
|
||||||
ox::Bounds getWindowBounds(Context const &ctx) noexcept;
|
ox::Bounds getWindowBounds(Context &ctx) noexcept;
|
||||||
|
|
||||||
ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) 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 {
|
void setWindowTitle(Context&, ox::StringViewCR) noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
int getScreenWidth(Context const&) noexcept {
|
int getScreenWidth(Context&) noexcept {
|
||||||
return 240;
|
return 240;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getScreenHeight(Context const&) noexcept {
|
int getScreenHeight(Context&) noexcept {
|
||||||
return 160;
|
return 160;
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Size getScreenSize(Context const&) noexcept {
|
ox::Size getScreenSize(Context&) noexcept {
|
||||||
return {240, 160};
|
return {240, 160};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Bounds getWindowBounds(Context const&) noexcept {
|
ox::Bounds getWindowBounds(Context&) noexcept {
|
||||||
return {0, 0, 240, 160};
|
return {0, 0, 240, 160};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,5 +21,4 @@ target_link_libraries(
|
|||||||
glad
|
glad
|
||||||
glfw
|
glfw
|
||||||
imgui
|
imgui
|
||||||
lodepng
|
|
||||||
)
|
)
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <lodepng.h>
|
|
||||||
#if TURBINE_USE_IMGUI
|
#if TURBINE_USE_IMGUI
|
||||||
#include <imgui_impl_glfw.h>
|
#include <imgui_impl_glfw.h>
|
||||||
#include <imgui_impl_opengl3.h>
|
#include <imgui_impl_opengl3.h>
|
||||||
@ -229,39 +228,6 @@ ox::Error initGfx(Context &ctx) noexcept {
|
|||||||
return {};
|
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 {
|
void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept {
|
||||||
auto cstr = ox_malloca(title.bytes() + 1, char);
|
auto cstr = ox_malloca(title.bytes() + 1, char);
|
||||||
ox::strncpy(cstr.get(), title.data(), title.bytes());
|
ox::strncpy(cstr.get(), title.data(), title.bytes());
|
||||||
@ -272,25 +238,25 @@ void focusWindow(Context &ctx) noexcept {
|
|||||||
glfwFocusWindow(ctx.window);
|
glfwFocusWindow(ctx.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getScreenWidth(Context const &ctx) noexcept {
|
int getScreenWidth(Context &ctx) noexcept {
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
glfwGetFramebufferSize(ctx.window, &w, &h);
|
glfwGetFramebufferSize(ctx.window, &w, &h);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getScreenHeight(Context const &ctx) noexcept {
|
int getScreenHeight(Context &ctx) noexcept {
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
glfwGetFramebufferSize(ctx.window, &w, &h);
|
glfwGetFramebufferSize(ctx.window, &w, &h);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Size getScreenSize(Context const &ctx) noexcept {
|
ox::Size getScreenSize(Context &ctx) noexcept {
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
glfwGetFramebufferSize(ctx.window, &w, &h);
|
glfwGetFramebufferSize(ctx.window, &w, &h);
|
||||||
return {w, h};
|
return {w, h};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Bounds getWindowBounds(Context const &ctx) noexcept {
|
ox::Bounds getWindowBounds(Context &ctx) noexcept {
|
||||||
ox::Bounds bnds;
|
ox::Bounds bnds;
|
||||||
glfwGetWindowPos(ctx.window, &bnds.x, &bnds.y);
|
glfwGetWindowPos(ctx.window, &bnds.x, &bnds.y);
|
||||||
glfwGetWindowSize(ctx.window, &bnds.width, &bnds.height);
|
glfwGetWindowSize(ctx.window, &bnds.width, &bnds.height);
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright 2016 - 2025 gary@drinkingtea.net
|
|
||||||
#
|
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
#
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import json
|
|
||||||
import pathlib
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def write_txt_file(path: str, txt: str):
|
|
||||||
with open(path, "w") as f:
|
|
||||||
f.write(txt)
|
|
||||||
print(f'Wrote {path}')
|
|
||||||
|
|
||||||
|
|
||||||
def file_to_hex(path: str, line_prefix: str) -> tuple[str, int]:
|
|
||||||
with open(path, 'rb') as f:
|
|
||||||
out = line_prefix
|
|
||||||
data = f.read()
|
|
||||||
i = 1
|
|
||||||
for b in data:
|
|
||||||
out += f"{b:#0{4}x},"
|
|
||||||
if i % 10 == 0:
|
|
||||||
out += '\n\t'
|
|
||||||
else:
|
|
||||||
out += ' '
|
|
||||||
i += 1
|
|
||||||
return out[:-1], len(data)
|
|
||||||
|
|
||||||
|
|
||||||
def file_to_cpp(path: str, cpp_name: str) -> tuple[str, str]:
|
|
||||||
cpp = ''
|
|
||||||
hpp = ''
|
|
||||||
data, data_len = file_to_hex(path, "\t")
|
|
||||||
cpp += f'\nstatic constexpr ox::Array<uint8_t, {data_len}> {cpp_name}Data {{\n{data}\n}};\n'
|
|
||||||
cpp += f'\nox::SpanView<uint8_t> {cpp_name}() noexcept {{ return {cpp_name}Data; }}\n'
|
|
||||||
hpp += f'\n[[nodiscard]]\nox::SpanView<uint8_t> {cpp_name}() noexcept;\n'
|
|
||||||
return cpp, hpp
|
|
||||||
|
|
||||||
|
|
||||||
def proc_rsrc_file(rsrc_path: str):# Open and read the JSON file
|
|
||||||
with open(rsrc_path, 'r') as file:
|
|
||||||
data = json.load(file)
|
|
||||||
base_path = pathlib.Path(rsrc_path).parent.absolute()
|
|
||||||
if 'all_files' in data:
|
|
||||||
all_files = data['all_files']
|
|
||||||
else:
|
|
||||||
all_files = None
|
|
||||||
if 'namespace' in data:
|
|
||||||
namespace = data['namespace']
|
|
||||||
else:
|
|
||||||
namespace = ''
|
|
||||||
if len(namespace) > 0:
|
|
||||||
push_ns = f'namespace {namespace} {{\n'
|
|
||||||
pop_ns = '\n}\n'
|
|
||||||
else:
|
|
||||||
push_ns = ''
|
|
||||||
pop_ns = ''
|
|
||||||
cpp = '// Generated\n\n#include <ox/std/array.hpp>\n'
|
|
||||||
cpp += '#include <ox/std/span.hpp>\n\n'
|
|
||||||
hpp = '// Generated\n\n#include <ox/std/span.hpp>\n\n'
|
|
||||||
cpp += push_ns
|
|
||||||
hpp += push_ns
|
|
||||||
all_files_func_decl = ''
|
|
||||||
all_files_func = ''
|
|
||||||
if all_files is not None:
|
|
||||||
all_files_func_decl += f'\n[[nodiscard]]\nox::Vector<ox::SpanView<uint8_t>> {all_files}() noexcept;\n'
|
|
||||||
all_files_func += f'\nox::Vector<ox::SpanView<uint8_t>> {all_files}() noexcept {{\n\treturn {{\n'
|
|
||||||
for f in data['files']:
|
|
||||||
if 'path' not in f:
|
|
||||||
print('src file path missing', file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
path = f['path']
|
|
||||||
if 'cpp_name' not in f:
|
|
||||||
print('var name missing', file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
cpp_name = f['cpp_name']
|
|
||||||
c, h = file_to_cpp(os.path.join(base_path, path), cpp_name)
|
|
||||||
cpp += c
|
|
||||||
if len(h) > 0:
|
|
||||||
hpp += h
|
|
||||||
if all_files is not None:
|
|
||||||
all_files_func += f'\t\t{cpp_name}(),\n'
|
|
||||||
cpp += all_files_func + '\t};\n}\n'
|
|
||||||
hpp += all_files_func_decl
|
|
||||||
cpp += pop_ns
|
|
||||||
hpp += pop_ns
|
|
||||||
write_txt_file(os.path.join(base_path, data['cpp']), cpp)
|
|
||||||
if 'hpp' in data:
|
|
||||||
write_txt_file(os.path.join(base_path, data['hpp']), hpp)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('--rsrc', help='path to file', required=True)
|
|
||||||
args = parser.parse_args()
|
|
||||||
proc_rsrc_file(args.rsrc)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
try:
|
|
||||||
err = main()
|
|
||||||
sys.exit(err)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
sys.exit(1)
|
|