Squashed 'deps/nostalgia/' changes from 791b7746..a3d6a58c
a3d6a58c [nostalgia/core/studio] Fix library cpp file ownership e598e7fe [nostalgia,keel] Add ability to types Obj to Obj ba9e720f [ox/model] Fix ModelTypeName_v to use requireModelTypeName 8e816a26 [nostalgia/core/studio] Cleanup, fix possible TileSheet fill tool failure 5b9929ab [keel] Add detail to preload logging ceb54b3f [nostalgia/core/opengl] Cleanup 87644447 [nostalgia/core] Add clearCbb functions ce9a0b1f [nostalgia/core/opengl] Cleanup memcpys f7a468ea [ox/std] Add spancpy 861d177a [studio] Cleanup 3936756b [nostalgia/developer-handbook] Update error handling to reflect the enablement of exceptions for GBA build 3e78ec3f [studio] Cleanup 3c3d53b4 [studio] Ensure Editor tabs do first draw immediately, fix shift key being missed with tab shortcuts 151d7c57 [nostalgia/core/gba] Fix partial tilesheet loading overrun 4e4d8d2c [nostalgia/core/gba] Make panic use standard abort call 03d1fd28 [ox/std] Add and integrate standard abort call 6701decc [gbabuildcore] Enable exceptions 6cff5266 [teagba] Add symbols needed for enabling exceptions dd50bd02 [studio] Remap toggle explorer keyboard shortcut, add Ctrl+1-0 mappings for jumping between tabs 55a16602 [nostalgia/core] Fix TileSheet validation/repair to ensure pixels gets cleared if there are subsheets ed365dfe [studio] Fix new project menu to return an appropriately sized string for name 23a09e4a [nostalgia/core/studio] Fix SubSheet editor to return an appropriately sized string b69e7ebb [nostalgia/core/studio/tilesheeteditor] Fix select all not to go beyond end 418d6e3f [nostalgia/core/studio] Fix crash that occurs when a non-leaf node subsheet is selected c44d8678 [nostalgia/core/studio] Fix tile insert to correct input when inserting past the last tile eb4cd710 [nostalgia/core/studio] Fix tile insert to work on last tile d259770f Merge commit '4ea4a61d542777a270c4e2c283e0e986fc9eec9c' 80bad608 [keel] Fix reloadAsset 2bce9a2b [ox/std] Add non-const SmallMap::pairs git-subtree-dir: deps/nostalgia git-subtree-split: a3d6a58cc898f88434e8901aacb579c819fac3e6
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
namespace keel {
|
||||
|
||||
class Context;
|
||||
using PackTransform = ox::Result<bool>(*)(Context&, ox::Buffer &clawData, ox::StringView);
|
||||
using PackTransform = ox::Result<bool>(*)(Context&, ox::Buffer &clawData, ox::StringViewCR);
|
||||
|
||||
class Context {
|
||||
public:
|
||||
|
@@ -70,7 +70,7 @@ constexpr auto makeLoader(Context &ctx) {
|
||||
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
||||
return err;
|
||||
}
|
||||
OX_RETURN_ERROR(convert<T>(ctx, buff, &obj));
|
||||
OX_RETURN_ERROR(convert<T>(ctx, buff, obj));
|
||||
}
|
||||
return std::move(obj);
|
||||
};
|
||||
|
@@ -125,7 +125,9 @@ ox::Error preloadObj(
|
||||
OX_RETURN_ERROR(err);
|
||||
keel::PreloadPtr const p{.preloadAddr = a};
|
||||
OX_RETURN_ERROR(ox::writeMC(p).moveTo(buff));
|
||||
oxOutf("preloaded {} as a {} @ {} to {}\n", path, obj.type()->typeName, a, a + size);
|
||||
auto const&pbufSz = pl.buff().size();
|
||||
oxOutf("preloaded {} as a {} @ {} to {} / {}, total size: {}\n",
|
||||
path, obj.type()->typeName, a, a + size, pbufSz - 1, pbufSz - a);
|
||||
} else {
|
||||
// strip the Claw header (it is not needed after preloading) and write back out to dest fs
|
||||
OX_RETURN_ERROR(ox::writeMC(obj).moveTo(buff));
|
||||
|
@@ -16,10 +16,43 @@ namespace keel {
|
||||
class Wrap {
|
||||
public:
|
||||
virtual ~Wrap() = default;
|
||||
[[nodiscard]]
|
||||
virtual ox::CStringView typeName() const noexcept = 0;
|
||||
[[nodiscard]]
|
||||
virtual int typeVersion() const noexcept = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class WrapInline: public Wrap {
|
||||
class WrapT: public Wrap {
|
||||
public:
|
||||
[[nodiscard]]
|
||||
virtual constexpr T &obj() noexcept = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class WrapRef final: public WrapT<T> {
|
||||
private:
|
||||
T &m_obj;
|
||||
|
||||
public:
|
||||
constexpr explicit WrapRef(T &obj): m_obj{obj} {}
|
||||
|
||||
ox::CStringView typeName() const noexcept override {
|
||||
return ox::ModelTypeName_v<T>;
|
||||
}
|
||||
|
||||
int typeVersion() const noexcept override {
|
||||
return ox::ModelTypeVersion_v<T>;
|
||||
}
|
||||
|
||||
constexpr T &obj() noexcept override {
|
||||
return m_obj;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class WrapInline final: public WrapT<T> {
|
||||
private:
|
||||
T m_obj;
|
||||
|
||||
@@ -30,8 +63,15 @@ class WrapInline: public Wrap {
|
||||
constexpr explicit WrapInline(Args &&...args): m_obj(ox::forward<Args>(args)...) {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T &obj() noexcept {
|
||||
ox::CStringView typeName() const noexcept override {
|
||||
return ox::ModelTypeName_v<T>;
|
||||
}
|
||||
|
||||
int typeVersion() const noexcept override {
|
||||
return ox::ModelTypeVersion_v<T>;
|
||||
}
|
||||
|
||||
constexpr T &obj() noexcept override {
|
||||
return m_obj;
|
||||
}
|
||||
|
||||
@@ -44,7 +84,7 @@ constexpr ox::UPtr<Wrap> makeWrap(Args &&...args) noexcept {
|
||||
|
||||
template<typename T>
|
||||
constexpr T &wrapCast(Wrap &ptr) noexcept {
|
||||
return static_cast<WrapInline<T>&>(ptr).obj();
|
||||
return static_cast<WrapT<T>&>(ptr).obj();
|
||||
}
|
||||
|
||||
class BaseConverter {
|
||||
@@ -70,10 +110,10 @@ class BaseConverter {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool matches(
|
||||
ox::StringViewCR srcTypeName, int srcTypeVersion,
|
||||
ox::StringViewCR dstTypeName, int dstTypeVersion) const noexcept {
|
||||
ox::StringViewCR srcTypeName, int const srcTypeVersion,
|
||||
ox::StringViewCR dstTypeName, int const dstTypeVersion) const noexcept {
|
||||
return srcMatches(srcTypeName, srcTypeVersion)
|
||||
&& dstMatches(dstTypeName, dstTypeVersion);
|
||||
&& dstMatches(dstTypeName, dstTypeVersion);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -109,17 +149,17 @@ class Converter: public BaseConverter {
|
||||
|
||||
ox::Result<ox::UPtr<Wrap>> convertPtrToPtr(
|
||||
keel::Context &ctx, Wrap &src) const noexcept final {
|
||||
auto dst = makeWrap<DstType>();
|
||||
OX_RETURN_ERROR(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(*dst)));
|
||||
return {std::move(dst)};
|
||||
ox::Result<ox::UPtr<Wrap>> dst{makeWrap<DstType>()};
|
||||
OX_RETURN_ERROR(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(*dst.value)));
|
||||
return dst;
|
||||
}
|
||||
|
||||
ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
|
||||
keel::Context &ctx, ox::BufferView const&srcBuff) const noexcept final {
|
||||
OX_REQUIRE_M(src, readAsset<SrcType>(srcBuff));
|
||||
auto dst = makeWrap<DstType>();
|
||||
OX_RETURN_ERROR(convert(ctx, src, wrapCast<DstType>(*dst)));
|
||||
return {std::move(dst)};
|
||||
ox::Result<ox::UPtr<Wrap>> dst{makeWrap<DstType>()};
|
||||
OX_RETURN_ERROR(convert(ctx, src, wrapCast<DstType>(*dst.value)));
|
||||
return dst;
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -133,34 +173,57 @@ ox::Result<ox::UPtr<Wrap>> convert(
|
||||
ox::StringViewCR dstTypeName,
|
||||
int dstTypeVersion) noexcept;
|
||||
|
||||
ox::Result<ox::UPtr<Wrap>> convert(
|
||||
keel::Context &ctx,
|
||||
Wrap &src,
|
||||
ox::StringViewCR dstTypeName,
|
||||
int dstTypeVersion) noexcept;
|
||||
|
||||
ox::Result<ox::UPtr<Wrap>> convert(
|
||||
keel::Context &ctx,
|
||||
auto &src,
|
||||
ox::StringViewCR dstTypeName,
|
||||
int const dstTypeVersion) noexcept {
|
||||
return convert(ctx, WrapRef{src}, dstTypeName, dstTypeVersion);
|
||||
}
|
||||
|
||||
template<typename DstType>
|
||||
ox::Result<DstType> convert(keel::Context &ctx, ox::BufferView const&srcBuffer) noexcept {
|
||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||
OX_REQUIRE(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
||||
ox::Result<DstType> convertObjToObj(
|
||||
keel::Context &ctx,
|
||||
auto &src) noexcept {
|
||||
OX_REQUIRE_M(out, convert(ctx, WrapRef{src}, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
|
||||
return std::move(wrapCast(*out));
|
||||
}
|
||||
|
||||
template<typename DstType>
|
||||
ox::Result<DstType> convert(keel::Context &ctx, ox::BufferView const&src) noexcept {
|
||||
OX_REQUIRE(out, convert(ctx, src, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
|
||||
return std::move(wrapCast<DstType>(out));
|
||||
}
|
||||
|
||||
template<typename DstType>
|
||||
ox::Error convert(keel::Context &ctx, ox::BufferView const&buff, DstType *outObj) noexcept {
|
||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||
OX_REQUIRE(outPtr, convert(ctx, buff, DstTypeName, DstTypeVersion));
|
||||
*outObj = std::move(wrapCast<DstType>(*outPtr));
|
||||
ox::Error convert(keel::Context &ctx, ox::BufferView const&buff, DstType &outObj) noexcept {
|
||||
OX_REQUIRE(out, convert(ctx, buff, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
|
||||
outObj = std::move(wrapCast<DstType>(*out));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename DstType>
|
||||
ox::Error convertObjToObj(keel::Context &ctx, auto &src, DstType &outObj) noexcept {
|
||||
OX_REQUIRE(outPtr, convert(ctx, src, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
|
||||
outObj = std::move(wrapCast<DstType>(*outPtr));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename DstType>
|
||||
ox::Result<ox::Buffer> convertBuffToBuff(
|
||||
keel::Context &ctx, ox::BufferView const&srcBuffer, ox::ClawFormat fmt) noexcept {
|
||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||
OX_REQUIRE(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
||||
keel::Context &ctx, ox::BufferView const&src, ox::ClawFormat const fmt) noexcept {
|
||||
OX_REQUIRE(out, convert(ctx, src, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
|
||||
return ox::writeClaw<DstType>(wrapCast<DstType>(*out), fmt);
|
||||
}
|
||||
|
||||
template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal>
|
||||
ox::Result<bool> transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) noexcept {
|
||||
ox::Result<bool> transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringViewCR typeId) noexcept {
|
||||
if (typeId == ox::ModelTypeId_v<From>) {
|
||||
OX_RETURN_ERROR(keel::convertBuffToBuff<To>(ctx, buff, fmt).moveTo(buff));
|
||||
return true;
|
||||
@@ -168,5 +231,4 @@ ox::Result<bool> transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringV
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
@@ -154,13 +154,12 @@ ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexce
|
||||
}
|
||||
|
||||
ox::Error reloadAsset(keel::Context &ctx, ox::StringViewCR assetId) noexcept {
|
||||
ox::UUIDStr uuidStr;
|
||||
if (beginsWith(assetId, "uuid://")) {
|
||||
return ctx.assetManager.reloadAsset(substr(assetId, 7));
|
||||
} else {
|
||||
auto const [uuid, uuidErr] = getUuid(ctx, assetId);
|
||||
auto const [uuid, uuidErr] = getUuid(ctx, assetId);
|
||||
if (!uuidErr) {
|
||||
return ctx.assetManager.reloadAsset(uuidStr);
|
||||
return ctx.assetManager.reloadAsset(uuid.toString());
|
||||
} else {
|
||||
return ctx.assetManager.reloadAsset(assetId);
|
||||
}
|
||||
|
@@ -10,30 +10,38 @@ namespace keel {
|
||||
static ox::Result<BaseConverter const*> findConverter(
|
||||
ox::SpanView<BaseConverter const*> const&converters,
|
||||
ox::StringViewCR srcTypeName,
|
||||
int srcTypeVersion,
|
||||
int const srcTypeVersion,
|
||||
ox::StringViewCR dstTypeName,
|
||||
int dstTypeVersion) noexcept {
|
||||
int const dstTypeVersion) noexcept {
|
||||
for (auto const&c : converters) {
|
||||
if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return ox::Error(1, "Could not find converter");
|
||||
return ox::Error{1, "Could not find converter"};
|
||||
};
|
||||
|
||||
static ox::Result<ox::UPtr<Wrap>> convert(BaseConverter const&c, Context &ctx, ox::BufferView const&src) noexcept {
|
||||
return c.convertBuffToPtr(ctx, src);
|
||||
}
|
||||
|
||||
static ox::Result<ox::UPtr<Wrap>> convert(BaseConverter const&c, Context &ctx, Wrap &src) noexcept {
|
||||
return c.convertPtrToPtr(ctx, src);
|
||||
}
|
||||
|
||||
static ox::Result<ox::UPtr<Wrap>> convert(
|
||||
keel::Context &ctx,
|
||||
Context &ctx,
|
||||
ox::SpanView<BaseConverter const*> const&converters,
|
||||
ox::BufferView const&srcBuffer,
|
||||
auto &src,
|
||||
ox::StringViewCR srcTypeName,
|
||||
int srcTypeVersion,
|
||||
int const srcTypeVersion,
|
||||
ox::StringViewCR dstTypeName,
|
||||
int dstTypeVersion) noexcept {
|
||||
int const dstTypeVersion) noexcept {
|
||||
// look for direct converter
|
||||
auto [c, err] = findConverter(
|
||||
auto const [c, err] = findConverter(
|
||||
converters, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion);
|
||||
if (!err) {
|
||||
return c->convertBuffToPtr(ctx, srcBuffer);
|
||||
return convert(*c, ctx, src);
|
||||
}
|
||||
// try to chain multiple converters
|
||||
for (auto const&subConverter : converters) {
|
||||
@@ -41,20 +49,20 @@ static ox::Result<ox::UPtr<Wrap>> convert(
|
||||
continue;
|
||||
}
|
||||
const auto [intermediate, chainErr] =
|
||||
convert(ctx, converters, srcBuffer, srcTypeName, srcTypeVersion,
|
||||
convert(ctx, converters, src, srcTypeName, srcTypeVersion,
|
||||
subConverter->srcTypeName(), subConverter->srcTypeVersion());
|
||||
if (!chainErr) {
|
||||
return subConverter->convertPtrToPtr(ctx, *intermediate);
|
||||
}
|
||||
}
|
||||
return ox::Error(1, "Could not convert between types");
|
||||
return ox::Error{1, "Could not convert between types"};
|
||||
}
|
||||
|
||||
ox::Result<ox::UPtr<Wrap>> convert(
|
||||
keel::Context &ctx,
|
||||
Context &ctx,
|
||||
ox::BufferView const&srcBuffer,
|
||||
ox::StringViewCR dstTypeName,
|
||||
int dstTypeVersion) noexcept {
|
||||
int const dstTypeVersion) noexcept {
|
||||
OX_REQUIRE(hdr, readAssetHeader(srcBuffer));
|
||||
return convert(
|
||||
ctx,
|
||||
@@ -66,4 +74,19 @@ ox::Result<ox::UPtr<Wrap>> convert(
|
||||
dstTypeVersion);
|
||||
}
|
||||
|
||||
ox::Result<ox::UPtr<Wrap>> convert(
|
||||
Context &ctx,
|
||||
Wrap &src,
|
||||
ox::StringViewCR dstTypeName,
|
||||
int const dstTypeVersion) noexcept {
|
||||
return convert(
|
||||
ctx,
|
||||
converters(ctx),
|
||||
src,
|
||||
src.typeName(),
|
||||
src.typeVersion(),
|
||||
dstTypeName,
|
||||
dstTypeVersion);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ void NewProject::draw(studio::StudioContext &ctx) noexcept {
|
||||
|
||||
void NewProject::drawNewProjectName(studio::StudioContext &sctx) noexcept {
|
||||
drawWindow(sctx.tctx, &m_open, [this, &sctx] {
|
||||
ImGui::InputText("Name", m_projectName.data(), m_projectName.cap());
|
||||
ig::InputText("Name", m_projectName);
|
||||
ImGui::Text("Path: %s", m_projectPath.c_str());
|
||||
if (ImGui::Button("Browse")) {
|
||||
oxLogError(studio::chooseDirectory().moveTo(m_projectPath));
|
||||
|
@@ -18,9 +18,9 @@
|
||||
|
||||
namespace studio {
|
||||
|
||||
static ox::Vector<studio::Module const*> modules;
|
||||
static ox::Vector<Module const*> modules;
|
||||
|
||||
void registerModule(studio::Module const*mod) noexcept {
|
||||
void registerModule(Module const*mod) noexcept {
|
||||
if (mod) {
|
||||
modules.emplace_back(mod);
|
||||
}
|
||||
@@ -45,25 +45,25 @@ OX_MODEL_END()
|
||||
|
||||
StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexcept:
|
||||
m_sctx(*this, ctx),
|
||||
m_ctx(ctx),
|
||||
m_tctx(ctx),
|
||||
m_projectDataDir(std::move(projectDataDir)),
|
||||
m_projectExplorer(m_ctx),
|
||||
m_projectExplorer(m_tctx),
|
||||
m_newProject(m_projectDataDir),
|
||||
m_aboutPopup(m_ctx) {
|
||||
turbine::setApplicationData(m_ctx, &m_sctx);
|
||||
m_aboutPopup(m_tctx) {
|
||||
turbine::setApplicationData(m_tctx, &m_sctx);
|
||||
m_projectExplorer.fileChosen.connect(this, &StudioUI::openFile);
|
||||
m_newProject.finished.connect(this, &StudioUI::createOpenProject);
|
||||
m_newMenu.finished.connect(this, &StudioUI::openFile);
|
||||
ImGui::GetIO().IniFilename = nullptr;
|
||||
loadModules();
|
||||
// open project and files
|
||||
auto const [config, err] = studio::readConfig<StudioConfig>(keelCtx(m_ctx));
|
||||
auto const [config, err] = studio::readConfig<StudioConfig>(keelCtx(m_tctx));
|
||||
m_showProjectExplorer = config.showProjectExplorer;
|
||||
if (!err) {
|
||||
auto const openProjErr = openProjectPath(config.projectPath);
|
||||
if (!openProjErr) {
|
||||
for (auto const&f: config.openFiles) {
|
||||
auto openFileErr = openFileActiveTab(f, config.activeTabItemName == f);
|
||||
auto const openFileErr = openFileActiveTab(f, config.activeTabItemName == f);
|
||||
if (openFileErr) {
|
||||
oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr));
|
||||
continue;
|
||||
@@ -82,8 +82,8 @@ StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexce
|
||||
}
|
||||
}
|
||||
|
||||
void StudioUI::handleKeyEvent(turbine::Key key, bool down) noexcept {
|
||||
for (auto p : m_popups) {
|
||||
void StudioUI::handleKeyEvent(turbine::Key const key, bool const down) noexcept {
|
||||
for (auto const p : m_popups) {
|
||||
if (p->isOpen()) {
|
||||
if (key == turbine::Key::Escape) {
|
||||
p->close();
|
||||
@@ -118,13 +118,13 @@ void StudioUI::draw() noexcept {
|
||||
for (auto &w: m_widgets) {
|
||||
w->draw(m_sctx);
|
||||
}
|
||||
for (auto p: m_popups) {
|
||||
for (auto const p: m_popups) {
|
||||
p->draw(m_sctx);
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
handleKeyInput();
|
||||
m_taskRunner.update(m_ctx);
|
||||
m_taskRunner.update(m_tctx);
|
||||
}
|
||||
|
||||
void StudioUI::drawMenu() noexcept {
|
||||
@@ -143,7 +143,7 @@ void StudioUI::drawMenu() noexcept {
|
||||
m_activeEditor->save();
|
||||
}
|
||||
if (ImGui::MenuItem("Quit", "Ctrl+Q")) {
|
||||
turbine::requestShutdown(m_ctx);
|
||||
turbine::requestShutdown(m_tctx);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -168,7 +168,7 @@ void StudioUI::drawMenu() noexcept {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("View")) {
|
||||
if (ImGui::MenuItem("Project Explorer", "Ctrl+1", m_showProjectExplorer)) {
|
||||
if (ImGui::MenuItem("Project Explorer", "Ctrl+Shift+1", m_showProjectExplorer)) {
|
||||
toggleProjectExplorer();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
@@ -204,9 +204,10 @@ void StudioUI::drawTabs() noexcept {
|
||||
if (ImGui::BeginTabItem(e->itemDisplayName().c_str(), &open, flags)) {
|
||||
if (m_activeEditor != e.get()) [[unlikely]] {
|
||||
m_activeEditor = e.get();
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) {
|
||||
config.activeTabItemName = m_activeEditor->itemPath();
|
||||
});
|
||||
turbine::setRefreshWithin(m_tctx, 0);
|
||||
} else [[likely]] {
|
||||
if (m_activeEditorUpdatePending == e.get()) [[unlikely]] {
|
||||
m_activeEditorUpdatePending = nullptr;
|
||||
@@ -237,13 +238,13 @@ void StudioUI::drawTabs() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void StudioUI::loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept {
|
||||
void StudioUI::loadEditorMaker(EditorMaker const&editorMaker) noexcept {
|
||||
for (auto const&ext : editorMaker.fileTypes) {
|
||||
m_editorMakers[ext] = editorMaker.make;
|
||||
}
|
||||
}
|
||||
|
||||
void StudioUI::loadModule(studio::Module const&mod) noexcept {
|
||||
void StudioUI::loadModule(Module const&mod) noexcept {
|
||||
for (auto const&editorMaker : mod.editors(m_sctx)) {
|
||||
loadEditorMaker(editorMaker);
|
||||
}
|
||||
@@ -260,20 +261,20 @@ void StudioUI::loadModules() noexcept {
|
||||
|
||||
void StudioUI::toggleProjectExplorer() noexcept {
|
||||
m_showProjectExplorer = !m_showProjectExplorer;
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
||||
editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) {
|
||||
config.showProjectExplorer = m_showProjectExplorer;
|
||||
});
|
||||
}
|
||||
|
||||
void StudioUI::redo() noexcept {
|
||||
auto undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
|
||||
auto const undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
|
||||
if (undoStack && undoStack->canRedo()) {
|
||||
oxLogError(m_activeEditor->undoStack()->redo());
|
||||
}
|
||||
}
|
||||
|
||||
void StudioUI::undo() noexcept {
|
||||
auto undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
|
||||
auto const undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
|
||||
if (undoStack && undoStack->canUndo()) {
|
||||
oxLogError(m_activeEditor->undoStack()->undo());
|
||||
}
|
||||
@@ -292,7 +293,7 @@ void StudioUI::handleKeyInput() noexcept {
|
||||
m_activeEditor->copy();
|
||||
}
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_N)) {
|
||||
if (turbine::buttonDown(m_ctx, turbine::Key::Mod_Shift)) {
|
||||
if (turbine::buttonDown(m_tctx, turbine::Key::Mod_Shift)) {
|
||||
m_newProject.open();
|
||||
} else {
|
||||
m_newMenu.open();
|
||||
@@ -302,7 +303,7 @@ void StudioUI::handleKeyInput() noexcept {
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_S)) {
|
||||
save();
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_Q)) {
|
||||
turbine::requestShutdown(m_ctx);
|
||||
turbine::requestShutdown(m_tctx);
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_V)) {
|
||||
if (m_activeEditor && m_activeEditor->pasteEnabled()) {
|
||||
m_activeEditor->paste();
|
||||
@@ -317,8 +318,22 @@ void StudioUI::handleKeyInput() noexcept {
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_Z)) {
|
||||
auto const undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
|
||||
if (undoStack) { oxLogError(undoStack->undo()); }
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_1)) {
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_1) && ImGui::IsKeyDown(ImGuiKey_ModShift)) {
|
||||
toggleProjectExplorer();
|
||||
} else {
|
||||
if (!m_editors.empty()) {
|
||||
auto const range = ox::min<size_t>(9u, m_editors.size()) - 1;
|
||||
for (auto i = 0u; i < 9; ++i) {
|
||||
if (ImGui::IsKeyPressed(static_cast<ImGuiKey>(static_cast<int>(ImGuiKey_1) + i))) {
|
||||
m_activeEditor = m_editors[i < m_editors.size() ? i : range].get();
|
||||
m_activeEditorUpdatePending = m_activeEditor;
|
||||
}
|
||||
}
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_0)) {
|
||||
m_activeEditor = m_editors[10 < m_editors.size() ? 10 : range].get();
|
||||
m_activeEditorUpdatePending = m_activeEditor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -333,18 +348,18 @@ ox::Error StudioUI::createOpenProject(ox::StringViewCR path) noexcept {
|
||||
|
||||
ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept {
|
||||
OX_REQUIRE_M(fs, keel::loadRomFs(path.view()));
|
||||
OX_RETURN_ERROR(keel::setRomFs(keelCtx(m_ctx), std::move(fs)));
|
||||
OX_RETURN_ERROR(keel::setRomFs(keelCtx(m_tctx), std::move(fs)));
|
||||
OX_RETURN_ERROR(
|
||||
ox::make_unique_catch<studio::Project>(keelCtx(m_ctx), std::move(path), m_projectDataDir)
|
||||
ox::make_unique_catch<Project>(keelCtx(m_tctx), std::move(path), m_projectDataDir)
|
||||
.moveTo(m_project));
|
||||
auto const sctx = applicationData<studio::StudioContext>(m_ctx);
|
||||
auto const sctx = applicationData<StudioContext>(m_tctx);
|
||||
sctx->project = m_project.get();
|
||||
turbine::setWindowTitle(m_ctx, ox::sfmt("{} - {}", keelCtx(m_ctx).appName, m_project->projectPath()));
|
||||
turbine::setWindowTitle(m_tctx, ox::sfmt("{} - {}", keelCtx(m_tctx).appName, m_project->projectPath()));
|
||||
m_project->fileAdded.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel);
|
||||
m_project->fileDeleted.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel);
|
||||
m_openFiles.clear();
|
||||
m_editors.clear();
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) {
|
||||
config.projectPath = ox::String(m_project->projectPath());
|
||||
config.openFiles.clear();
|
||||
});
|
||||
@@ -355,7 +370,7 @@ ox::Error StudioUI::openFile(ox::StringViewCR path) noexcept {
|
||||
return openFileActiveTab(path, true);
|
||||
}
|
||||
|
||||
ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool makeActiveTab) noexcept {
|
||||
ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool const makeActiveTab) noexcept {
|
||||
if (!m_project) {
|
||||
return ox::Error(1, "No project open to open a file from");
|
||||
}
|
||||
@@ -369,7 +384,7 @@ ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool makeActiveTab)
|
||||
}
|
||||
return {};
|
||||
}
|
||||
OX_REQUIRE(ext, studio::fileExt(path));
|
||||
OX_REQUIRE(ext, fileExt(path));
|
||||
// create Editor
|
||||
BaseEditor *editor = nullptr;
|
||||
auto const err = m_editorMakers.contains(ext) ?
|
||||
@@ -391,7 +406,7 @@ ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool makeActiveTab)
|
||||
m_activeEditorUpdatePending = editor;
|
||||
}
|
||||
// save to config
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&path](StudioConfig &config) {
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&path](StudioConfig &config) {
|
||||
if (!config.openFiles.contains(path)) {
|
||||
config.openFiles.emplace_back(path);
|
||||
}
|
||||
@@ -405,7 +420,7 @@ ox::Error StudioUI::closeFile(ox::StringViewCR path) noexcept {
|
||||
}
|
||||
std::ignore = m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path));
|
||||
// save to config
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) {
|
||||
std::ignore = config.openFiles.erase(std::remove(config.openFiles.begin(), config.openFiles.end(), path));
|
||||
});
|
||||
return {};
|
||||
|
@@ -24,23 +24,23 @@ class StudioUI: public ox::SignalHandler {
|
||||
friend class StudioUIDrawer;
|
||||
|
||||
private:
|
||||
studio::StudioContext m_sctx;
|
||||
turbine::Context &m_ctx;
|
||||
StudioContext m_sctx;
|
||||
turbine::Context &m_tctx;
|
||||
ox::String m_projectDataDir;
|
||||
ox::UPtr<studio::Project> m_project;
|
||||
studio::TaskRunner m_taskRunner;
|
||||
ox::Vector<ox::UPtr<studio::BaseEditor>> m_editors;
|
||||
ox::Vector<ox::UPtr<studio::Widget>> m_widgets;
|
||||
ox::HashMap<ox::String, studio::EditorMaker::Func> m_editorMakers;
|
||||
ox::UPtr<Project> m_project;
|
||||
TaskRunner m_taskRunner;
|
||||
ox::Vector<ox::UPtr<BaseEditor>> m_editors;
|
||||
ox::Vector<ox::UPtr<Widget>> m_widgets;
|
||||
ox::HashMap<ox::String, EditorMaker::Func> m_editorMakers;
|
||||
ProjectExplorer m_projectExplorer;
|
||||
ox::Vector<ox::String> m_openFiles;
|
||||
studio::BaseEditor *m_activeEditorOnLastDraw = nullptr;
|
||||
studio::BaseEditor *m_activeEditor = nullptr;
|
||||
studio::BaseEditor *m_activeEditorUpdatePending = nullptr;
|
||||
BaseEditor *m_activeEditorOnLastDraw = nullptr;
|
||||
BaseEditor *m_activeEditor = nullptr;
|
||||
BaseEditor *m_activeEditorUpdatePending = nullptr;
|
||||
NewMenu m_newMenu;
|
||||
NewProject m_newProject;
|
||||
AboutPopup m_aboutPopup;
|
||||
ox::Array<studio::Popup*, 3> const m_popups = {
|
||||
ox::Array<Popup*, 3> const m_popups = {
|
||||
&m_newMenu,
|
||||
&m_newProject,
|
||||
&m_aboutPopup
|
||||
@@ -53,7 +53,7 @@ class StudioUI: public ox::SignalHandler {
|
||||
void handleKeyEvent(turbine::Key, bool down) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr studio::Project *project() noexcept {
|
||||
constexpr Project *project() noexcept {
|
||||
return m_project.get();
|
||||
}
|
||||
|
||||
@@ -67,9 +67,9 @@ class StudioUI: public ox::SignalHandler {
|
||||
|
||||
void drawTabs() noexcept;
|
||||
|
||||
void loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept;
|
||||
void loadEditorMaker(EditorMaker const&editorMaker) noexcept;
|
||||
|
||||
void loadModule(studio::Module const&mod) noexcept;
|
||||
void loadModule(Module const&mod) noexcept;
|
||||
|
||||
void loadModules() noexcept;
|
||||
|
||||
|
Reference in New Issue
Block a user