diff --git a/src/nostalgia/scene/studio/CMakeLists.txt b/src/nostalgia/scene/studio/CMakeLists.txt new file mode 100644 index 00000000..1aa7d323 --- /dev/null +++ b/src/nostalgia/scene/studio/CMakeLists.txt @@ -0,0 +1,25 @@ +add_library( + NostalgiaScene-Studio OBJECT + module.cpp + sceneeditor-imgui.cpp + sceneeditor.cpp + sceneeditorview.cpp +) + +if(NOT MSVC) + target_compile_options(NostalgiaScene-Studio PRIVATE -Wsign-conversion) +endif() + +target_link_libraries( + NostalgiaScene-Studio PUBLIC + NostalgiaGlUtils + NostalgiaStudio + NostalgiaScene +) + +install( + TARGETS + NostalgiaScene-Studio + LIBRARY DESTINATION + ${NOSTALGIA_DIST_MODULE} +) diff --git a/src/nostalgia/scene/studio/module.cpp b/src/nostalgia/scene/studio/module.cpp new file mode 100644 index 00000000..6a794aca --- /dev/null +++ b/src/nostalgia/scene/studio/module.cpp @@ -0,0 +1,32 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include + +#include "sceneeditor-imgui.hpp" +#include "module.hpp" + +namespace nostalgia::scene { + +ox::Vector StudioModule::editors(core::Context *ctx) noexcept { + return { + { + {"nscn"}, + [ctx](ox::CRStringView path) -> ox::Result { + try { + return ox::make(ctx, path); + } catch (const ox::Exception &ex) { + return ex.toError(); + } + } + }, + }; +} + +ox::Vector> StudioModule::itemMakers(core::Context*) noexcept { + ox::Vector> out; + return out; +} + +} diff --git a/src/nostalgia/scene/studio/module.hpp b/src/nostalgia/scene/studio/module.hpp new file mode 100644 index 00000000..bd0b14a5 --- /dev/null +++ b/src/nostalgia/scene/studio/module.hpp @@ -0,0 +1,17 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +#include + +namespace nostalgia::scene { + +class StudioModule: public studio::Module { + public: + ox::Vector editors(core::Context *ctx) noexcept override; + ox::Vector> itemMakers(core::Context*) noexcept override; +}; + +} diff --git a/src/nostalgia/scene/studio/sceneeditor-imgui.cpp b/src/nostalgia/scene/studio/sceneeditor-imgui.cpp new file mode 100644 index 00000000..fb4e205f --- /dev/null +++ b/src/nostalgia/scene/studio/sceneeditor-imgui.cpp @@ -0,0 +1,59 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include + +#include +#include +#include + +#include "sceneeditor-imgui.hpp" + +namespace nostalgia::scene { + +SceneEditorImGui::SceneEditorImGui(core::Context *ctx, ox::CRStringView path): + m_editor(ctx, path), + m_view(ctx, m_editor.scene()) { + m_ctx = ctx; + m_itemPath = path; + const auto lastSlash = std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset(); + m_itemName = m_itemPath.substr(lastSlash + 1); + setRequiresConstantRefresh(false); +} + +ox::CRString SceneEditorImGui::itemName() const noexcept { + return m_itemPath; +} + +ox::CRString SceneEditorImGui::itemDisplayName() const noexcept { + return m_itemName; +} + +void SceneEditorImGui::draw(core::Context*) noexcept { + const auto paneSize = ImGui::GetContentRegionAvail(); + const geo::Size fbSize{ + static_cast(paneSize.x), + static_cast(paneSize.y)}; + m_view.draw(fbSize.width, fbSize.height); + auto &fb = m_view.framebuffer(); + const uintptr_t buffId = fb.color.id; + ImGui::Image( + reinterpret_cast(buffId), + paneSize, + ImVec2(0, 1), + ImVec2(1, 0)); +} + +void SceneEditorImGui::onActivated() noexcept { + m_view.setupScene(); +} + +ox::Error SceneEditorImGui::saveItem() noexcept { + const auto sctx = applicationData(m_ctx); + oxReturnError(sctx->project->writeObj(m_itemPath, &m_editor.scene())); + oxReturnError(m_ctx->assetManager.setAsset(m_itemPath, m_editor.scene())); + return {}; +} + +} diff --git a/src/nostalgia/scene/studio/sceneeditor-imgui.hpp b/src/nostalgia/scene/studio/sceneeditor-imgui.hpp new file mode 100644 index 00000000..8fb2c817 --- /dev/null +++ b/src/nostalgia/scene/studio/sceneeditor-imgui.hpp @@ -0,0 +1,43 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +#include +#include + +#include "sceneeditor.hpp" +#include "sceneeditorview.hpp" + +namespace nostalgia::scene { + +class SceneEditorImGui: public studio::Editor { + + private: + core::Context *m_ctx = nullptr; + ox::String m_itemName; + ox::String m_itemPath; + SceneEditor m_editor; + SceneEditorView m_view; + + public: + SceneEditorImGui(core::Context *ctx, ox::CRStringView path); + + /** + * Returns the name of item being edited. + */ + ox::CRString itemName() const noexcept final; + + ox::CRString itemDisplayName() const noexcept final; + + void draw(core::Context*) noexcept final; + + void onActivated() noexcept override; + + protected: + ox::Error saveItem() noexcept final; + +}; + +} diff --git a/src/nostalgia/scene/studio/sceneeditor.cpp b/src/nostalgia/scene/studio/sceneeditor.cpp new file mode 100644 index 00000000..b5a28bf4 --- /dev/null +++ b/src/nostalgia/scene/studio/sceneeditor.cpp @@ -0,0 +1,15 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include "sceneeditor.hpp" + +namespace nostalgia::scene { + +SceneEditor::SceneEditor(core::Context *ctx, ox::CRStringView path) { + m_ctx = ctx; + oxRequireT(scn, foundation::readObj(m_ctx, path)); + m_scene = *scn; +} + +} diff --git a/src/nostalgia/scene/studio/sceneeditor.hpp b/src/nostalgia/scene/studio/sceneeditor.hpp new file mode 100644 index 00000000..8ee29c59 --- /dev/null +++ b/src/nostalgia/scene/studio/sceneeditor.hpp @@ -0,0 +1,33 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +#include +#include +#include + +namespace nostalgia::scene { + +class SceneEditor { + + private: + core::Context *m_ctx = nullptr; + ox::String m_itemName; + ox::String m_itemPath; + SceneStatic m_scene; + + public: + SceneEditor(core::Context *ctx, ox::CRStringView path); + + const SceneStatic &scene() noexcept { + return m_scene; + } + + protected: + ox::Error saveItem() noexcept; + +}; + +} diff --git a/src/nostalgia/scene/studio/sceneeditorview.cpp b/src/nostalgia/scene/studio/sceneeditorview.cpp new file mode 100644 index 00000000..bea6b23e --- /dev/null +++ b/src/nostalgia/scene/studio/sceneeditorview.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#include "sceneeditorview.hpp" + +namespace nostalgia::scene { + +SceneEditorView::SceneEditorView(core::Context *ctx, const SceneStatic &sceneStatic) noexcept: + m_ctx(*ctx), + m_sceneStatic(sceneStatic), + m_scene(m_sceneStatic) { +} + +void SceneEditorView::setupScene() noexcept { + oxIgnoreError(m_scene.setupDisplay(&m_ctx)); +} + +void SceneEditorView::draw(int width, int height) noexcept { + if (width != m_frameBuffer.width || height != m_frameBuffer.height) { + glutils::resizeInitFrameBuffer(&m_frameBuffer, width, height); + core::gl::setRenderSize(&m_ctx, width, height); + oxIgnoreError(m_scene.setupDisplay(&m_ctx)); + } + glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer); + glViewport(0, 0, m_frameBuffer.width, m_frameBuffer.height); + // draw begin + core::gl::drawMainView(&m_ctx); + // draw end + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +const glutils::FrameBuffer &SceneEditorView::framebuffer() const noexcept { + return m_frameBuffer; +} + +} diff --git a/src/nostalgia/scene/studio/sceneeditorview.hpp b/src/nostalgia/scene/studio/sceneeditorview.hpp new file mode 100644 index 00000000..a3072d95 --- /dev/null +++ b/src/nostalgia/scene/studio/sceneeditorview.hpp @@ -0,0 +1,33 @@ +/* + * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. + */ + +#pragma once + +#include +#include +#include + +namespace nostalgia::scene { + +class SceneEditorView { + + private: + core::Context &m_ctx; + const SceneStatic &m_sceneStatic; + Scene m_scene; + glutils::FrameBuffer m_frameBuffer; + + public: + SceneEditorView(core::Context *ctx, const SceneStatic &sceneStatic) noexcept; + + void setupScene() noexcept; + + void draw(int width, int height) noexcept; + + [[nodiscard]] + const glutils::FrameBuffer &framebuffer() const noexcept; + +}; + +}