<commit_before>#include "SceneDebugger.h"
#include "FSEObject/FSEObject.h"
//#include "../imgui-1.49/imgui.h"
#include "../FSE/FSE-ImGui/imgui-colorpicker.h"
#include "../imgui-1.49/imgui_internal.h"

#include <iomanip>
#include <sstream>

namespace fse
{

	std::unordered_map<rttr::type,
		std::function<void(rttr::property, rttr::instance*)>> SceneDebugger::item_edit_funcs_;

	SceneDebugger::SceneDebugger()
	{

	}

	SceneDebugger::SceneDebugger(Scene* scene) : scene_(scene)
	{

		objects_ = std::set<FSEObject*, std::function<bool(FSEObject*, FSEObject*)>>(
			[](FSEObject* lhs, FSEObject* rhs) {return lhs->getID() < rhs->getID(); });

		if (item_edit_funcs_.size() == 0)
			item_edit_funcs_ = CreateDefaultItemEditMap();
	}

	void SceneDebugger::Update()
	{
		if (scene_ == nullptr)
			return;

		objects_.clear();
		for (const auto& object : *scene_->getFSEObjects())
			objects_.insert(object.get());

		ImGui::Begin("SceneDebugger##MainMenu");

		ShowSceneStatus();

		ShowObjectList();

		if (ImGui::CollapsingHeader("Object Editor##SceneDebugger"))
			ShowObjectEditor();

		ImGui::End();
	}

	void SceneDebugger::RegisterItemEditFunc(rttr::type type,
		std::function<void(rttr::property, rttr::instance*)> func)
	{
		item_edit_funcs_[type] = func;
	}
	
	void SceneDebugger::ShowObjectList()
	{
		if (ImGui::CollapsingHeader("Subscene Objects##SceneDebugger"))
		{
			ImGui::BeginChild("##Objects##SceneDebugger", ImVec2(0, 250), true);
			int id;
			for (const auto& object : objects_)
			{
				id = object->getID();
				rttr::type type = rttr::type::get(*object);
				std::string nodename = std::string(type.get_name().data()) + "##SceneDebugger" + std::to_string(id);
				int pos;
				while ((pos = nodename.find("class "), pos) != std::string::npos)
					nodename.erase(pos, 6);
				if (ImGui::Selectable(nodename.data(), id == selected_id_))
					selected_id_ = id;
			}
			ImGui::EndChild();
		}
	}

	void SceneDebugger::ShowObjectEditor()
	{
		ImGui::BeginChild("##ObjectEditor##SceneDebugger", ImVec2(0, ImGui::GetCurrentWindow()->Size.y / 2.f), true);
		auto it = std::find_if(objects_.begin(), objects_.end(), [this](FSEObject* object){ return object->getID() == selected_id_;});
		if (it == objects_.end())
		{
			ImGui::Text("Object: <None>");
			ImGui::Separator();
			ImGui::EndChild();
			return;
		} 
		ImGui::PushItemWidth(ImGui::GetCurrentWindow()->Size.x - 150);
		rttr::type type = rttr::type::get(**it);
		ImGui::Text(std::string("Object: " + std::string(type.get_name().data())).data());
		ImGui::Separator();

		ShowObjectEditorItems(type, &rttr::instance(*it));

		for (auto& method : type.get_methods())
		{
			if (method.get_name().compare("destroy") == 0)
			{
				ImGui::Separator();
				if (ImGui::Button("Destroy##SceneDebugger"))
				{
					type.invoke("destroy", *it, {}); //with fire
				}
			}
		}

		ImGui::PopItemWidth();
		ImGui::EndChild();
	}

	void SceneDebugger::ShowObjectEditorItems(rttr::type type, rttr::instance* object) const
	{
		for (auto& prop : type.get_properties())
		{
			if (item_edit_funcs_.count(prop.get_type()))
				item_edit_funcs_[prop.get_type()](prop, object);
			else if (prop.get_type().get_properties().size() > 0)
			{
				std::string propname(std::string(prop.get_name().data()) + "##" + std::to_string(reinterpret_cast<int>(object)));
				if (ImGui::TreeNode(propname.data()))
				{
					auto val = prop.get_value(*object);
					auto inst = rttr::instance(val);
					ShowObjectEditorItems(prop.get_type(), &inst);
					prop.set_value(*object, val);

					ImGui::TreePop();
				}
			}
		}
	}
<commit_msg>SceneDebugger: Proper nested types + display unsupported types<commit_after>#include "SceneDebugger.h"
#include "FSEObject/FSEObject.h"
//#include "../imgui-1.49/imgui.h"
#include "../FSE/FSE-ImGui/imgui-colorpicker.h"
#include "../imgui-1.49/imgui_internal.h"

#include <iomanip>
#include <sstream>

namespace fse
{

