Skip to content

Commit

Permalink
0.2a
Browse files Browse the repository at this point in the history
- 0.2a Reindex objects
- 0.2a Navigate to specific object in column view
- 0.2a Automatic state id distribution
- 0.2a Class hint
- 0.2a Opitimize buildRefList
  • Loading branch information
Pentalimbed committed May 6, 2022
1 parent ff40d74 commit 7383912
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 48 deletions.
23 changes: 13 additions & 10 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
- Rework state and state selection
- Automate variable binding process
- Copy/paste ref management
- Disable unavailable classes options
- Display all available classes options in list view
- 0.1a Rework state and state selection
- 0.1a Automate variable binding process
- 0.1a Copy/paste ref management
- 0.1a Disable unavailable classes options
- 0.1a Display all available classes options in list view
Loading character file
Editing character file
Bone edit
Animation edit
Behaviour diagnosis
- Class hint
- New file
- Reindex objects
Navigate to specific object in column view
Automatic state id distribution
- 0.2a Class hint
- 0.1a New file
- 0.2a Reindex objects
- 0.2a Navigate to specific object in column view
- 0.2a Automatic state id distribution
Bone weight/index array
- 0.2a Opitimize buildRefList
64 changes: 64 additions & 0 deletions src/hkx/hkutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "hkxfile.h"
#include "utils.h"

#include <stack>

namespace Haviour
{
inline pugi::xml_node getParentStateMachine(pugi::xml_node hkparam, Hkx::HkxFile& file)
Expand Down Expand Up @@ -45,4 +47,66 @@ inline pugi::xml_node getStateById(pugi::xml_node state_machine, int32_t state_i
return {};
}

inline int getBiggestStateId(pugi::xml_node state_machine, Hkx::HkxFile& file)
{
if (strcmp(state_machine.attribute("class").as_string(), "hkbStateMachine"))
return -1;

auto states_node = state_machine.getByName("states");
size_t num_objs = states_node.attribute("numelements").as_ullong();
std::istringstream states_stream(states_node.text().as_string());
auto max_id = -1;

for (size_t i = 0; i < num_objs; ++i)
{
std::string temp_str;
states_stream >> temp_str;

auto state = file.getObj(temp_str);
auto id = state.getByName("stateId").text().as_int();

max_id = std::max(max_id, id);
}
return max_id;
}

// get a path from a child to parent
// the return starts(idx=0) from parent to child
inline void getNavPath(const std::string& from, const std::string& to, Hkx::HkxFile& file, std::vector<std::string>& out)
{
StringMap<std::string> prev_obj;
std::stack<std::string> objs_to_check;

// DFS
objs_to_check.push(from);
prev_obj[from] = {};
while (!objs_to_check.empty())
{
auto top = objs_to_check.top();
objs_to_check.pop();

if (top == to)
{
out = {to};
auto prev = prev_obj[to];
while (!prev.empty())
{
out.push_back(prev);
prev = prev_obj[prev];
}
}

std::vector<std::string> obj_refs = {};
file.getObjRefs(top, obj_refs);
for (auto& ref : obj_refs)
{
if (!prev_obj.contains(ref))
{
objs_to_check.push(ref);
prev_obj[ref] = top;
}
}
}
}

} // namespace Haviour
55 changes: 32 additions & 23 deletions src/hkx/hkxfile.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "hkxfile.h"
#include "hkclass.inl"
#include "hkutils.h"

#include <memory>
#include <execution>
Expand Down Expand Up @@ -169,21 +168,8 @@ void HkxFile::buildRefList()
m_obj_ref_list[obj.attribute("name").as_string()] = {};
}

