From 4a95a79926715528bf4ca7466d5b382c0aa00c6f Mon Sep 17 00:00:00 2001
From: Gary Talent <gary@drinkingtea.net>
Date: Sat, 11 Mar 2023 18:45:35 -0600
Subject: [PATCH] [nostalgia/scene] ACTUALLY add Scene Studio module

---
 src/nostalgia/scene/studio/CMakeLists.txt     | 25 ++++++++
 src/nostalgia/scene/studio/module.cpp         | 32 ++++++++++
 src/nostalgia/scene/studio/module.hpp         | 17 ++++++
 .../scene/studio/sceneeditor-imgui.cpp        | 59 +++++++++++++++++++
 .../scene/studio/sceneeditor-imgui.hpp        | 43 ++++++++++++++
 src/nostalgia/scene/studio/sceneeditor.cpp    | 15 +++++
 src/nostalgia/scene/studio/sceneeditor.hpp    | 33 +++++++++++
 .../scene/studio/sceneeditorview.cpp          | 37 ++++++++++++
 .../scene/studio/sceneeditorview.hpp          | 33 +++++++++++
 9 files changed, 294 insertions(+)
 create mode 100644 src/nostalgia/scene/studio/CMakeLists.txt
 create mode 100644 src/nostalgia/scene/studio/module.cpp
 create mode 100644 src/nostalgia/scene/studio/module.hpp
 create mode 100644 src/nostalgia/scene/studio/sceneeditor-imgui.cpp
 create mode 100644 src/nostalgia/scene/studio/sceneeditor-imgui.hpp
 create mode 100644 src/nostalgia/scene/studio/sceneeditor.cpp
 create mode 100644 src/nostalgia/scene/studio/sceneeditor.hpp
 create mode 100644 src/nostalgia/scene/studio/sceneeditorview.cpp
 create mode 100644 src/nostalgia/scene/studio/sceneeditorview.hpp

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 <ox/std/memory.hpp>
+
+#include "sceneeditor-imgui.hpp"
+#include "module.hpp"
+
+namespace nostalgia::scene {
+
+ox::Vector<studio::EditorMaker> StudioModule::editors(core::Context *ctx) noexcept {
+	return {
+		{
+			{"nscn"},
+			[ctx](ox::CRStringView path) -> ox::Result<studio::BaseEditor*> {
+				try {
+					return ox::make<SceneEditorImGui>(ctx, path);
+				} catch (const ox::Exception &ex) {
+					return ex.toError();
+				}
+			}
+		},
+	};
+}
+
+ox::Vector<ox::UPtr<studio::ItemMaker>> StudioModule::itemMakers(core::Context*) noexcept {
+	ox::Vector<ox::UPtr<studio::ItemMaker>> 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 <nostalgia/studio/studio.hpp>
+
+namespace nostalgia::scene {
+
+class StudioModule: public studio::Module {
+	public:
+		ox::Vector<studio::EditorMaker> editors(core::Context *ctx) noexcept override;
+		ox::Vector<ox::UPtr<studio::ItemMaker>> 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 <imgui.h>
+
+#include <nostalgia/core/gfx.hpp>
+#include <nostalgia/foundation/media.hpp>
+#include <ox/std/memory.hpp>
+
+#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<int>(paneSize.x),
+		static_cast<int>(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<void*>(buffId),
+		paneSize,
+		ImVec2(0, 1),
+		ImVec2(1, 0));
+}
+
+void SceneEditorImGui::onActivated() noexcept {
+	m_view.setupScene();
+}
+
+ox::Error SceneEditorImGui::saveItem() noexcept {
+	const auto sctx = applicationData<studio::StudioContext>(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 <nostalgia/core/gfx.hpp>
+#include <nostalgia/studio/studio.hpp>
+
+#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<SceneStatic>(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 <nostalgia/core/gfx.hpp>
+#include <nostalgia/studio/studio.hpp>
+#include <nostalgia/scene/scene.hpp>
+
+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 <nostalgia/core/gfx.hpp>
+#include <nostalgia/glutils/glutils.hpp>
+#include <nostalgia/scene/scene.hpp>
+
+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;
+
+};
+
+}