176 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
 | |
|  */
 | |
| 
 | |
| #include <imgui.h>
 | |
| 
 | |
| #include "clawviewer.hpp"
 | |
| 
 | |
| namespace studio {
 | |
| 
 | |
| ClawEditor::ClawEditor(Context &sctx, ox::StringParam path):
 | |
| 	Editor(sctx, std::move(path)),
 | |
| 	m_obj(sctx.project->loadObj<ox::ModelObject>(itemPath()).unwrapThrow()) {
 | |
| }
 | |
| 
 | |
| void ClawEditor::draw(Context&) noexcept {
 | |
| 	ImGui::BeginChild("PaletteEditor");
 | |
| 	static constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
 | |
| 	if (ImGui::BeginTable("ObjTree", 3, flags)) {
 | |
| 		ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 100);
 | |
| 		ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 250);
 | |
| 		ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_NoHide);
 | |
| 		ImGui::TableHeadersRow();
 | |
| 		ObjPath objPath;
 | |
| 		drawTree(objPath, m_obj);
 | |
| 		ImGui::EndTable();
 | |
| 	}
 | |
| 	ImGui::EndChild();
 | |
| }
 | |
| 
 | |
| void ClawEditor::drawRow(ox::ModelValue const&value) noexcept {
 | |
| 	using Str = ox::BasicString<100>;
 | |
| 	Str val, type;
 | |
| 	switch (value.type()) {
 | |
| 		case ox::ModelValue::Type::Undefined:
 | |
| 			val = "undefined";
 | |
| 			type = "undefined";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::Bool:
 | |
| 			val = value.get<bool>() ? "true" : "false";
 | |
| 			type = "bool";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::UnsignedInteger8:
 | |
| 			val = ox::sfmt<Str>("{}", value.get<uint8_t>());
 | |
| 			type = "uint8";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::UnsignedInteger16:
 | |
| 			val = ox::sfmt<Str>("{}", value.get<uint16_t>());
 | |
| 			type = "uint16";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::UnsignedInteger32:
 | |
| 			val = ox::sfmt<Str>("{}", value.get<uint32_t>());
 | |
| 			type = "uint32";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::UnsignedInteger64:
 | |
| 			val = ox::sfmt<Str>("{}", value.get<uint64_t>());
 | |
| 			type = "uint64";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::SignedInteger8:
 | |
| 			val = ox::sfmt<Str>("{}", value.get<int8_t>());
 | |
| 			type = "int8";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::SignedInteger16:
 | |
| 			val = ox::sfmt<Str>("{}", value.get<int16_t>());
 | |
| 			type = "int16";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::SignedInteger32:
 | |
| 			val = ox::sfmt<Str>("{}", value.get<int32_t>());
 | |
| 			type = "int32";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::SignedInteger64:
 | |
| 			val = ox::sfmt<Str>("{}", value.get<int64_t>());
 | |
| 			type = "int64";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::String:
 | |
| 			val = ox::sfmt<Str>("\"{}\"", value.get<ox::String>());
 | |
| 			type = "string";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::Object:
 | |
| 			type = value.get<ox::ModelObject>().type()->typeName.c_str();
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::Union:
 | |
| 			type = "union";
 | |
| 			break;
 | |
| 		case ox::ModelValue::Type::InlineArray:
 | |
| 		case ox::ModelValue::Type::Vector:
 | |
| 			type = "list";
 | |
| 			break;
 | |
| 	}
 | |
| 	ImGui::TableNextColumn();
 | |
| 	ImGui::Text("%s", type.c_str());
 | |
| 	ImGui::TableNextColumn();
 | |
| 	ImGui::Text("%s", val.c_str());
 | |
| }
 | |
| 
 | |
| void ClawEditor::drawVar(ObjPath &path, ox::StringViewCR name, ox::ModelValue const&value) noexcept {
 | |
| 	using Str = ox::BasicString<100>;
 | |
| 	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) {
 | |
| 		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);
 | |
| 		auto const open = ImGui::TreeNodeEx(lbl.c_str(), flags);
 | |
| 		ImGui::SameLine();
 | |
| 		drawRow(value);
 | |
| 		if (open) {
 | |
| 			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();
 | |
| 				++i;
 | |
| 			}
 | |
| 			ImGui::TreePop();
 | |
| 		}
 | |
| 	} else {
 | |
| 		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);
 | |
| 		auto const open = ImGui::TreeNodeEx(lbl.c_str(), flags);
 | |
| 		ImGui::SameLine();
 | |
| 		drawRow(value);
 | |
| 		if (open) {
 | |
| 			ImGui::TreePop();
 | |
| 		}
 | |
| 	}
 | |
| 	path.pop_back();
 | |
| }
 | |
| 
 | |
| 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 lbl = ox::sfmt<Str>("{}##{}", c->name, pathStr);
 | |
| 		const auto rowSelected = false;
 | |
| 		const auto hasChildren = c->value.type() == ox::ModelValue::Type::Object
 | |
| 		                                || c->value.type() == ox::ModelValue::Type::Vector;
 | |
| 		const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
 | |
| 		                   | ImGuiTreeNodeFlags_OpenOnArrow
 | |
| 		                   | (hasChildren ? 0 : ImGuiTreeNodeFlags_Leaf)
 | |
| 		                   | (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
 | |
| 		ImGui::TableNextColumn();
 | |
| 		//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();
 | |
| 			drawRow(c->value);
 | |
| 			if (open) {
 | |
| 				drawTree(path, c->value.get<ox::ModelObject>());
 | |
| 				ImGui::TreePop();
 | |
| 			}
 | |
| 		} else {
 | |
| 			drawVar(path, c->name, c->value);
 | |
| 		}
 | |
| 		path.pop_back();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| }
 |