Merge commit 'dceeaaa9302b7e9ce85fa773fc187bc593f3c93c'
All checks were successful
Build / build (push) Successful in 1m16s
All checks were successful
Build / build (push) Successful in 1m16s
This commit is contained in:
@@ -10,6 +10,9 @@
|
||||
|
||||
namespace studio {
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Vector<Module const*> const &modules() noexcept;
|
||||
|
||||
void registerModule(Module const*) noexcept;
|
||||
|
||||
}
|
||||
|
@@ -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 {};
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -673,14 +677,18 @@ ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept {
|
||||
auto p = std::move(*pcIt);
|
||||
std::ignore = config.projects.erase(pcIt);
|
||||
auto &pc = *config.projects.emplace(0, std::move(p));
|
||||
for (auto const &f: pc.openFiles) {
|
||||
auto const openFileErr = openFileActiveTab(f, pc.activeTabItemName == f);
|
||||
if (openFileErr) {
|
||||
oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr));
|
||||
continue;
|
||||
}
|
||||
m_activeEditor = m_editors.back().value->get();
|
||||
}
|
||||
std::ignore = pc.openFiles.erase(
|
||||
std::remove_if(
|
||||
pc.openFiles.begin(), pc.openFiles.end(),
|
||||
[&](ox::String const &f) {
|
||||
auto const openFileErr = openFileActiveTab(f, pc.activeTabItemName == f);
|
||||
if (openFileErr) {
|
||||
oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr));
|
||||
return true;
|
||||
}
|
||||
m_activeEditor = m_editors.back().value->get();
|
||||
return false;
|
||||
}));
|
||||
} else {
|
||||
config.projects.emplace(0, StudioConfig::ProjectConfig{
|
||||
.projectPath = ox::String{m_project->projectPath()},
|
||||
|
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -6,6 +6,10 @@
|
||||
|
||||
namespace studio {
|
||||
|
||||
ox::Vector<Command> Module::commands() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Vector<EditorMaker> Module::editors(Context&) const {
|
||||
return {};
|
||||
}
|
||||
|
@@ -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),
|
||||
|
@@ -50,7 +50,7 @@ OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
constexpr auto headerP1Len = ox::strlen(headerP2);
|
||||
constexpr auto headerP2Len = ox::strlen(headerP1);
|
||||
constexpr auto headerLen = headerP1Len + headerP2Len;
|
||||
for (auto current = MEM_ROM; current < reinterpret_cast<char*>(0x0a000000); current += headerLen) {
|
||||
for (auto current = MEM_ROM.data(); current < reinterpret_cast<char*>(0x0a000000); current += headerLen) {
|
||||
if (memcmp(current, headerP1, headerP1Len) == 0 &&
|
||||
memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) {
|
||||
return reinterpret_cast<std::size_t>(current + headerLen);
|
||||
|
Reference in New Issue
Block a user