[studio,nostalgia/gfx] Add system for adding sub-commands in Modules, add export-tilesheet command
All checks were successful
Build / build (push) Successful in 1m16s

This commit is contained in:
2025-07-24 01:25:32 -05:00
parent fdf39d1a25
commit 0c866d1b96
15 changed files with 326 additions and 17 deletions

View File

@@ -10,6 +10,9 @@
namespace studio {
[[nodiscard]]
ox::Vector<Module const*> const &modules() noexcept;
void registerModule(Module const*) noexcept;
}

View File

@@ -2,15 +2,18 @@
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <complex>
#include <ctime>
#include <ox/logconn/logconn.hpp>
#include <ox/std/trace.hpp>
#include <ox/std/uuid.hpp>
#include <keel/media.hpp>
#include <keel/keel.hpp>
#include <turbine/turbine.hpp>
#include <studio/context.hpp>
#include <studioapp/studioapp.hpp>
#include "studioui.hpp"
namespace studio {
@@ -40,7 +43,7 @@ static void mouseButtonEventHandler(turbine::Context &ctx, int const btn, bool c
[[nodiscard]]
ox::Vector<ox::SpanView<uint8_t>> WindowIcons() noexcept;
static ox::Error runApp(
static ox::Error runStudio(
ox::StringViewCR appName,
ox::StringViewCR projectDataDir,
ox::UPtr<ox::FileSystem> &&fs) noexcept {
@@ -61,17 +64,46 @@ static ox::Error runApp(
static ox::Error run(
ox::StringViewCR appName,
ox::StringViewCR projectDataDir,
ox::SpanView<ox::CString>) {
ox::SpanView<ox::CString> const &args) {
// seed UUID generator
auto const time = std::time(nullptr);
ox::UUID::seedGenerator({
static_cast<uint64_t>(time),
static_cast<uint64_t>(time << 1)
});
// run app
auto const err = runApp(appName, projectDataDir, ox::UPtr<ox::FileSystem>{});
oxAssert(err, "Something went wrong...");
return err;
if (args.size() > 1 && ox::StringView{args[1]} == "cmd") {
if (args.size() < 5) {
return ox::Error{1, "insufficient arguments for sub-command"};
}
auto constexpr numCmdArgs = 5;
ox::StringView const projectDir = args[2];
ox::StringView const moduleId = args[3];
ox::StringView const subCmd = args[4];
for (auto const m : modules()) {
if (m->id() == moduleId) {
for (auto const &c : m->commands()) {
if (c.name == subCmd) {
auto kctx = keel::init(
ox::make_unique<ox::PassThroughFS>(projectDir),
c.name);
if (kctx.error) {
return ox::Error{2, "failed to load project directory"};
}
Project project{*kctx.value, projectDir, projectDataDir};
return c.func(project, args + numCmdArgs);
}
}
return ox::Error{1, "command not found"};
}
}
return ox::Error{1, "module not found"};
} else {
// run app
auto const err = runStudio(appName, projectDataDir, ox::UPtr<ox::FileSystem>{});
oxAssert(err, "Something went wrong...");
return err;
}
return {};
}
}

View File

@@ -37,11 +37,15 @@ static bool shutdownHandler(turbine::Context &ctx) {
namespace ig {
extern bool s_mainWinHasFocus;
}
static ox::Vector<Module const*> modules;
static ox::Vector<Module const*> g_modules;
ox::Vector<Module const*> const &modules() noexcept {
return g_modules;
}
void registerModule(Module const*mod) noexcept {
if (mod) {
modules.emplace_back(mod);
g_modules.emplace_back(mod);
}
}
@@ -443,7 +447,7 @@ void StudioUI::loadModule(Module const &mod) noexcept {
}
void StudioUI::loadModules() noexcept {
for (auto const mod : modules) {
for (auto const mod : g_modules) {
loadModule(*mod);
}
}

View File

@@ -23,15 +23,34 @@ struct EditorMaker {
Func make;
};
struct Command {
ox::String name;
std::function<ox::Error(Project&, ox::SpanView<ox::CString>)> func;
Command(
ox::StringParam name,
std::function<ox::Error(Project&, ox::SpanView<ox::CString>)> func) noexcept:
name(std::move(name)),
func(std::move(func)) {}
};
class Module {
public:
virtual ~Module() noexcept = default;
virtual ox::Vector<EditorMaker> editors(studio::Context &ctx) const;
[[nodiscard]]
virtual ox::String id() const noexcept = 0;
virtual ox::Vector<ox::UPtr<ItemMaker>> itemMakers(studio::Context&) const;
[[nodiscard]]
virtual ox::Vector<Command> commands() const;
virtual ox::Vector<ox::UPtr<ItemTemplate>> itemTemplates(studio::Context&) const;
[[nodiscard]]
virtual ox::Vector<EditorMaker> editors(Context &ctx) const;
[[nodiscard]]
virtual ox::Vector<ox::UPtr<ItemMaker>> itemMakers(Context&) const;
[[nodiscard]]
virtual ox::Vector<ox::UPtr<ItemTemplate>> itemTemplates(Context&) const;
};

View File

@@ -59,7 +59,7 @@ class Project: public ox::SignalHandler {
ox::HashMap<ox::String, ox::Vector<ox::String>> m_fileExtFileMap;
public:
explicit Project(keel::Context &ctx, ox::String path, ox::StringViewCR projectDataDir);
explicit Project(keel::Context &ctx, ox::StringParam path, ox::StringViewCR projectDataDir);
ox::Error create() noexcept;
@@ -101,6 +101,16 @@ class Project: public ox::SignalHandler {
ox::Error deleteItem(ox::StringViewCR path) noexcept;
[[nodiscard]]
keel::Context &kctx() noexcept {
return m_kctx;
}
[[nodiscard]]
keel::Context const &kctx() const noexcept {
return m_kctx;
}
[[nodiscard]]
bool exists(ox::StringViewCR path) const noexcept;

View File

@@ -6,6 +6,10 @@
namespace studio {
ox::Vector<Command> Module::commands() const {
return {};
}
ox::Vector<EditorMaker> Module::editors(Context&) const {
return {};
}

View File

@@ -54,7 +54,7 @@ static constexpr bool isParentOf(ox::StringViewCR parent, ox::StringViewCR child
return beginsWith(sfmt("{}/", child), parent);
}
Project::Project(keel::Context &ctx, ox::String path, ox::StringViewCR projectDataDir):
Project::Project(keel::Context &ctx, ox::StringParam path, ox::StringViewCR projectDataDir):
m_kctx(ctx),
m_path(std::move(path)),
m_projectDataDir(projectDataDir),