[nostalgia,studio] Make studio a library

This commit is contained in:
Gary Talent 2023-06-03 02:53:15 -05:00
parent 6593d429fe
commit 10d1e860bb
65 changed files with 381 additions and 371 deletions

View File

@ -2,6 +2,7 @@ include_directories(".")
if(NOSTALGIA_BUILD_TYPE STREQUAL "Native") if(NOSTALGIA_BUILD_TYPE STREQUAL "Native")
add_subdirectory(glutils) add_subdirectory(glutils)
add_subdirectory(studio)
endif() endif()
add_subdirectory(keel) add_subdirectory(keel)
add_subdirectory(nostalgia) add_subdirectory(nostalgia)

View File

@ -4,7 +4,7 @@
#pragma once #pragma once
#include <nostalgia/studio/studio.hpp> #include <studio/studio.hpp>
namespace nostalgia::core { namespace nostalgia::core {

View File

@ -4,8 +4,9 @@
#pragma once #pragma once
#include <studio/studio.hpp>
#include <nostalgia/core/gfx.hpp> #include <nostalgia/core/gfx.hpp>
#include <nostalgia/studio/studio.hpp>
namespace nostalgia::core { namespace nostalgia::core {

View File

@ -4,8 +4,9 @@
#pragma once #pragma once
#include <studio/studio.hpp>
#include <nostalgia/core/gfx.hpp> #include <nostalgia/core/gfx.hpp>
#include <nostalgia/studio/studio.hpp>
namespace nostalgia::core { namespace nostalgia::core {

View File

@ -8,8 +8,7 @@
#include <ox/std/vec.hpp> #include <ox/std/vec.hpp>
#include <glutils/glutils.hpp> #include <glutils/glutils.hpp>
#include <studio/editor.hpp>
#include <nostalgia/studio/studio.hpp>
#include "tilesheetpixelgrid.hpp" #include "tilesheetpixelgrid.hpp"
#include "tilesheetpixels.hpp" #include "tilesheetpixels.hpp"

View File

@ -9,8 +9,9 @@
#include <ox/std/trace.hpp> #include <ox/std/trace.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include <studio/studio.hpp>
#include <nostalgia/core/gfx.hpp> #include <nostalgia/core/gfx.hpp>
#include <nostalgia/studio/studio.hpp>
namespace nostalgia::core { namespace nostalgia::core {

View File

@ -8,9 +8,9 @@
#include <ox/model/def.hpp> #include <ox/model/def.hpp>
#include <glutils/glutils.hpp> #include <glutils/glutils.hpp>
#include <studio/studio.hpp>
#include <nostalgia/core/gfx.hpp> #include <nostalgia/core/gfx.hpp>
#include <nostalgia/studio/studio.hpp>
#include "tilesheeteditormodel.hpp" #include "tilesheeteditormodel.hpp"
#include "tilesheetpixelgrid.hpp" #include "tilesheetpixelgrid.hpp"

View File

@ -5,9 +5,9 @@
#pragma once #pragma once
#include <glutils/glutils.hpp> #include <glutils/glutils.hpp>
#include <studio/studio.hpp>
#include <nostalgia/core/gfx.hpp> #include <nostalgia/core/gfx.hpp>
#include <nostalgia/studio/studio.hpp>
namespace nostalgia::core { namespace nostalgia::core {

View File

@ -7,9 +7,9 @@
#include <ox/std/vec.hpp> #include <ox/std/vec.hpp>
#include <glutils/glutils.hpp> #include <glutils/glutils.hpp>
#include <studio/studio.hpp>
#include <nostalgia/core/gfx.hpp> #include <nostalgia/core/gfx.hpp>
#include <nostalgia/studio/studio.hpp>
namespace nostalgia::core { namespace nostalgia::core {

View File

@ -12,8 +12,8 @@ endif()
target_link_libraries( target_link_libraries(
NostalgiaScene-Studio PUBLIC NostalgiaScene-Studio PUBLIC
NostalgiaStudio
NostalgiaScene NostalgiaScene
Studio
) )
install( install(

View File

@ -5,8 +5,7 @@
#pragma once #pragma once
#include <turbine/turbine.hpp> #include <turbine/turbine.hpp>
#include <studio/studio.hpp>
#include <nostalgia/studio/studio.hpp>
namespace nostalgia::scene { namespace nostalgia::scene {

View File

@ -4,8 +4,9 @@
#pragma once #pragma once
#include <studio/studio.hpp>
#include <nostalgia/core/gfx.hpp> #include <nostalgia/core/gfx.hpp>
#include <nostalgia/studio/studio.hpp>
#include "sceneeditor.hpp" #include "sceneeditor.hpp"
#include "sceneeditorview.hpp" #include "sceneeditorview.hpp"

View File

@ -4,8 +4,9 @@
#pragma once #pragma once
#include <studio/studio.hpp>
#include <nostalgia/core/gfx.hpp> #include <nostalgia/core/gfx.hpp>
#include <nostalgia/studio/studio.hpp>
#include <nostalgia/scene/scene.hpp> #include <nostalgia/scene/scene.hpp>
namespace nostalgia::scene { namespace nostalgia::scene {

View File

@ -2,25 +2,15 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable( add_executable(
nostalgia-studio MACOSX_BUNDLE nostalgia-studio MACOSX_BUNDLE
aboutpopup.cpp
builtinmodules.cpp
clawviewer.cpp
filedialogmanager.cpp
main.cpp main.cpp
newmenu.cpp
projectexplorer.cpp
projecttreemodel.cpp
studioapp.cpp
) )
target_link_libraries( target_link_libraries(
nostalgia-studio nostalgia-studio
OxClArgs
OxLogConn
NostalgiaAppModules NostalgiaAppModules
NostalgiaStudio
NostalgiaCore-Studio NostalgiaCore-Studio
NostalgiaScene-Studio NostalgiaScene-Studio
StudioAppLib
) )
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32) if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32)
@ -46,5 +36,3 @@ install(
${NOSTALGIA_DIST_BIN} ${NOSTALGIA_DIST_BIN}
BUNDLE DESTINATION . BUNDLE DESTINATION .
) )
add_subdirectory(lib)

View File

@ -1,22 +0,0 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#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" inline list in a header file...
ox::Vector<std::function<ox::UPtr<studio::Module>()>> 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());
},
};
}

View File

@ -1,58 +0,0 @@
add_library(
NostalgiaStudio
configio.cpp
editor.cpp
imguiutil.cpp
module.cpp
popup.cpp
project.cpp
task.cpp
undostack.cpp
widget.cpp
filedialog_nfd.cpp
)
if(NOT MSVC)
target_compile_options(NostalgiaStudio PUBLIC -Wsign-conversion)
endif()
install(
TARGETS
NostalgiaStudio
DESTINATION
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
generate_export_header(NostalgiaStudio)
target_include_directories(NostalgiaStudio PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
include_directories(
SYSTEM
${GTK3_INCLUDE_DIRS}
)
target_link_libraries(
NostalgiaStudio PUBLIC
nfd
OxEvent
Turbine
)
install(
FILES
configio.hpp
context.hpp
editor.hpp
filedialog.hpp
itemmaker.hpp
module.hpp
popup.hpp
project.hpp
task.hpp
undostack.hpp
widget.hpp
${CMAKE_CURRENT_BINARY_DIR}/nostalgiastudio_export.h
DESTINATION
include/nostalgia/studio/lib
)

View File

@ -1,9 +0,0 @@
/*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include "popup.hpp"
namespace nostalgia::studio {
}

View File

@ -1,9 +0,0 @@
/*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include "widget.hpp"
namespace nostalgia::studio {
}

View File

@ -2,87 +2,27 @@
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include <ctime> #include <ox/std/memory.hpp>
#include <ox/logconn/logconn.hpp>
#include <ox/std/trace.hpp>
#include <ox/std/uuid.hpp>
#include <keel/media.hpp>
#include <turbine/turbine.hpp>
#include <nostalgia/appmodules/appmodules.hpp> #include <nostalgia/appmodules/appmodules.hpp>
#include <nostalgia/core/studio/module.hpp>
#include <nostalgia/scene/studio/module.hpp>
#include "lib/context.hpp" #include <studioapp/studioapp.hpp>
#include "studioapp.hpp"
namespace nostalgia { using namespace nostalgia;
class StudioUIDrawer: public turbine::gl::Drawer { [[maybe_unused]] // GCC warns about the existence of this "unused" inline list in a header file...
private: ox::Vector<std::function<ox::UPtr<studio::Module>()>> BuiltinModules = {
StudioUI *m_ui = nullptr; []() -> ox::UPtr<studio::Module> {
public: return ox::UPtr<studio::Module>(new core::StudioModule());
explicit StudioUIDrawer(StudioUI *ui) noexcept: m_ui(ui) { },
} []() -> ox::UPtr<studio::Module> {
protected: return ox::UPtr<studio::Module>(new scene::StudioModule());
void draw(turbine::Context&) noexcept final { },
m_ui->draw();
}
}; };
static int updateHandler(turbine::Context &ctx) noexcept {
auto sctx = turbine::applicationData<studio::StudioContext>(ctx);
auto ui = dynamic_cast<StudioUI*>(sctx->ui);
ui->update();
return 16;
}
static void keyEventHandler(turbine::Context &ctx, turbine::Key key, bool down) noexcept {
auto sctx = turbine::applicationData<studio::StudioContext>(ctx);
auto ui = dynamic_cast<StudioUI*>(sctx->ui);
ui->handleKeyEvent(key, down);
}
static ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept {
oxRequireM(ctx, turbine::init(std::move(fs), "NostalgiaStudio"));
turbine::setWindowTitle(*ctx, "Nostalgia Studio");
turbine::setUpdateHandler(*ctx, updateHandler);
turbine::setKeyEventHandler(*ctx, keyEventHandler);
turbine::setConstantRefresh(*ctx, false);
studio::StudioContext studioCtx;
turbine::setApplicationData(*ctx, &studioCtx);
StudioUI ui(ctx.get());
studioCtx.ui = &ui;
StudioUIDrawer drawer(&ui);
turbine::gl::addDrawer(*ctx, &drawer);
const auto err = turbine::run(*ctx);
turbine::gl::removeDrawer(*ctx, &drawer);
return err;
}
static ox::Error run(int, const char**) noexcept {
ox::trace::init();
const auto time = std::time(nullptr);
ox::UUID::seedGenerator({
static_cast<uint64_t>(time),
static_cast<uint64_t>(time << 1)
});
loadModules();
return run(ox::UniquePtr<ox::FileSystem>(nullptr));
}
}
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
#ifdef DEBUG nostalgia::loadModules();
ox::LoggerConn loggerConn; return studio::main("Nostalgia Studio", ".nostalgia", argc, argv);
const auto loggerErr = loggerConn.initConn("Nostalgia Studio");
if (loggerErr) {
oxErrf("Could not connect to logger: {}\n", toStr(loggerErr));
} else {
ox::trace::setLogger(&loggerConn);
}
#endif
const auto err = nostalgia::run(argc, argv);
oxAssert(err, "Something went wrong...");
return static_cast<int>(err);
} }

View File

@ -1,17 +0,0 @@
/*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include "lib/context.hpp"
#include "lib/editor.hpp"
#include "lib/filedialog.hpp"
#include "lib/imguiuitl.hpp"
#include "lib/module.hpp"
#include "lib/itemmaker.hpp"
#include "lib/popup.hpp"
#include "lib/project.hpp"
#include "lib/task.hpp"
#include "lib/undostack.hpp"
#include "lib/widget.hpp"

View File

@ -0,0 +1,2 @@
add_subdirectory(applib)
add_subdirectory(modlib)

View File

@ -0,0 +1 @@
add_subdirectory(src)

View File

@ -0,0 +1,17 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <ox/std/string.hpp>
namespace studio {
int main(
const char *appName,
ox::String projectDataDir,
[[maybe_unused]] int argc,
[[maybe_unused]] const char **argv);
}

View File

@ -0,0 +1,33 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_library(
StudioAppLib
aboutpopup.cpp
clawviewer.cpp
filedialogmanager.cpp
main.cpp
newmenu.cpp
projectexplorer.cpp
projecttreemodel.cpp
studioapp.cpp
)
target_link_libraries(
StudioAppLib PUBLIC
OxClArgs
OxLogConn
Studio
)
target_include_directories(
StudioAppLib PUBLIC
../include
)
install(
TARGETS
StudioAppLib
DESTINATION
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

View File

@ -4,10 +4,12 @@
#include <imgui.h> #include <imgui.h>
#include "lib/imguiuitl.hpp" #include <studio/imguiuitl.hpp>
#include "aboutpopup.hpp" #include "aboutpopup.hpp"
namespace nostalgia { AboutPopup::AboutPopup(turbine::Context &ctx) noexcept {
m_text = ox::sfmt("{} - dev build", ctx.appName);
}
void AboutPopup::open() noexcept { void AboutPopup::open() noexcept {
m_stage = Stage::Opening; m_stage = Stage::Opening;
@ -36,7 +38,7 @@ void AboutPopup::draw(turbine::Context *ctx) noexcept {
studio::ig::centerNextWindow(ctx); studio::ig::centerNextWindow(ctx);
auto open = true; auto open = true;
if (ImGui::BeginPopupModal("About", &open, modalFlags)) { if (ImGui::BeginPopupModal("About", &open, modalFlags)) {
ImGui::Text("Nostalgia Studio - dev build"); ImGui::Text("%s", m_text.c_str());
ImGui::NewLine(); ImGui::NewLine();
ImGui::Dummy(ImVec2(148.0f, 0.0f)); ImGui::Dummy(ImVec2(148.0f, 0.0f));
ImGui::SameLine(); ImGui::SameLine();
@ -53,5 +55,3 @@ void AboutPopup::draw(turbine::Context *ctx) noexcept {
} }
} }
} }
}

View File

@ -9,9 +9,7 @@
#include <turbine/context.hpp> #include <turbine/context.hpp>
#include "lib/popup.hpp" #include <studio/popup.hpp>
namespace nostalgia {
class AboutPopup: public studio::Popup { class AboutPopup: public studio::Popup {
public: public:
@ -23,8 +21,11 @@ class AboutPopup: public studio::Popup {
private: private:
Stage m_stage = Stage::Closed; Stage m_stage = Stage::Closed;
ox::String m_text;
public: public:
explicit AboutPopup(turbine::Context &ctx) noexcept;
void open() noexcept override; void open() noexcept override;
void close() noexcept override; void close() noexcept override;
@ -35,5 +36,3 @@ class AboutPopup: public studio::Popup {
void draw(turbine::Context *ctx) noexcept override; void draw(turbine::Context *ctx) noexcept override;
}; };
}

View File

@ -4,12 +4,8 @@
#pragma once #pragma once
#include "lib/module.hpp" #include <studio/module.hpp>
#include <ox/std/memory.hpp> #include <ox/std/memory.hpp>
namespace nostalgia {
extern ox::Vector<std::function<ox::UPtr<studio::Module>()>> BuiltinModules; extern ox::Vector<std::function<ox::UPtr<studio::Module>()>> BuiltinModules;
}

View File

@ -6,8 +6,6 @@
#include "clawviewer.hpp" #include "clawviewer.hpp"
namespace nostalgia {
ClawEditor::ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept: ClawEditor::ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept:
m_itemName(path), m_itemName(path),
m_itemDisplayName(pathToItemName(path)), m_itemDisplayName(pathToItemName(path)),
@ -182,5 +180,3 @@ void ClawEditor::drawTree(ObjPath *path, const ox::ModelObject &obj) noexcept {
path->pop_back(); path->pop_back();
} }
} }
}

View File

@ -7,9 +7,7 @@
#include <ox/model/modelvalue.hpp> #include <ox/model/modelvalue.hpp>
#include <turbine/context.hpp> #include <turbine/context.hpp>
#include "lib/editor.hpp" #include <studio/editor.hpp>
namespace nostalgia {
class ClawEditor: public studio::Editor { class ClawEditor: public studio::Editor {
private: private:
@ -37,4 +35,3 @@ class ClawEditor: public studio::Editor {
void drawTree(ObjPath *path, const ox::ModelObject &obj) noexcept; void drawTree(ObjPath *path, const ox::ModelObject &obj) noexcept;
}; };
}

View File

@ -6,8 +6,6 @@
#include "filedialogmanager.hpp" #include "filedialogmanager.hpp"
namespace nostalgia {
studio::TaskState FileDialogManager::update(turbine::Context *ctx) noexcept { studio::TaskState FileDialogManager::update(turbine::Context *ctx) noexcept {
switch (m_state) { switch (m_state) {
case UpdateProjectPathState::EnableSystemCursor: { case UpdateProjectPathState::EnableSystemCursor: {
@ -26,12 +24,11 @@ studio::TaskState FileDialogManager::update(turbine::Context *ctx) noexcept {
oxAssert(err, "Path chosen response failed"); oxAssert(err, "Path chosen response failed");
} }
m_state = UpdateProjectPathState::None; m_state = UpdateProjectPathState::None;
return nostalgia::studio::TaskState::Done; return studio::TaskState::Done;
} }
case UpdateProjectPathState::None: case UpdateProjectPathState::None:
break; break;
} }
return nostalgia::studio::TaskState::Running; return studio::TaskState::Running;
} }
}

View File

@ -9,12 +9,10 @@
#include <turbine/context.hpp> #include <turbine/context.hpp>
#include "lib/filedialog.hpp" #include <studio/filedialog.hpp>
#include "lib/task.hpp" #include <studio/task.hpp>
namespace nostalgia { class FileDialogManager : public studio::Task {
class FileDialogManager : public nostalgia::studio::Task {
private: private:
enum class UpdateProjectPathState { enum class UpdateProjectPathState {
None, None,
@ -33,11 +31,9 @@ class FileDialogManager : public nostalgia::studio::Task {
~FileDialogManager() noexcept override = default; ~FileDialogManager() noexcept override = default;
nostalgia::studio::TaskState update(turbine::Context *ctx) noexcept final; studio::TaskState update(turbine::Context *ctx) noexcept final;
// signals // signals
ox::Signal<ox::Error(const ox::String &)> pathChosen; ox::Signal<ox::Error(const ox::String &)> pathChosen;
}; };
}

View File

@ -0,0 +1,91 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <ctime>
#include <ox/logconn/logconn.hpp>
#include <ox/std/trace.hpp>
#include <ox/std/uuid.hpp>
#include <keel/media.hpp>
#include <turbine/turbine.hpp>
#include <nostalgia/appmodules/appmodules.hpp>
#include <studio/context.hpp>
#include "studioapp.hpp"
class StudioUIDrawer: public turbine::gl::Drawer {
private:
StudioUI *m_ui = nullptr;
public:
explicit StudioUIDrawer(StudioUI *ui) noexcept: m_ui(ui) {
}
protected:
void draw(turbine::Context&) noexcept final {
m_ui->draw();
}
};
static int updateHandler(turbine::Context &ctx) noexcept {
auto sctx = turbine::applicationData<studio::StudioContext>(ctx);
auto ui = dynamic_cast<StudioUI*>(sctx->ui);
ui->update();
return 16;
}
static void keyEventHandler(turbine::Context &ctx, turbine::Key key, bool down) noexcept {
auto sctx = turbine::applicationData<studio::StudioContext>(ctx);
auto ui = dynamic_cast<StudioUI*>(sctx->ui);
ui->handleKeyEvent(key, down);
}
static ox::Error runApp(
ox::CRStringView appName,
ox::String projectDataDir,
ox::UniquePtr<ox::FileSystem> fs) noexcept {
oxRequireM(ctx, turbine::init(std::move(fs), appName));
turbine::setWindowTitle(*ctx, ctx->appName);
turbine::setUpdateHandler(*ctx, updateHandler);
turbine::setKeyEventHandler(*ctx, keyEventHandler);
turbine::setConstantRefresh(*ctx, false);
studio::StudioContext studioCtx;
turbine::setApplicationData(*ctx, &studioCtx);
StudioUI ui(ctx.get(), std::move(projectDataDir));
studioCtx.ui = &ui;
StudioUIDrawer drawer(&ui);
turbine::gl::addDrawer(*ctx, &drawer);
const auto err = turbine::run(*ctx);
turbine::gl::removeDrawer(*ctx, &drawer);
return err;
}
namespace studio {
int main(
const char *appName,
ox::String projectDataDir,
[[maybe_unused]] int argc,
[[maybe_unused]] const char **argv) {
#ifdef DEBUG
ox::LoggerConn loggerConn;
const auto loggerErr = loggerConn.initConn(appName);
if (loggerErr) {
oxErrf("Could not connect to logger: {}\n", toStr(loggerErr));
} else {
ox::trace::setLogger(&loggerConn);
}
#endif
ox::trace::init();
// run app
const auto time = std::time(nullptr);
ox::UUID::seedGenerator({
static_cast<uint64_t>(time),
static_cast<uint64_t>(time << 1)
});
const auto err = runApp(appName, std::move(projectDataDir), ox::UniquePtr<ox::FileSystem>(nullptr));
oxAssert(err, "Something went wrong...");
return static_cast<int>(err);
}
}

View File

@ -4,13 +4,11 @@
#include <imgui.h> #include <imgui.h>
#include "lib/context.hpp" #include <studio/context.hpp>
#include "lib/imguiuitl.hpp" #include <studio/imguiuitl.hpp>
#include "newmenu.hpp" #include "newmenu.hpp"
namespace nostalgia {
NewMenu::NewMenu() noexcept { NewMenu::NewMenu() noexcept {
setTitle("New Item"); setTitle("New Item");
setSize({225, 110}); setSize({225, 110});
@ -117,5 +115,3 @@ void NewMenu::finish(turbine::Context *ctx) noexcept {
finished.emit(""); finished.emit("");
m_stage = Stage::Closed; m_stage = Stage::Closed;
} }
}

View File

@ -8,10 +8,8 @@
#include <ox/event/signal.hpp> #include <ox/event/signal.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include "lib/itemmaker.hpp" #include <studio/itemmaker.hpp>
#include "lib/popup.hpp" #include <studio/popup.hpp>
namespace nostalgia {
class NewMenu: public studio::Popup { class NewMenu: public studio::Popup {
public: public:
@ -75,5 +73,3 @@ template<typename T>
void NewMenu::addItemType(ox::String displayName, ox::String parentDir, ox::String fileExt, ox::ClawFormat pFmt) noexcept { void NewMenu::addItemType(ox::String displayName, ox::String parentDir, ox::String fileExt, ox::ClawFormat pFmt) noexcept {
m_types.emplace_back(ox::make<studio::ItemMakerT<T>>(std::move(displayName), std::move(parentDir), std::move(fileExt), pFmt)); m_types.emplace_back(ox::make<studio::ItemMakerT<T>>(std::move(displayName), std::move(parentDir), std::move(fileExt), pFmt));
} }
}

View File

@ -8,8 +8,6 @@
#include "projectexplorer.hpp" #include "projectexplorer.hpp"
namespace nostalgia {
static ox::Result<ox::UniquePtr<ProjectTreeModel>> static ox::Result<ox::UniquePtr<ProjectTreeModel>>
buildProjectTreeModel(ProjectExplorer *explorer, ox::CRStringView name, ox::CRStringView path, ProjectTreeModel *parent) noexcept { buildProjectTreeModel(ProjectExplorer *explorer, ox::CRStringView name, ox::CRStringView path, ProjectTreeModel *parent) noexcept {
const auto fs = explorer->romFs(); const auto fs = explorer->romFs();
@ -61,6 +59,3 @@ ox::Error ProjectExplorer::refreshProjectTreeModel(ox::CRStringView) noexcept {
setModel(std::move(model)); setModel(std::move(model));
return OxError(0); return OxError(0);
} }
}

View File

@ -7,11 +7,9 @@
#include <ox/event/signal.hpp> #include <ox/event/signal.hpp>
#include <ox/std/memory.hpp> #include <ox/std/memory.hpp>
#include "lib/widget.hpp" #include <studio/widget.hpp>
#include "projecttreemodel.hpp" #include "projecttreemodel.hpp"
namespace nostalgia {
class ProjectExplorer: public studio::Widget { class ProjectExplorer: public studio::Widget {
private: private:
ox::UniquePtr<ProjectTreeModel> m_treeModel; ox::UniquePtr<ProjectTreeModel> m_treeModel;
@ -34,5 +32,3 @@ class ProjectExplorer: public studio::Widget {
public: public:
ox::Signal<ox::Error(const ox::StringView&)> fileChosen; ox::Signal<ox::Error(const ox::StringView&)> fileChosen;
}; };
}

View File

@ -7,8 +7,6 @@
#include "projectexplorer.hpp" #include "projectexplorer.hpp"
#include "projecttreemodel.hpp" #include "projecttreemodel.hpp"
namespace nostalgia {
ProjectTreeModel::ProjectTreeModel(ProjectExplorer *explorer, ox::String name, ProjectTreeModel::ProjectTreeModel(ProjectExplorer *explorer, ox::String name,
ProjectTreeModel *parent) noexcept: ProjectTreeModel *parent) noexcept:
m_explorer(explorer), m_explorer(explorer),
@ -54,5 +52,3 @@ ox::BasicString<255> ProjectTreeModel::fullPath() const noexcept {
} }
return ""; return "";
} }
}

View File

@ -9,8 +9,6 @@
#include <turbine/context.hpp> #include <turbine/context.hpp>
namespace nostalgia {
class ProjectTreeModel { class ProjectTreeModel {
private: private:
class ProjectExplorer *m_explorer = nullptr; class ProjectExplorer *m_explorer = nullptr;
@ -31,5 +29,3 @@ class ProjectTreeModel {
[[nodiscard]] [[nodiscard]]
ox::BasicString<255> fullPath() const noexcept; ox::BasicString<255> fullPath() const noexcept;
}; };
}

View File

@ -7,16 +7,14 @@
#include <keel/media.hpp> #include <keel/media.hpp>
#include <turbine/turbine.hpp> #include <turbine/turbine.hpp>
#include "lib/configio.hpp" #include <studio/configio.hpp>
#include "builtinmodules.hpp" #include "builtinmodules.hpp"
#include "clawviewer.hpp" #include "clawviewer.hpp"
#include "filedialogmanager.hpp" #include "filedialogmanager.hpp"
#include "studioapp.hpp" #include "studioapp.hpp"
namespace nostalgia {
struct StudioConfig { struct StudioConfig {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.studio.StudioConfig"; static constexpr auto TypeName = "net.drinkingtea.studio.StudioConfig";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
ox::String projectPath; ox::String projectPath;
ox::String activeTabItemName; ox::String activeTabItemName;
@ -31,9 +29,11 @@ oxModelBegin(StudioConfig)
oxModelFieldRename(show_project_explorer, showProjectExplorer) oxModelFieldRename(show_project_explorer, showProjectExplorer)
oxModelEnd() oxModelEnd()
StudioUI::StudioUI(turbine::Context *ctx) noexcept { StudioUI::StudioUI(turbine::Context *ctx, ox::String projectDir) noexcept:
m_ctx = ctx; m_ctx(ctx),
m_projectExplorer = ox::make_unique<ProjectExplorer>(m_ctx); m_projectDir(std::move(projectDir)),
m_projectExplorer(ox::make_unique<ProjectExplorer>(m_ctx)),
m_aboutPopup(*ctx) {
m_projectExplorer->fileChosen.connect(this, &StudioUI::openFile); m_projectExplorer->fileChosen.connect(this, &StudioUI::openFile);
ImGui::GetIO().IniFilename = nullptr; ImGui::GetIO().IniFilename = nullptr;
loadModules(); loadModules();
@ -292,8 +292,8 @@ void StudioUI::save() noexcept {
ox::Error StudioUI::openProject(ox::CRStringView path) noexcept { ox::Error StudioUI::openProject(ox::CRStringView path) noexcept {
oxRequireM(fs, keel::loadRomFs(path)); oxRequireM(fs, keel::loadRomFs(path));
oxReturnError(keel::setRomFs(m_ctx, std::move(fs))); oxReturnError(keel::setRomFs(m_ctx, std::move(fs)));
turbine::setWindowTitle(*m_ctx, ox::sfmt("Nostalgia Studio - {}", path)); turbine::setWindowTitle(*m_ctx, ox::sfmt("{} - {}", m_ctx->appName, path));
m_project = ox::make_unique<studio::Project>(m_ctx, path); m_project = ox::make_unique<studio::Project>(m_ctx, path, m_projectDir);
auto sctx = applicationData<studio::StudioContext>(*m_ctx); auto sctx = applicationData<studio::StudioContext>(*m_ctx);
sctx->project = m_project.get(); sctx->project = m_project.get();
m_project->fileAdded.connect(m_projectExplorer.get(), &ProjectExplorer::refreshProjectTreeModel); m_project->fileAdded.connect(m_projectExplorer.get(), &ProjectExplorer::refreshProjectTreeModel);
@ -355,7 +355,7 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
config->openFiles.emplace_back(path); config->openFiles.emplace_back(path);
} }
}); });
return OxError(0); return {};
} }
ox::Error StudioUI::closeFile(const ox::String &path) noexcept { ox::Error StudioUI::closeFile(const ox::String &path) noexcept {
@ -369,5 +369,3 @@ ox::Error StudioUI::closeFile(const ox::String &path) noexcept {
}); });
return OxError(0); return OxError(0);
} }
}

View File

@ -8,24 +8,23 @@
#include <ox/std/memory.hpp> #include <ox/std/memory.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include "lib/editor.hpp" #include <studio/editor.hpp>
#include "lib/module.hpp" #include <studio/module.hpp>
#include "lib/project.hpp" #include <studio/project.hpp>
#include "lib/task.hpp" #include <studio/task.hpp>
#include "aboutpopup.hpp" #include "aboutpopup.hpp"
#include "newmenu.hpp" #include "newmenu.hpp"
#include "projectexplorer.hpp" #include "projectexplorer.hpp"
#include "projecttreemodel.hpp" #include "projecttreemodel.hpp"
namespace nostalgia {
class StudioUI: public ox::SignalHandler { class StudioUI: public ox::SignalHandler {
friend class StudioUIDrawer; friend class StudioUIDrawer;
private: private:
turbine::Context *m_ctx = nullptr;
ox::String m_projectDir;
ox::UniquePtr<studio::Project> m_project; ox::UniquePtr<studio::Project> m_project;
studio::TaskRunner m_taskRunner; studio::TaskRunner m_taskRunner;
turbine::Context *m_ctx = nullptr;
ox::Vector<ox::UniquePtr<studio::BaseEditor>> m_editors; ox::Vector<ox::UniquePtr<studio::BaseEditor>> m_editors;
ox::Vector<ox::UniquePtr<studio::Widget>> m_widgets; ox::Vector<ox::UniquePtr<studio::Widget>> m_widgets;
ox::HashMap<ox::String, studio::EditorMaker::Func> m_editorMakers; ox::HashMap<ox::String, studio::EditorMaker::Func> m_editorMakers;
@ -43,7 +42,7 @@ class StudioUI: public ox::SignalHandler {
bool m_showProjectExplorer = true; bool m_showProjectExplorer = true;
public: public:
explicit StudioUI(turbine::Context *ctx) noexcept; explicit StudioUI(turbine::Context *ctx, ox::String projectDir) noexcept;
void update() noexcept; void update() noexcept;
@ -87,4 +86,12 @@ class StudioUI: public ox::SignalHandler {
ox::Error closeFile(const ox::String &path) noexcept; ox::Error closeFile(const ox::String &path) noexcept;
}; };
namespace studio {
int main(
const char *appName,
ox::String projectDataDir,
[[maybe_unused]] int argc,
[[maybe_unused]] const char **argv);
} }

View File

@ -0,0 +1 @@
add_subdirectory(src)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#pragma once #pragma once
@ -15,7 +15,7 @@
#include <keel/context.hpp> #include <keel/context.hpp>
namespace nostalgia::studio { namespace studio {
[[nodiscard]] [[nodiscard]]
ox::String configPath(const keel::Context *ctx) noexcept; ox::String configPath(const keel::Context *ctx) noexcept;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#pragma once #pragma once
@ -8,7 +8,7 @@
#include "project.hpp" #include "project.hpp"
namespace nostalgia::studio { namespace studio {
struct StudioContext { struct StudioContext {
ox::SignalHandler *ui = nullptr; ox::SignalHandler *ui = nullptr;

View File

@ -9,15 +9,11 @@
#include "undostack.hpp" #include "undostack.hpp"
#include "widget.hpp" #include "widget.hpp"
#include "nostalgiastudio_export.h"
namespace nostalgia {
class StudioUI; class StudioUI;
}
namespace nostalgia::studio { namespace studio {
class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget { class BaseEditor: public Widget {
friend StudioUI; friend StudioUI;

View File

@ -1,12 +1,12 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#pragma once #pragma once
#include <ox/std/defines.hpp> #include <ox/std/defines.hpp>
namespace nostalgia::studio { namespace studio {
struct FDFilterItem { struct FDFilterItem {
#ifdef OX_OS_Windows #ifdef OX_OS_Windows

View File

@ -6,7 +6,7 @@
#include <turbine/context.hpp> #include <turbine/context.hpp>
namespace nostalgia::studio::ig { namespace studio::ig {
void centerNextWindow(turbine::Context *ctx) noexcept; void centerNextWindow(turbine::Context *ctx) noexcept;

View File

@ -11,7 +11,7 @@
#include "context.hpp" #include "context.hpp"
namespace nostalgia::studio { namespace studio {
class ItemMaker { class ItemMaker {
public: public:

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#pragma once #pragma once
@ -11,9 +11,7 @@
#include <turbine/context.hpp> #include <turbine/context.hpp>
#include <nostalgia/studio/studio.hpp> namespace studio {
namespace nostalgia::studio {
class ItemMaker; class ItemMaker;

View File

@ -12,7 +12,7 @@
#include "imguiuitl.hpp" #include "imguiuitl.hpp"
namespace nostalgia::studio { namespace studio {
class Popup { class Popup {

View File

@ -15,9 +15,7 @@
#include <keel/typestore.hpp> #include <keel/typestore.hpp>
#include <keel/media.hpp> #include <keel/media.hpp>
#include "nostalgiastudio_export.h" namespace studio {
namespace nostalgia::studio {
enum class ProjectEvent { enum class ProjectEvent {
None, None,
@ -38,16 +36,17 @@ constexpr ox::Result<ox::StringView> fileExt(ox::CRStringView path) noexcept {
return path.substr(extStart + 1); return path.substr(extStart + 1);
} }
class NOSTALGIASTUDIO_EXPORT Project { class Project {
private: private:
keel::Context *m_ctx = nullptr;
ox::String m_path; ox::String m_path;
ox::String m_projectDataDir;
mutable keel::TypeStore m_typeStore; mutable keel::TypeStore m_typeStore;
mutable ox::FileSystem *m_fs = nullptr; mutable ox::FileSystem *m_fs = nullptr;
keel::Context *m_ctx = nullptr;
ox::HashMap<ox::String, ox::Vector<ox::String>> m_fileExtFileMap; ox::HashMap<ox::String, ox::Vector<ox::String>> m_fileExtFileMap;
public: public:
explicit Project(keel::Context *ctx, ox::String path) noexcept; explicit Project(keel::Context *ctx, ox::String path, ox::CRStringView projectDir) noexcept;
ox::Error create() noexcept; ox::Error create() noexcept;
@ -113,7 +112,7 @@ ox::Error Project::writeObj(const ox::String &path, const T *obj, ox::ClawFormat
oxReturnError(ox::buildTypeDef(&m_typeStore, obj)); oxReturnError(ox::buildTypeDef(&m_typeStore, obj));
} }
// write out type store // write out type store
static constexpr auto descPath = "/.nostalgia/type_descriptors"; const auto descPath = ox::sfmt("/.{}/type_descriptors", m_projectDataDir);
oxReturnError(mkdir(descPath)); oxReturnError(mkdir(descPath));
for (const auto &t : m_typeStore.typeList()) { for (const auto &t : m_typeStore.typeList()) {
oxRequireM(typeOut, ox::writeClaw(t, ox::ClawFormat::Organic)); oxRequireM(typeOut, ox::writeClaw(t, ox::ClawFormat::Organic));

View File

@ -0,0 +1,17 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <studio/context.hpp>
#include <studio/editor.hpp>
#include <studio/filedialog.hpp>
#include <studio/imguiuitl.hpp>
#include <studio/module.hpp>
#include <studio/itemmaker.hpp>
#include <studio/popup.hpp>
#include <studio/project.hpp>
#include <studio/task.hpp>
#include <studio/undostack.hpp>
#include <studio/widget.hpp>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#pragma once #pragma once
@ -8,7 +8,7 @@
#include <turbine/context.hpp> #include <turbine/context.hpp>
namespace nostalgia::studio { namespace studio {
enum class TaskState { enum class TaskState {
Running, Running,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#pragma once #pragma once
@ -9,7 +9,7 @@
#include <ox/std/memory.hpp> #include <ox/std/memory.hpp>
#include <ox/std/vector.hpp> #include <ox/std/vector.hpp>
namespace nostalgia::studio { namespace studio {
class UndoCommand { class UndoCommand {
public: public:

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#pragma once #pragma once
@ -8,7 +8,7 @@
#include <turbine/context.hpp> #include <turbine/context.hpp>
namespace nostalgia::studio { namespace studio {
class Widget: public ox::SignalHandler { class Widget: public ox::SignalHandler {
public: public:

View File

@ -0,0 +1,60 @@
add_library(
Studio
configio.cpp
editor.cpp
imguiutil.cpp
module.cpp
popup.cpp
project.cpp
task.cpp
undostack.cpp
widget.cpp
filedialog_nfd.cpp
)
if(NOT MSVC)
target_compile_options(Studio PUBLIC -Wsign-conversion)
endif()
install(
TARGETS
Studio
DESTINATION
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
target_include_directories(
Studio PUBLIC
../include
)
include_directories(
SYSTEM
${GTK3_INCLUDE_DIRS}
)
target_link_libraries(
Studio PUBLIC
nfd
OxEvent
Turbine
)
install(
FILES
../include/studio/configio.hpp
../include/studio/context.hpp
../include/studio/editor.hpp
../include/studio/filedialog.hpp
../include/studio/itemmaker.hpp
../include/studio/module.hpp
../include/studio/popup.hpp
../include/studio/project.hpp
../include/studio/studio.hpp
../include/studio/task.hpp
../include/studio/undostack.hpp
../include/studio/widget.hpp
DESTINATION
include/studio/
)

View File

@ -1,10 +1,10 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include "configio.hpp" #include <studio/configio.hpp>
namespace nostalgia::studio { namespace studio {
constexpr auto ConfigDir = [] { constexpr auto ConfigDir = [] {
switch (ox::defines::OS) { switch (ox::defines::OS) {

View File

@ -6,9 +6,9 @@
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include "editor.hpp" #include <studio/editor.hpp>
namespace nostalgia::studio { namespace studio {
const ox::String &BaseEditor::itemDisplayName() const noexcept { const ox::String &BaseEditor::itemDisplayName() const noexcept {
return itemName(); return itemName();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include <nfd.hpp> #include <nfd.hpp>
@ -7,9 +7,9 @@
#include <ox/std/error.hpp> #include <ox/std/error.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include "filedialog.hpp" #include <studio/filedialog.hpp>
namespace nostalgia::studio { namespace studio {
FDFilterItem::FDFilterItem(ox::CRStringView pName, ox::CRStringView pSpec) noexcept { FDFilterItem::FDFilterItem(ox::CRStringView pName, ox::CRStringView pSpec) noexcept {
name.resize(pName.len() + 1); name.resize(pName.len() + 1);

View File

@ -1,12 +1,12 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include <imgui.h> #include <imgui.h>
#include <turbine/gfx.hpp> #include <turbine/gfx.hpp>
namespace nostalgia::studio::ig { namespace studio::ig {
void centerNextWindow(turbine::Context *ctx) noexcept { void centerNextWindow(turbine::Context *ctx) noexcept {
const auto sz = turbine::getScreenSize(*ctx); const auto sz = turbine::getScreenSize(*ctx);

View File

@ -1,10 +1,10 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include "module.hpp" #include <studio/module.hpp>
namespace nostalgia::studio { namespace studio {
ox::Vector<EditorMaker> Module::editors(turbine::Context*) { ox::Vector<EditorMaker> Module::editors(turbine::Context*) {
return {}; return {};

View File

@ -0,0 +1,7 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
namespace studio {
}

View File

@ -9,9 +9,9 @@
#include <keel/module.hpp> #include <keel/module.hpp>
#include "project.hpp" #include <studio/project.hpp>
namespace nostalgia::studio { namespace studio {
static void generateTypes(ox::TypeStore *ts) noexcept { static void generateTypes(ox::TypeStore *ts) noexcept {
for (const auto mod : keel::modules()) { for (const auto mod : keel::modules()) {
@ -21,12 +21,13 @@ static void generateTypes(ox::TypeStore *ts) noexcept {
} }
} }
Project::Project(keel::Context *ctx, ox::String path) noexcept: Project::Project(keel::Context *ctx, ox::String path, ox::CRStringView projectDataDir) noexcept:
m_path(std::move(path)), m_ctx(ctx),
m_typeStore(ctx->rom.get(), "/.nostalgia/type_descriptors"), m_path(path),
m_fs(ctx->rom.get()), m_projectDataDir(projectDataDir),
m_ctx(ctx) { m_typeStore(ctx->rom.get(), ox::sfmt("/.{}/type_descriptors", projectDataDir)),
oxTracef("nostalgia::studio", "Project: {}", m_path); m_fs(ctx->rom.get()) {
oxTracef("studio", "Project: {}", m_path);
generateTypes(&m_typeStore); generateTypes(&m_typeStore);
buildFileIndex(); buildFileIndex();
} }
@ -68,7 +69,7 @@ void Project::buildFileIndex() noexcept {
m_fileExtFileMap.clear(); m_fileExtFileMap.clear();
std::sort(files.begin(), files.end()); std::sort(files.begin(), files.end());
for (const auto &file : files) { for (const auto &file : files) {
if (!beginsWith(file, "/.nostalgia/")) { if (!beginsWith(file, ox::sfmt("/.{}/", m_projectDataDir))) {
indexFile(file); indexFile(file);
} }
} }

View File

@ -1,12 +1,12 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include <algorithm> #include <algorithm>
#include "task.hpp" #include <studio/task.hpp>
namespace nostalgia::studio { namespace studio {
void TaskRunner::update(turbine::Context *ctx) noexcept { void TaskRunner::update(turbine::Context *ctx) noexcept {
oxIgnoreError(m_tasks.erase(std::remove_if(m_tasks.begin(), m_tasks.end(), [&](ox::UPtr<studio::Task> &t) { oxIgnoreError(m_tasks.erase(std::remove_if(m_tasks.begin(), m_tasks.end(), [&](ox::UPtr<studio::Task> &t) {

View File

@ -1,10 +1,10 @@
/* /*
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include "undostack.hpp" #include <studio/undostack.hpp>
namespace nostalgia::studio { namespace studio {
bool UndoCommand::mergeWith(const UndoCommand*) noexcept { bool UndoCommand::mergeWith(const UndoCommand*) noexcept {
return false; return false;

View File

@ -0,0 +1,9 @@
/*
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <studio/widget.hpp>
namespace studio {
}