std::for_each(
std::execution::par,
m_obj_list.begin(), m_obj_list.end(),
[=](auto entry) {
std::string_view id = entry.second.attribute("name").as_string();
for (auto& [parent_id, parent_obj] : m_obj_list)
{
if (id != parent_id && isRefBy(id, parent_obj))
if (getObj(id) && getObj(parent_id))
m_obj_ref_by_list.find(id)->second.emplace(parent_id);
}
}); // try to be fast here
for (auto& [id, ref_by] : m_obj_ref_by_list)
for (auto parent : ref_by)
m_obj_ref_list.find(parent)->second.emplace(id);
for (auto& [id, obj] : m_obj_list)
buildRefList(id);
}
void HkxFile::buildRefList(std::string_view id)
{
Expand All @@ -194,9 +180,32 @@ void HkxFile::buildRefList(std::string_view id)
for (auto ref_obj_id : refed_objs)
deRef(ref_obj_id, id);

for (auto& [ref_id, ref_obj] : m_obj_list)
if (id != ref_id && isRefBy(ref_id, obj))
addRef(ref_id, id);
struct Walker : pugi::xml_tree_walker
{
StringSet* m_refs;

virtual bool for_each(pugi::xml_node& node)
{
if (node.type() == pugi::node_pcdata)
{
std::string text = node.value();
size_t pos = text.find('#');
while (pos != text.npos)
{
if (!pos || (text[pos - 1] != '&')) // in case html entity, fuck html entities
m_refs->emplace(&text[pos], 5);
pos = text.find('#', pos + 1);
}
node.text() = text.c_str();
}
return true; // continue traversal
}
} walker;
walker.m_refs = &m_obj_ref_list.find(id)->second;
obj.traverse(walker);

for (auto& refed_id : *walker.m_refs)
m_obj_ref_by_list.find(refed_id)->second.emplace(id);
}

std::string_view HkxFile::addObj(std::string_view hkclass)
Expand All @@ -211,11 +220,11 @@ std::string_view HkxFile::addObj(std::string_view hkclass)
auto& class_def_map = getClassDefaultMap();
if (class_def_map.contains(hkclass))
{
auto retval = appendXmlString(m_data_node, class_def_map.at(hkclass));
auto id_str = std::format("#{:04}", ++m_latest_id);
retval.attribute("name") = id_str.c_str();
auto new_obj = appendXmlString(m_data_node, class_def_map.at(hkclass));
auto id_str = std::format("#{:04}", ++m_latest_id);
new_obj.attribute("name") = id_str.c_str();

m_obj_list[id_str] = retval;
m_obj_list[id_str] = new_obj;
if (!m_obj_class_list.contains(hkclass))
m_obj_class_list[std::string(hkclass)] = {};
m_obj_class_list.find(hkclass)->second.push_back(id_str);
Expand Down
33 changes: 24 additions & 9 deletions src/ui/columnview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
#include "widgets.h"
#include "propedit.h"
#include "hkx/hkclass.inl"
#include "hkx/hkutils.h"

#include <memory>

#include <spdlog/spdlog.h>

namespace Haviour
{
namespace Ui
Expand Down Expand Up @@ -50,19 +53,29 @@ void ColumnView::show()
auto file_manager = Hkx::HkxFileManager::getSingleton();
if (ImGui::Begin("Column View", &m_show, ImGuiWindowFlags_HorizontalScrollbar))
{
// if (ImGui::BeginTable("colviewtable", 2, ImGuiTableFlags_Resizable))
// {
// settings
// ImGui::TableNextColumn();
ImGui::TextDisabled("placeholder text");
ImGui::Separator();

// columns
// ImGui::TableNextColumn();
if (file_manager->isFileSelected())
{
auto& file = file_manager->getCurrentFile();
std::string root_state_machine = file.getRootStateMachine().data();

if (ImGui::InputText("Navigate to object", &m_nav_edit_str, ImGuiInputTextFlags_EnterReturnsTrue))
{
spdlog::info("Navigating to {}", m_nav_edit_str);
std::vector<std::string> path = {};
getNavPath(m_nav_edit_str, root_state_machine, file, path);
if (!path.empty())
{
if (m_columns.size() < path.size())
m_columns.resize(path.size());
for (int i = 0; i < path.size(); ++i)
m_columns[i].m_selected.insert(path[i].data());
}
else
spdlog::warn("Failed to navigate to {}", m_nav_edit_str);
}
addTooltip("Press enter to navigate.");
ImGui::Separator();

if (root_state_machine.empty() || !file.getObj(root_state_machine))
ImGui::TextDisabled("Failed to get root generator object");
else
Expand Down Expand Up @@ -140,6 +153,8 @@ void ColumnView::show()

reflist.push_back("> " + disp_name);
file.getRefedObjs(ref, reflist);
if (reflist.back() == "> " + disp_name)
reflist.pop_back(); // empty ones don't get shown
}

if (reflist.empty())
Expand Down
2 changes: 2 additions & 0 deletions src/ui/columnview.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class ColumnView

StringSet m_class_show;
StringMap<ImColor> m_class_color_map;

std::string m_nav_edit_str;
};
} // namespace Ui
} // namespace Haviour
4 changes: 3 additions & 1 deletion src/ui/propedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ void PropEdit::show()