	std::unordered_map<rttr::type,
		std::function<void(rttr::property, rttr::instance*)>> SceneDebugger::item_edit_funcs_;

	SceneDebugger::SceneDebugger()
	{

	}

	SceneDebugger::SceneDebugger(Scene* scene) : scene_(scene)
	{

		objects_ = std::set<FSEObject*, std::function<bool(FSEObject*, FSEObject*)>>(
			[](FSEObject* lhs, FSEObject* rhs) {return lhs->getID() < rhs->getID(); });

		if (item_edit_funcs_.size() == 0)
			item_edit_funcs_ = CreateDefaultItemEditMap();
	}

	void SceneDebugger::Update()
	{
		if (scene_ == nullptr)
			return;

		objects_.clear();
		for (const auto& object : *scene_->getFSEObjects())
			objects_.insert(object.get());

		ImGui::Begin("SceneDebugger##MainMenu");

		ShowSceneStatus();

		ShowObjectList();

		if (ImGui::CollapsingHeader("Object Editor##SceneDebugger"))
			ShowObjectEditor();

		ImGui::End();
	}

	void SceneDebugger::RegisterItemEditFunc(rttr::type type,
		std::function<void(rttr::property, rttr::instance*)> func)
	{
		item_edit_funcs_[type] = func;
	}
	
	void SceneDebugger::ShowObjectList()
	{
		if (ImGui::CollapsingHeader("Subscene Objects##SceneDebugger"))
		{
			ImGui::BeginChild("##Objects##SceneDebugger", ImVec2(0, 250), true);
			int id;
			for (const auto& object : objects_)
			{
				id = object->getID();
				rttr::type type = rttr::type::get(*object);
				std::string nodename = std::string(type.get_name().data()) + "##SceneDebugger" + std::to_string(id);
				int pos;
				while ((pos = nodename.find("class "), pos) != std::string::npos)
					nodename.erase(pos, 6);
				if (ImGui::Selectable(nodename.data(), id == selected_id_))
					selected_id_ = id;
			}
			ImGui::EndChild();
		}
	}

	void SceneDebugger::ShowObjectEditor()
	{
		ImGui::BeginChild("##ObjectEditor##SceneDebugger", ImVec2(0, ImGui::GetCurrentWindow()->Size.y / 2.f), true);
		auto it = std::find_if(objects_.begin(), objects_.end(), [this](FSEObject* object){ return object->getID() == selected_id_;});
		if (it == objects_.end())
		{
			ImGui::Text("Object: <None>");
			ImGui::Separator();
			ImGui::EndChild();
			return;
		} 
		ImGui::PushItemWidth(ImGui::GetCurrentWindow()->Size.x - 150);
		rttr::type type = rttr::type::get(**it);
		ImGui::Text(std::string("Object: " + std::string(type.get_name().data())).data());
		ImGui::Separator();

		ShowObjectEditorItems(type, &rttr::instance(*it));

		for (auto& method : type.get_methods())
		{
			if (method.get_name().compare("destroy") == 0)
			{
				ImGui::Separator();
				if (ImGui::Button("Destroy##SceneDebugger"))
				{
					type.invoke("destroy", *it, {}); //with fire
				}
			}
		}

		ImGui::PopItemWidth();
		ImGui::EndChild();
	}

	void SceneDebugger::ShowObjectEditorItems(rttr::type type, rttr::instance* object) const
	{
		for (auto& prop : type.get_properties())
		{
			if (item_edit_funcs_.count(prop.get_type()))
				item_edit_funcs_[prop.get_type()](prop, object);
			else if (prop.get_type().get_properties().size() > 0)
			{
				for (auto& pr : prop.get_type().get_properties())
				{
					if (item_edit_funcs_.count(pr.get_type()))
					{
						std::string propname(std::string(prop.get_name().data()) + "##" + std::to_string(reinterpret_cast<int>(object)));
						if (ImGui::TreeNode(propname.data()))
						{
							auto val = prop.get_value(*object);
							auto inst = rttr::instance(val);
							ShowObjectEditorItems(prop.get_type(), &inst);
							prop.set_value(*object, val);

							ImGui::TreePop();
						}
						break;
					}
				}
			} else {
				std::string propname("Unsupported type: " 
					+ std::string(prop.get_type().get_name().data()) + "; "
					+ std::string(prop.get_name().data()));
				ImGui::Text(propname.data());
			}
		}
	}

{'fraction_non_alphanumeric': 0.1924244423914478, 'fraction_numerical': 0.005543090933086974, 'mean_word_length': 4.580265095729013, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4783765', 'n_tokens_mistral': 3109, 'n_tokens_neox': 2694, 'n_words': 410}