Compare commits
2 Commits
4e5c749918
...
6924147686
Author | SHA1 | Date | |
---|---|---|---|
6924147686 | |||
6e2b4fa7b4 |
9
Makefile
9
Makefile
@ -5,9 +5,11 @@ BUILDCORE_PATH=deps/buildcore
|
||||
include ${BUILDCORE_PATH}/base.mk
|
||||
|
||||
ifeq ($(BC_VAR_OS),darwin)
|
||||
PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME}.app/Contents/MacOS/${BC_VAR_PROJECT_NAME}
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio.app/Contents/MacOS/${BC_VAR_PROJECT_NAME_CAP}Studio
|
||||
MGBA=/Applications/mGBA.app/Contents/MacOS/mGBA
|
||||
else
|
||||
PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME}
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}Studio
|
||||
MGBA=mgba-qt
|
||||
endif
|
||||
@ -16,9 +18,12 @@ endif
|
||||
pkg-gba: build
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
|
||||
|
||||
.PHONY: build-player
|
||||
build-player:
|
||||
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} ${BC_VAR_PROJECT_NAME}
|
||||
.PHONY: run
|
||||
run: build
|
||||
./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
|
||||
run: build-player
|
||||
${PROJECT_PLAYER} sample_project
|
||||
.PHONY: run-studio
|
||||
run-studio: build
|
||||
${NOSTALGIA_STUDIO}
|
||||
|
@ -22,6 +22,12 @@ void NewMenu::open() noexcept {
|
||||
m_selectedType = 0;
|
||||
m_itemName = "";
|
||||
m_typeName = "";
|
||||
m_path = "";
|
||||
}
|
||||
|
||||
void NewMenu::openPath(ox::StringParam path) noexcept {
|
||||
open();
|
||||
m_path = std::move(path);
|
||||
}
|
||||
|
||||
void NewMenu::close() noexcept {
|
||||
@ -158,14 +164,14 @@ void NewMenu::finish(StudioContext &sctx) noexcept {
|
||||
oxLogError(ox::Error{1, "New file error: no file name"});
|
||||
return;
|
||||
}
|
||||
auto const&im = *m_types[static_cast<std::size_t>(m_selectedType)];
|
||||
if (sctx.project->exists(im.itemPath(m_itemName))) {
|
||||
auto const&im = *m_types[m_selectedType];
|
||||
auto const path = m_path.len() ?
|
||||
im.itemPath(m_itemName, m_path) : im.itemPath(m_itemName);
|
||||
if (sctx.project->exists(path)) {
|
||||
oxLogError(ox::Error{1, "New file error: file already exists"});
|
||||
return;
|
||||
}
|
||||
auto const [path, err] =
|
||||
im.write(sctx, m_itemName, m_selectedTemplate);
|
||||
if (err) {
|
||||
if (auto const err = im.write(sctx, path, m_selectedTemplate)) {
|
||||
oxLogError(err);
|
||||
return;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ class NewMenu final: public Popup {
|
||||
Stage m_stage = Stage::Closed;
|
||||
ox::String m_typeName;
|
||||
ox::IString<255> m_itemName;
|
||||
ox::String m_path;
|
||||
ox::Vector<ox::UPtr<studio::ItemMaker>> m_types;
|
||||
size_t m_selectedType = 0;
|
||||
size_t m_selectedTemplate = 0;
|
||||
@ -38,6 +39,8 @@ class NewMenu final: public Popup {
|
||||
public:
|
||||
NewMenu() noexcept;
|
||||
|
||||
void openPath(ox::StringParam path) noexcept;
|
||||
|
||||
void open() noexcept override;
|
||||
|
||||
void close() noexcept override;
|
||||
|
@ -19,7 +19,8 @@ class ProjectExplorer: public Widget {
|
||||
|
||||
public:
|
||||
// slots
|
||||
ox::Signal<ox::Error(ox::StringView const&)> fileChosen;
|
||||
ox::Signal<ox::Error(ox::StringViewCR)> fileChosen;
|
||||
ox::Signal<ox::Error(ox::StringViewCR)> addItem;
|
||||
|
||||
explicit ProjectExplorer(turbine::Context &ctx) noexcept;
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <studio/imguiutil.hpp>
|
||||
|
||||
#include "projectexplorer.hpp"
|
||||
#include "projecttreemodel.hpp"
|
||||
|
||||
@ -30,10 +32,14 @@ bool ProjectTreeModel::draw(turbine::Context &ctx) const noexcept {
|
||||
constexpr auto dirFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
|
||||
if (!m_children.empty()) {
|
||||
if (ImGui::TreeNodeEx(m_name.c_str(), dirFlags)) {
|
||||
drawDirContextMenu();
|
||||
for (auto const&child : m_children) {
|
||||
updated = child->draw(ctx) || updated;
|
||||
}
|
||||
ImGui::TreePop();
|
||||
} else {
|
||||
ig::IDStackItem const idStackItem{m_name};
|
||||
drawDirContextMenu();
|
||||
}
|
||||
} else {
|
||||
auto const path = fullPath();
|
||||
@ -58,6 +64,15 @@ void ProjectTreeModel::setChildren(ox::Vector<ox::UPtr<ProjectTreeModel>> childr
|
||||
m_children = std::move(children);
|
||||
}
|
||||
|
||||
void ProjectTreeModel::drawDirContextMenu() const noexcept {
|
||||
if (ImGui::BeginPopupContextItem("DirMenu", ImGuiPopupFlags_MouseButtonRight)) {
|
||||
if (ImGui::MenuItem("Add Item")) {
|
||||
m_explorer.addItem.emit(fullPath());
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
ox::BasicString<255> ProjectTreeModel::fullPath() const noexcept {
|
||||
if (m_parent) {
|
||||
return m_parent->fullPath() + "/" + ox::StringView(m_name);
|
||||
|
@ -31,6 +31,8 @@ class ProjectTreeModel {
|
||||
void setChildren(ox::Vector<ox::UPtr<ProjectTreeModel>> children) noexcept;
|
||||
|
||||
private:
|
||||
void drawDirContextMenu() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::BasicString<255> fullPath() const noexcept;
|
||||
|
||||
|
@ -52,6 +52,7 @@ StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexce
|
||||
m_aboutPopup(m_tctx) {
|
||||
turbine::setApplicationData(m_tctx, &m_sctx);
|
||||
m_projectExplorer.fileChosen.connect(this, &StudioUI::openFile);
|
||||
m_projectExplorer.addItem.connect(this, &StudioUI::addFile);
|
||||
m_newProject.finished.connect(this, &StudioUI::createOpenProject);
|
||||
m_newMenu.finished.connect(this, &StudioUI::openFile);
|
||||
ImGui::GetIO().IniFilename = nullptr;
|
||||
@ -342,6 +343,11 @@ void StudioUI::handleKeyInput() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error StudioUI::addFile(ox::StringViewCR path) noexcept {
|
||||
m_newMenu.openPath(path);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error StudioUI::createOpenProject(ox::StringViewCR path) noexcept {
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(toStdStringView(path), ec);
|
||||
|
@ -83,6 +83,8 @@ class StudioUI: public ox::SignalHandler {
|
||||
|
||||
void handleKeyInput() noexcept;
|
||||
|
||||
ox::Error addFile(ox::StringViewCR path) noexcept;
|
||||
|
||||
ox::Error createOpenProject(ox::StringViewCR path) noexcept;
|
||||
|
||||
ox::Error openProjectPath(ox::StringParam path) noexcept;
|
||||
|
@ -128,6 +128,16 @@ class ItemMaker {
|
||||
return m_templates;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String const&defaultPath() const noexcept {
|
||||
return m_parentDir;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String itemPath(ox::StringViewCR pName, ox::StringViewCR pPath) const noexcept {
|
||||
return ox::sfmt("/{}/{}.{}", pPath, pName, m_fileExt);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String itemPath(ox::StringViewCR pName) const noexcept {
|
||||
return ox::sfmt("/{}/{}.{}", m_parentDir, pName, m_fileExt);
|
||||
@ -142,12 +152,40 @@ class ItemMaker {
|
||||
/**
|
||||
* Returns path of the file created.
|
||||
* @param ctx
|
||||
* @param pPath
|
||||
* @param pTemplateIdx
|
||||
* @return path of file or error in Result
|
||||
*/
|
||||
ox::Error write(
|
||||
StudioContext &ctx,
|
||||
ox::StringViewCR pPath,
|
||||
size_t pTemplateIdx) const noexcept {
|
||||
return writeItem(ctx, pPath, pTemplateIdx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns path of the file created.
|
||||
* @param ctx
|
||||
* @param pPath
|
||||
* @param pName
|
||||
* @param pTemplateIdx
|
||||
* @return path of file or error in Result
|
||||
*/
|
||||
virtual ox::Result<ox::String> write(
|
||||
StudioContext &ctx, ox::StringViewCR pName, size_t pTemplateIdx) const noexcept = 0;
|
||||
ox::Error write(
|
||||
StudioContext &ctx,
|
||||
ox::StringViewCR pPath,
|
||||
ox::StringViewCR pName,
|
||||
size_t pTemplateIdx) const noexcept {
|
||||
auto const path = itemPath(pName, pPath);
|
||||
return writeItem(ctx, path, pTemplateIdx);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ox::Error writeItem(
|
||||
StudioContext &ctx,
|
||||
ox::StringViewCR pPath,
|
||||
size_t pTemplateIdx) const noexcept = 0;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@ -205,20 +243,19 @@ class ItemMakerT final: public ItemMaker {
|
||||
return ox::ModelTypeVersion_v<T>;
|
||||
}
|
||||
|
||||
ox::Result<ox::String> write(
|
||||
StudioContext &sctx,
|
||||
ox::StringViewCR pName,
|
||||
ox::Error writeItem(
|
||||
StudioContext &ctx,
|
||||
ox::StringViewCR pPath,
|
||||
size_t const pTemplateIdx) const noexcept override {
|
||||
auto const path = itemPath(pName);
|
||||
createUuidMapping(keelCtx(sctx.tctx), path, ox::UUID::generate().unwrap());
|
||||
createUuidMapping(keelCtx(ctx.tctx), pPath, ox::UUID::generate().unwrap());
|
||||
auto const&templates = itemTemplates();
|
||||
auto const tmplIdx = pTemplateIdx < templates.size() ? pTemplateIdx : 0;
|
||||
OX_REQUIRE_M(tmpl, templates[tmplIdx]->getItem(
|
||||
keelCtx(sctx), typeName(), typeVersion()));
|
||||
keelCtx(ctx), typeName(), typeVersion()));
|
||||
auto item = tmpl.template get<T>();
|
||||
OX_RETURN_ERROR(sctx.project->writeObj(path, *item, m_fmt));
|
||||
OX_RETURN_ERROR(ctx.project->writeObj(pPath, *item, m_fmt));
|
||||
tmpl.free();
|
||||
return path;
|
||||
return {};
|
||||
}
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user