ImGui::Separator();

ImGui::Text("Editing: %s", hkobj2str(file.getObj(m_edit_obj_id)).c_str());
ImGui::Text("Editing: %s", hkobj2str(edit_obj).c_str());
if (auto class_info = Hkx::getClassInfo(); class_info.contains(edit_obj.attribute("class").as_string()))
addTooltip(class_info.at(edit_obj.attribute("class").as_string()).data());

ImGui::Separator();

Expand Down
6 changes: 3 additions & 3 deletions src/ui/varedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void VarEdit::showVarList()
ImGui::SameLine();
if (ImGui::Button(ICON_FA_FILTER))
current_file.cleanupVariables();
addTooltip("Remove unused variables");
addTooltip("Remove unused variables (USE WITH CAUTION!)");
ImGui::SameLine();
if (ImGui::Button(ICON_FA_HASHTAG))
current_file.reindexVariables();
Expand Down Expand Up @@ -191,7 +191,7 @@ void VarEdit::showEvtList()
ImGui::SameLine();
if (ImGui::Button(ICON_FA_FILTER))
current_file.cleanupEvents();
addTooltip("Remove unused events");
addTooltip("Remove unused events (USE WITH CAUTION!)");
ImGui::SameLine();
if (ImGui::Button(ICON_FA_HASHTAG))
current_file.reindexEvents();
Expand Down Expand Up @@ -271,7 +271,7 @@ void VarEdit::showPropList()
ImGui::SameLine();
if (ImGui::Button(ICON_FA_FILTER))
current_file.cleanupProps();
addTooltip("Remove unused properties");
addTooltip("Remove unused properties (USE WITH CAUTION!)");
ImGui::SameLine();
if (ImGui::Button(ICON_FA_HASHTAG))
current_file.reindexProperties();
Expand Down
3 changes: 3 additions & 0 deletions src/ui/widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,9 @@ bool refEdit(std::string& value,
if (!isRefBy(old_value, parent))
file.deRef(old_value, parent_id);
file.addRef(value, parent_id);
// for states
if (auto obj = file.getObj(value); !strcmp(obj.attribute("class").as_string(), "hkbStateMachineStateInfo"))
obj.getByName("stateId").text() = getBiggestStateId(getParentStateMachine(obj, file), file) + 1;
}

ImGui::PopID();
Expand Down
5 changes: 3 additions & 2 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <string>
#include <tuple>
#include <functional>
#include <strstream>

#include <robin_hood.h>
#include <pugixml.hpp>
Expand Down Expand Up @@ -77,7 +78,7 @@ inline pugi::xml_node appendXmlString(pugi::xml_node target, std::string_view sr
{
// parse XML string as document
pugi::xml_document doc;
if (!doc.load_buffer(srcString.data(), srcString.length()))
if (!doc.load_buffer(srcString.data(), srcString.length(), pugi::parse_default & (~pugi::parse_escapes)))
return {};

if (target.attribute("numelements"))
Expand All @@ -89,7 +90,7 @@ inline pugi::xml_node appendXmlString(pugi::xml_node target, std::string_view sr

inline bool isRefBy(std::string_view id, pugi::xml_node obj)
{
return obj.find_node([=](pugi::xml_node node) { return std::string_view(node.text().as_string()).contains(id); });
return obj.find_node([=](pugi::xml_node node) { return (node.type() == pugi::node_pcdata) && std::string_view(node.value()).contains(id); });
}

inline pugi::xml_node getParentObj(pugi::xml_node node)
Expand Down

0 comments on commit 7383912

Please sign in to comment.