From 6769ada4b6eaee6d78610d15d110087ceb470ae5 Mon Sep 17 00:00:00 2001 From: codeboss <2422523675@qq.com> Date: Sun, 29 Jun 2025 22:58:45 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E6=8E=92=E5=BA=8F=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E7=94=9F=E6=95=88=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ComponentBasic/BehaviorPerform.cpp | 34 ++++-- ComponentBasic/BehaviorPerform.h | 167 ++++++++++++++--------------- SimsWorld/BehaviorEditor.cpp | 163 ++++++++++++++++++++++++++++ SimsWorld/BehaviorEditor.h | 75 ++++++++++++- SimsWorld/SimsWorld.vcxproj | 2 +- SimsWorld/main.cpp | 39 ++++++- TestProject/main.cpp | 33 ------ 7 files changed, 380 insertions(+), 133 deletions(-) diff --git a/ComponentBasic/BehaviorPerform.cpp b/ComponentBasic/BehaviorPerform.cpp index 60fc86e..f63f64e 100644 --- a/ComponentBasic/BehaviorPerform.cpp +++ b/ComponentBasic/BehaviorPerform.cpp @@ -122,7 +122,7 @@ LogicalNode::LogicalNode(NodeKind t /*= NodeKind::ACTIONNODE*/) :_node_type(t) { } -void LogicalNode::setParent(std::weak_ptr pnode) +void LogicalNode::_set_parent_node(std::weak_ptr pnode) { this->_parent_bind = pnode; } @@ -153,7 +153,7 @@ int LogicalNode::getID() const return this->_node_id; } -QString LogicalNode::runtimeName() const +QString LogicalNode::rtName() const { return QString("%1(%2)").arg(this->typeName()).arg(getID()); } @@ -163,8 +163,8 @@ std::weak_ptr LogicalNode::parent() const return this->_parent_bind; } -BehaviorMapNode::BehaviorMapNode(std::shared_ptr core) - :LogicalNode(NodeKind::MAPNODE), MapKernal(core) { +BehaviorMapNode::BehaviorMapNode(std::shared_ptr core) + :LogicalNode(NodeKind::MAPNODE), _bind_kernal(core) { } void BehaviorMapNode::setVariable(const QString& key, IO_TYPE t, std::shared_ptr ins) @@ -190,7 +190,7 @@ void BehaviorMapNode::resetName(const QString& val) std::shared_ptr BehaviorMapNode::newDefault() const { - return std::make_shared(this->messageLoader()); + return std::make_shared(this->_bind_kernal); } void BehaviorMapNode::recoveryFrom(const QJsonObject& obj) @@ -340,21 +340,22 @@ void SequenceNode::reset() this->_state_map.clear(); } -QList> ComposeNode::children() const +QList> LogicalNode::children() const { return _child_list; } -void ComposeNode::insert(std::shared_ptr node, int index /*= -1*/) +void LogicalNode::insert(std::shared_ptr node, int index /*= -1*/) { for (auto it : _child_list) if (it->getID() == node->getID()) return; + node->_set_parent_node(this->shared_from_this()); _child_list.insert(index, node); } -void ComposeNode::remove(std::shared_ptr node) +void LogicalNode::remove(std::shared_ptr node) { _child_list.removeAll(node); } @@ -531,6 +532,23 @@ LogicalResult CompareNode::execute() return LogicalResult::FAILURE; } +void CompareNode::insert(std::shared_ptr node, int index /*= -1*/) +{ + if (this->children().size()) + return; + + LogicalNode::insert(node, index); +} + +QList> CompareNode::getForwards() const +{ + return QList>(); +} + +bool CompareNode::fallback(std::shared_ptr node, LogicalResult ste) { + return true; +} + std::shared_ptr CompareNode::newDefault() const { return std::make_shared(); diff --git a/ComponentBasic/BehaviorPerform.h b/ComponentBasic/BehaviorPerform.h index 73f0c22..55da8f7 100644 --- a/ComponentBasic/BehaviorPerform.h +++ b/ComponentBasic/BehaviorPerform.h @@ -226,13 +226,20 @@ enum class NodeKind { /// /// 所有逻辑节点的基类 /// -class COMPONENTBASIC_EXPORT LogicalNode : virtual public Serializable { +class COMPONENTBASIC_EXPORT LogicalNode : virtual public Serializable, public std::enable_shared_from_this { private: int _node_id = 0; NodeKind _node_type = NodeKind::ACTIONNODE; + std::weak_ptr _parent_bind; QList> _child_list; + /// + /// 重置父节点 + /// + /// + void _set_parent_node(std::weak_ptr pnode); + public: LogicalNode(NodeKind t = NodeKind::ACTIONNODE); virtual ~LogicalNode() = default; @@ -243,16 +250,6 @@ public: /// NodeKind nodeKind() const; - /// - /// 重置父节点 - /// - /// - void setParent(std::weak_ptr pnode); - /// - /// 回退节点 - /// - /// - std::weak_ptr parent() const; /// /// 获取包含树图节点 /// @@ -260,62 +257,10 @@ public: std::shared_ptr bindMap() const; /// - /// 设置节点id - /// - /// - void setID(int unique_id); - /// - /// 提取节点id + /// 回退节点 /// /// - int getID() const; - /// - /// 实例化节点名称 - /// - /// - QString runtimeName() const; - - /// - /// 重置内部状态 - /// - virtual void reset() = 0; - /// - /// 获取节点名称 - /// - /// - virtual QString typeName() const = 0; - /// - /// 执行逻辑节点 - /// - /// - /// - virtual LogicalResult execute() = 0; - /// - /// 声明输入变量的内部标识和数据接口 - /// - /// map{name, type-ins} - virtual QHash> inputList() const = 0; - /// - /// 声明输出变量的内部标识和数据接口 - /// - /// map{name, type-ins} - virtual QHash> outputList() const = 0; - - /// - /// 新建默认实例 - /// - /// - virtual std::shared_ptr newDefault() const = 0; -}; - -/// -/// 组合节点 -/// -class COMPONENTBASIC_EXPORT ComposeNode { -private: - QList> _child_list; - -public: + std::weak_ptr parent() const; /// /// 获取子节点列表 /// @@ -333,6 +278,46 @@ public: /// virtual void remove(std::shared_ptr node); + + + + /// + /// 设置节点id + /// + /// + void setID(int unique_id); + /// + /// 提取节点id + /// + /// + int getID() const; + /// + /// 实例化节点名称 + /// + /// + QString rtName() const; + + /// + /// 获取节点名称 + /// + /// + virtual QString typeName() const = 0; + /// + /// 声明输入变量的内部标识和数据接口 + /// + /// map{name, type-ins} + virtual QHash> inputList() const = 0; + /// + /// 声明输出变量的内部标识和数据接口 + /// + /// map{name, type-ins} + virtual QHash> outputList() const = 0; + + + /// + /// 重置内部状态 + /// + virtual void reset() = 0; /// /// 获取执行入口节点 /// @@ -345,8 +330,22 @@ public: /// /// 接续执行标志 virtual bool fallback(std::shared_ptr node, LogicalResult ste) = 0; + /// + /// 执行逻辑节点 + /// + /// + /// + virtual LogicalResult execute() = 0; + + + /// + /// 新建默认实例 + /// + /// + virtual std::shared_ptr newDefault() const = 0; }; + /// /// 逻辑树节点输入输出类型 /// @@ -356,18 +355,19 @@ enum class IO_TYPE { /// /// 自定义行为树节点根节点实例 /// -class COMPONENTBASIC_EXPORT BehaviorMapNode - : public MapKernal, public LogicalNode, public ComposeNode { +class COMPONENTBASIC_EXPORT BehaviorMapNode : public LogicalNode { private: + std::shared_ptr _bind_kernal; + QString _map_name; + /// /// 地图变量表 /// QHash>> _variables; - QString _map_name; LogicalResult _state_value; public: - BehaviorMapNode(std::shared_ptr core); + BehaviorMapNode(std::shared_ptr kernal); /// @@ -443,8 +443,7 @@ public: /// /// 顺序节点 /// -class COMPONENTBASIC_EXPORT SequenceNode - : public ComposeNode, public LogicalNode { +class COMPONENTBASIC_EXPORT SequenceNode : public LogicalNode { private: QHash _state_map; @@ -475,8 +474,7 @@ public: /// /// 选择节点 /// -class COMPONENTBASIC_EXPORT SelectorNode - : public ComposeNode, public LogicalNode { +class COMPONENTBASIC_EXPORT SelectorNode : public LogicalNode { private: QHash _state_map; @@ -507,8 +505,7 @@ public: /// /// 并行节点 /// -class COMPONENTBASIC_EXPORT ParallelNode - : public ComposeNode, public LogicalNode { +class COMPONENTBASIC_EXPORT ParallelNode : public LogicalNode { private: QHash _state_map; @@ -532,7 +529,6 @@ public: /// /// virtual std::shared_ptr newDefault() const override; - void recoveryFrom(const QJsonObject& obj) override; void saveTo(QJsonObject& obj) const override; }; @@ -548,23 +544,21 @@ private: public: CompareNode(); - /// - /// 委托名称 - /// - /// QString delegateName() const; - /// - /// 绑定比较委托 - /// - /// void bindDelegate(std::shared_ptr ins); QHash> inputList() const override; QHash> outputList() const override; - QString typeName() const override; - LogicalResult execute() override; + virtual void insert(std::shared_ptr node, int index /*= -1*/) override; + QString typeName() const override; + + virtual QList> getForwards() const override; + virtual bool fallback(std::shared_ptr node, LogicalResult ste) override; + + + LogicalResult execute() override; void reset() override; /// @@ -573,7 +567,6 @@ public: /// /// virtual std::shared_ptr newDefault() const override; - void recoveryFrom(const QJsonObject& obj) override; void saveTo(QJsonObject& obj) const override; }; diff --git a/SimsWorld/BehaviorEditor.cpp b/SimsWorld/BehaviorEditor.cpp index f401e94..9341290 100644 --- a/SimsWorld/BehaviorEditor.cpp +++ b/SimsWorld/BehaviorEditor.cpp @@ -1 +1,164 @@ #include "BehaviorEditor.h" + +NodePresent::NodePresent(std::shared_ptr bind) + :_node_bind(bind) { +} + +QRectF NodePresent::contentMeasure() const +{ + return QRectF(0, 0, 200, 40); +} + +QRectF NodePresent::boundingRect() const +{ + return contentMeasure() + QMargins(0, 0, 20, 20); +} + +void NodePresent::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) +{ + //painter->drawRect(boundingRect()); + painter->translate(QPointF(10, 10)); + + auto rect = contentMeasure(); + painter->fillRect(rect, Qt::red); +} + +BehaviorsPresent::BehaviorsPresent(QWidget* parent /*= nullptr*/) + : QGraphicsView(parent) { + this->setScene(&_bind_scene); +} + +void BehaviorsPresent::setRoot(std::shared_ptr root) +{ + qDeleteAll(_present_peers); + _present_peers.clear(); + + this->_bind_maproot = root; + contentRelayout(); +} + +void BehaviorsPresent::presentAllocate(std::shared_ptr ins) +{ + switch (ins->nodeKind()) + { + case NodeKind::MAPNODE: + case NodeKind::PARALLELNODE: + case NodeKind::SEQUENCENODE: + case NodeKind::SELECTORNODE: + if (ins->nodeKind() != NodeKind::MAPNODE || !ins->bindMap()) { + auto type = ins->nodeKind(); + for (auto it : ins->children()) + presentAllocate(it); + } + + default: + if (_present_peers.contains(ins)) + return; + + _present_peers[ins] = new NodePresent(ins); + this->_bind_scene.addItem(_present_peers[ins]); + break; + } +} + +void BehaviorsPresent::presentRelease(std::shared_ptr ins) +{ + switch (ins->nodeKind()) + { + case NodeKind::MAPNODE: + case NodeKind::PARALLELNODE: + case NodeKind::SELECTORNODE: + case NodeKind::SEQUENCENODE: { + for (auto item : ins->children()) { + presentRelease(item); + } + }break; + default: + if (this->_present_peers.contains(ins)) + delete this->_present_peers[ins]; + break; + } +} + +void BehaviorsPresent::contentRelayout() +{ + if (!_bind_maproot) + return; + + // 初始化显示节点 + presentAllocate(_bind_maproot); + + QHash, std::pair> results; + // 尺寸测量 + outlineMeasure(_bind_maproot, results); + // 元素排布 + nodeRelayout(results, _bind_maproot, QPointF()); +} + +QSizeF BehaviorsPresent::outlineMeasure(std::shared_ptr ins, QHash, std::pair>& _outline_occupy) +{ + QSizeF outline_box(0, 0); + + switch (ins->nodeKind()) { + case NodeKind::MAPNODE: + case NodeKind::PARALLELNODE: + case NodeKind::SELECTORNODE: + case NodeKind::SEQUENCENODE: + // 测量子节点集合尺寸,根节点必须是行为树顶部根节点 + if (ins->nodeKind() != NodeKind::MAPNODE || !ins->bindMap()) { + for (auto nit : ins->children()) { + auto nit_size = outlineMeasure(nit, _outline_occupy); + outline_box.setWidth(std::max(outline_box.width(), nit_size.width() + _space_h)); + outline_box += QSizeF(0, nit_size.height()); + } + } + default: { + auto root_peer = _present_peers[ins]; + auto root_box = root_peer->boundingRect(); + outline_box += QSizeF(root_box.width(), 0); + outline_box.setHeight(std::max(outline_box.height(), root_box.height())); + + _outline_occupy[ins] = std::make_pair(outline_box, root_box.size()); + return outline_box; + }break; + } +} + +QPointF BehaviorsPresent::nodeRelayout(QHash, std::pair>& _outline_occupy, + std::shared_ptr ins, const QPointF& origin_offset) { + // 提取尺寸记录 + auto outline_occupy = _outline_occupy[ins]; + auto node_outline = outline_occupy.first; + auto node_occupy = outline_occupy.second; + + // 提取显示节点 + auto present_node = _present_peers[ins]; + + // 设置节点位置 + QPointF local_origin_offset(0, (node_outline.height() - node_occupy.height()) / 2); + present_node->setPos(origin_offset + local_origin_offset); + + // 计算子节点位置 + QPointF child_origin = origin_offset + QPointF(node_occupy.width() + _space_h, 0); + switch (ins->nodeKind()) + { + case NodeKind::ACTIONNODE: + case NodeKind::COMPARENODE: + break; + default: + // 布局子节点集合位置,根节点必须是顶端根节点 + if (ins->nodeKind() != NodeKind::MAPNODE || !ins->bindMap()) { + for (auto item : ins->children()) { + child_origin = nodeRelayout(_outline_occupy, item, child_origin); + } + }break; + } + + // 计算左下角位置 + return origin_offset + QPointF(0, node_outline.height()); +} + +uint qHash(const std::shared_ptr data, uint seed) noexcept +{ + return qHash((void*)data.get(), seed); +} diff --git a/SimsWorld/BehaviorEditor.h b/SimsWorld/BehaviorEditor.h index f50f22b..ad598ab 100644 --- a/SimsWorld/BehaviorEditor.h +++ b/SimsWorld/BehaviorEditor.h @@ -1,12 +1,81 @@ #pragma once #include #include "BehaviorPerform.h" +#include +#include + +class NodePresent : public QGraphicsItem { +private: + std::shared_ptr _node_bind; -class BehaviorEditor : public QMainWindow -{ public: - BehaviorEditor(std::shared_ptr map_ins, QWidget *parent = nullptr); + NodePresent(std::shared_ptr bind); + QRectF contentMeasure() const; + // 通过 QGraphicsItem 继承 + QRectF boundingRect() const override; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override; +}; + + +uint qHash(const std::shared_ptr data, uint seed) noexcept; +/// +/// 行为树编辑展示 +/// +class BehaviorsPresent : public QGraphicsView +{ +private: + QGraphicsScene _bind_scene; + + const double _space_h = 120; + QHash, NodePresent*> _present_peers; + + /// + /// 绑定行为树节点 + /// + std::shared_ptr _bind_maproot = nullptr; + +public: + BehaviorsPresent(QWidget* parent = nullptr); + + /// + /// 替换行为树 + /// + /// + void setRoot(std::shared_ptr root); + + /// + /// 显示节点分配 + /// + /// + /// + void presentAllocate(std::shared_ptr ins); + /// + /// 递归释放显示节点 + /// + /// + void presentRelease(std::shared_ptr ins); + + /// + /// 内容重新布局 + /// + void contentRelayout(); + /// + /// 尺寸测量 + /// + /// + /// + /// + QSizeF outlineMeasure(std::shared_ptr ins, QHash, std::pair>& _outline_occupy); + /// + /// 节点布局 + /// + /// 尺寸记录 + /// 指定节点 + /// 左上角 + /// 左下角 + QPointF nodeRelayout(QHash, std::pair>& _outline_occupy, + std::shared_ptr ins, const QPointF &origin_offset); }; diff --git a/SimsWorld/SimsWorld.vcxproj b/SimsWorld/SimsWorld.vcxproj index e5a08cf..6107745 100644 --- a/SimsWorld/SimsWorld.vcxproj +++ b/SimsWorld/SimsWorld.vcxproj @@ -37,7 +37,7 @@ 5.12.11_msvc2017_64 - core;gui;widgets + core;gui;widgets;qml debug diff --git a/SimsWorld/main.cpp b/SimsWorld/main.cpp index ac128ab..bded88a 100644 --- a/SimsWorld/main.cpp +++ b/SimsWorld/main.cpp @@ -1,11 +1,48 @@ #include "sims_world.h" #include "TempletAssemble.h" #include +#include "BehaviorEditor.h" +#include int main(int argc, char *argv[]) { QApplication a(argc, argv); - SimsWorld w; + BehaviorsPresent w; w.show(); + + auto loader = std::make_shared(); + auto kernal = std::make_shared(loader); + + auto root = std::make_shared(kernal); + root->setID(0); + + auto seqs = std::make_shared(); + seqs->setID(10); + root->insert(seqs); + + auto seqsx = std::make_shared(); + seqsx->setID(100); + seqs->insert(seqsx); + + auto selex = std::make_shared(); + selex->setID(101); + seqs->insert(selex); + + auto parallel = std::make_shared(); + parallel->setID(1000); + selex->insert(parallel); + parallel = std::make_shared(); + parallel->setID(1001); + selex->insert(parallel); + + auto item = std::make_shared(); + item->setID(10000); + parallel->insert(item); + item = std::make_shared(); + item->setID(10001); + parallel->insert(item); + + w.setRoot(root); + return a.exec(); } diff --git a/TestProject/main.cpp b/TestProject/main.cpp index 56e3a22..dedc44b 100644 --- a/TestProject/main.cpp +++ b/TestProject/main.cpp @@ -11,38 +11,5 @@ int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); - auto cmd = std::make_shared(); - cmd->_start_time = 0; - cmd->_speed_motion = 20; - cmd->_center_point = QVector3D(200000, 0, 0); - cmd->_rotate_deg = 90; - - auto enti = std::make_shared(); - auto motion = std::make_shared(); - enti->append(motion); - auto box3d = std::make_shared(); - enti->append(box3d); - - auto immediate = std::make_shared(enti); - QList> out; - motion->execute(immediate, cmd, out); - - for (auto rst : out) - qDebug() << rst->_success_mark << rst->_reason_text; - - - auto total = cmd->timeExpend(); - for (auto timepoint = 0; timepoint < total; timepoint += 1) { - //qDebug() << cmd->posAtTimeSpan(timepoint); - - auto sync = std::make_shared(); - sync->_time_current = timepoint; - motion->execute(immediate, sync, out); - - qDebug() <_self_lla._lon_deg).arg(box3d->_self_lla._lat_deg).arg(box3d->_self_lla._alt_m); - //qDebug() << box3d->_self_posture._azimuth_deg << box3d->_self_posture._pitch_deg << box3d->_self_posture._roll_deg; - //qDebug() << timepoint << "========================"; - } - return app.exec(); }