[olympic/studio/modlib] East const Studio
This commit is contained in:
		@@ -10,6 +10,6 @@
 | 
			
		||||
 | 
			
		||||
namespace studio {
 | 
			
		||||
 | 
			
		||||
void registerModule(const studio::Module*) noexcept;
 | 
			
		||||
void registerModule(studio::Module const*) noexcept;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ ClawEditor::ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept:
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ClawEditor::draw(turbine::Context&) noexcept {
 | 
			
		||||
	//const auto paneSize = ImGui::GetContentRegionAvail();
 | 
			
		||||
	ImGui::BeginChild("PaletteEditor");
 | 
			
		||||
	static constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
 | 
			
		||||
	if (ImGui::BeginTable("ObjTree", 3, flags)) {
 | 
			
		||||
@@ -23,13 +22,13 @@ void ClawEditor::draw(turbine::Context&) noexcept {
 | 
			
		||||
		ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_NoHide);
 | 
			
		||||
		ImGui::TableHeadersRow();
 | 
			
		||||
		ObjPath objPath;
 | 
			
		||||
		drawTree(&objPath, m_obj);
 | 
			
		||||
		drawTree(objPath, m_obj);
 | 
			
		||||
		ImGui::EndTable();
 | 
			
		||||
	}
 | 
			
		||||
	ImGui::EndChild();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ClawEditor::drawRow(const ox::ModelValue &value) noexcept {
 | 
			
		||||
void ClawEditor::drawRow(ox::ModelValue const&value) noexcept {
 | 
			
		||||
	using Str = ox::BasicString<100>;
 | 
			
		||||
	Str val, type;
 | 
			
		||||
	switch (value.type()) {
 | 
			
		||||
@@ -93,56 +92,56 @@ void ClawEditor::drawRow(const ox::ModelValue &value) noexcept {
 | 
			
		||||
	ImGui::Text("%s", val.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ClawEditor::drawVar(ObjPath *path, ox::CRStringView name, const ox::ModelValue &value) noexcept {
 | 
			
		||||
void ClawEditor::drawVar(ObjPath &path, ox::CRStringView name, ox::ModelValue const&value) noexcept {
 | 
			
		||||
	using Str = ox::BasicString<100>;
 | 
			
		||||
	path->push_back(name);
 | 
			
		||||
	path.push_back(name);
 | 
			
		||||
	if (value.type() == ox::ModelValue::Type::Object) {
 | 
			
		||||
		drawTree(path, value.get<ox::ModelObject>());
 | 
			
		||||
	} else if (value.type() == ox::ModelValue::Type::Vector) {
 | 
			
		||||
		const auto &vec = value.get<ox::ModelValueVector>();
 | 
			
		||||
		const auto pathStr = ox::join<Str>("##", *path).unwrap();
 | 
			
		||||
		const auto lbl = ox::sfmt<Str>("{}##{}", name, pathStr);
 | 
			
		||||
		const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
 | 
			
		||||
		auto const&vec = value.get<ox::ModelValueVector>();
 | 
			
		||||
		auto const pathStr = ox::join<Str>("##", path).unwrap();
 | 
			
		||||
		auto const lbl = ox::sfmt<Str>("{}##{}", name, pathStr);
 | 
			
		||||
		auto const flags = ImGuiTreeNodeFlags_SpanFullWidth
 | 
			
		||||
		                 | ImGuiTreeNodeFlags_OpenOnArrow
 | 
			
		||||
		                 | (vec.size() ? 0 : ImGuiTreeNodeFlags_Leaf)
 | 
			
		||||
		                 | (false ? ImGuiTreeNodeFlags_Selected : 0);
 | 
			
		||||
		const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
 | 
			
		||||
		auto const open = ImGui::TreeNodeEx(lbl.c_str(), flags);
 | 
			
		||||
		ImGui::SameLine();
 | 
			
		||||
		drawRow(value);
 | 
			
		||||
		if (open) {
 | 
			
		||||
			for (auto i = 0lu; const auto &e: vec) {
 | 
			
		||||
				const auto iStr = ox::sfmt<Str>("{}", i);
 | 
			
		||||
				path->push_back(iStr);
 | 
			
		||||
			for (auto i = 0lu; auto const&e: vec) {
 | 
			
		||||
				auto const iStr = ox::sfmt<Str>("{}", i);
 | 
			
		||||
				path.push_back(iStr);
 | 
			
		||||
				ImGui::TableNextRow(0, 5);
 | 
			
		||||
				ImGui::TableNextColumn();
 | 
			
		||||
				drawVar(path, ox::sfmt<Str>("[{}]", i), e);
 | 
			
		||||
				path->pop_back();
 | 
			
		||||
				path.pop_back();
 | 
			
		||||
				++i;
 | 
			
		||||
			}
 | 
			
		||||
			ImGui::TreePop();
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		const auto pathStr = ox::join<Str>("##", *path).unwrap();
 | 
			
		||||
		const auto lbl = ox::sfmt<Str>("{}##{}", name, pathStr);
 | 
			
		||||
		const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
 | 
			
		||||
		auto const pathStr = ox::join<Str>("##", path).unwrap();
 | 
			
		||||
		auto const lbl = ox::sfmt<Str>("{}##{}", name, pathStr);
 | 
			
		||||
		auto const flags = ImGuiTreeNodeFlags_SpanFullWidth
 | 
			
		||||
		                   | ImGuiTreeNodeFlags_OpenOnArrow
 | 
			
		||||
		                   | ImGuiTreeNodeFlags_Leaf
 | 
			
		||||
		                   | (false ? ImGuiTreeNodeFlags_Selected : 0);
 | 
			
		||||
		const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
 | 
			
		||||
		auto const open = ImGui::TreeNodeEx(lbl.c_str(), flags);
 | 
			
		||||
		ImGui::SameLine();
 | 
			
		||||
		drawRow(value);
 | 
			
		||||
		if (open) {
 | 
			
		||||
			ImGui::TreePop();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	path->pop_back();
 | 
			
		||||
	path.pop_back();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ClawEditor::drawTree(ObjPath *path, const ox::ModelObject &obj) noexcept {
 | 
			
		||||
void ClawEditor::drawTree(ObjPath &path, ox::ModelObject const&obj) noexcept {
 | 
			
		||||
	using Str = ox::BasicString<100>;
 | 
			
		||||
	for (const auto &c : obj) {
 | 
			
		||||
		ImGui::TableNextRow(0, 5);
 | 
			
		||||
		auto pathStr = ox::join<Str>("##", *path).unwrap();
 | 
			
		||||
		auto pathStr = ox::join<Str>("##", path).unwrap();
 | 
			
		||||
		auto lbl = ox::sfmt<Str>("{}##{}", c->name, pathStr);
 | 
			
		||||
		const auto rowSelected = false;
 | 
			
		||||
		const auto hasChildren = c->value.type() == ox::ModelValue::Type::Object
 | 
			
		||||
@@ -152,13 +151,11 @@ void ClawEditor::drawTree(ObjPath *path, const ox::ModelObject &obj) noexcept {
 | 
			
		||||
		                   | (hasChildren ? 0 : ImGuiTreeNodeFlags_Leaf)
 | 
			
		||||
		                   | (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
 | 
			
		||||
		ImGui::TableNextColumn();
 | 
			
		||||
		if (ImGui::IsItemClicked()) {
 | 
			
		||||
			//model()->setActiveSubsheet(*path);
 | 
			
		||||
		}
 | 
			
		||||
		if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsItemHovered()) {
 | 
			
		||||
			//showSubsheetEditor();
 | 
			
		||||
		}
 | 
			
		||||
		path->push_back(c->name);
 | 
			
		||||
		//if (ImGui::IsItemClicked()) {
 | 
			
		||||
		//}
 | 
			
		||||
		//if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsItemHovered()) {
 | 
			
		||||
		//}
 | 
			
		||||
		path.push_back(c->name);
 | 
			
		||||
		if (c->value.type() == ox::ModelValue::Type::Object) {
 | 
			
		||||
			const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
 | 
			
		||||
			ImGui::SameLine();
 | 
			
		||||
@@ -170,7 +167,7 @@ void ClawEditor::drawTree(ObjPath *path, const ox::ModelObject &obj) noexcept {
 | 
			
		||||
		} else {
 | 
			
		||||
			drawVar(path, c->name, c->value);
 | 
			
		||||
		}
 | 
			
		||||
		path->pop_back();
 | 
			
		||||
		path.pop_back();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,11 +21,11 @@ class ClawEditor: public studio::Editor {
 | 
			
		||||
		void draw(turbine::Context&) noexcept final;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		static void drawRow(const ox::ModelValue &value) noexcept;
 | 
			
		||||
		static void drawRow(ox::ModelValue const&value) noexcept;
 | 
			
		||||
 | 
			
		||||
		void drawVar(ObjPath *path, ox::CRStringView name, const ox::ModelValue &value) noexcept;
 | 
			
		||||
		void drawVar(ObjPath &path, ox::CRStringView name, ox::ModelValue const&value) noexcept;
 | 
			
		||||
 | 
			
		||||
		void drawTree(ObjPath *path, const ox::ModelObject &obj) noexcept;
 | 
			
		||||
		void drawTree(ObjPath &path, ox::ModelObject const&obj) noexcept;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
 | 
			
		||||
namespace studio {
 | 
			
		||||
 | 
			
		||||
class FileDialogManager : public studio::Task {
 | 
			
		||||
class FileDialogManager: public studio::Task {
 | 
			
		||||
	private:
 | 
			
		||||
		enum class UpdateProjectPathState {
 | 
			
		||||
				None,
 | 
			
		||||
@@ -36,7 +36,7 @@ class FileDialogManager : public studio::Task {
 | 
			
		||||
		studio::TaskState update(turbine::Context &ctx) noexcept final;
 | 
			
		||||
 | 
			
		||||
		// signals
 | 
			
		||||
		ox::Signal<ox::Error(const ox::String &)> pathChosen;
 | 
			
		||||
		ox::Signal<ox::Error(ox::String const&)> pathChosen;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ static ox::Error runApp(
 | 
			
		||||
	studioCtx.ui = &ui;
 | 
			
		||||
	StudioUIDrawer drawer(ui);
 | 
			
		||||
	turbine::gl::addDrawer(*ctx, &drawer);
 | 
			
		||||
	const auto err = turbine::run(*ctx);
 | 
			
		||||
	auto const err = turbine::run(*ctx);
 | 
			
		||||
	turbine::gl::removeDrawer(*ctx, &drawer);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
@@ -66,15 +66,15 @@ ox::Error run(
 | 
			
		||||
		ox::CRStringView appName,
 | 
			
		||||
		ox::CRStringView projectDataDir,
 | 
			
		||||
		int,
 | 
			
		||||
		const char**) {
 | 
			
		||||
		char const**) {
 | 
			
		||||
	// seed UUID generator
 | 
			
		||||
	const auto time = std::time(nullptr);
 | 
			
		||||
	auto const time = std::time(nullptr);
 | 
			
		||||
	ox::UUID::seedGenerator({
 | 
			
		||||
		static_cast<uint64_t>(time),
 | 
			
		||||
		static_cast<uint64_t>(time << 1)
 | 
			
		||||
	});
 | 
			
		||||
	// run app
 | 
			
		||||
	const auto err = runApp(appName, projectDataDir, ox::UniquePtr<ox::FileSystem>(nullptr));
 | 
			
		||||
	auto const err = runApp(appName, projectDataDir, ox::UniquePtr<ox::FileSystem>(nullptr));
 | 
			
		||||
	oxAssert(err, "Something went wrong...");
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
@@ -88,7 +88,7 @@ ox::Error run(
 | 
			
		||||
		ox::StringView appName,
 | 
			
		||||
		ox::StringView projectDataDir,
 | 
			
		||||
		int argc,
 | 
			
		||||
		const char **argv) noexcept {
 | 
			
		||||
		char const**argv) noexcept {
 | 
			
		||||
	return studio::run(ox::sfmt("{} {}", project, appName), projectDataDir, argc, argv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -61,8 +61,8 @@ void NewMenu::addItemMaker(ox::UniquePtr<studio::ItemMaker> im) noexcept {
 | 
			
		||||
 | 
			
		||||
void NewMenu::drawNewItemType(turbine::Context &ctx) noexcept {
 | 
			
		||||
	drawWindow(ctx, &m_open, [this] {
 | 
			
		||||
		auto items = ox_malloca(m_types.size() * sizeof(const char*), const char*, nullptr);
 | 
			
		||||
		for (auto i = 0u; const auto &im : m_types) {
 | 
			
		||||
		auto items = ox_malloca(m_types.size() * sizeof(char const*), char const*, nullptr);
 | 
			
		||||
		for (auto i = 0u; auto const&im : m_types) {
 | 
			
		||||
			items.get()[i] = im->name.c_str();
 | 
			
		||||
			++i;
 | 
			
		||||
		}
 | 
			
		||||
@@ -73,7 +73,7 @@ void NewMenu::drawNewItemType(turbine::Context &ctx) noexcept {
 | 
			
		||||
 | 
			
		||||
void NewMenu::drawNewItemName(turbine::Context &ctx) noexcept {
 | 
			
		||||
	drawWindow(ctx, &m_open, [this, &ctx] {
 | 
			
		||||
		const auto typeIdx = static_cast<std::size_t>(m_selectedType);
 | 
			
		||||
		auto const typeIdx = static_cast<std::size_t>(m_selectedType);
 | 
			
		||||
		if (typeIdx < m_types.size()) {
 | 
			
		||||
			ImGui::InputText("Name", m_itemName.data(), m_itemName.cap());
 | 
			
		||||
		}
 | 
			
		||||
@@ -113,7 +113,7 @@ void NewMenu::drawLastPageButtons(turbine::Context &ctx) noexcept {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NewMenu::finish(turbine::Context &ctx) noexcept {
 | 
			
		||||
	const auto err = m_types[static_cast<std::size_t>(m_selectedType)]->write(ctx, m_itemName);
 | 
			
		||||
	auto const err = m_types[static_cast<std::size_t>(m_selectedType)]->write(ctx, m_itemName);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		oxLogError(err);
 | 
			
		||||
		return;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,17 +11,17 @@
 | 
			
		||||
namespace studio {
 | 
			
		||||
 | 
			
		||||
static ox::Result<ox::UniquePtr<ProjectTreeModel>>
 | 
			
		||||
buildProjectTreeModel(ProjectExplorer *explorer, ox::StringView name, ox::CRStringView path, ProjectTreeModel *parent) noexcept {
 | 
			
		||||
	const auto fs = explorer->romFs();
 | 
			
		||||
buildProjectTreeModel(ProjectExplorer &explorer, ox::StringView name, ox::CRStringView path, ProjectTreeModel *parent) noexcept {
 | 
			
		||||
	auto const fs = explorer.romFs();
 | 
			
		||||
	oxRequire(stat, fs->stat(path));
 | 
			
		||||
	auto out = ox::make_unique<ProjectTreeModel>(explorer, ox::String(name), parent);
 | 
			
		||||
	if (stat.fileType == ox::FileType::Directory) {
 | 
			
		||||
		oxRequireM(children, fs->ls(path));
 | 
			
		||||
		std::sort(children.begin(), children.end());
 | 
			
		||||
		ox::Vector<ox::UniquePtr<ProjectTreeModel>> outChildren;
 | 
			
		||||
		for (const auto &childName : children) {
 | 
			
		||||
		for (auto const&childName : children) {
 | 
			
		||||
			if (childName[0] != '.') {
 | 
			
		||||
				const auto childPath = ox::sfmt("{}/{}", path, childName);
 | 
			
		||||
				auto const childPath = ox::sfmt("{}/{}", path, childName);
 | 
			
		||||
				oxRequireM(child, buildProjectTreeModel(explorer, childName, childPath, out.get()));
 | 
			
		||||
				outChildren.emplace_back(std::move(child));
 | 
			
		||||
			}
 | 
			
		||||
@@ -35,7 +35,7 @@ ProjectExplorer::ProjectExplorer(turbine::Context &ctx) noexcept: m_ctx(ctx) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ProjectExplorer::draw(turbine::Context &ctx) noexcept {
 | 
			
		||||
	const auto viewport = ImGui::GetContentRegionAvail();
 | 
			
		||||
	auto const viewport = ImGui::GetContentRegionAvail();
 | 
			
		||||
	ImGui::BeginChild("ProjectExplorer", ImVec2(300, viewport.y), true);
 | 
			
		||||
	ImGui::SetNextItemOpen(true);
 | 
			
		||||
	if (m_treeModel) {
 | 
			
		||||
@@ -44,12 +44,12 @@ void ProjectExplorer::draw(turbine::Context &ctx) noexcept {
 | 
			
		||||
	ImGui::EndChild();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ProjectExplorer::setModel(ox::UniquePtr<ProjectTreeModel> model) noexcept {
 | 
			
		||||
void ProjectExplorer::setModel(ox::UPtr<ProjectTreeModel> model) noexcept {
 | 
			
		||||
	m_treeModel = std::move(model);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error ProjectExplorer::refreshProjectTreeModel(ox::CRStringView) noexcept {
 | 
			
		||||
	oxRequireM(model, buildProjectTreeModel(this, "Project", "/", nullptr));
 | 
			
		||||
	oxRequireM(model, buildProjectTreeModel(*this, "Project", "/", nullptr));
 | 
			
		||||
	setModel(std::move(model));
 | 
			
		||||
	return OxError(0);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,14 +14,14 @@ namespace studio {
 | 
			
		||||
 | 
			
		||||
class ProjectExplorer: public studio::Widget {
 | 
			
		||||
	private:
 | 
			
		||||
		ox::UniquePtr<ProjectTreeModel> m_treeModel;
 | 
			
		||||
		ox::UPtr<ProjectTreeModel> m_treeModel;
 | 
			
		||||
		turbine::Context &m_ctx;
 | 
			
		||||
	public:
 | 
			
		||||
		explicit ProjectExplorer(turbine::Context &ctx) noexcept;
 | 
			
		||||
 | 
			
		||||
		void draw(turbine::Context &ctx) noexcept override;
 | 
			
		||||
 | 
			
		||||
		void setModel(ox::UniquePtr<ProjectTreeModel> model) noexcept;
 | 
			
		||||
		void setModel(ox::UPtr<ProjectTreeModel> model) noexcept;
 | 
			
		||||
 | 
			
		||||
		ox::Error refreshProjectTreeModel(ox::CRStringView = {}) noexcept;
 | 
			
		||||
 | 
			
		||||
@@ -32,7 +32,7 @@ class ProjectExplorer: public studio::Widget {
 | 
			
		||||
 | 
			
		||||
	// slots
 | 
			
		||||
	public:
 | 
			
		||||
		ox::Signal<ox::Error(const ox::StringView&)> fileChosen;
 | 
			
		||||
		ox::Signal<ox::Error(ox::StringView const&)> fileChosen;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
 | 
			
		||||
namespace studio {
 | 
			
		||||
 | 
			
		||||
ProjectTreeModel::ProjectTreeModel(ProjectExplorer *explorer, ox::String name,
 | 
			
		||||
ProjectTreeModel::ProjectTreeModel(ProjectExplorer &explorer, ox::String name,
 | 
			
		||||
                                   ProjectTreeModel *parent) noexcept:
 | 
			
		||||
	m_explorer(explorer),
 | 
			
		||||
	m_parent(parent),
 | 
			
		||||
@@ -27,17 +27,17 @@ void 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)) {
 | 
			
		||||
			for (const auto &child : m_children) {
 | 
			
		||||
			for (auto const&child : m_children) {
 | 
			
		||||
				child->draw(ctx);
 | 
			
		||||
			}
 | 
			
		||||
			ImGui::TreePop();
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		const auto path = fullPath();
 | 
			
		||||
		const auto name = ox::sfmt<ox::BasicString<255>>("{}##{}", m_name, path);
 | 
			
		||||
		auto const path = fullPath();
 | 
			
		||||
		auto const name = ox::sfmt<ox::BasicString<255>>("{}##{}", m_name, path);
 | 
			
		||||
		if (ImGui::TreeNodeEx(name.c_str(), ImGuiTreeNodeFlags_Leaf)) {
 | 
			
		||||
			if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
 | 
			
		||||
				m_explorer->fileChosen.emit(path);
 | 
			
		||||
				m_explorer.fileChosen.emit(path);
 | 
			
		||||
			}
 | 
			
		||||
			ImGui::TreePop();
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,12 +13,12 @@ namespace studio {
 | 
			
		||||
 | 
			
		||||
class ProjectTreeModel {
 | 
			
		||||
	private:
 | 
			
		||||
		class ProjectExplorer *m_explorer = nullptr;
 | 
			
		||||
		class ProjectExplorer &m_explorer;
 | 
			
		||||
		ProjectTreeModel *m_parent = nullptr;
 | 
			
		||||
		ox::String m_name;
 | 
			
		||||
		ox::Vector<ox::UniquePtr<ProjectTreeModel>> m_children;
 | 
			
		||||
	public:
 | 
			
		||||
		explicit ProjectTreeModel(class ProjectExplorer *explorer, ox::String name,
 | 
			
		||||
		explicit ProjectTreeModel(class ProjectExplorer &explorer, ox::String name,
 | 
			
		||||
		                          ProjectTreeModel *parent = nullptr) noexcept;
 | 
			
		||||
 | 
			
		||||
		ProjectTreeModel(ProjectTreeModel &&other) noexcept;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
 | 
			
		||||
namespace studio {
 | 
			
		||||
 | 
			
		||||
static ox::Vector<const studio::Module*> modules;
 | 
			
		||||
static ox::Vector<studio::Module const*> modules;
 | 
			
		||||
 | 
			
		||||
void registerModule(studio::Module const*mod) noexcept {
 | 
			
		||||
	modules.emplace_back(mod);
 | 
			
		||||
@@ -52,7 +52,7 @@ StudioUI::StudioUI(turbine::Context &ctx, ox::StringView projectDataDir) noexcep
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		auto const openProjErr = openProject(config.projectPath);
 | 
			
		||||
		if (!openProjErr) {
 | 
			
		||||
			for (const auto &f: config.openFiles) {
 | 
			
		||||
			for (auto const&f: config.openFiles) {
 | 
			
		||||
				auto openFileErr = openFileActiveTab(f, config.activeTabItemName == f);
 | 
			
		||||
				if (openFileErr) {
 | 
			
		||||
					oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr));
 | 
			
		||||
@@ -75,7 +75,7 @@ void StudioUI::update() noexcept {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StudioUI::handleKeyEvent(turbine::Key key, bool down) noexcept {
 | 
			
		||||
	const auto ctrlDown = turbine::buttonDown(m_ctx, turbine::Key::Mod_Ctrl);
 | 
			
		||||
	auto const ctrlDown = turbine::buttonDown(m_ctx, turbine::Key::Mod_Ctrl);
 | 
			
		||||
	for (auto p : m_popups) {
 | 
			
		||||
		if (p->isOpen()) {
 | 
			
		||||
			if (key == turbine::Key::Escape) {
 | 
			
		||||
@@ -136,7 +136,7 @@ void StudioUI::handleKeyEvent(turbine::Key key, bool down) noexcept {
 | 
			
		||||
void StudioUI::draw() noexcept {
 | 
			
		||||
	glutils::clearScreen();
 | 
			
		||||
	drawMenu();
 | 
			
		||||
	const auto viewport = ImGui::GetMainViewport();
 | 
			
		||||
	auto const viewport = ImGui::GetMainViewport();
 | 
			
		||||
	constexpr auto menuHeight = 18;
 | 
			
		||||
	ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + menuHeight));
 | 
			
		||||
	ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, viewport->Size.y - menuHeight));
 | 
			
		||||
@@ -216,7 +216,7 @@ void StudioUI::drawMenu() noexcept {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StudioUI::drawTabBar() noexcept {
 | 
			
		||||
	const auto viewport = ImGui::GetContentRegionAvail();
 | 
			
		||||
	auto const viewport = ImGui::GetContentRegionAvail();
 | 
			
		||||
	ImGui::BeginChild("TabWindow##MainWindow##Studio", ImVec2(viewport.x, viewport.y));
 | 
			
		||||
	constexpr auto tabBarFlags = ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_TabListPopupButton;
 | 
			
		||||
	if (ImGui::BeginTabBar("TabBar##TabWindow##MainWindow##Studio", tabBarFlags)) {
 | 
			
		||||
@@ -230,9 +230,9 @@ void StudioUI::drawTabs() noexcept {
 | 
			
		||||
	for (auto it = m_editors.begin(); it != m_editors.end();) {
 | 
			
		||||
		auto const &e = *it;
 | 
			
		||||
		auto open = true;
 | 
			
		||||
		const auto unsavedChanges = e->unsavedChanges() ? ImGuiTabItemFlags_UnsavedDocument : 0;
 | 
			
		||||
		const auto selected = m_activeEditorUpdatePending == e.get() ?  ImGuiTabItemFlags_SetSelected : 0;
 | 
			
		||||
		const auto flags = unsavedChanges | selected;
 | 
			
		||||
		auto const unsavedChanges = e->unsavedChanges() ? ImGuiTabItemFlags_UnsavedDocument : 0;
 | 
			
		||||
		auto const selected = m_activeEditorUpdatePending == e.get() ?  ImGuiTabItemFlags_SetSelected : 0;
 | 
			
		||||
		auto const flags = unsavedChanges | selected;
 | 
			
		||||
		if (ImGui::BeginTabItem(e->itemDisplayName().c_str(), &open, flags)) {
 | 
			
		||||
			if (m_activeEditor != e.get()) {
 | 
			
		||||
				m_activeEditor = e.get();
 | 
			
		||||
@@ -258,9 +258,9 @@ void StudioUI::drawTabs() noexcept {
 | 
			
		||||
			}
 | 
			
		||||
			try {
 | 
			
		||||
				oxThrowError(m_editors.erase(it).moveTo(it));
 | 
			
		||||
			} catch (const ox::Exception &ex) {
 | 
			
		||||
			} catch (ox::Exception const&ex) {
 | 
			
		||||
				oxErrf("Editor tab deletion failed: {} ({}:{})\n", ex.what(), ex.file, ex.line);
 | 
			
		||||
			} catch (const std::exception &ex) {
 | 
			
		||||
			} catch (std::exception const&ex) {
 | 
			
		||||
				oxErrf("Editor tab deletion failed: {}\n", ex.what());
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
@@ -275,8 +275,8 @@ void StudioUI::loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StudioUI::loadModule(const studio::Module *mod) noexcept {
 | 
			
		||||
	for (const auto &editorMaker : mod->editors(m_ctx)) {
 | 
			
		||||
void StudioUI::loadModule(studio::Module const*mod) noexcept {
 | 
			
		||||
	for (auto const&editorMaker : mod->editors(m_ctx)) {
 | 
			
		||||
		loadEditorMaker(editorMaker);
 | 
			
		||||
	}
 | 
			
		||||
	for (auto &im : mod->itemMakers(m_ctx)) {
 | 
			
		||||
@@ -363,7 +363,7 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
 | 
			
		||||
		}
 | 
			
		||||
		editor = ox::make<ClawEditor>(path, std::move(obj));
 | 
			
		||||
	} else {
 | 
			
		||||
		const auto err = m_editorMakers[ext](path).moveTo(editor);
 | 
			
		||||
		auto const err = m_editorMakers[ext](path).moveTo(editor);
 | 
			
		||||
		if (err) {
 | 
			
		||||
			if constexpr(!ox::defines::Debug) {
 | 
			
		||||
				oxErrf("Could not open Editor: {}\n", toStr(err));
 | 
			
		||||
 
 | 
			
		||||
@@ -23,9 +23,9 @@ ox::String configPath(keel::Context const&ctx) noexcept;
 | 
			
		||||
template<typename T>
 | 
			
		||||
ox::Result<T> readConfig(keel::Context &ctx, ox::CRStringView name) noexcept {
 | 
			
		||||
	oxAssert(name != "", "Config type has no TypeName");
 | 
			
		||||
	const auto path = ox::sfmt("/{}.json", name);
 | 
			
		||||
	auto const path = ox::sfmt("/{}.json", name);
 | 
			
		||||
	ox::PassThroughFS fs(configPath(ctx));
 | 
			
		||||
	const auto [buff, err] = fs.read(path);
 | 
			
		||||
	auto const [buff, err] = fs.read(path);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		oxErrf("Could not read config file: {}\n", toStr(err));
 | 
			
		||||
		return err;
 | 
			
		||||
@@ -42,19 +42,19 @@ ox::Result<T> readConfig(keel::Context &ctx) noexcept {
 | 
			
		||||
template<typename T>
 | 
			
		||||
ox::Error writeConfig(keel::Context &ctx, ox::CRStringView name, T *data) noexcept {
 | 
			
		||||
	oxAssert(name != "", "Config type has no TypeName");
 | 
			
		||||
	const auto path = ox::sfmt("/{}.json", name);
 | 
			
		||||
	auto const path = ox::sfmt("/{}.json", name);
 | 
			
		||||
	ox::PassThroughFS fs(configPath(ctx));
 | 
			
		||||
	if (const auto err = fs.mkdir("/", true)) {
 | 
			
		||||
	if (auto const err = fs.mkdir("/", true)) {
 | 
			
		||||
		oxErrf("Could not create config directory: {}\n", toStr(err));
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	oxRequireM(buff, ox::writeOC(*data));
 | 
			
		||||
	*buff.back().value = '\n';
 | 
			
		||||
	if (const auto err = fs.write(path, buff.data(), buff.size())) {
 | 
			
		||||
	if (auto const err = fs.write(path, buff.data(), buff.size())) {
 | 
			
		||||
		oxErrf("Could not read config file: {}\n", toStr(err));
 | 
			
		||||
		return OxError(2, "Could not read config file");
 | 
			
		||||
	}
 | 
			
		||||
	return OxError(0);
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
@@ -66,7 +66,7 @@ ox::Error writeConfig(keel::Context &ctx, T *data) noexcept {
 | 
			
		||||
template<typename T, typename Func>
 | 
			
		||||
void openConfig(keel::Context &ctx, ox::CRStringView name, Func f) noexcept {
 | 
			
		||||
	oxAssert(name != "", "Config type has no TypeName");
 | 
			
		||||
	const auto [c, err] = readConfig<T>(ctx, name);
 | 
			
		||||
	auto const [c, err] = readConfig<T>(ctx, name);
 | 
			
		||||
	oxLogError(err);
 | 
			
		||||
	f(&c);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,9 +15,9 @@ namespace studio {
 | 
			
		||||
 | 
			
		||||
class ItemMaker {
 | 
			
		||||
	public:
 | 
			
		||||
		const ox::String name;
 | 
			
		||||
		const ox::String parentDir;
 | 
			
		||||
		const ox::String fileExt;
 | 
			
		||||
		ox::String const name;
 | 
			
		||||
		ox::String const parentDir;
 | 
			
		||||
		ox::String const fileExt;
 | 
			
		||||
		constexpr explicit ItemMaker(ox::StringView pName, ox::StringView pParentDir, ox::CRStringView pFileExt) noexcept:
 | 
			
		||||
			name(pName),
 | 
			
		||||
			parentDir(pParentDir),
 | 
			
		||||
@@ -30,8 +30,8 @@ class ItemMaker {
 | 
			
		||||
template<typename T>
 | 
			
		||||
class ItemMakerT: public ItemMaker {
 | 
			
		||||
	private:
 | 
			
		||||
		const T item;
 | 
			
		||||
		const ox::ClawFormat fmt;
 | 
			
		||||
		T const item;
 | 
			
		||||
		ox::ClawFormat const fmt;
 | 
			
		||||
	public:
 | 
			
		||||
		constexpr ItemMakerT(
 | 
			
		||||
				ox::StringView pDisplayName,
 | 
			
		||||
@@ -62,7 +62,7 @@ class ItemMakerT: public ItemMaker {
 | 
			
		||||
			 fmt(pFmt) {
 | 
			
		||||
		}
 | 
			
		||||
		ox::Error write(turbine::Context &ctx, ox::CRStringView pName) const noexcept override {
 | 
			
		||||
			const auto path = ox::sfmt("/{}/{}.{}", parentDir, pName, fileExt);
 | 
			
		||||
			auto const path = ox::sfmt("/{}/{}.{}", parentDir, pName, fileExt);
 | 
			
		||||
			auto sctx = turbine::applicationData<studio::StudioContext>(ctx);
 | 
			
		||||
			keel::createUuidMapping(keelCtx(ctx), path, ox::UUID::generate().unwrap());
 | 
			
		||||
			return sctx->project->writeObj(path, item, fmt);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ class Popup {
 | 
			
		||||
		ox::String m_title;
 | 
			
		||||
	public:
 | 
			
		||||
		// emits path parameter
 | 
			
		||||
		ox::Signal<ox::Error(const ox::String&)> finished;
 | 
			
		||||
		ox::Signal<ox::Error(ox::String const&)> finished;
 | 
			
		||||
 | 
			
		||||
		virtual ~Popup() noexcept = default;
 | 
			
		||||
 | 
			
		||||
@@ -43,7 +43,7 @@ class Popup {
 | 
			
		||||
			m_title = std::move(title);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		constexpr const ox::String &title() const noexcept {
 | 
			
		||||
		constexpr ox::String const&title() const noexcept {
 | 
			
		||||
			return m_title;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ enum class ProjectEvent {
 | 
			
		||||
 | 
			
		||||
[[nodiscard]]
 | 
			
		||||
constexpr ox::Result<ox::StringView> fileExt(ox::CRStringView path) noexcept {
 | 
			
		||||
	const auto extStart = ox::find(path.crbegin(), path.crend(), '.').offset();
 | 
			
		||||
	auto const extStart = ox::find(path.crbegin(), path.crend(), '.').offset();
 | 
			
		||||
	if (!extStart) {
 | 
			
		||||
		return OxError(1, "Cannot open a file without valid extension.");
 | 
			
		||||
	}
 | 
			
		||||
@@ -76,7 +76,7 @@ class Project {
 | 
			
		||||
		ox::Error subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&slot) const noexcept;
 | 
			
		||||
 | 
			
		||||
		[[nodiscard]]
 | 
			
		||||
		const ox::Vector<ox::String> &fileList(ox::CRStringView ext) noexcept;
 | 
			
		||||
		ox::Vector<ox::String> const&fileList(ox::CRStringView ext) noexcept;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		void buildFileIndex() noexcept;
 | 
			
		||||
@@ -114,14 +114,14 @@ ox::Error Project::writeObj(ox::CRStringView path, T const&obj, ox::ClawFormat f
 | 
			
		||||
		oxReturnError(ox::buildTypeDef(&m_typeStore, &obj));
 | 
			
		||||
	}
 | 
			
		||||
	// write out type store
 | 
			
		||||
	const auto descPath = ox::sfmt("/{}/type_descriptors", m_projectDataDir);
 | 
			
		||||
	auto const descPath = ox::sfmt("/{}/type_descriptors", m_projectDataDir);
 | 
			
		||||
	oxReturnError(mkdir(descPath));
 | 
			
		||||
	for (auto const&t : m_typeStore.typeList()) {
 | 
			
		||||
		oxRequireM(typeOut, ox::writeClaw(*t, ox::ClawFormat::Organic));
 | 
			
		||||
		// replace garbage last character with new line
 | 
			
		||||
		*typeOut.back().value = '\n';
 | 
			
		||||
		// write to FS
 | 
			
		||||
		const auto typePath = ox::sfmt("/{}/{}", descPath, buildTypeId(*t));
 | 
			
		||||
		auto const typePath = ox::sfmt("/{}/{}", descPath, buildTypeId(*t));
 | 
			
		||||
		oxReturnError(writeBuff(typePath, typeOut));
 | 
			
		||||
	}
 | 
			
		||||
	oxReturnError(keel::setAsset(m_ctx, path, obj));
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ class UndoCommand {
 | 
			
		||||
		virtual void undo() noexcept = 0;
 | 
			
		||||
		[[nodiscard]]
 | 
			
		||||
		virtual int commandId() const noexcept = 0;
 | 
			
		||||
		virtual bool mergeWith(const UndoCommand *cmd) noexcept;
 | 
			
		||||
		virtual bool mergeWith(UndoCommand const*cmd) noexcept;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class UndoStack {
 | 
			
		||||
@@ -43,9 +43,9 @@ class UndoStack {
 | 
			
		||||
			return m_stackIdx;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ox::Signal<ox::Error(const studio::UndoCommand*)> redoTriggered;
 | 
			
		||||
		ox::Signal<ox::Error(const studio::UndoCommand*)> undoTriggered;
 | 
			
		||||
		ox::Signal<ox::Error(const studio::UndoCommand*)> changeTriggered;
 | 
			
		||||
		ox::Signal<ox::Error(studio::UndoCommand const*)> redoTriggered;
 | 
			
		||||
		ox::Signal<ox::Error(studio::UndoCommand const*)> undoTriggered;
 | 
			
		||||
		ox::Signal<ox::Error(studio::UndoCommand const*)> changeTriggered;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ add_library(
 | 
			
		||||
		project.cpp
 | 
			
		||||
		task.cpp
 | 
			
		||||
		undostack.cpp
 | 
			
		||||
		widget.cpp
 | 
			
		||||
		filedialog_nfd.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,8 @@ constexpr auto ConfigDir = [] {
 | 
			
		||||
	}
 | 
			
		||||
}();
 | 
			
		||||
 | 
			
		||||
ox::String configPath(const keel::Context &ctx) noexcept {
 | 
			
		||||
	const auto homeDir = std::getenv(ox::defines::OS == ox::OS::Windows ? "USERPROFILE" : "HOME");
 | 
			
		||||
ox::String configPath(keel::Context const&ctx) noexcept {
 | 
			
		||||
	auto const homeDir = std::getenv(ox::defines::OS == ox::OS::Windows ? "USERPROFILE" : "HOME");
 | 
			
		||||
	return ox::sfmt(ConfigDir, homeDir, ctx.appName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ void BaseEditor::close() const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BaseEditor::save() noexcept {
 | 
			
		||||
	const auto err = saveItem();
 | 
			
		||||
	auto const err = saveItem();
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		setUnsavedChanges(false);
 | 
			
		||||
	} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ static ox::Result<ox::String> toResult(nfdresult_t r, NFD::UniquePathN const&pat
 | 
			
		||||
		case NFD_OKAY: {
 | 
			
		||||
			ox::String out;
 | 
			
		||||
			for (auto i = 0u; path.get()[i]; ++i) {
 | 
			
		||||
				const auto c = static_cast<char>(path.get()[i]);
 | 
			
		||||
				auto const c = static_cast<char>(path.get()[i]);
 | 
			
		||||
				oxIgnoreError(out.append(&c, 1));
 | 
			
		||||
			}
 | 
			
		||||
			return out;
 | 
			
		||||
@@ -39,7 +39,7 @@ ox::Result<ox::String> saveFile(ox::Vector<FDFilterItem> const&filters) noexcept
 | 
			
		||||
	NFD::Guard const guard;
 | 
			
		||||
	NFD::UniquePathN path;
 | 
			
		||||
	ox::Vector<nfdnfilteritem_t, 5> filterItems(filters.size());
 | 
			
		||||
	for (auto i = 0u; const auto &f : filters) {
 | 
			
		||||
	for (auto i = 0u; auto const&f : filters) {
 | 
			
		||||
		filterItems[i].name = f.name.data();
 | 
			
		||||
		filterItems[i].spec = f.spec.data();
 | 
			
		||||
		++i;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,10 +9,10 @@
 | 
			
		||||
namespace studio::ig {
 | 
			
		||||
 | 
			
		||||
void centerNextWindow(turbine::Context &ctx) noexcept {
 | 
			
		||||
	const auto sz = turbine::getScreenSize(ctx);
 | 
			
		||||
	const auto screenW = static_cast<float>(sz.width);
 | 
			
		||||
	const auto screenH = static_cast<float>(sz.height);
 | 
			
		||||
	const auto mod = ImGui::GetWindowDpiScale() * 2;
 | 
			
		||||
	auto const sz = turbine::getScreenSize(ctx);
 | 
			
		||||
	auto const screenW = static_cast<float>(sz.width);
 | 
			
		||||
	auto const screenH = static_cast<float>(sz.height);
 | 
			
		||||
	auto const mod = ImGui::GetWindowDpiScale() * 2;
 | 
			
		||||
	ImGui::SetNextWindowPos(ImVec2(screenW / mod, screenH / mod), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
namespace studio {
 | 
			
		||||
 | 
			
		||||
static void generateTypes(ox::TypeStore &ts) noexcept {
 | 
			
		||||
	for (const auto mod : keel::modules()) {
 | 
			
		||||
	for (auto const mod : keel::modules()) {
 | 
			
		||||
		for (auto gen : mod->types()) {
 | 
			
		||||
			oxLogError(gen(ts));
 | 
			
		||||
		}
 | 
			
		||||
@@ -56,7 +56,7 @@ bool Project::exists(ox::CRStringView path) const noexcept {
 | 
			
		||||
	return m_fs.stat(path).error == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ox::Vector<ox::String> &Project::fileList(ox::CRStringView ext) noexcept {
 | 
			
		||||
ox::Vector<ox::String> const&Project::fileList(ox::CRStringView ext) noexcept {
 | 
			
		||||
	return m_fileExtFileMap[ext];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -68,7 +68,7 @@ void Project::buildFileIndex() noexcept {
 | 
			
		||||
	}
 | 
			
		||||
	m_fileExtFileMap.clear();
 | 
			
		||||
	std::sort(files.begin(), files.end());
 | 
			
		||||
	for (const auto &file : files) {
 | 
			
		||||
	for (auto const&file : files) {
 | 
			
		||||
		if (!beginsWith(file, ox::sfmt("/.{}/", m_projectDataDir))) {
 | 
			
		||||
			indexFile(file);
 | 
			
		||||
		}
 | 
			
		||||
@@ -76,7 +76,7 @@ void Project::buildFileIndex() noexcept {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Project::indexFile(ox::CRStringView path) noexcept {
 | 
			
		||||
	const auto [ext, err] = fileExt(path);
 | 
			
		||||
	auto const [ext, err] = fileExt(path);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
@@ -88,12 +88,12 @@ ox::Error Project::writeBuff(ox::CRStringView path, ox::Buffer const&buff) noexc
 | 
			
		||||
	ox::Buffer outBuff;
 | 
			
		||||
	outBuff.reserve(buff.size() + HdrSz);
 | 
			
		||||
	ox::BufferWriter writer(&outBuff);
 | 
			
		||||
	const auto [uuid, err] = m_ctx.pathToUuid.at(path);
 | 
			
		||||
	auto const [uuid, err] = m_ctx.pathToUuid.at(path);
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		oxReturnError(keel::writeUuidHeader(writer, *uuid));
 | 
			
		||||
	}
 | 
			
		||||
	oxReturnError(writer.write(buff.data(), buff.size()));
 | 
			
		||||
	const auto newFile = m_fs.stat(path).error != 0;
 | 
			
		||||
	auto const newFile = m_fs.stat(path).error != 0;
 | 
			
		||||
	oxReturnError(m_fs.write(path, outBuff.data(), outBuff.size(), ox::FileType::NormalFile));
 | 
			
		||||
	if (newFile) {
 | 
			
		||||
		fileAdded.emit(path);
 | 
			
		||||
@@ -110,7 +110,7 @@ ox::Result<ox::Buffer> Project::loadBuff(ox::CRStringView path) const noexcept {
 | 
			
		||||
 | 
			
		||||
ox::Error Project::lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView path) const noexcept {
 | 
			
		||||
	oxRequire(files, m_fs.ls(path));
 | 
			
		||||
	for (const auto &name : files) {
 | 
			
		||||
	for (auto const&name : files) {
 | 
			
		||||
		auto fullPath = ox::sfmt("{}/{}", path, name);
 | 
			
		||||
		oxRequire(stat, m_fs.stat(ox::StringView(fullPath)));
 | 
			
		||||
		switch (stat.fileType) {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ namespace studio {
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
		const auto done = t->update(ctx) == TaskState::Done;
 | 
			
		||||
		auto const done = t->update(ctx) == TaskState::Done;
 | 
			
		||||
		if (done) {
 | 
			
		||||
			t->finished.emit();
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,12 @@
 | 
			
		||||
 | 
			
		||||
namespace studio {
 | 
			
		||||
 | 
			
		||||
bool UndoCommand::mergeWith(const UndoCommand*) noexcept {
 | 
			
		||||
bool UndoCommand::mergeWith(UndoCommand const*) noexcept {
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UndoStack::push(ox::UPtr<UndoCommand> &&cmd) noexcept {
 | 
			
		||||
	for (const auto i = m_stackIdx; i < m_stack.size();) {
 | 
			
		||||
	for (auto const i = m_stackIdx; i < m_stack.size();) {
 | 
			
		||||
		oxIgnoreError(m_stack.erase(i));
 | 
			
		||||
	}
 | 
			
		||||
	cmd->redo();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <studio/widget.hpp>
 | 
			
		||||
 | 
			
		||||
namespace studio {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user