[nostalgia] Add start for Scene editor in Studio
This commit is contained in:
@@ -19,6 +19,7 @@ target_link_libraries(
|
||||
NostalgiaAppModules
|
||||
NostalgiaStudio
|
||||
NostalgiaCore-Studio
|
||||
NostalgiaScene-Studio
|
||||
)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32)
|
||||
|
@@ -7,13 +7,17 @@
|
||||
#include <ox/std/memory.hpp>
|
||||
|
||||
#include <nostalgia/core/studio/module.hpp>
|
||||
#include <nostalgia/scene/studio/module.hpp>
|
||||
|
||||
namespace nostalgia {
|
||||
|
||||
[[maybe_unused]] // GCC warns about the existence of this "unused" constexpr list in a header file...
|
||||
constexpr auto BuiltinModules = {
|
||||
[] {
|
||||
return ox::make_unique<core::StudioModule>();
|
||||
[[maybe_unused]] // GCC warns about the existence of this "unused" inline list in a header file...
|
||||
inline ox::Vector<std::function<ox::UPtr<studio::Module>()>, 2> BuiltinModules = {
|
||||
[]() -> ox::UPtr<studio::Module> {
|
||||
return ox::UPtr<studio::Module>(new core::StudioModule());
|
||||
},
|
||||
[]() -> ox::UPtr<studio::Module> {
|
||||
return ox::UPtr<studio::Module>(new scene::StudioModule());
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -23,7 +23,7 @@ constexpr auto ConfigDir = [] {
|
||||
}
|
||||
}();
|
||||
|
||||
ox::String configPath(const core::Context *ctx) noexcept {
|
||||
ox::String configPath(const foundation::Context *ctx) noexcept {
|
||||
const auto homeDir = std::getenv(ox::defines::OS == ox::OS::Windows ? "USERPROFILE" : "HOME");
|
||||
return ox::sfmt(ConfigDir, homeDir, ctx->appName);
|
||||
}
|
||||
|
@@ -18,10 +18,10 @@
|
||||
namespace nostalgia::studio {
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String configPath(const core::Context *ctx) noexcept;
|
||||
ox::String configPath(const foundation::Context *ctx) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<T> readConfig(core::Context *ctx, ox::CRStringView name) noexcept {
|
||||
ox::Result<T> readConfig(foundation::Context *ctx, ox::CRStringView name) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
const auto path = ox::sfmt("/{}.json", name);
|
||||
ox::PassThroughFS fs(configPath(ctx));
|
||||
@@ -34,13 +34,13 @@ ox::Result<T> readConfig(core::Context *ctx, ox::CRStringView name) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Result<T> readConfig(core::Context *ctx) noexcept {
|
||||
ox::Result<T> readConfig(foundation::Context *ctx) noexcept {
|
||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||
return readConfig<T>(ctx, TypeName);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeConfig(core::Context *ctx, ox::CRStringView name, T *data) noexcept {
|
||||
ox::Error writeConfig(foundation::Context *ctx, ox::CRStringView name, T *data) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
const auto path = ox::sfmt("/{}.json", name);
|
||||
ox::PassThroughFS fs(configPath(ctx));
|
||||
@@ -58,13 +58,13 @@ ox::Error writeConfig(core::Context *ctx, ox::CRStringView name, T *data) noexce
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeConfig(core::Context *ctx, T *data) noexcept {
|
||||
ox::Error writeConfig(foundation::Context *ctx, T *data) noexcept {
|
||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||
return writeConfig(ctx, TypeName, data);
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
void openConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
void openConfig(foundation::Context *ctx, const auto &name, Func f) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
const auto [c, err] = readConfig<T>(ctx, name);
|
||||
oxLogError(err);
|
||||
@@ -72,13 +72,13 @@ void openConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
void openConfig(core::Context *ctx, Func f) noexcept {
|
||||
void openConfig(foundation::Context *ctx, Func f) noexcept {
|
||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||
openConfig<T>(ctx, TypeName, f);
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
void editConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
void editConfig(foundation::Context *ctx, const auto &name, Func f) noexcept {
|
||||
oxAssert(ox_strcmp(name, ""), "Config type has no TypeName");
|
||||
auto [c, err] = readConfig<T>(ctx, name);
|
||||
oxLogError(err);
|
||||
@@ -87,7 +87,7 @@ void editConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
void editConfig(core::Context *ctx, Func f) noexcept {
|
||||
void editConfig(foundation::Context *ctx, Func f) noexcept {
|
||||
constexpr auto TypeName = ox::requireModelTypeName<T>();
|
||||
editConfig<T>(ctx, TypeName, f);
|
||||
}
|
||||
|
@@ -29,6 +29,13 @@ void BaseEditor::exportFile() {
|
||||
void BaseEditor::keyStateChanged(core::Key, bool) {
|
||||
}
|
||||
|
||||
void BaseEditor::onActivated() noexcept {
|
||||
}
|
||||
|
||||
bool BaseEditor::requiresConstantRefresh() const noexcept {
|
||||
return m_requiresConstantRefresh;
|
||||
}
|
||||
|
||||
void BaseEditor::close() const {
|
||||
this->closed.emit(itemName());
|
||||
}
|
||||
@@ -100,6 +107,11 @@ ox::StringView BaseEditor::pathToItemName(ox::CRStringView path) noexcept {
|
||||
return path.substr(lastSlash + 1);
|
||||
}
|
||||
|
||||
void BaseEditor::setRequiresConstantRefresh(bool value) noexcept {
|
||||
m_requiresConstantRefresh = value;
|
||||
}
|
||||
|
||||
|
||||
Editor::Editor() noexcept {
|
||||
m_undoStack.changeTriggered.connect(this, &Editor::markUnsavedChanges);
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget {
|
||||
bool m_cutEnabled = false;
|
||||
bool m_copyEnabled = false;
|
||||
bool m_pasteEnabled = false;
|
||||
bool m_requiresConstantRefresh = false;
|
||||
|
||||
public:
|
||||
~BaseEditor() override = default;
|
||||
@@ -50,6 +51,11 @@ class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget {
|
||||
|
||||
virtual void keyStateChanged(core::Key key, bool down);
|
||||
|
||||
virtual void onActivated() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
bool requiresConstantRefresh() const noexcept;
|
||||
|
||||
void close() const;
|
||||
|
||||
/**
|
||||
@@ -102,6 +108,8 @@ class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget {
|
||||
|
||||
static ox::StringView pathToItemName(ox::CRStringView path) noexcept;
|
||||
|
||||
void setRequiresConstantRefresh(bool value) noexcept;
|
||||
|
||||
// signals
|
||||
public:
|
||||
ox::Signal<ox::Error(bool)> unsavedChangesChanged;
|
||||
|
@@ -14,7 +14,7 @@
|
||||
namespace nostalgia::studio {
|
||||
|
||||
static void generateTypes(ox::TypeStore *ts) noexcept {
|
||||
for (const auto mod : *foundation::modules()) {
|
||||
for (const auto mod : foundation::modules()) {
|
||||
for (auto gen : mod->types()) {
|
||||
oxLogError(gen(ts));
|
||||
}
|
||||
|
@@ -48,13 +48,16 @@ static ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept {
|
||||
core::setUpdateHandler(ctx.get(), updateHandler);
|
||||
core::setKeyEventHandler(ctx.get(), keyEventHandler);
|
||||
core::setConstantRefresh(ctx.get(), false);
|
||||
core::gl::setMainViewEnabled(false);
|
||||
studio::StudioContext studioCtx;
|
||||
core::setApplicationData(ctx.get(), &studioCtx);
|
||||
StudioUI ui(ctx.get());
|
||||
studioCtx.ui = &ui;
|
||||
StudioUIDrawer drawer(&ui);
|
||||
ctx->drawers.emplace_back(&drawer);
|
||||
return core::run(ctx.get());
|
||||
core::addCustomDrawer(ctx.get(), &drawer);
|
||||
auto err = core::run(ctx.get());
|
||||
core::removeCustomDrawer(ctx.get(), &drawer);
|
||||
return err;
|
||||
}
|
||||
|
||||
static ox::Error run(int, const char**) noexcept {
|
||||
|
@@ -217,7 +217,12 @@ void StudioUI::drawTabs() noexcept {
|
||||
if (m_activeEditorUpdatePending == e.get()) {
|
||||
m_activeEditorUpdatePending = nullptr;
|
||||
}
|
||||
if (m_activeEditorOnLastDraw != e.get()) [[unlikely]] {
|
||||
m_activeEditor->onActivated();
|
||||
core::setConstantRefresh(m_ctx, m_activeEditor->requiresConstantRefresh());
|
||||
}
|
||||
e->draw(m_ctx);
|
||||
m_activeEditorOnLastDraw = e.get();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (!open) {
|
||||
@@ -346,7 +351,7 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
|
||||
}
|
||||
// save to config
|
||||
studio::editConfig<StudioConfig>(m_ctx, [&](StudioConfig *config) {
|
||||
if (!config->openFiles.contains((path))) {
|
||||
if (!config->openFiles.contains(path)) {
|
||||
config->openFiles.emplace_back(path);
|
||||
}
|
||||
});
|
||||
|
@@ -31,6 +31,7 @@ class StudioUI: public ox::SignalHandler {
|
||||
ox::HashMap<ox::String, studio::EditorMaker::Func> m_editorMakers;
|
||||
ox::UniquePtr<ProjectExplorer> m_projectExplorer;
|
||||
ox::Vector<ox::String> m_openFiles;
|
||||
studio::BaseEditor *m_activeEditorOnLastDraw = nullptr;
|
||||
studio::BaseEditor *m_activeEditor = nullptr;
|
||||
studio::BaseEditor *m_activeEditorUpdatePending = nullptr;
|
||||
NewMenu m_newMenu;
|
||||
|
Reference in New Issue
Block a user