refactor(new_editor/app): reorganize host structure and add smoke test
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#include "Hierarchy/ProductHierarchyModel.h"
|
||||
#include "HierarchyModel.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
@@ -10,14 +10,14 @@ namespace XCEngine::UI::Editor::App {
|
||||
|
||||
namespace {
|
||||
|
||||
const ProductHierarchyNode* FindNodeRecursive(
|
||||
const std::vector<ProductHierarchyNode>& nodes,
|
||||
const HierarchyNode* FindNodeRecursive(
|
||||
const std::vector<HierarchyNode>& nodes,
|
||||
std::string_view nodeId) {
|
||||
for (const ProductHierarchyNode& node : nodes) {
|
||||
for (const HierarchyNode& node : nodes) {
|
||||
if (node.nodeId == nodeId) {
|
||||
return &node;
|
||||
}
|
||||
if (const ProductHierarchyNode* child =
|
||||
if (const HierarchyNode* child =
|
||||
FindNodeRecursive(node.children, nodeId);
|
||||
child != nullptr) {
|
||||
return child;
|
||||
@@ -26,14 +26,14 @@ const ProductHierarchyNode* FindNodeRecursive(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ProductHierarchyNode* FindNodeRecursive(
|
||||
std::vector<ProductHierarchyNode>& nodes,
|
||||
HierarchyNode* FindNodeRecursive(
|
||||
std::vector<HierarchyNode>& nodes,
|
||||
std::string_view nodeId) {
|
||||
for (ProductHierarchyNode& node : nodes) {
|
||||
for (HierarchyNode& node : nodes) {
|
||||
if (node.nodeId == nodeId) {
|
||||
return &node;
|
||||
}
|
||||
if (ProductHierarchyNode* child =
|
||||
if (HierarchyNode* child =
|
||||
FindNodeRecursive(node.children, nodeId);
|
||||
child != nullptr) {
|
||||
return child;
|
||||
@@ -43,11 +43,11 @@ ProductHierarchyNode* FindNodeRecursive(
|
||||
}
|
||||
|
||||
bool FindNodeParentRecursive(
|
||||
const std::vector<ProductHierarchyNode>& nodes,
|
||||
const std::vector<HierarchyNode>& nodes,
|
||||
std::string_view nodeId,
|
||||
const ProductHierarchyNode*& parent) {
|
||||
for (const ProductHierarchyNode& node : nodes) {
|
||||
for (const ProductHierarchyNode& child : node.children) {
|
||||
const HierarchyNode*& parent) {
|
||||
for (const HierarchyNode& node : nodes) {
|
||||
for (const HierarchyNode& child : node.children) {
|
||||
if (child.nodeId == nodeId) {
|
||||
parent = &node;
|
||||
return true;
|
||||
@@ -62,9 +62,9 @@ bool FindNodeParentRecursive(
|
||||
}
|
||||
|
||||
bool ExtractNodeRecursive(
|
||||
std::vector<ProductHierarchyNode>& nodes,
|
||||
std::vector<HierarchyNode>& nodes,
|
||||
std::string_view nodeId,
|
||||
ProductHierarchyNode& extractedNode) {
|
||||
HierarchyNode& extractedNode) {
|
||||
for (std::size_t index = 0u; index < nodes.size(); ++index) {
|
||||
if (nodes[index].nodeId == nodeId) {
|
||||
extractedNode = std::move(nodes[index]);
|
||||
@@ -80,11 +80,11 @@ bool ExtractNodeRecursive(
|
||||
}
|
||||
|
||||
void BuildTreeItemsRecursive(
|
||||
const std::vector<ProductHierarchyNode>& nodes,
|
||||
const std::vector<HierarchyNode>& nodes,
|
||||
std::uint32_t depth,
|
||||
const ::XCEngine::UI::UITextureHandle& icon,
|
||||
std::vector<Widgets::UIEditorTreeViewItem>& items) {
|
||||
for (const ProductHierarchyNode& node : nodes) {
|
||||
for (const HierarchyNode& node : nodes) {
|
||||
Widgets::UIEditorTreeViewItem item = {};
|
||||
item.itemId = node.nodeId;
|
||||
item.label = node.label;
|
||||
@@ -98,29 +98,29 @@ void BuildTreeItemsRecursive(
|
||||
|
||||
} // namespace
|
||||
|
||||
ProductHierarchyModel ProductHierarchyModel::BuildDefault() {
|
||||
ProductHierarchyModel model = {};
|
||||
HierarchyModel HierarchyModel::BuildDefault() {
|
||||
HierarchyModel model = {};
|
||||
model.m_roots = {
|
||||
ProductHierarchyNode{ "main_camera", "Main Camera", {} },
|
||||
ProductHierarchyNode{ "directional_light", "Directional Light", {} },
|
||||
ProductHierarchyNode{
|
||||
HierarchyNode{ "main_camera", "Main Camera", {} },
|
||||
HierarchyNode{ "directional_light", "Directional Light", {} },
|
||||
HierarchyNode{
|
||||
"player",
|
||||
"Player",
|
||||
{
|
||||
ProductHierarchyNode{ "camera_pivot", "Camera Pivot", {} },
|
||||
ProductHierarchyNode{ "player_mesh", "Mesh", {} }
|
||||
HierarchyNode{ "camera_pivot", "Camera Pivot", {} },
|
||||
HierarchyNode{ "player_mesh", "Mesh", {} }
|
||||
} },
|
||||
ProductHierarchyNode{
|
||||
HierarchyNode{
|
||||
"environment",
|
||||
"Environment",
|
||||
{
|
||||
ProductHierarchyNode{ "ground", "Ground", {} },
|
||||
ProductHierarchyNode{
|
||||
HierarchyNode{ "ground", "Ground", {} },
|
||||
HierarchyNode{
|
||||
"props",
|
||||
"Props",
|
||||
{
|
||||
ProductHierarchyNode{ "crate_01", "Crate_01", {} },
|
||||
ProductHierarchyNode{ "barrel_01", "Barrel_01", {} }
|
||||
HierarchyNode{ "crate_01", "Crate_01", {} },
|
||||
HierarchyNode{ "barrel_01", "Barrel_01", {} }
|
||||
} }
|
||||
} }
|
||||
};
|
||||
@@ -128,24 +128,24 @@ ProductHierarchyModel ProductHierarchyModel::BuildDefault() {
|
||||
return model;
|
||||
}
|
||||
|
||||
bool ProductHierarchyModel::Empty() const {
|
||||
bool HierarchyModel::Empty() const {
|
||||
return m_roots.empty();
|
||||
}
|
||||
|
||||
bool ProductHierarchyModel::ContainsNode(std::string_view nodeId) const {
|
||||
bool HierarchyModel::ContainsNode(std::string_view nodeId) const {
|
||||
return FindNode(nodeId) != nullptr;
|
||||
}
|
||||
|
||||
const ProductHierarchyNode* ProductHierarchyModel::FindNode(std::string_view nodeId) const {
|
||||
const HierarchyNode* HierarchyModel::FindNode(std::string_view nodeId) const {
|
||||
return FindNodeRecursive(m_roots, nodeId);
|
||||
}
|
||||
|
||||
ProductHierarchyNode* ProductHierarchyModel::FindNode(std::string_view nodeId) {
|
||||
HierarchyNode* HierarchyModel::FindNode(std::string_view nodeId) {
|
||||
return FindNodeRecursive(m_roots, nodeId);
|
||||
}
|
||||
|
||||
std::optional<std::string> ProductHierarchyModel::GetParentId(std::string_view nodeId) const {
|
||||
const ProductHierarchyNode* parent = nullptr;
|
||||
std::optional<std::string> HierarchyModel::GetParentId(std::string_view nodeId) const {
|
||||
const HierarchyNode* parent = nullptr;
|
||||
if (!FindNodeParentRecursive(m_roots, nodeId, parent) || parent == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -153,8 +153,8 @@ std::optional<std::string> ProductHierarchyModel::GetParentId(std::string_view n
|
||||
return parent->nodeId;
|
||||
}
|
||||
|
||||
bool ProductHierarchyModel::RenameNode(std::string_view nodeId, std::string label) {
|
||||
ProductHierarchyNode* node = FindNode(nodeId);
|
||||
bool HierarchyModel::RenameNode(std::string_view nodeId, std::string label) {
|
||||
HierarchyNode* node = FindNode(nodeId);
|
||||
if (node == nullptr || label.empty() || node->label == label) {
|
||||
return false;
|
||||
}
|
||||
@@ -163,38 +163,38 @@ bool ProductHierarchyModel::RenameNode(std::string_view nodeId, std::string labe
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ProductHierarchyModel::CreateChild(
|
||||
std::string HierarchyModel::CreateChild(
|
||||
std::string_view parentId,
|
||||
std::string_view label) {
|
||||
ProductHierarchyNode* parent = FindNode(parentId);
|
||||
HierarchyNode* parent = FindNode(parentId);
|
||||
if (parent == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
ProductHierarchyNode node = {};
|
||||
HierarchyNode node = {};
|
||||
node.nodeId = AllocateNodeId();
|
||||
node.label = label.empty() ? std::string("GameObject") : std::string(label);
|
||||
parent->children.push_back(std::move(node));
|
||||
return parent->children.back().nodeId;
|
||||
}
|
||||
|
||||
bool ProductHierarchyModel::DeleteNode(std::string_view nodeId) {
|
||||
bool HierarchyModel::DeleteNode(std::string_view nodeId) {
|
||||
if (nodeId.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ProductHierarchyNode removed = {};
|
||||
HierarchyNode removed = {};
|
||||
return ExtractNodeRecursive(m_roots, nodeId, removed);
|
||||
}
|
||||
|
||||
bool ProductHierarchyModel::CanReparent(
|
||||
bool HierarchyModel::CanReparent(
|
||||
std::string_view sourceNodeId,
|
||||
std::string_view targetParentId) const {
|
||||
if (sourceNodeId.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ProductHierarchyNode* source = FindNode(sourceNodeId);
|
||||
const HierarchyNode* source = FindNode(sourceNodeId);
|
||||
if (source == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -203,11 +203,11 @@ bool ProductHierarchyModel::CanReparent(
|
||||
return true;
|
||||
}
|
||||
|
||||
const ProductHierarchyNode* targetParent = FindNode(targetParentId);
|
||||
const HierarchyNode* targetParent = FindNode(targetParentId);
|
||||
return CanAdopt(sourceNodeId, targetParent);
|
||||
}
|
||||
|
||||
bool ProductHierarchyModel::Reparent(
|
||||
bool HierarchyModel::Reparent(
|
||||
std::string_view sourceNodeId,
|
||||
std::string_view targetParentId) {
|
||||
if (!CanReparent(sourceNodeId, targetParentId) || targetParentId.empty()) {
|
||||
@@ -219,12 +219,12 @@ bool ProductHierarchyModel::Reparent(
|
||||
return false;
|
||||
}
|
||||
|
||||
ProductHierarchyNode movedNode = {};
|
||||
HierarchyNode movedNode = {};
|
||||
if (!ExtractNodeRecursive(m_roots, sourceNodeId, movedNode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ProductHierarchyNode* targetParent = FindNode(targetParentId);
|
||||
HierarchyNode* targetParent = FindNode(targetParentId);
|
||||
if (targetParent == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ bool ProductHierarchyModel::Reparent(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProductHierarchyModel::MoveToRoot(std::string_view sourceNodeId) {
|
||||
bool HierarchyModel::MoveToRoot(std::string_view sourceNodeId) {
|
||||
if (sourceNodeId.empty() || !ContainsNode(sourceNodeId)) {
|
||||
return false;
|
||||
}
|
||||
@@ -242,7 +242,7 @@ bool ProductHierarchyModel::MoveToRoot(std::string_view sourceNodeId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ProductHierarchyNode movedNode = {};
|
||||
HierarchyNode movedNode = {};
|
||||
if (!ExtractNodeRecursive(m_roots, sourceNodeId, movedNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -251,27 +251,27 @@ bool ProductHierarchyModel::MoveToRoot(std::string_view sourceNodeId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Widgets::UIEditorTreeViewItem> ProductHierarchyModel::BuildTreeItems(
|
||||
std::vector<Widgets::UIEditorTreeViewItem> HierarchyModel::BuildTreeItems(
|
||||
const ::XCEngine::UI::UITextureHandle& icon) const {
|
||||
std::vector<Widgets::UIEditorTreeViewItem> items = {};
|
||||
BuildTreeItemsRecursive(m_roots, 0u, icon, items);
|
||||
return items;
|
||||
}
|
||||
|
||||
std::string ProductHierarchyModel::AllocateNodeId() {
|
||||
std::string HierarchyModel::AllocateNodeId() {
|
||||
std::ostringstream stream = {};
|
||||
stream << "generated_node_" << m_nextGeneratedNodeId++;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
bool ProductHierarchyModel::CanAdopt(
|
||||
bool HierarchyModel::CanAdopt(
|
||||
std::string_view sourceNodeId,
|
||||
const ProductHierarchyNode* targetParent) const {
|
||||
const HierarchyNode* targetParent) const {
|
||||
if (targetParent == nullptr || sourceNodeId == targetParent->nodeId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ProductHierarchyNode* source = FindNode(sourceNodeId);
|
||||
const HierarchyNode* source = FindNode(sourceNodeId);
|
||||
if (source == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -279,10 +279,10 @@ bool ProductHierarchyModel::CanAdopt(
|
||||
return !ContainsDescendant(*source, targetParent->nodeId);
|
||||
}
|
||||
|
||||
bool ProductHierarchyModel::ContainsDescendant(
|
||||
const ProductHierarchyNode& node,
|
||||
bool HierarchyModel::ContainsDescendant(
|
||||
const HierarchyNode& node,
|
||||
std::string_view candidateId) const {
|
||||
for (const ProductHierarchyNode& child : node.children) {
|
||||
for (const HierarchyNode& child : node.children) {
|
||||
if (child.nodeId == candidateId || ContainsDescendant(child, candidateId)) {
|
||||
return true;
|
||||
}
|
||||
@@ -291,3 +291,6 @@ bool ProductHierarchyModel::ContainsDescendant(
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user