├── QtNodeEditor ├── .gitignore ├── include │ └── nodes │ │ ├── Node │ │ ├── FlowView │ │ ├── NodeData │ │ ├── Connection │ │ ├── FlowScene │ │ ├── NodeState │ │ ├── NodeStyle │ │ ├── FlowViewStyle │ │ ├── NodeDataModel │ │ ├── TypeConverter │ │ ├── ConnectionStyle │ │ ├── NodeGeometry │ │ ├── DataModelRegistry │ │ ├── NodePainterDelegate │ │ └── internal │ │ ├── QUuidStdHash.hpp │ │ ├── Serializable.hpp │ │ ├── QStringStdHash.hpp │ │ ├── Style.hpp │ │ ├── TypeConverter.hpp │ │ ├── NodePainterDelegate.hpp │ │ ├── NodeData.hpp │ │ ├── FlowViewStyle.hpp │ │ ├── memory.hpp │ │ ├── NodeStyle.hpp │ │ ├── PortType.hpp │ │ ├── ConnectionGeometry.hpp │ │ ├── ConnectionState.hpp │ │ ├── ConnectionStyle.hpp │ │ ├── FlowView.hpp │ │ ├── Export.hpp │ │ ├── ConnectionGraphicsObject.hpp │ │ ├── Compiler.hpp │ │ ├── NodeState.hpp │ │ ├── NodeGraphicsObject.hpp │ │ ├── NodeDataModel.hpp │ │ └── Node.hpp ├── pictures │ ├── flow.png │ ├── vid1.png │ ├── chigraph.png │ ├── calculator.png │ └── style_example.png ├── resources │ ├── convert.png │ ├── resources.qrc │ └── DefaultStyle.json ├── .codeclimate.yml ├── src │ ├── Properties.cpp │ ├── ConnectionBlurEffect.hpp │ ├── ConnectionPainter.hpp │ ├── ConnectionBlurEffect.cpp │ ├── NodeDataModel.cpp │ ├── Properties.hpp │ ├── ConnectionState.cpp │ ├── StyleCollection.hpp │ ├── StyleCollection.cpp │ ├── NodePainter.hpp │ ├── DataModelRegistry.cpp │ ├── NodeConnectionInteraction.hpp │ ├── FlowViewStyle.cpp │ ├── NodeState.cpp │ └── ConnectionGeometry.cpp ├── cmake │ └── NodeEditorConfig.cmake.in ├── .appveyor.yml ├── LICENSE ├── .travis.yml ├── CMakeLists.txt └── README.md ├── groot_icon.png ├── video_MOOD2Be.png ├── groot-screenshot.png ├── .gitignore ├── bt_editor ├── resources │ ├── BT.png │ ├── play.png │ ├── BT-edit.png │ ├── BT-log.png │ ├── close_x.png │ ├── BT-monitor.png │ ├── green_star.png │ ├── red-circle.png │ ├── BT-horizontal.png │ ├── BT-vertical.png │ ├── green-circle.png │ ├── palette.txt │ ├── style.qrc │ ├── stylesheet.qss │ ├── svg │ │ ├── robot_talk.svg │ │ ├── upload.svg │ │ ├── download.svg │ │ ├── save_dark.svg │ │ ├── save_white.svg │ │ ├── folder.svg │ │ ├── star.svg │ │ ├── zoom_home.svg │ │ ├── magic-wand.svg │ │ ├── low_battery.svg │ │ ├── list_add.svg │ │ ├── arrow_right.svg │ │ ├── lock_open.svg │ │ ├── letter_C.svg │ │ ├── target_radar.svg │ │ ├── lock.svg │ │ ├── maze_path.svg │ │ ├── letter_i.svg │ │ ├── letter_o.svg │ │ ├── letter_A.svg │ │ ├── manipulator.svg │ │ ├── asterix.svg │ │ ├── goto_map.svg │ │ ├── settings.svg │ │ ├── not_equal.svg │ │ ├── question_mark.svg │ │ └── robot.svg │ ├── NodesStyle.json │ └── icons.qrc ├── models │ ├── RootNodeModel.cpp │ ├── RootNodeModel.hpp │ ├── SubtreeNodeModel.hpp │ ├── SubtreeNodeModel.cpp │ └── BehaviorTreeNodeModel.hpp ├── startup_dialog.h ├── XML_utilities.hpp ├── editor_flowscene.h ├── custom_node_dialog.h ├── package.xml.disabled ├── graveyard │ └── model_repository_dialog.h ├── utils.h ├── sidepanel_editor.h ├── sidepanel_monitor.h ├── action_form.ui ├── sidepanel_replay.h ├── graphic_container.h └── sidepanel_monitor.ui ├── test_data ├── crossdoor_trace.fbl ├── issue_24.xml ├── simple_without_model.xml ├── issue_3.xml ├── test_subtrees_issue_8.xml ├── test_files.qrc ├── Simple.xml ├── crossdoor_palette.xml ├── subtree_test_fail.xml ├── custom_ports.xml ├── subtree_with_remapping.xml ├── SystemSkillTest.skills.json ├── show_all.xml ├── crossdoor_with_subtree.xml └── test_xml_key_reordering_issue.xml ├── .github └── FUNDING.yml ├── .gitmodules ├── Groot.desktop ├── installer ├── config.xml └── org.eurecat.Groot │ └── meta │ ├── package.xml │ ├── license.txt │ └── installscript.qs ├── qt_installer_howto.md ├── snap └── snapcraft.yaml ├── .travis.yml ├── test ├── CMakeLists.txt ├── .gitignore ├── replay_test.cpp ├── groot_test_base.h └── groot_test_base.cpp ├── CHANGELOG.rst ├── .appveyor.yml ├── appimage_howto.md ├── cmake └── FindZMQ.cmake └── package.xml /QtNodeEditor/.gitignore: -------------------------------------------------------------------------------- 1 | *.py 2 | *.pyc 3 | CMakeLists.txt.user 4 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/Node: -------------------------------------------------------------------------------- 1 | #include "internal/Node.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/FlowView: -------------------------------------------------------------------------------- 1 | #include "internal/FlowView.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/NodeData: -------------------------------------------------------------------------------- 1 | #include "internal/NodeData.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/Connection: -------------------------------------------------------------------------------- 1 | #include "internal/Connection.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/FlowScene: -------------------------------------------------------------------------------- 1 | #include "internal/FlowScene.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/NodeState: -------------------------------------------------------------------------------- 1 | #include "internal/NodeState.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/NodeStyle: -------------------------------------------------------------------------------- 1 | #include "internal/NodeStyle.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/FlowViewStyle: -------------------------------------------------------------------------------- 1 | #include "internal/FlowViewStyle.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/NodeDataModel: -------------------------------------------------------------------------------- 1 | #include "internal/NodeDataModel.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/TypeConverter: -------------------------------------------------------------------------------- 1 | #include "internal/TypeConverter.hpp" 2 | -------------------------------------------------------------------------------- /groot_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/groot_icon.png -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/ConnectionStyle: -------------------------------------------------------------------------------- 1 | #include "internal/ConnectionStyle.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/NodeGeometry: -------------------------------------------------------------------------------- 1 | #include "internal/NodeGeometry.hpp" 2 | 3 | -------------------------------------------------------------------------------- /video_MOOD2Be.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/video_MOOD2Be.png -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/DataModelRegistry: -------------------------------------------------------------------------------- 1 | #include "internal/DataModelRegistry.hpp" 2 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/NodePainterDelegate: -------------------------------------------------------------------------------- 1 | #include "internal/NodePainterDelegate.hpp" 2 | -------------------------------------------------------------------------------- /groot-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/groot-screenshot.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /CMakeLists.txt.user 2 | /build* 3 | /test_data/*_test.xml 4 | /test/CMakeLists.txt.user 5 | -------------------------------------------------------------------------------- /bt_editor/resources/BT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/BT.png -------------------------------------------------------------------------------- /bt_editor/resources/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/play.png -------------------------------------------------------------------------------- /test_data/crossdoor_trace.fbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/test_data/crossdoor_trace.fbl -------------------------------------------------------------------------------- /QtNodeEditor/pictures/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/QtNodeEditor/pictures/flow.png -------------------------------------------------------------------------------- /QtNodeEditor/pictures/vid1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/QtNodeEditor/pictures/vid1.png -------------------------------------------------------------------------------- /bt_editor/resources/BT-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/BT-edit.png -------------------------------------------------------------------------------- /bt_editor/resources/BT-log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/BT-log.png -------------------------------------------------------------------------------- /bt_editor/resources/close_x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/close_x.png -------------------------------------------------------------------------------- /QtNodeEditor/pictures/chigraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/QtNodeEditor/pictures/chigraph.png -------------------------------------------------------------------------------- /QtNodeEditor/resources/convert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/QtNodeEditor/resources/convert.png -------------------------------------------------------------------------------- /bt_editor/resources/BT-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/BT-monitor.png -------------------------------------------------------------------------------- /bt_editor/resources/green_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/green_star.png -------------------------------------------------------------------------------- /bt_editor/resources/red-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/red-circle.png -------------------------------------------------------------------------------- /QtNodeEditor/.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | fixme: 3 | enabled: true 4 | ratings: 5 | paths: [] 6 | exclude_paths: [] 7 | -------------------------------------------------------------------------------- /QtNodeEditor/pictures/calculator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/QtNodeEditor/pictures/calculator.png -------------------------------------------------------------------------------- /bt_editor/resources/BT-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/BT-horizontal.png -------------------------------------------------------------------------------- /bt_editor/resources/BT-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/BT-vertical.png -------------------------------------------------------------------------------- /bt_editor/resources/green-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/bt_editor/resources/green-circle.png -------------------------------------------------------------------------------- /QtNodeEditor/pictures/style_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BehaviorTree/Groot/HEAD/QtNodeEditor/pictures/style_example.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: facontidavide 4 | custom: https://www.paypal.me/facontidavide 5 | -------------------------------------------------------------------------------- /bt_editor/resources/palette.txt: -------------------------------------------------------------------------------- 1 | dark_background: #1c2b36 2 | dark_blueish: #005562 3 | green: #b9f2a1 4 | mint: #10c4b5 5 | 6 | 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "depend/BehaviorTree.CPP"] 2 | path = depend/BehaviorTree.CPP 3 | url = https://github.com/BehaviorTree/BehaviorTree.CPP/ 4 | branch = master 5 | -------------------------------------------------------------------------------- /bt_editor/resources/style.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | NodesStyle.json 4 | stylesheet.qss 5 | 6 | 7 | -------------------------------------------------------------------------------- /QtNodeEditor/resources/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | DefaultStyle.json 4 | convert.png 5 | 6 | 7 | -------------------------------------------------------------------------------- /Groot.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=Groot 4 | Exec=Groot 5 | Icon=groot_icon 6 | Comment=Graphical Editor for BehaviorTrees 7 | Terminal=false 8 | Categories=Development; 9 | Name[en_US]=Groot 10 | -------------------------------------------------------------------------------- /QtNodeEditor/src/Properties.cpp: -------------------------------------------------------------------------------- 1 | #include "Properties.hpp" 2 | 3 | using QtNodes::Properties; 4 | 5 | void 6 | Properties:: 7 | put(QString const &name, QVariant const &v) 8 | { 9 | _values.insert(name, v); 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /test_data/issue_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test_data/simple_without_model.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test_data/issue_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /installer/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Groot 4 | 1.0.0 5 | Groot installer 6 | Davide Faconti 7 | Applications 8 | @ApplicationsDir@/PlotJuggler 9 | 10 | 11 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/QUuidStdHash.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace std 9 | { 10 | template<> 11 | struct hash 12 | { 13 | inline 14 | std::size_t 15 | operator()(QUuid const& uid) const 16 | { 17 | return qHash(uid); 18 | } 19 | }; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/Serializable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace QtNodes 6 | { 7 | 8 | class Serializable 9 | { 10 | public: 11 | 12 | virtual 13 | ~Serializable() = default; 14 | 15 | virtual 16 | QJsonObject 17 | save() const = 0; 18 | 19 | virtual void 20 | restore(QJsonObject const & /*p*/) {} 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/QStringStdHash.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 9 | namespace std 10 | { 11 | template<> 12 | struct hash 13 | { 14 | inline std::size_t 15 | operator()(QString const &s) const 16 | { 17 | return qHash(s); 18 | } 19 | }; 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/Style.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class Style 6 | { 7 | public: 8 | 9 | virtual 10 | ~Style() = default; 11 | 12 | private: 13 | 14 | virtual void 15 | loadJsonText(QString jsonText) = 0; 16 | 17 | virtual void 18 | loadJsonFile(QString fileName) = 0; 19 | 20 | virtual void 21 | loadJsonFromByteArray(QByteArray const &byteArray) = 0; 22 | }; 23 | -------------------------------------------------------------------------------- /QtNodeEditor/src/ConnectionBlurEffect.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace QtNodes 6 | { 7 | 8 | class ConnectionGraphicsObject; 9 | 10 | class ConnectionBlurEffect : public QGraphicsBlurEffect 11 | { 12 | 13 | public: 14 | 15 | ConnectionBlurEffect(ConnectionGraphicsObject* item); 16 | 17 | void 18 | draw(QPainter* painter) override; 19 | 20 | private: 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /installer/org.eurecat.Groot/meta/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Groot 4 | The fancy BehaviorTree editor 5 | 1.0.0 6 | 2019-03-4 7 | 8 | 9 | 10 | script 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /QtNodeEditor/src/ConnectionPainter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace QtNodes 6 | { 7 | 8 | class ConnectionGeometry; 9 | class ConnectionState; 10 | class Connection; 11 | 12 | class ConnectionPainter 13 | { 14 | public: 15 | 16 | static 17 | void 18 | paint(QPainter* painter, 19 | Connection const& connection); 20 | 21 | static 22 | QPainterPath 23 | getPainterStroke(ConnectionGeometry const& geom); 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/TypeConverter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "NodeData.hpp" 4 | #include "memory.hpp" 5 | 6 | #include 7 | 8 | namespace QtNodes 9 | { 10 | 11 | using SharedNodeData = std::shared_ptr; 12 | 13 | // a function taking in NodeData and returning NodeData 14 | using TypeConverter = 15 | std::function; 16 | 17 | // data-type-in, data-type-out 18 | using TypeConverterId = 19 | std::pair; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /bt_editor/models/RootNodeModel.cpp: -------------------------------------------------------------------------------- 1 | #include "RootNodeModel.hpp" 2 | #include 3 | #include 4 | 5 | RootNodeModel::RootNodeModel(): 6 | BehaviorTreeDataModel ( NodeModel() ) 7 | { 8 | _line_edit_name->setHidden(true); 9 | } 10 | 11 | unsigned int RootNodeModel::nPorts(QtNodes::PortType portType) const 12 | { 13 | return (portType==PortType::In) ? 0:1; 14 | } 15 | 16 | 17 | NodeDataModel::ConnectionPolicy RootNodeModel::portOutConnectionPolicy(QtNodes::PortIndex) const 18 | { 19 | return ConnectionPolicy::One; 20 | } 21 | -------------------------------------------------------------------------------- /test_data/test_subtrees_issue_8.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/NodePainterDelegate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "NodeGeometry.hpp" 6 | #include "NodeDataModel.hpp" 7 | #include "Export.hpp" 8 | 9 | namespace QtNodes { 10 | 11 | /// Class to allow for custom painting 12 | class NODE_EDITOR_PUBLIC NodePainterDelegate 13 | { 14 | 15 | public: 16 | 17 | virtual 18 | ~NodePainterDelegate() = default; 19 | 20 | virtual void 21 | paint(QPainter* painter, 22 | NodeGeometry const& geom, 23 | NodeDataModel const * model) = 0; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /qt_installer_howto.md: -------------------------------------------------------------------------------- 1 | # Download QT Installer Framework 2 | 3 | https://download.qt.io/official_releases/qt-installer-framework/ 4 | 5 | # Create the installer 6 | 7 | mkdir build 8 | cd build 9 | cmake .. 10 | make -j$(nproc) 11 | cd .. 12 | 13 | cp build/bin* installer/io/plotjuggler.app/data/ 14 | 15 | ~/Qt/QtIFW-3.0.6/bin/binarycreator --offline-only -c installer/config.xml -p installer PlotJugglerInstaller 16 | 17 | WIN: 18 | 19 | c:\Qt\Tools\QtInstallerFramework\3.0\bin\binarycreator.exe --offline-only -c installer/config.xml -p installer PlotJugglerInstaller.exe -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: behavior-tree-editor 2 | version: "1.0" 3 | summary: Qt Application Example 4 | description: A simple behavior-tree editor 5 | confinement: strict 6 | 7 | apps: 8 | behavior-tree-editor: 9 | command: qt5-launch application 10 | plugs: 11 | - home 12 | 13 | parts: 14 | application: 15 | plugin: cmake 16 | qt-version: qt5 17 | source: ../ 18 | build-packages: 19 | - g++ 20 | - qttools5-dev-tools 21 | stage-packages: 22 | # Here for the plugins-- they're not linked in automatically. 23 | - libqt5gui5 24 | 25 | -------------------------------------------------------------------------------- /QtNodeEditor/cmake/NodeEditorConfig.cmake.in: -------------------------------------------------------------------------------- 1 | get_filename_component(NodeEditor_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 2 | 3 | include(CMakeFindDependencyMacro) 4 | 5 | # NOTE Had to use find_package because find_dependency does not support COMPONENTS or MODULE until 3.8.0 6 | 7 | find_package(Qt5 REQUIRED COMPONENTS 8 | Core 9 | Widgets 10 | Gui 11 | OpenGL) 12 | 13 | if(NOT TARGET NodeEditor::nodes) 14 | include("${NodeEditor_CMAKE_DIR}/NodeEditorTargets.cmake") 15 | endif() 16 | 17 | set(NodeEditor_LIBRARIES NodeEditor::nodes) 18 | -------------------------------------------------------------------------------- /test_data/test_files.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | crossdoor_with_subtree.xml 4 | test_xml_key_reordering_issue.xml 5 | crossdoor_palette.xml 6 | show_all.xml 7 | crossdoor_trace.fbl 8 | test_subtrees_issue_8.xml 9 | SystemSkillTest.skills.json 10 | simple_without_model.xml 11 | subtree_test_fail.xml 12 | issue_3.xml 13 | issue_24.xml 14 | 15 | 16 | -------------------------------------------------------------------------------- /QtNodeEditor/src/ConnectionBlurEffect.cpp: -------------------------------------------------------------------------------- 1 | #include "ConnectionBlurEffect.hpp" 2 | 3 | #include "ConnectionGraphicsObject.hpp" 4 | #include "ConnectionPainter.hpp" 5 | 6 | using QtNodes::ConnectionBlurEffect; 7 | using QtNodes::ConnectionGraphicsObject; 8 | 9 | ConnectionBlurEffect:: 10 | ConnectionBlurEffect(ConnectionGraphicsObject*) 11 | { 12 | // 13 | } 14 | 15 | 16 | void 17 | ConnectionBlurEffect:: 18 | draw(QPainter* painter) 19 | { 20 | QGraphicsBlurEffect::draw(painter); 21 | 22 | //ConnectionPainter::paint(painter, 23 | //_object->connectionGeometry(), 24 | //_object->connectionState()); 25 | 26 | //_item->paint(painter, nullptr, nullptr); 27 | } 28 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/NodeData.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Export.hpp" 6 | 7 | namespace QtNodes 8 | { 9 | 10 | struct NodeDataType 11 | { 12 | QString id; 13 | QString name; 14 | }; 15 | 16 | /// Class represents data transferred between nodes. 17 | /// @param type is used for comparing the types 18 | /// The actual data is stored in subtypes 19 | class NODE_EDITOR_PUBLIC NodeData 20 | { 21 | public: 22 | 23 | virtual ~NodeData() = default; 24 | 25 | virtual bool sameType(NodeData const &nodeData) const 26 | { 27 | return (this->type().id == nodeData.type().id); 28 | } 29 | 30 | /// Type for inner use 31 | virtual NodeDataType type() const = 0; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /test_data/Simple.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/FlowViewStyle.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Export.hpp" 6 | #include "Style.hpp" 7 | 8 | namespace QtNodes 9 | { 10 | 11 | class NODE_EDITOR_PUBLIC FlowViewStyle : public Style 12 | { 13 | public: 14 | 15 | FlowViewStyle(); 16 | 17 | FlowViewStyle(QString jsonText); 18 | 19 | public: 20 | 21 | static void setStyle(QString jsonText); 22 | 23 | private: 24 | 25 | void loadJsonText(QString jsonText) override; 26 | 27 | void loadJsonFile(QString fileName) override; 28 | 29 | void loadJsonFromByteArray(QByteArray const &byteArray) override; 30 | 31 | public: 32 | 33 | QColor BackgroundColor; 34 | QColor FineGridColor; 35 | QColor CoarseGridColor; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /QtNodeEditor/src/NodeDataModel.cpp: -------------------------------------------------------------------------------- 1 | #include "NodeDataModel.hpp" 2 | 3 | #include "StyleCollection.hpp" 4 | 5 | using QtNodes::NodeDataModel; 6 | using QtNodes::NodeStyle; 7 | 8 | NodeDataModel:: 9 | NodeDataModel() 10 | : _nodeStyle(StyleCollection::nodeStyle()) 11 | { 12 | // Derived classes can initialize specific style here 13 | } 14 | 15 | QJsonObject 16 | NodeDataModel:: 17 | save() const 18 | { 19 | QJsonObject modelJson; 20 | 21 | modelJson["name"] = name(); 22 | 23 | return modelJson; 24 | } 25 | 26 | 27 | NodeStyle const& 28 | NodeDataModel:: 29 | nodeStyle() const 30 | { 31 | return _nodeStyle; 32 | } 33 | 34 | 35 | void 36 | NodeDataModel:: 37 | setNodeStyle(NodeStyle const& style) 38 | { 39 | _nodeStyle = style; 40 | } 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: xenial 3 | 4 | language: 5 | - minimal 6 | - cpp 7 | 8 | os: 9 | - linux 10 | 11 | compiler: 12 | - gcc 13 | - clang 14 | 15 | before_install: 16 | - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa 17 | - sudo apt-get update -qq 18 | - sudo apt-get install qtbase5-dev qtbase5-dev libqt5svg5-dev libqt5opengl5-dev 19 | - sudo apt-get install qt5-default qttools5-dev-tools libdw-dev 20 | 21 | before_script: 22 | - git submodule update --init --recursive 23 | - mkdir build 24 | - cd build 25 | - cmake .. 26 | 27 | script: 28 | - make -j4 29 | 30 | notifications: 31 | email: 32 | recipients: 33 | - davide.faconti@gmail.com 34 | on_success: change 35 | on_failure: always 36 | -------------------------------------------------------------------------------- /test_data/crossdoor_palette.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | /> 16 | 17 | 18 | x,y,theta 19 | 20 | /> 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /QtNodeEditor/src/Properties.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "Export.hpp" 8 | 9 | namespace QtNodes 10 | { 11 | 12 | class NODE_EDITOR_PUBLIC Properties 13 | { 14 | public: 15 | 16 | void 17 | put(QString const &name, QVariant const &v); 18 | 19 | template 20 | bool 21 | get(QString name, T* v) const 22 | { 23 | QVariant const &var = _values[name]; 24 | 25 | if (var.canConvert()) 26 | { 27 | *v = _values[name].value(); 28 | 29 | return true; 30 | } 31 | 32 | return false; 33 | } 34 | 35 | QVariantMap const & 36 | values() const 37 | { return _values; } 38 | 39 | QVariantMap & 40 | values() 41 | { return _values; } 42 | 43 | private: 44 | 45 | QVariantMap _values; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/memory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace QtNodes 7 | { 8 | namespace detail { 9 | #if (!defined(_MSC_VER) && (__cplusplus < 201300)) || \ 10 | ( defined(_MSC_VER) && (_MSC_VER < 1800)) 11 | //_MSC_VER == 1800 is Visual Studio 2013, which is already somewhat C++14 compilant, 12 | // and it has make_unique in it's standard library implementation 13 | template 14 | std::unique_ptr make_unique(Args&&... args) 15 | { 16 | return std::unique_ptr(new T(std::forward(args)...)); 17 | } 18 | #else 19 | template 20 | std::unique_ptr make_unique(Args&&... args) 21 | { 22 | return std::make_unique(std::forward(args)...); 23 | } 24 | #endif 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /bt_editor/resources/stylesheet.qss: -------------------------------------------------------------------------------- 1 | QMenu { 2 | background-color: #101020; 3 | color:white; 4 | } 5 | 6 | QMenu::item { 7 | background: transparent; 8 | color:white; 9 | } 10 | 11 | QMenu::item:selected { 12 | background: #404050; 13 | color:white; 14 | } 15 | 16 | QMenu::item:disabled { 17 | background: transparent; 18 | color:grey; 19 | } 20 | 21 | QComboBox { 22 | color: black; 23 | background-color: white; 24 | selection-background-color: #b5b5b5; 25 | border-radius: 2px; 26 | border: 1px solid grey; 27 | padding-top: 2px; /* This fix #103, #111*/ 28 | padding-bottom: 2px; /* This fix #103, #111*/ 29 | padding-left: 4px; 30 | padding-right: 4px; 31 | } 32 | 33 | QComboBox:disabled { 34 | color: blue; 35 | background-color: grey; 36 | selection-background-color: grey; 37 | } 38 | -------------------------------------------------------------------------------- /test_data/subtree_test_fail.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /bt_editor/startup_dialog.h: -------------------------------------------------------------------------------- 1 | #ifndef STARTUP_DIALOG_H 2 | #define STARTUP_DIALOG_H 3 | 4 | #include 5 | #include 6 | #include "bt_editor_base.h" 7 | 8 | namespace Ui { 9 | class StartupDialog; 10 | } 11 | 12 | class StartupDialog : public QDialog 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit StartupDialog(QWidget *parent = nullptr); 18 | ~StartupDialog(); 19 | 20 | GraphicMode getGraphicMode() const { return _mode; } 21 | 22 | private slots: 23 | void on_toolButtonEditor_clicked(); 24 | 25 | void on_toolButtonMonitor_clicked(); 26 | 27 | void on_toolButtonReplay_clicked(); 28 | 29 | void updateCurrentMode(); 30 | 31 | void on_toolButtonStart_clicked(); 32 | 33 | void on_pushButtonClose_clicked(); 34 | 35 | private: 36 | Ui::StartupDialog *ui; 37 | 38 | GraphicMode _mode; 39 | 40 | }; 41 | 42 | #endif // STARTUP_DIALOG_H 43 | -------------------------------------------------------------------------------- /QtNodeEditor/src/ConnectionState.cpp: -------------------------------------------------------------------------------- 1 | #include "ConnectionState.hpp" 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "FlowScene.hpp" 8 | #include "Node.hpp" 9 | 10 | using QtNodes::ConnectionState; 11 | using QtNodes::Node; 12 | 13 | ConnectionState:: 14 | ~ConnectionState() 15 | { 16 | resetLastHoveredNode(); 17 | } 18 | 19 | 20 | void 21 | ConnectionState:: 22 | interactWithNode(Node* node) 23 | { 24 | if (node) 25 | { 26 | _lastHoveredNode = node; 27 | } 28 | else 29 | { 30 | resetLastHoveredNode(); 31 | } 32 | } 33 | 34 | 35 | void 36 | ConnectionState:: 37 | setLastHoveredNode(Node* node) 38 | { 39 | _lastHoveredNode = node; 40 | } 41 | 42 | 43 | void 44 | ConnectionState:: 45 | resetLastHoveredNode() 46 | { 47 | if (_lastHoveredNode) 48 | _lastHoveredNode->resetReactionToConnection(); 49 | 50 | _lastHoveredNode = nullptr; 51 | } 52 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.1) 2 | 3 | PROJECT(GrootTest LANGUAGES CXX) 4 | 5 | find_package(Qt5Test REQUIRED) 6 | find_package(Qt5Gui REQUIRED) 7 | 8 | SET(CMAKE_AUTOMOC ON) 9 | SET(CMAKE_AUTORCC ON) 10 | SET(CMAKE_INCLUDE_CURRENT_DIR ON) 11 | SET(CMAKE_CXX_STANDARD 11) 12 | SET(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | ENABLE_TESTING() 14 | 15 | function(CompileTest name) 16 | add_executable(${name} ${name}.cpp groot_test_base.cpp ${RESOURCE_FILES} ) 17 | target_link_libraries(${name} PRIVATE Qt5::Gui Qt5::Test behavior_tree_editor) 18 | add_test(NAME ${name} COMMAND ${name}) 19 | endfunction() 20 | 21 | set(RESOURCE_FILES 22 | ../QtNodeEditor/resources/resources.qrc 23 | ../bt_editor/resources/icons.qrc 24 | ../bt_editor/resources/style.qrc 25 | ../test_data/test_files.qrc 26 | ) 27 | 28 | CompileTest( editor_test ) 29 | CompileTest( replay_test ) 30 | -------------------------------------------------------------------------------- /test_data/custom_ports.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | interesting 14 | 15 | 16 | Cool 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test_data/subtree_with_remapping.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /bt_editor/XML_utilities.hpp: -------------------------------------------------------------------------------- 1 | #ifndef XMLPARSERS_HPP 2 | #define XMLPARSERS_HPP 3 | 4 | #include 5 | #include "bt_editor_base.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | NodeModels ReadTreeNodesModel(const QDomElement& root); 14 | 15 | void RecursivelyCreateXml(const QtNodes::FlowScene &scene, 16 | QDomDocument& doc, 17 | QDomElement& parent_element, 18 | const QtNodes::Node* node); 19 | 20 | bool VerifyXML(QDomDocument& doc, 21 | const std::vector ®istered_ID, 22 | std::vector &error_messages); 23 | 24 | NodeModel buildTreeNodeModelFromXML(const QDomElement &node); 25 | 26 | QDomElement writePortModel(const QString &port_name, const PortModel &port, QDomDocument &doc); 27 | 28 | 29 | #endif // XMLPARSERS_HPP 30 | -------------------------------------------------------------------------------- /bt_editor/models/RootNodeModel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include "BehaviorTreeNodeModel.hpp" 10 | 11 | /* 12 | class RootNodeModel : public BehaviorTreeDataModel 13 | { 14 | 15 | public: 16 | RootNodeModel(); 17 | 18 | virtual ~RootNodeModel() = default; 19 | 20 | public: 21 | 22 | unsigned int nPorts(PortType portType) const override; 23 | 24 | virtual ConnectionPolicy portOutConnectionPolicy(PortIndex) const override; 25 | 26 | virtual const char* className() const final 27 | { 28 | return RootNodeModel::Name(); 29 | } 30 | static const char* Name() { return "Root"; } 31 | 32 | static const TreeNodeModel& NodeModel() 33 | { 34 | static TreeNodeModel model = { Name(), NodeType::ROOT, {} }; 35 | return model; 36 | } 37 | 38 | virtual NodeType nodeType() const final { return NodeType::ROOT; } 39 | }; 40 | */ 41 | -------------------------------------------------------------------------------- /QtNodeEditor/src/StyleCollection.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "NodeStyle.hpp" 4 | #include "ConnectionStyle.hpp" 5 | #include "FlowViewStyle.hpp" 6 | 7 | namespace QtNodes 8 | { 9 | 10 | class StyleCollection 11 | { 12 | public: 13 | 14 | static 15 | NodeStyle const& 16 | nodeStyle(); 17 | 18 | static 19 | ConnectionStyle const& 20 | connectionStyle(); 21 | 22 | static 23 | FlowViewStyle const& 24 | flowViewStyle(); 25 | 26 | public: 27 | 28 | static 29 | void 30 | setNodeStyle(NodeStyle); 31 | 32 | static 33 | void 34 | setConnectionStyle(ConnectionStyle); 35 | 36 | static 37 | void 38 | setFlowViewStyle(FlowViewStyle); 39 | 40 | private: 41 | 42 | StyleCollection() = default; 43 | 44 | StyleCollection(StyleCollection const&) = delete; 45 | 46 | StyleCollection& 47 | operator=(StyleCollection const&) = delete; 48 | 49 | static 50 | StyleCollection& 51 | instance(); 52 | 53 | private: 54 | 55 | NodeStyle _nodeStyle; 56 | 57 | ConnectionStyle _connectionStyle; 58 | 59 | FlowViewStyle _flowViewStyle; 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | 4 | *~ 5 | *.autosave 6 | *.a 7 | *.core 8 | *.moc 9 | *.o 10 | *.obj 11 | *.orig 12 | *.rej 13 | *.so 14 | *.so.* 15 | *_pch.h.cpp 16 | *_resource.rc 17 | *.qm 18 | .#* 19 | *.*# 20 | core 21 | !core/ 22 | tags 23 | .DS_Store 24 | .directory 25 | *.debug 26 | Makefile* 27 | *.prl 28 | *.app 29 | moc_*.cpp 30 | ui_*.h 31 | qrc_*.cpp 32 | Thumbs.db 33 | *.res 34 | *.rc 35 | /.qmake.cache 36 | /.qmake.stash 37 | 38 | # qtcreator generated files 39 | *.pro.user* 40 | 41 | # xemacs temporary files 42 | *.flc 43 | 44 | # Vim temporary files 45 | .*.swp 46 | 47 | # Visual Studio generated files 48 | *.ib_pdb_index 49 | *.idb 50 | *.ilk 51 | *.pdb 52 | *.sln 53 | *.suo 54 | *.vcproj 55 | *vcproj.*.*.user 56 | *.ncb 57 | *.sdf 58 | *.opensdf 59 | *.vcxproj 60 | *vcxproj.* 61 | 62 | # MinGW generated files 63 | *.Debug 64 | *.Release 65 | 66 | # Python byte code 67 | *.pyc 68 | 69 | # Binaries 70 | # -------- 71 | *.dll 72 | *.exe 73 | 74 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Changelog for package Groot 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4 | 5 | 1.0.0 (2019-03-04) 6 | ------------------ 7 | * Updated to V3 of BehaviorTree.CPP 8 | * Contributors: Davide Faconti, Victor Lopez 9 | 10 | 0.4.2 (2018-11-26) 11 | ------------------ 12 | * CRITICAL BUG fixed: QLineEdit where not editble in the embeddedWidget 13 | * Contributors: Davide Faconti 14 | 15 | 0.4.1 (2018-11-23) 16 | ------------------ 17 | * improved node reorder 18 | * Fix issue #8 (and more changes) 19 | - Added EditorFlowScene::createNodeAtPos to simplify code 20 | - fixed the placement of nodes in GraphicContainer::recursiveLoadStep 21 | - visualize instanceName is different than registrationName 22 | * Added Help->About dialog 23 | * different splashscreen palette 24 | * Update README.md 25 | * qDebug removed 26 | * CMake Install + AppImage Howto 27 | * minor updates 28 | * Contributors: Davide Faconti, liuxin00738 29 | 30 | 0.4.0 (2018-11-21) 31 | ------------------ 32 | * First beta version. All functional features included. 33 | * Contributors: Davide Faconti, davide.faconti 34 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/robot_talk.svg: -------------------------------------------------------------------------------- 1 | 17Created by Jugalbandifrom the Noun Project -------------------------------------------------------------------------------- /bt_editor/editor_flowscene.h: -------------------------------------------------------------------------------- 1 | #ifndef EDITOR_FLOWSCENE_H 2 | #define EDITOR_FLOWSCENE_H 3 | 4 | #include 5 | #include 6 | #include "bt_editor/bt_editor_base.h" 7 | 8 | class EditorFlowScene : public QtNodes::FlowScene 9 | { 10 | public: 11 | EditorFlowScene(std::shared_ptr registry, 12 | QObject * parent = Q_NULLPTR); 13 | 14 | bool isLocked() const { return _editor_locked; } 15 | void lock(bool lock_editor) { _editor_locked = lock_editor; } 16 | 17 | QtNodes::Node& createNodeAtPos(const QString& ID, const QString& instance_name, QPointF scene_pos); 18 | 19 | private: 20 | 21 | void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override; 22 | void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) override; 23 | void dropEvent(QGraphicsSceneDragDropEvent *event) override; 24 | void dragMoveEvent(QGraphicsSceneDragDropEvent* event) override; 25 | 26 | void keyPressEvent( QKeyEvent * event ) override; 27 | 28 | bool _editor_locked; 29 | AbstractTreeNode _clipboard_node; 30 | }; 31 | 32 | #endif // EDITOR_FLOWSCENE_H 33 | -------------------------------------------------------------------------------- /bt_editor/custom_node_dialog.h: -------------------------------------------------------------------------------- 1 | #ifndef CUSTOM_NODE_DIALOG_H 2 | #define CUSTOM_NODE_DIALOG_H 3 | 4 | #include "bt_editor_base.h" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace Ui { 10 | class CustomNodeDialog; 11 | } 12 | 13 | class CustomNodeDialog : public QDialog 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit CustomNodeDialog(const NodeModels& models, QString to_edit = QString(), QWidget *parent = nullptr); 19 | 20 | ~CustomNodeDialog() override; 21 | 22 | NodeModel getTreeNodeModel() const; 23 | 24 | private slots: 25 | void on_pushButtonAdd_pressed(); 26 | 27 | void on_pushButtonRemove_pressed(); 28 | 29 | void checkValid(); 30 | 31 | virtual void closeEvent(QCloseEvent *) override; 32 | 33 | void on_buttonBox_clicked(QAbstractButton *button); 34 | 35 | void on_tableWidget_itemSelectionChanged(); 36 | 37 | void on_comboBox_currentIndexChanged(const QString &node_type); 38 | 39 | private: 40 | Ui::CustomNodeDialog *ui; 41 | const NodeModels &_models; 42 | QValidator *_validator; 43 | bool _editing; 44 | }; 45 | 46 | #endif // CUSTOM_NODE_DIALOG_H 47 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/NodeStyle.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Export.hpp" 6 | #include "Style.hpp" 7 | 8 | namespace QtNodes 9 | { 10 | 11 | class NODE_EDITOR_PUBLIC NodeStyle : public Style 12 | { 13 | public: 14 | 15 | NodeStyle(); 16 | 17 | NodeStyle(QString jsonText); 18 | 19 | public: 20 | 21 | static void setNodeStyle(QString jsonText); 22 | 23 | private: 24 | 25 | void loadJsonText(QString jsonText) override; 26 | 27 | void loadJsonFile(QString fileName) override; 28 | 29 | void loadJsonFromByteArray(QByteArray const &byteArray) override; 30 | 31 | public: 32 | 33 | QColor NormalBoundaryColor; 34 | QColor SelectedBoundaryColor; 35 | QColor GradientColor0; 36 | QColor GradientColor1; 37 | QColor GradientColor2; 38 | QColor GradientColor3; 39 | QColor ShadowColor; 40 | QColor FontColor; 41 | QColor FontColorFaded; 42 | 43 | QColor ConnectionPointColor; 44 | QColor FilledConnectionPointColor; 45 | 46 | QColor WarningColor; 47 | QColor ErrorColor; 48 | 49 | float PenWidth; 50 | float HoveredPenWidth; 51 | 52 | float ConnectionPointDiameter; 53 | 54 | float Opacity; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /bt_editor/package.xml.disabled: -------------------------------------------------------------------------------- 1 | 2 | 3 | behavior_tree_editor 4 | 0.1.0 5 | BehaviorTre Editor and Monitor 6 | 7 | Davide Faconti 8 | LGPLv3 9 | 10 | https://github.com/facontidavide/ 11 | 12 | Davide Faconti 13 | 14 | catkin 15 | 16 | rosbag 17 | rosbag_storage 18 | roscpp 19 | rostime 20 | qtbase5-dev 21 | binutils 22 | 23 | rosbag 24 | rosbag_storage 25 | roscpp 26 | rostime 27 | qtbase5-dev 28 | binutils 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test_data/SystemSkillTest.skills.json: -------------------------------------------------------------------------------- 1 | 2 | [ 3 | {"skill" : 4 | { 5 | "name" : "moverobot_approach_region_purepursuit", 6 | "skillDefinitionFQN" : "CommNavigationObjects.CdlSkills.moverobot_approach_region_purepursuit", 7 | "inAttribute" : { 8 | "location" : "String" 9 | }, 10 | "outAttribute" : { 11 | }, 12 | "results" : [ 13 | { "result" : "ERROR", "resultValue" : "UNKNOWN LOCATION" }, 14 | { "result" : "ERROR", "resultValue" : "ROBOT BLOCKED" }, 15 | { "result" : "SUCCESS", "resultValue" : "OK" }, 16 | { "result" : "SUCCESS", "resultValue" : "" } 17 | ] 18 | } 19 | }, 20 | {"skill" : 21 | { 22 | "name" : "moverobot_approach_region_purepursuit_xy", 23 | "skillDefinitionFQN" : "CommNavigationObjects.CdlSkills.moverobot_approach_region_purepursuit_xy", 24 | "inAttribute" : { 25 | "x" : "Double", 26 | "y" : "Double" 27 | }, 28 | "outAttribute" : { 29 | }, 30 | "results" : [ 31 | { "result" : "ERROR", "resultValue" : "UNKNOWN LOCATION" }, 32 | { "result" : "ERROR", "resultValue" : "ROBOT BLOCKED" }, 33 | { "result" : "SUCCESS", "resultValue" : "OK" }, 34 | { "result" : "SUCCESS", "resultValue" : "" } 35 | ] 36 | } 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /installer/org.eurecat.Groot/meta/license.txt: -------------------------------------------------------------------------------- 1 | # Licence 2 | 3 | Copyright (c) 2018-2019 FUNDACIO EURECAT 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a 6 | copy of this software and associated documentation files (the "Software"), 7 | to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | and/or sell copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /QtNodeEditor/src/StyleCollection.cpp: -------------------------------------------------------------------------------- 1 | #include "StyleCollection.hpp" 2 | 3 | using QtNodes::StyleCollection; 4 | using QtNodes::NodeStyle; 5 | using QtNodes::ConnectionStyle; 6 | using QtNodes::FlowViewStyle; 7 | 8 | NodeStyle const& 9 | StyleCollection:: 10 | nodeStyle() 11 | { 12 | return instance()._nodeStyle; 13 | } 14 | 15 | 16 | ConnectionStyle const& 17 | StyleCollection:: 18 | connectionStyle() 19 | { 20 | return instance()._connectionStyle; 21 | } 22 | 23 | 24 | FlowViewStyle const& 25 | StyleCollection:: 26 | flowViewStyle() 27 | { 28 | return instance()._flowViewStyle; 29 | } 30 | 31 | 32 | void 33 | StyleCollection:: 34 | setNodeStyle(NodeStyle nodeStyle) 35 | { 36 | instance()._nodeStyle = nodeStyle; 37 | } 38 | 39 | 40 | void 41 | StyleCollection:: 42 | setConnectionStyle(ConnectionStyle connectionStyle) 43 | { 44 | instance()._connectionStyle = connectionStyle; 45 | } 46 | 47 | 48 | void 49 | StyleCollection:: 50 | setFlowViewStyle(FlowViewStyle flowViewStyle) 51 | { 52 | instance()._flowViewStyle = flowViewStyle; 53 | } 54 | 55 | 56 | 57 | StyleCollection& 58 | StyleCollection:: 59 | instance() 60 | { 61 | static StyleCollection collection; 62 | 63 | return collection; 64 | } 65 | -------------------------------------------------------------------------------- /bt_editor/graveyard/model_repository_dialog.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGS_DIALOG_H 2 | #define SETTINGS_DIALOG_H 3 | 4 | #include 5 | #include "bt_editor_base.h" 6 | 7 | namespace Ui { 8 | class SettingsDialog; 9 | } 10 | 11 | class ModelsRepositoryDialog : public QDialog 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | typedef std::map ModelsByFile; 17 | 18 | explicit ModelsRepositoryDialog(TreeNodeModel* tree_node_models, QWidget *parent = 0); 19 | 20 | ~ModelsRepositoryDialog(); 21 | 22 | static ModelsByFile LoadFromSettings(); 23 | 24 | static bool parseFile(const QString& filename, ModelsByFile& models_by_file); 25 | 26 | static bool parseXML(const QString& filename, ModelsByFile& models_by_file, QString* error_message); 27 | 28 | private slots: 29 | 30 | void on_buttonAddFile_clicked(); 31 | 32 | void on_buttonRemoveFile_clicked(); 33 | 34 | void checkSelections(); 35 | 36 | void on_buttonBox_accepted(); 37 | 38 | void on_listFiles_itemSelectionChanged(); 39 | 40 | private: 41 | Ui::SettingsDialog *ui; 42 | 43 | ModelsByFile _models_by_file; 44 | 45 | TreeNodeModel* _tree_node_models; 46 | }; 47 | 48 | 49 | 50 | #endif // SETTINGS_DIALOG_H 51 | -------------------------------------------------------------------------------- /test/replay_test.cpp: -------------------------------------------------------------------------------- 1 | #include "groot_test_base.h" 2 | #include "bt_editor/sidepanel_replay.h" 3 | #include 4 | 5 | class ReplyTest : public GrootTestBase 6 | { 7 | Q_OBJECT 8 | 9 | public: 10 | ReplyTest() {} 11 | ~ReplyTest() {} 12 | 13 | private slots: 14 | void initTestCase(); 15 | void cleanupTestCase(); 16 | void basicLoad(); 17 | }; 18 | 19 | 20 | void ReplyTest::initTestCase() 21 | { 22 | main_win = new MainWindow(GraphicMode::REPLAY, nullptr); 23 | main_win->resize(1200, 800); 24 | main_win->show(); 25 | } 26 | 27 | void ReplyTest::cleanupTestCase() 28 | { 29 | QApplication::processEvents(); 30 | sleepAndRefresh( 1000 ); 31 | main_win->on_actionClear_triggered(); 32 | main_win->close(); 33 | } 34 | 35 | void ReplyTest::basicLoad() 36 | { 37 | auto sidepanel_replay = main_win->findChild("SidepanelReplay"); 38 | QVERIFY2( sidepanel_replay, "Can't get pointer to SidepanelReplay" ); 39 | 40 | QByteArray log = readFile("://crossdoor_trace.fbl"); 41 | sidepanel_replay->loadLog( log ); 42 | 43 | QCOMPARE( sidepanel_replay->transitionsCount(), size_t(27) ); 44 | } 45 | 46 | QTEST_MAIN(ReplyTest) 47 | 48 | #include "replay_test.moc" 49 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/PortType.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace QtNodes 7 | { 8 | 9 | enum class PortType 10 | { 11 | None, 12 | In, 13 | Out 14 | }; 15 | 16 | enum class PortLayout 17 | { 18 | Horizontal, 19 | Vertical 20 | }; 21 | 22 | static const int INVALID = -1; 23 | 24 | using PortIndex = int; 25 | 26 | struct Port 27 | { 28 | PortType type; 29 | 30 | PortIndex index; 31 | 32 | Port() 33 | : type(PortType::None) 34 | , index(INVALID) 35 | {} 36 | 37 | Port(PortType t, PortIndex i) 38 | : type(t) 39 | , index(i) 40 | {} 41 | 42 | bool 43 | indexIsValid() { return index != INVALID; } 44 | 45 | bool 46 | portTypeIsValid() { return type != PortType::None; } 47 | }; 48 | 49 | //using PortAddress = std::pair; 50 | 51 | inline 52 | PortType 53 | oppositePort(PortType port) 54 | { 55 | PortType result = PortType::None; 56 | 57 | switch (port) 58 | { 59 | case PortType::In: 60 | result = PortType::Out; 61 | break; 62 | 63 | case PortType::Out: 64 | result = PortType::In; 65 | break; 66 | 67 | default: 68 | break; 69 | } 70 | 71 | return result; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/upload.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /bt_editor/models/SubtreeNodeModel.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SUBTREE_NODEMODEL_HPP 2 | #define SUBTREE_NODEMODEL_HPP 3 | 4 | #include "BehaviorTreeNodeModel.hpp" 5 | #include 6 | 7 | class SubtreeNodeModel : public BehaviorTreeDataModel 8 | { 9 | Q_OBJECT 10 | public: 11 | 12 | SubtreeNodeModel(const NodeModel& model); 13 | 14 | ~SubtreeNodeModel() override = default; 15 | 16 | void setExpanded(bool expand); 17 | 18 | bool expanded() const { return _expanded; } 19 | 20 | unsigned int nPorts(PortType portType) const override 21 | { 22 | int out_port = _expanded ? 1 : 0; 23 | return portType == PortType::In ? 1:out_port; 24 | } 25 | 26 | virtual const char* className() const final { return Name(); } 27 | 28 | static const char* Name() { return "SubTree"; } 29 | 30 | QPushButton* expandButton() { return _expand_button; } 31 | 32 | virtual void setInstanceName(const QString& name) override; 33 | 34 | QJsonObject save() const override; 35 | 36 | void restore(QJsonObject const &) override; 37 | 38 | signals: 39 | void expandButtonPushed(); 40 | 41 | private: 42 | QPushButton* _expand_button; 43 | bool _expanded; 44 | 45 | }; 46 | 47 | 48 | #endif // SUBTREE_NODEMODEL_HPP 49 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /QtNodeEditor/resources/DefaultStyle.json: -------------------------------------------------------------------------------- 1 | { 2 | "FlowViewStyle": { 3 | "BackgroundColor": [45, 45, 45], 4 | "FineGridColor": [45, 45, 45], 5 | "CoarseGridColor": [45, 45, 45] 6 | }, 7 | "NodeStyle": { 8 | "NormalBoundaryColor": [255, 255, 255], 9 | "SelectedBoundaryColor": [255, 165, 0], 10 | "GradientColor0": [80, 80, 80], 11 | "GradientColor1": [80, 80, 80], 12 | "GradientColor2": [80, 80, 80], 13 | "GradientColor3": [80, 80, 80], 14 | "ShadowColor": [20, 20, 20], 15 | "FontColor" : "white", 16 | "FontColorFaded" : "gray", 17 | "ConnectionPointColor": [150, 150, 169], 18 | "FilledConnectionPointColor": "cyan", 19 | "ErrorColor": "red", 20 | "WarningColor": [128, 128, 0], 21 | 22 | "PenWidth": 1.0, 23 | "HoveredPenWidth": 1.5, 24 | 25 | "ConnectionPointDiameter": 8.0, 26 | 27 | "Opacity": 1.0 28 | }, 29 | "ConnectionStyle": { 30 | "ConstructionColor": "gray", 31 | "NormalColor": "darkcyan", 32 | "SelectedColor": [100, 100, 100], 33 | "SelectedHaloColor": "orange", 34 | "HoveredColor": "lightcyan", 35 | 36 | "LineWidth": 3.0, 37 | "ConstructionLineWidth": 2.0, 38 | "PointDiameter": 10.0, 39 | 40 | "UseDataDefinedColors": false 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | clone_depth: 5 2 | 3 | environment: 4 | matrix: 5 | - GENERATOR : "MinGW Makefiles" 6 | QTDIR: C:\Qt\5.9.7\mingw53_32 7 | PLATFORM: x86 8 | - GENERATOR : "Visual Studio 15 2017 Win64" 9 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 10 | QTDIR: C:\Qt\5.9.7\msvc2017_64 11 | PLATFORM: x64 12 | # - GENERATOR : "Visual Studio 14 2015 Win64" 13 | # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 14 | # QTDIR: C:\Qt\5.9.7\msvc2015_64 15 | # - GENERATOR : "Visual Studio 14 2015" 16 | # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 17 | # QTDIR: C:\Qt\5.9.7\msvc2015 18 | # PLATFORM: Win32 19 | 20 | 21 | configuration: 22 | - Release 23 | 24 | install: 25 | - set PATH=%QTDIR%\bin;%PATH% 26 | - set Qt5_DIR=%QTDIR%\lib\cmake\Qt5 27 | - set PATH=C:\MinGW\bin;C:\MinGW\msys\1.0;%PATH% 28 | - set PATH=C:\Qt\Tools\mingw530_32;%PATH% 29 | - set PATH=%PATH:C:\Program Files\Git\usr\bin=% # trick to remove sh.exe 30 | 31 | 32 | before_build: 33 | - git submodule update --init --recursive 34 | - mkdir build 35 | - cd build 36 | - set PATH=%QTDIR%\bin;%PATH% 37 | - cmake "-G%GENERATOR%" "-DCMAKE_PREFIX_PATH=%QTDIR%" .. 38 | 39 | build_script: 40 | - cmake --build . 41 | -------------------------------------------------------------------------------- /appimage_howto.md: -------------------------------------------------------------------------------- 1 | # First time 2 | 3 | Add the right repository form [here](https://launchpad.net/~beineri) 4 | 5 | For instance, on Ubuntu Trusty (14.04) 6 | 7 | sudo add-apt-repository ppa:beineri/opt-qt596-trusty -y 8 | 9 | whilst for Ubuntu Xenial (16.04) 10 | 11 | sudo add-apt-repository ppa:beineri/opt-qt596-xenial -y 12 | 13 | Then, run: 14 | 15 | sudo apt-get update 16 | sudo apt-get install qt59base qt59svg -y 17 | 18 | Download the latest version of [LinuxDeployQt](https://github.com/probonopd/linuxdeployqt) and make it executable with __chmod__: 19 | 20 | wget "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" -O ~/linuxdeployq.AppImage 21 | chmod +x ~/linuxdeployq.AppImage 22 | 23 | # Build the AppImage 24 | 25 | In the root folder of Groot: 26 | 27 | mkdir build; cd build 28 | source /opt/qt59/bin/qt59-env.sh 29 | cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=install .. 30 | make -j$(nproc) install 31 | 32 | export VERSION=$(git describe --abbrev=0 --tags); echo $VERSION 33 | unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH 34 | ~/linuxdeployq.AppImage ./install/share/applications/Groot.desktop -appimage 35 | 36 | 37 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/ConnectionGeometry.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PortType.hpp" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace QtNodes 11 | { 12 | 13 | class ConnectionGeometry 14 | { 15 | public: 16 | 17 | ConnectionGeometry(); 18 | 19 | public: 20 | 21 | QPointF const& 22 | getEndPoint(PortType portType) const; 23 | 24 | void 25 | setEndPoint(PortType portType, QPointF const& point); 26 | 27 | void 28 | moveEndPoint(PortType portType, QPointF const &offset); 29 | 30 | QRectF 31 | boundingRect() const; 32 | 33 | std::pair 34 | pointsC1C2() const; 35 | 36 | QPointF 37 | source() const { return _out; } 38 | QPointF 39 | sink() const { return _in; } 40 | 41 | double 42 | lineWidth() const { return _lineWidth; } 43 | 44 | bool 45 | hovered() const { return _hovered; } 46 | void 47 | setHovered(bool hovered) { _hovered = hovered; } 48 | 49 | void setPortLayout( PortLayout layout); 50 | 51 | private: 52 | // local object coordinates 53 | QPointF _in; 54 | QPointF _out; 55 | 56 | //int _animationPhase; 57 | 58 | double _lineWidth; 59 | 60 | bool _hovered; 61 | 62 | PortLayout _ports_layout; 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/ConnectionState.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "PortType.hpp" 6 | 7 | class QPointF; 8 | 9 | namespace QtNodes 10 | { 11 | 12 | class Node; 13 | 14 | /// Stores currently draggind end. 15 | /// Remembers last hovered Node. 16 | class ConnectionState 17 | { 18 | public: 19 | 20 | ConnectionState(PortType port = PortType::None) 21 | : _requiredPort(port) 22 | {} 23 | 24 | ConnectionState(const ConnectionState&) = delete; 25 | ConnectionState operator=(const ConnectionState&) = delete; 26 | 27 | ~ConnectionState(); 28 | 29 | public: 30 | 31 | void setRequiredPort(PortType end) 32 | { _requiredPort = end; } 33 | 34 | PortType requiredPort() const 35 | { return _requiredPort; } 36 | 37 | bool requiresPort() const 38 | { return _requiredPort != PortType::None; } 39 | 40 | void setNoRequiredPort() 41 | { _requiredPort = PortType::None; } 42 | 43 | public: 44 | 45 | void interactWithNode(Node* node); 46 | 47 | void setLastHoveredNode(Node* node); 48 | 49 | Node* 50 | lastHoveredNode() const 51 | { return _lastHoveredNode; } 52 | 53 | void resetLastHoveredNode(); 54 | 55 | private: 56 | 57 | PortType _requiredPort; 58 | 59 | Node* _lastHoveredNode{nullptr}; 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/ConnectionStyle.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Export.hpp" 6 | #include "Style.hpp" 7 | 8 | namespace QtNodes 9 | { 10 | 11 | class NODE_EDITOR_PUBLIC ConnectionStyle : public Style 12 | { 13 | public: 14 | 15 | ConnectionStyle(); 16 | 17 | ConnectionStyle(QString jsonText); 18 | 19 | public: 20 | 21 | static void setConnectionStyle(QString jsonText); 22 | 23 | private: 24 | 25 | void loadJsonText(QString jsonText) override; 26 | 27 | void loadJsonFile(QString fileName) override; 28 | 29 | void loadJsonFromByteArray(QByteArray const &byteArray) override; 30 | 31 | public: 32 | 33 | QColor constructionColor() const; 34 | QColor normalColor() const; 35 | QColor normalColor(QString typeId) const; 36 | QColor selectedColor() const; 37 | QColor selectedHaloColor() const; 38 | QColor hoveredColor() const; 39 | 40 | float lineWidth() const; 41 | float constructionLineWidth() const; 42 | float pointDiameter() const; 43 | 44 | bool useDataDefinedColors() const; 45 | 46 | QColor ConstructionColor; 47 | QColor NormalColor; 48 | QColor SelectedColor; 49 | QColor SelectedHaloColor; 50 | QColor HoveredColor; 51 | 52 | float LineWidth; 53 | float ConstructionLineWidth; 54 | float PointDiameter; 55 | 56 | bool UseDataDefinedColors; 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /test_data/show_all.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /test_data/crossdoor_with_subtree.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/save_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /test/groot_test_base.h: -------------------------------------------------------------------------------- 1 | #ifndef GROOT_TEST_BASE_H 2 | #define GROOT_TEST_BASE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "bt_editor/mainwindow.h" 11 | #include "bt_editor/utils.h" 12 | #include "bt_editor/models/SubtreeNodeModel.hpp" 13 | 14 | #define TEST_LOCATION() { __FILE__, __LINE__ } 15 | 16 | class GrootTestBase : public QObject 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | struct TestLocation{ 22 | const char* file; 23 | int line; 24 | }; 25 | 26 | protected: 27 | QByteArray readFile(const char* name); 28 | 29 | void sleepAndRefresh(int ms); 30 | 31 | void testMouseEvent(QGraphicsView* view, QEvent::Type type, QPoint pos, 32 | Qt::MouseButton button, 33 | Qt::KeyboardModifier modifier = Qt::NoModifier); 34 | 35 | void testDragObject(QGraphicsView* view, const QPoint& screen_pos, const QPoint& pos_offset); 36 | 37 | AbsBehaviorTree getAbstractTree(const QString& name = QString()); 38 | 39 | void testMessageBox(int deplay_ms, TestLocation location, 40 | std::function callable_action, 41 | QMessageBox::StandardButton button_to_press = QMessageBox::Default); 42 | 43 | MainWindow *main_win; 44 | }; 45 | 46 | #endif // GROOT_TEST_BASE_H 47 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/save_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /QtNodeEditor/.appveyor.yml: -------------------------------------------------------------------------------- 1 | clone_depth: 5 2 | 3 | environment: 4 | matrix: 5 | - GENERATOR : "MinGW Makefiles" 6 | QTDIR: C:\Qt\5.6\mingw49_32 7 | PLATFORM: x86 8 | - GENERATOR : "Visual Studio 14 2015 Win64" 9 | QTDIR: C:\Qt\5.7\msvc2015_64 10 | PLATFORM: x64 11 | - GENERATOR : "Visual Studio 14 2015" 12 | QTDIR: C:\Qt\5.7\msvc2015 13 | PLATFORM: Win32 14 | 15 | configuration: 16 | - Release 17 | 18 | #branches: 19 | #only: 20 | #- master 21 | 22 | before_build: 23 | - mkdir build 24 | - cd build 25 | - set PATH=%QTDIR%\bin;%PATH% 26 | - set PATH=C:\MinGW\bin;C:\MinGW\msys\1.0;%PATH% 27 | - set PATH=%PATH:C:\Program Files\Git\usr\bin=% # trick to remove sh.exe 28 | - cmake "-G%GENERATOR%" -DCMAKE_PREFIX_PATH="%QTDIR/lib/cmake/Qt5" .. 29 | 30 | 31 | build_script: 32 | - if "%PLATFORM%" == "x86" cmake --build . 33 | - if "%PLATFORM%" == "x64" msbuild NodeEditor.sln 34 | - if "%PLATFORM%" == "Win32" msbuild NodeEditor.sln 35 | 36 | 37 | 38 | after_build: 39 | - 7z a examples.zip %APPVEYOR_BUILD_FOLDER%/build/bin 40 | - cmd: cd 41 | - cmd: dir \S \P "examples.zip" 42 | 43 | artifacts: 44 | - path: build\examples.zip 45 | name: ex 46 | 47 | #deploy: 48 | #release: $(APPVEYOR_REPO_TAG_NAME) 49 | #provider: GitHub 50 | #artifact: /.*\.exe/ 51 | #auth_token: 52 | #secure: j0nBV9xVItdG3j6d0gHoyvrzi7TOhAy9/QIeyCbFeP8PTqq7DPr1oYwL5WIkPaXe 53 | #draft: false 54 | #prerelease: false 55 | #on: 56 | #appveyor_repo_tag: true 57 | -------------------------------------------------------------------------------- /QtNodeEditor/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, Dmitry Pinaev 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of copyright holder, nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /cmake/FindZMQ.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find ZMQ 2 | # Once done this will define 3 | # 4 | # ZMQ_FOUND - system has ZMQ 5 | # ZMQ_INCLUDE_DIRS - the ZMQ include directory 6 | # ZMQ_LIBRARIES - Link these to use ZMQ 7 | # ZMQ_DEFINITIONS - Compiler switches required for using ZMQ 8 | # 9 | # Copyright (c) 2011 Lee Hambley 10 | # 11 | # Redistribution and use is allowed according to the terms of the New 12 | # BSD license. 13 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 14 | # 15 | 16 | if (ZMQ_LIBRARIES AND ZMQ_INCLUDE_DIRS) 17 | # in cache already 18 | set(ZMQ_FOUND TRUE) 19 | else (ZMQ_LIBRARIES AND ZMQ_INCLUDE_DIRS) 20 | 21 | find_path(ZMQ_INCLUDE_DIR 22 | NAMES 23 | zmq.h 24 | PATHS 25 | /usr/include 26 | /usr/local/include 27 | /opt/local/include 28 | /sw/include 29 | ) 30 | 31 | find_library(ZMQ_LIBRARY 32 | NAMES 33 | zmq 34 | PATHS 35 | /usr/lib 36 | /usr/local/lib 37 | /opt/local/lib 38 | /sw/lib 39 | ) 40 | 41 | set(ZMQ_INCLUDE_DIRS 42 | ${ZMQ_INCLUDE_DIR} 43 | ) 44 | 45 | if (ZMQ_LIBRARY) 46 | set(ZMQ_LIBRARIES 47 | ${ZMQ_LIBRARIES} 48 | ${ZMQ_LIBRARY} 49 | ) 50 | endif (ZMQ_LIBRARY) 51 | 52 | include(FindPackageHandleStandardArgs) 53 | find_package_handle_standard_args(ZMQ DEFAULT_MSG ZMQ_LIBRARIES ZMQ_INCLUDE_DIRS) 54 | 55 | # show the ZMQ_INCLUDE_DIRS and ZMQ_LIBRARIES variables only in the advanced view 56 | mark_as_advanced(ZMQ_INCLUDE_DIRS ZMQ_LIBRARIES) 57 | 58 | endif (ZMQ_LIBRARIES AND ZMQ_INCLUDE_DIRS) 59 | 60 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/FlowView.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Export.hpp" 6 | 7 | namespace QtNodes 8 | { 9 | 10 | class FlowScene; 11 | 12 | class NODE_EDITOR_PUBLIC FlowView 13 | : public QGraphicsView 14 | { 15 | Q_OBJECT 16 | public: 17 | 18 | FlowView(QWidget *parent = Q_NULLPTR); 19 | FlowView(FlowScene *scene, QWidget *parent = Q_NULLPTR); 20 | 21 | FlowView(const FlowView&) = delete; 22 | FlowView operator=(const FlowView&) = delete; 23 | 24 | QAction* clearSelectionAction() const; 25 | 26 | QAction* deleteSelectionAction() const; 27 | 28 | void setScene(FlowScene *scene); 29 | 30 | public slots: 31 | 32 | void scaleUp(); 33 | 34 | void scaleDown(); 35 | 36 | void deleteSelectedNodes(); 37 | 38 | signals: 39 | 40 | void startNodeDelete(); 41 | 42 | void finishNodeDelete(); 43 | 44 | protected: 45 | 46 | void contextMenuEvent(QContextMenuEvent *event) override; 47 | 48 | void wheelEvent(QWheelEvent *event) override; 49 | 50 | void keyPressEvent(QKeyEvent *event) override; 51 | 52 | void keyReleaseEvent(QKeyEvent *event) override; 53 | 54 | void mousePressEvent(QMouseEvent *event) override; 55 | 56 | void mouseMoveEvent(QMouseEvent *event) override; 57 | 58 | void drawBackground(QPainter* painter, const QRectF& r) override; 59 | 60 | void showEvent(QShowEvent *event) override; 61 | 62 | protected: 63 | 64 | FlowScene * scene(); 65 | 66 | private: 67 | 68 | QAction* _clearSelectionAction; 69 | 70 | QAction* _deleteSelectionAction; 71 | 72 | QPointF _clickPos; 73 | 74 | FlowScene* _scene; 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /QtNodeEditor/.travis.yml: -------------------------------------------------------------------------------- 1 | language: none 2 | 3 | matrix: 4 | include: 5 | - os: linux 6 | dist: trusty 7 | compiler: clang 8 | env: CXX=clang++-3.8 CC=clang-3.8 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | - llvm-toolchain-precise-3.8 14 | packages: 15 | - clang-3.8 16 | # VERY IMPORTANT TO INSTALL g++-5! clang doesn't come with a standard library, so 17 | # we need to install g++-5 for a C++14 standard library. 18 | - g++-5 19 | 20 | - os: linux 21 | dist: trusty 22 | compiler: gcc 23 | env: CXX=g++-5 CC=gcc-5 QT=5 24 | addons: 25 | apt: 26 | sources: 27 | - ubuntu-toolchain-r-test 28 | packages: 29 | - g++-5 30 | 31 | - os: osx 32 | osx_image: xcode8.3 33 | compiler: clang 34 | env: CMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.10.1:$CMAKE_PREFIX_PATH 35 | 36 | git: 37 | depth: 10 38 | 39 | before_install: 40 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi 41 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install qt; fi 42 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq ; fi 43 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install build-essential libgl1-mesa-dev ; fi 44 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -yy install qtbase5-dev ; fi 45 | 46 | 47 | script: 48 | - mkdir build 49 | - cd build 50 | - cmake -DCMAKE_VERBOSE_MAKEFILE=$VERBOSE_BUILD .. && make -j 51 | 52 | notifications: 53 | email: false 54 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | groot 5 | 1.0.0 6 | Graphical editor to create behaviour trees 7 | 8 | Davide Faconti 9 | 10 | 11 | 12 | MIT 13 | 14 | catkin 15 | cmake_modules 16 | ament_cmake 17 | ament_index_cpp 18 | 19 | behaviortree_cpp_v3 20 | qtbase5-dev 21 | libqt5-core 22 | libqt5-gui 23 | libqt5-svg-dev 24 | libqt5-opengl-dev 25 | libqt5-widgets 26 | libqt5-xml 27 | qttools5-dev-tools 28 | libdw-dev 29 | libzmq3-dev 30 | 31 | behaviortree_cpp_v3 32 | 33 | 34 | catkin 35 | ament_cmake 36 | 37 | 38 | -------------------------------------------------------------------------------- /bt_editor/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_UTILS_H 2 | #define NODE_UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "bt_editor_base.h" 10 | #include 11 | #include 12 | 13 | QtNodes::Node* findRoot(const QtNodes::FlowScene &scene); 14 | 15 | std::vector getChildren(const QtNodes::FlowScene &scene, 16 | const QtNodes::Node &parent_node, 17 | bool ordered); 18 | 19 | AbsBehaviorTree BuildTreeFromScene(const QtNodes::FlowScene *scene, 20 | QtNodes::Node *root_node = nullptr); 21 | 22 | std::pair > 23 | BuildTreeFromFlatbuffers(const Serialization::BehaviorTree* bt ); 24 | 25 | AbsBehaviorTree BuildTreeFromXML(const QDomElement &bt_root, const NodeModels &models); 26 | 27 | void NodeReorder(QtNodes::FlowScene &scene, AbsBehaviorTree &abstract_tree ); 28 | 29 | std::pair 30 | getStyleFromStatus(NodeStatus status, NodeStatus prev_status); 31 | 32 | QtNodes::Node* GetParentNode(QtNodes::Node* node); 33 | 34 | std::set GetModelsToRemove(QWidget* parent, 35 | NodeModels& prev_models, 36 | const NodeModels& new_models); 37 | 38 | BT::NodeType convert( Serialization::NodeType type); 39 | 40 | BT::NodeStatus convert(Serialization::NodeStatus type); 41 | 42 | BT::PortDirection convert(Serialization::PortDirection direction); 43 | 44 | 45 | #endif // NODE_UTILS_H 46 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/Export.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Compiler.hpp" 4 | #include "OperatingSystem.hpp" 5 | 6 | #ifdef NODE_EDITOR_PLATFORM_WINDOWS 7 | # define NODE_EDITOR_EXPORT __declspec(dllexport) 8 | # define NODE_EDITOR_IMPORT __declspec(dllimport) 9 | # define NODE_EDITOR_LOCAL 10 | #elif \ 11 | NODE_EDITOR_COMPILER_GNU_VERSION_MAJOR >= 4 || \ 12 | defined (NODE_EDITOR_COMPILER_CLANG) 13 | # define NODE_EDITOR_EXPORT __attribute__((visibility("default"))) 14 | # define NODE_EDITOR_IMPORT __attribute__((visibility("default"))) 15 | # define NODE_EDITOR_LOCAL __attribute__((visibility("hidden"))) 16 | #else 17 | # define NODE_EDITOR_EXPORT 18 | # define NODE_EDITOR_IMPORT 19 | # define NODE_EDITOR_LOCAL 20 | #endif 21 | 22 | #ifdef __cplusplus 23 | # define NODE_EDITOR_DEMANGLED extern "C" 24 | #else 25 | # define NODE_EDITOR_DEMANGLED 26 | #endif 27 | 28 | 29 | #if defined (NODE_EDITOR_SHARED) && !defined (NODE_EDITOR_STATIC) 30 | # ifdef NODE_EDITOR_EXPORTS 31 | # define NODE_EDITOR_PUBLIC NODE_EDITOR_EXPORT 32 | # else 33 | # define NODE_EDITOR_PUBLIC NODE_EDITOR_IMPORT 34 | # endif 35 | # define NODE_EDITOR_PRIVATE NODE_EDITOR_LOCAL 36 | #elif !defined (NODE_EDITOR_SHARED) && defined (NODE_EDITOR_STATIC) 37 | # define NODE_EDITOR_PUBLIC 38 | # define NODE_EDITOR_PRIVATE 39 | #elif defined (NODE_EDITOR_SHARED) && defined (NODE_EDITOR_STATIC) 40 | # ifdef NODE_EDITOR_EXPORTS 41 | # error "Cannot build as shared and static simultaneously." 42 | # else 43 | # error "Cannot link against shared and static simultaneously." 44 | # endif 45 | #else 46 | # ifdef NODE_EDITOR_EXPORTS 47 | # error "Choose whether to build as shared or static." 48 | # else 49 | # error "Choose whether to link against shared or static." 50 | # endif 51 | #endif 52 | -------------------------------------------------------------------------------- /QtNodeEditor/src/NodePainter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace QtNodes 6 | { 7 | 8 | class Node; 9 | class NodeState; 10 | class NodeGeometry; 11 | class NodeGraphicsObject; 12 | class NodeDataModel; 13 | class FlowItemEntry; 14 | class FlowScene; 15 | 16 | class NodePainter 17 | { 18 | public: 19 | 20 | NodePainter(); 21 | 22 | public: 23 | 24 | static 25 | void 26 | paint(QPainter* painter, 27 | Node& node, 28 | FlowScene const& scene); 29 | 30 | static 31 | void 32 | drawNodeRect(QPainter* painter, 33 | NodeGeometry const& geom, 34 | NodeDataModel const* model, 35 | NodeGraphicsObject const & graphicsObject); 36 | 37 | static 38 | void 39 | drawEntryLabels(QPainter* painter, 40 | NodeGeometry const& geom, 41 | NodeState const& state, 42 | NodeDataModel const * model); 43 | 44 | static 45 | void 46 | drawConnectionPoints(QPainter* painter, 47 | NodeGeometry const& geom, 48 | NodeState const& state, 49 | NodeDataModel const * model, 50 | FlowScene const & scene); 51 | 52 | static 53 | void 54 | drawFilledConnectionPoints(QPainter* painter, 55 | NodeGeometry const& geom, 56 | NodeState const& state, 57 | NodeDataModel const * model); 58 | 59 | static 60 | void 61 | drawResizeRect(QPainter* painter, 62 | NodeGeometry const& geom, 63 | NodeDataModel const * model); 64 | 65 | static 66 | void 67 | drawValidationRect(QPainter * painter, 68 | NodeGeometry const & geom, 69 | NodeDataModel const * model, 70 | NodeGraphicsObject const & graphicsObject); 71 | }; 72 | } 73 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/ConnectionGraphicsObject.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | class QGraphicsSceneMouseEvent; 8 | 9 | namespace QtNodes 10 | { 11 | 12 | class FlowScene; 13 | class Connection; 14 | class ConnectionGeometry; 15 | class Node; 16 | 17 | /// Graphic Object for connection. Adds itself to scene 18 | class ConnectionGraphicsObject 19 | : public QGraphicsObject 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | 25 | ConnectionGraphicsObject(FlowScene &scene, 26 | Connection &connection); 27 | 28 | virtual 29 | ~ConnectionGraphicsObject(); 30 | 31 | enum { Type = UserType + 2 }; 32 | int 33 | type() const override { return Type; } 34 | 35 | public: 36 | 37 | Connection& 38 | connection(); 39 | 40 | QRectF 41 | boundingRect() const override; 42 | 43 | QPainterPath 44 | shape() const override; 45 | 46 | void 47 | setGeometryChanged(); 48 | 49 | /// Updates the position of both ends 50 | void 51 | move(); 52 | 53 | void 54 | lock(bool locked); 55 | 56 | protected: 57 | 58 | void 59 | paint(QPainter* painter, 60 | QStyleOptionGraphicsItem const* option, 61 | QWidget* widget = 0) override; 62 | 63 | void 64 | mousePressEvent(QGraphicsSceneMouseEvent* event) override; 65 | 66 | void 67 | mouseMoveEvent(QGraphicsSceneMouseEvent* event) override; 68 | 69 | void 70 | mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override; 71 | 72 | void 73 | hoverEnterEvent(QGraphicsSceneHoverEvent* event) override; 74 | 75 | void 76 | hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override; 77 | 78 | void 79 | contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override; 80 | 81 | private: 82 | 83 | void 84 | addGraphicsEffect(); 85 | 86 | private: 87 | 88 | FlowScene & _scene; 89 | 90 | Connection& _connection; 91 | }; 92 | } 93 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/star.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 52 | 56 | 57 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/zoom_home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/magic-wand.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/Compiler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if \ 4 | defined (__MINGW32__) || \ 5 | defined (__MINGW64__) 6 | # define NODE_EDITOR_COMPILER "MinGW" 7 | # define NODE_EDITOR_COMPILER_MINGW 8 | #elif \ 9 | defined (__GNUC__) 10 | # define NODE_EDITOR_COMPILER "GNU" 11 | # define NODE_EDITOR_COMPILER_GNU 12 | # define NODE_EDITOR_COMPILER_GNU_VERSION_MAJOR __GNUC__ 13 | # define NODE_EDITOR_COMPILER_GNU_VERSION_MINOR __GNUC_MINOR__ 14 | # define NODE_EDITOR_COMPILER_GNU_VERSION_PATCH __GNUC_PATCHLEVEL__ 15 | #elif \ 16 | defined (__clang__) 17 | # define NODE_EDITOR_COMPILER "Clang" 18 | # define NODE_EDITOR_COMPILER_CLANG 19 | #elif \ 20 | defined (_MSC_VER) 21 | # define NODE_EDITOR_COMPILER "Microsoft Visual C++" 22 | # define NODE_EDITOR_COMPILER_MICROSOFT 23 | #elif \ 24 | defined (__BORLANDC__) 25 | # define NODE_EDITOR_COMPILER "Borland C++ Builder" 26 | # define NODE_EDITOR_COMPILER_BORLAND 27 | #elif \ 28 | defined (__CODEGEARC__) 29 | # define NODE_EDITOR_COMPILER "CodeGear C++ Builder" 30 | # define NODE_EDITOR_COMPILER_CODEGEAR 31 | #elif \ 32 | defined (__INTEL_COMPILER) || \ 33 | defined (__ICL) 34 | # define NODE_EDITOR_COMPILER "Intel C++" 35 | # define NODE_EDITOR_COMPILER_INTEL 36 | #elif \ 37 | defined (__xlC__) || \ 38 | defined (__IBMCPP__) 39 | # define NODE_EDITOR_COMPILER "IBM XL C++" 40 | # define NODE_EDITOR_COMPILER_IBM 41 | #elif \ 42 | defined (__HP_aCC) 43 | # define NODE_EDITOR_COMPILER "HP aC++" 44 | # define NODE_EDITOR_COMPILER_HP 45 | #elif \ 46 | defined (__WATCOMC__) 47 | # define NODE_EDITOR_COMPILER "Watcom C++" 48 | # define NODE_EDITOR_COMPILER_WATCOM 49 | #endif 50 | 51 | #ifndef NODE_EDITOR_COMPILER 52 | # error "Current compiler is not supported." 53 | #endif 54 | -------------------------------------------------------------------------------- /bt_editor/sidepanel_editor.h: -------------------------------------------------------------------------------- 1 | #ifndef SIDE_PANEL_EDITOR_H 2 | #define SIDE_PANEL_EDITOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "XML_utilities.hpp" 9 | 10 | namespace Ui { 11 | class SidepanelEditor; 12 | } 13 | 14 | class SidepanelEditor : public QFrame 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit SidepanelEditor(QtNodes::DataModelRegistry* registry, 20 | NodeModels& tree_nodes_model, 21 | QWidget *parent = nullptr); 22 | ~SidepanelEditor(); 23 | 24 | void updateTreeView(); 25 | 26 | void clear(); 27 | 28 | public slots: 29 | void onRemoveModel(QString selected_name); 30 | 31 | void onReplaceModel(const QString &old_name, const NodeModel &new_model); 32 | 33 | 34 | private slots: 35 | 36 | void on_paletteTreeWidget_itemSelectionChanged(); 37 | 38 | void on_lineEditFilter_textChanged(const QString &arg1); 39 | 40 | void on_buttonAddNode_clicked(); 41 | 42 | void onContextMenu(const QPoint &point); 43 | 44 | void on_buttonUpload_clicked(); 45 | 46 | void on_buttonDownload_clicked(); 47 | 48 | void on_buttonLock_toggled(bool checked); 49 | 50 | void onDoubleClick(QTreeWidgetItem *item, int column); 51 | 52 | signals: 53 | 54 | void addNewModel(const NodeModel &new_model); 55 | 56 | void modelRemoveRequested(QString ID); 57 | 58 | void nodeModelEdited(QString prev_ID, QString new_ID); 59 | 60 | void addSubtree(QString ID); 61 | 62 | void renameSubtree(QString prev_ID, QString new_ID); 63 | 64 | void destroySubtree(QString ID); 65 | 66 | void setTabScope(const QString& subtreeName); 67 | 68 | private: 69 | Ui::SidepanelEditor *ui; 70 | NodeModels &_tree_nodes_model; 71 | QtNodes::DataModelRegistry* _model_registry; 72 | std::map _tree_view_category_items; 73 | 74 | NodeModels importFromXML(QFile *file); 75 | 76 | NodeModels importFromSkills(const QString& filename); 77 | 78 | }; 79 | 80 | #endif // NODE_PALETTE_H 81 | -------------------------------------------------------------------------------- /QtNodeEditor/src/DataModelRegistry.cpp: -------------------------------------------------------------------------------- 1 | #include "DataModelRegistry.hpp" 2 | 3 | #include 4 | #include 5 | 6 | using QtNodes::DataModelRegistry; 7 | using QtNodes::NodeDataModel; 8 | using QtNodes::NodeDataType; 9 | using QtNodes::TypeConverter; 10 | 11 | std::unique_ptr 12 | DataModelRegistry:: 13 | create(QString const &modelName) 14 | { 15 | auto it = _registeredItemCreators.find(modelName); 16 | 17 | if (it != _registeredItemCreators.end()) 18 | { 19 | return it->second(); 20 | } 21 | 22 | qDebug() << "DataModelRegistry::create : unable to create [" << 23 | modelName << "]\nCandidates are:\n"; 24 | for(auto& creator_it: _registeredItemCreators) 25 | { 26 | qDebug() << " " << creator_it.first; 27 | } 28 | return nullptr; 29 | } 30 | 31 | 32 | DataModelRegistry::RegisteredModelCreatorsMap const & 33 | DataModelRegistry:: 34 | registeredModelCreators() const 35 | { 36 | return _registeredItemCreators; 37 | } 38 | 39 | 40 | DataModelRegistry::RegisteredModelsCategoryMap const & 41 | DataModelRegistry:: 42 | registeredModelsCategoryAssociation() const 43 | { 44 | return _registeredModelsCategory; 45 | } 46 | 47 | 48 | DataModelRegistry::CategoriesSet const & 49 | DataModelRegistry:: 50 | categories() const 51 | { 52 | return _categories; 53 | } 54 | 55 | 56 | TypeConverter 57 | DataModelRegistry:: 58 | getTypeConverter(NodeDataType const & d1, 59 | NodeDataType const & d2) const 60 | { 61 | TypeConverterId converterId = std::make_pair(d1, d2); 62 | 63 | auto it = _registeredTypeConverters.find(converterId); 64 | 65 | if (it != _registeredTypeConverters.end()) 66 | { 67 | return it->second; 68 | } 69 | 70 | return TypeConverter{}; 71 | } 72 | 73 | std::unordered_set DataModelRegistry::registeredModelsByCategory(const QString &category) 74 | { 75 | std::unordered_set names_in_category; 76 | for (auto& it: _registeredModelsCategory) 77 | { 78 | if( it.second == category) 79 | { 80 | names_in_category.insert(it.first); 81 | } 82 | } 83 | return names_in_category; 84 | } 85 | -------------------------------------------------------------------------------- /bt_editor/resources/NodesStyle.json: -------------------------------------------------------------------------------- 1 | { 2 | "Action": { 3 | "icon": ":/icons/svg/letter_A.svg" 4 | }, 5 | 6 | "Condition": { 7 | "icon": ":/icons/svg/letter_C.svg", 8 | "caption_color": "#44bb44" 9 | }, 10 | 11 | "Decorator": { 12 | "caption_color": "#ffee77" 13 | }, 14 | 15 | "SubTree": { 16 | "icon": ":/icons/svg/subtree.svg" 17 | }, 18 | 19 | "AlwaysFailure": { 20 | "icon": ":/icons/svg/letter_A.svg", 21 | "caption_color": "#ff2222", 22 | "caption_alias": "Failure" 23 | }, 24 | 25 | "ForceFailure": { 26 | "icon": ":/icons/svg/letter_A.svg", 27 | "caption_color": "#ff2222" 28 | }, 29 | 30 | "AlwaysSuccess": { 31 | "icon": ":/icons/svg/letter_A.svg", 32 | "caption_color": "#00FF00", 33 | "caption_alias": "Success" 34 | }, 35 | 36 | "ForceSuccess": { 37 | "icon": ":/icons/svg/letter_A.svg", 38 | "caption_color": "#00FF00" 39 | }, 40 | 41 | "SetBlackboard": { 42 | "icon": ":/icons/svg/edit_list.svg" 43 | }, 44 | 45 | "RetryUntilSuccessful": { 46 | "icon": ":/icons/svg/retry.svg" 47 | }, 48 | 49 | "Inverter": { 50 | "icon": ":/icons/svg/not_equal.svg" 51 | }, 52 | 53 | "Repeat": { 54 | "icon": ":/icons/svg/repeat.svg" 55 | }, 56 | 57 | "Timeout": { 58 | "icon": ":/icons/svg/timeout.svg" 59 | }, 60 | 61 | "Sequence": { 62 | "icon": ":/icons/svg/sequence.svg", 63 | "caption_color": "#ff99bb" 64 | }, 65 | 66 | "SequenceStar": { 67 | "icon": ":/icons/svg/sequence_star.svg", 68 | "caption_color": "#ffaacc" 69 | }, 70 | 71 | "ReactiveSequence": { 72 | "icon": ":/icons/svg/sequence_reactive.svg", 73 | "caption_color": "#ff77aa" 74 | }, 75 | 76 | "Fallback": { 77 | "icon": ":/icons/svg/fallback.svg", 78 | "caption_color": "#77ccff" 79 | }, 80 | 81 | "ReactiveFallback": { 82 | "icon": ":/icons/svg/fallback_reactive.svg", 83 | "caption_color": "#44aadd" 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /bt_editor/sidepanel_monitor.h: -------------------------------------------------------------------------------- 1 | #ifndef SIDEPANEL_MONITOR_H 2 | #define SIDEPANEL_MONITOR_H 3 | 4 | #include 5 | #include 6 | 7 | #include "bt_editor_base.h" 8 | 9 | namespace Ui { 10 | class SidepanelMonitor; 11 | } 12 | 13 | class SidepanelMonitor : public QFrame 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | /// Timer period in milliseconds. 19 | static constexpr int _timer_period_ms = 20; 20 | /// Default timeout to get behavior tree, in milliseconds. 21 | static constexpr int _load_tree_default_timeout_ms = 1000; 22 | /// Timeout to get behavior tree during autoconnect, in milliseconds. 23 | static constexpr int _load_tree_autoconnect_timeout_ms = 10000; 24 | 25 | explicit SidepanelMonitor(QWidget *parent = nullptr, 26 | const QString &address = "", 27 | const QString &publisher_port = "", 28 | const QString &server_port = ""); 29 | ~SidepanelMonitor(); 30 | 31 | void clear(); 32 | 33 | void set_load_tree_timeout_ms(const int timeout_ms) 34 | { 35 | _load_tree_timeout_ms = timeout_ms; 36 | }; 37 | 38 | public slots: 39 | 40 | void on_Connect(); 41 | 42 | private slots: 43 | 44 | void on_timer(); 45 | 46 | signals: 47 | void loadBehaviorTree(const AbsBehaviorTree& tree, const QString &bt_name ); 48 | 49 | void connectionUpdate(bool connected); 50 | 51 | void changeNodeStyle(const QString& bt_name, 52 | const std::vector>& node_status); 53 | 54 | void addNewModel(const NodeModel &new_model); 55 | 56 | private: 57 | Ui::SidepanelMonitor *ui; 58 | 59 | zmq::context_t _zmq_context; 60 | zmq::socket_t _zmq_subscriber; 61 | 62 | QTimer* _timer; 63 | 64 | bool _connected; 65 | std::string _connection_address_pub; 66 | std::string _connection_address_req; 67 | int _msg_count; 68 | 69 | int _load_tree_timeout_ms; // Timeout to get behavior tree. 70 | AbsBehaviorTree _loaded_tree; 71 | std::unordered_map _uid_to_index; 72 | 73 | bool getTreeFromServer(); 74 | 75 | QWidget *_parent; 76 | 77 | }; 78 | 79 | #endif // SIDEPANEL_MONITOR_H 80 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/low_battery.svg: -------------------------------------------------------------------------------- 1 | Created by AFY Studiofrom the Noun Project -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/NodeState.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "Export.hpp" 9 | 10 | #include "PortType.hpp" 11 | #include "NodeData.hpp" 12 | #include "memory.hpp" 13 | 14 | namespace QtNodes 15 | { 16 | 17 | class Connection; 18 | class NodeDataModel; 19 | 20 | /// Contains vectors of connected input and output connections. 21 | /// Stores bool for reacting on hovering connections 22 | class NODE_EDITOR_PUBLIC NodeState 23 | { 24 | public: 25 | enum ReactToConnectionState 26 | { 27 | REACTING, 28 | NOT_REACTING 29 | }; 30 | 31 | public: 32 | 33 | NodeState(std::unique_ptr const &model); 34 | 35 | public: 36 | 37 | using ConnectionPtrSet = 38 | std::unordered_map; 39 | 40 | /// Returns vector of connections ID. 41 | /// Some of them can be empty (null) 42 | std::vector const& 43 | getEntries(PortType) const; 44 | 45 | std::vector & 46 | getEntries(PortType); 47 | 48 | ConnectionPtrSet 49 | connections(PortType portType, PortIndex portIndex) const; 50 | 51 | void 52 | setConnection(PortType portType, 53 | PortIndex portIndex, 54 | Connection& connection); 55 | 56 | void 57 | eraseConnection(PortType portType, 58 | PortIndex portIndex, 59 | QUuid id); 60 | 61 | ReactToConnectionState 62 | reaction() const; 63 | 64 | PortType 65 | reactingPortType() const; 66 | 67 | NodeDataType 68 | reactingDataType() const; 69 | 70 | void 71 | setReaction(ReactToConnectionState reaction, 72 | PortType reactingPortType = PortType::None, 73 | 74 | NodeDataType reactingDataType = 75 | NodeDataType()); 76 | 77 | bool 78 | isReacting() const; 79 | 80 | void 81 | setResizing(bool resizing); 82 | 83 | bool 84 | resizing() const; 85 | 86 | private: 87 | 88 | std::vector _inConnections; 89 | std::vector _outConnections; 90 | 91 | ReactToConnectionState _reaction; 92 | PortType _reactingPortType; 93 | NodeDataType _reactingDataType; 94 | 95 | bool _resizing; 96 | }; 97 | } 98 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/list_add.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 52 | 56 | 61 | 62 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/arrow_right.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /QtNodeEditor/src/NodeConnectionInteraction.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Node.hpp" 4 | #include "Connection.hpp" 5 | 6 | namespace QtNodes 7 | { 8 | 9 | class DataModelRegistry; 10 | class FlowScene; 11 | class NodeDataModel; 12 | 13 | /// Class performs various operations on the Node and Connection pair. 14 | /// An instance should be created on the stack and destroyed when 15 | /// the operation is completed 16 | class NodeConnectionInteraction 17 | { 18 | public: 19 | NodeConnectionInteraction(Node& node, 20 | Connection& connection, 21 | FlowScene& scene); 22 | 23 | /// Can connect when following conditions are met: 24 | /// 1) Connection 'requires' a port 25 | /// 2) Connection's vacant end is above the node port 26 | /// 3) Node port is vacant 27 | /// 4) Connection type equals node port type, or there is a registered type conversion that can translate between the two 28 | bool canConnect(PortIndex & portIndex, 29 | TypeConverter & converter) const; 30 | 31 | /// 1) Check conditions from 'canConnect' 32 | /// 1.5) If the connection is possible but a type conversion is needed, add a converter node to the scene, and connect it properly 33 | /// 2) Assign node to required port in Connection 34 | /// 3) Assign Connection to empty port in NodeState 35 | /// 4) Adjust Connection geometry 36 | /// 5) Poke model to initiate data transfer 37 | bool tryConnect() const; 38 | 39 | 40 | /// 1) Node and Connection should be already connected 41 | /// 2) If so, clear Connection entry in the NodeState 42 | /// 3) Propagate invalid data to IN node 43 | /// 4) Set Connection end to 'requiring a port' 44 | bool disconnect(PortType portToDisconnect) const; 45 | 46 | private: 47 | 48 | PortType connectionRequiredPort() const; 49 | 50 | QPointF connectionEndScenePosition(PortType) const; 51 | 52 | QPointF nodePortScenePosition(PortType portType, 53 | PortIndex portIndex) const; 54 | 55 | PortIndex nodePortIndexUnderScenePoint(PortType portType, 56 | QPointF const &p) const; 57 | 58 | bool nodePortIsEmpty(PortType portType, PortIndex portIndex) const; 59 | 60 | private: 61 | 62 | Node* _node; 63 | 64 | Connection* _connection; 65 | 66 | FlowScene* _scene; 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /bt_editor/models/SubtreeNodeModel.cpp: -------------------------------------------------------------------------------- 1 | #include "SubtreeNodeModel.hpp" 2 | #include 3 | #include 4 | 5 | SubtreeNodeModel::SubtreeNodeModel(const NodeModel &model): 6 | BehaviorTreeDataModel ( model ), 7 | _expanded(false) 8 | { 9 | _line_edit_name->setReadOnly(true); 10 | _line_edit_name->setHidden(true); 11 | 12 | _expand_button = new QPushButton( _expanded ? "Collapse" : "Expand", _main_widget ); 13 | _expand_button->setMaximumWidth(100); 14 | _main_layout->addWidget(_expand_button); 15 | _main_layout->setAlignment(_expand_button, Qt::AlignHCenter); 16 | 17 | _expand_button->setStyleSheet( 18 | "QPushButton{" 19 | " color: black; background-color: white; " 20 | " border: 0px rgb(115, 210, 22);" 21 | " padding: 4px; border-radius: 3px;}\n" 22 | "QPushButton:disabled { color: #303030; background-color: #a0a0a0; }"); 23 | _expand_button->setFlat(false); 24 | _expand_button->setFocusPolicy(Qt::NoFocus); 25 | _expand_button->adjustSize(); 26 | 27 | connect( _expand_button, &QPushButton::clicked, 28 | this, [this]() 29 | { 30 | emit expandButtonPushed() ; 31 | }); 32 | 33 | updateNodeSize(); 34 | } 35 | 36 | void SubtreeNodeModel::setExpanded(bool expand) 37 | { 38 | _expanded = expand; 39 | _expand_button->setText( _expanded ? "Collapse" : "Expand"); 40 | _expand_button->adjustSize(); 41 | _main_widget->adjustSize(); 42 | } 43 | 44 | void SubtreeNodeModel::setInstanceName(const QString &name) 45 | { 46 | _line_edit_name->setHidden( name == registrationName() ); 47 | BehaviorTreeDataModel::setInstanceName(name); 48 | } 49 | 50 | QJsonObject SubtreeNodeModel::save() const 51 | { 52 | QJsonObject modelJson; 53 | modelJson["name"] = registrationName(); 54 | modelJson["alias"] = instanceName(); 55 | modelJson["expanded"] = _expanded; 56 | 57 | return modelJson; 58 | } 59 | 60 | void SubtreeNodeModel::restore(const QJsonObject &modelJson) 61 | { 62 | if( registrationName() != modelJson["name"].toString() ) 63 | { 64 | throw std::runtime_error(" error restoring: different registration_name"); 65 | } 66 | QString alias = modelJson["alias"].toString(); 67 | setInstanceName( alias ); 68 | setExpanded( modelJson["expanded"].toBool() ); 69 | } 70 | -------------------------------------------------------------------------------- /bt_editor/action_form.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Form 4 | 5 | 6 | 7 | 0 8 | 0 9 | 188 10 | 72 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Action 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | A 31 | 32 | 33 | 34 | 35 | B 36 | 37 | 38 | 39 | 40 | C 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 0 52 | 53 | 54 | 0 55 | 56 | 57 | 0 58 | 59 | 60 | 0 61 | 62 | 63 | 0 64 | 65 | 66 | 0 67 | 68 | 69 | 70 | 71 | Param1 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /bt_editor/sidepanel_replay.h: -------------------------------------------------------------------------------- 1 | #ifndef SIDEPANEL_REPLAY_H 2 | #define SIDEPANEL_REPLAY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "bt_editor_base.h" 9 | 10 | 11 | namespace Ui { 12 | class SidepanelReplay; 13 | } 14 | 15 | class SidepanelReplay : public QFrame 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit SidepanelReplay(QWidget *parent = 0); 21 | ~SidepanelReplay() override; 22 | 23 | void clear(); 24 | 25 | void loadLog(const QByteArray& content); 26 | 27 | size_t transitionsCount() const { return _transitions.size(); } 28 | 29 | public slots: 30 | 31 | void on_LoadLog(); 32 | 33 | private slots: 34 | 35 | void on_pushButtonPlay_toggled(bool checked); 36 | 37 | void on_spinBox_valueChanged(int arg1); 38 | 39 | void on_timeSlider_valueChanged(int value); 40 | 41 | void on_tableView_clicked(const QModelIndex &index); 42 | 43 | void onTimerUpdate(); 44 | 45 | void onPlayUpdate(); 46 | 47 | void on_lineEditFilter_textChanged(const QString &filter_text); 48 | 49 | signals: 50 | void loadBehaviorTree(const AbsBehaviorTree& tree, const QString& name ); 51 | 52 | void changeNodeStyle(const QString& bt_name, 53 | const std::vector>& node_status); 54 | 55 | void addNewModel(const NodeModel &new_model); 56 | 57 | private: 58 | 59 | bool eventFilter(QObject *object, QEvent *event) override; 60 | 61 | void loadFromFlatbuffers(const std::vector& serialized_description); 62 | 63 | void onRowChanged(int value); 64 | 65 | Ui::SidepanelReplay *ui; 66 | 67 | struct Transition{ 68 | int16_t index; 69 | double timestamp; 70 | NodeStatus prev_status; 71 | NodeStatus status; 72 | bool is_tree_restart; 73 | int nearest_restart_transition_index; 74 | }; 75 | std::vector _transitions; 76 | std::vector< std::pair> _timepoint; 77 | 78 | int _prev_row; 79 | int _next_row; 80 | 81 | void updatedSpinAndSlider(int row); 82 | 83 | QStandardItemModel* _table_model; 84 | 85 | QTimer *_layout_update_timer; 86 | 87 | QTimer *_play_timer; 88 | 89 | AbsBehaviorTree _loaded_tree; 90 | 91 | void updateTableModel(const AbsBehaviorTree &tree); 92 | 93 | QWidget *_parent; 94 | }; 95 | 96 | #endif // SIDEPANEL_REPLAY_H 97 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/NodeGraphicsObject.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Connection.hpp" 7 | 8 | #include "NodeGeometry.hpp" 9 | #include "NodeState.hpp" 10 | 11 | class QGraphicsProxyWidget; 12 | 13 | namespace QtNodes 14 | { 15 | 16 | class FlowScene; 17 | class FlowItemEntry; 18 | 19 | /// Class reacts on GUI events, mouse clicks and 20 | /// forwards painting operation. 21 | class NodeGraphicsObject : public QGraphicsObject 22 | { 23 | Q_OBJECT 24 | 25 | public: 26 | NodeGraphicsObject(FlowScene &scene, 27 | Node& node); 28 | 29 | virtual 30 | ~NodeGraphicsObject(); 31 | 32 | Node& 33 | node(); 34 | 35 | Node const& 36 | node() const; 37 | 38 | QRectF 39 | boundingRect() const override; 40 | 41 | void 42 | setGeometryChanged(); 43 | 44 | /// Visits all attached connections and corrects 45 | /// their corresponding end points. 46 | void 47 | moveConnections() const; 48 | 49 | enum { Type = UserType + 1 }; 50 | 51 | int 52 | type() const override { return Type; } 53 | 54 | void 55 | lock(bool locked); 56 | 57 | void 58 | updateEmbeddedQWidget(); 59 | 60 | protected: 61 | void 62 | paint(QPainter* painter, 63 | QStyleOptionGraphicsItem const* option, 64 | QWidget* widget = 0) override; 65 | 66 | QVariant 67 | itemChange(GraphicsItemChange change, const QVariant &value) override; 68 | 69 | void 70 | mousePressEvent(QGraphicsSceneMouseEvent* event) override; 71 | 72 | void 73 | mouseMoveEvent(QGraphicsSceneMouseEvent* event) override; 74 | 75 | void 76 | mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override; 77 | 78 | void 79 | hoverEnterEvent(QGraphicsSceneHoverEvent* event) override; 80 | 81 | void 82 | hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override; 83 | 84 | void 85 | hoverMoveEvent(QGraphicsSceneHoverEvent *) override; 86 | 87 | void 88 | mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) override; 89 | 90 | void 91 | contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override; 92 | 93 | private: 94 | 95 | FlowScene & _scene; 96 | 97 | Node& _node; 98 | 99 | bool _locked; 100 | 101 | bool _double_clicked; 102 | 103 | // either nullptr or owned by parent QGraphicsItem 104 | QGraphicsProxyWidget * _proxyWidget; 105 | QPoint _press_pos; 106 | }; 107 | } 108 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/lock_open.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 59 | 60 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/letter_C.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 57 | C: 68 | 69 | 70 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/NodeDataModel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "PortType.hpp" 6 | #include "NodeData.hpp" 7 | #include "Serializable.hpp" 8 | #include "NodeGeometry.hpp" 9 | #include "NodeStyle.hpp" 10 | #include "NodePainterDelegate.hpp" 11 | #include "Export.hpp" 12 | #include "memory.hpp" 13 | 14 | namespace QtNodes 15 | { 16 | 17 | enum class NodeValidationState 18 | { 19 | Valid, 20 | Warning, 21 | Error 22 | }; 23 | 24 | class StyleCollection; 25 | 26 | class NODE_EDITOR_PUBLIC NodeDataModel 27 | : public QObject 28 | , public Serializable 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | 34 | NodeDataModel(); 35 | 36 | virtual 37 | ~NodeDataModel() = default; 38 | 39 | /// Name makes this model unique 40 | virtual QString 41 | name() const = 0; 42 | 43 | public: 44 | 45 | QJsonObject 46 | save() const override; 47 | 48 | public: 49 | 50 | virtual 51 | unsigned int nPorts(PortType portType) const = 0; 52 | 53 | virtual 54 | NodeDataType dataType(PortType portType, PortIndex portIndex) const = 0; 55 | 56 | public: 57 | 58 | enum class ConnectionPolicy 59 | { 60 | One, 61 | Many, 62 | }; 63 | 64 | virtual 65 | ConnectionPolicy 66 | portOutConnectionPolicy(PortIndex) const 67 | { 68 | return ConnectionPolicy::Many; 69 | } 70 | 71 | NodeStyle const& 72 | nodeStyle() const; 73 | 74 | void 75 | setNodeStyle(NodeStyle const& style); 76 | 77 | public: 78 | 79 | /// Triggers the algorithm 80 | virtual 81 | void 82 | setInData(std::shared_ptr nodeData, 83 | PortIndex port) = 0; 84 | 85 | virtual 86 | std::shared_ptr 87 | outData(PortIndex port) = 0; 88 | 89 | virtual 90 | QWidget * 91 | embeddedWidget() = 0; 92 | 93 | virtual 94 | bool 95 | resizable() const { return false; } 96 | 97 | virtual 98 | NodeValidationState 99 | validationState() const { return NodeValidationState::Valid; } 100 | 101 | virtual 102 | QString 103 | validationMessage() const { return QString(""); } 104 | 105 | virtual 106 | NodePainterDelegate* painterDelegate() const { return nullptr; } 107 | 108 | signals: 109 | 110 | void 111 | dataUpdated(PortIndex index); 112 | 113 | void 114 | dataInvalidated(PortIndex index); 115 | 116 | void 117 | computingStarted(); 118 | 119 | void 120 | computingFinished(); 121 | 122 | void embeddedWidgetSizeUpdated(); 123 | 124 | private: 125 | 126 | NodeStyle _nodeStyle; 127 | }; 128 | } 129 | -------------------------------------------------------------------------------- /bt_editor/resources/icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | svg/arrow_right.svg 4 | svg/edit_list.svg 5 | svg/exclaimation_mark.svg 6 | svg/gears.svg 7 | svg/goto_map.svg 8 | svg/low_battery.svg 9 | svg/manipulator.svg 10 | svg/maze_path.svg 11 | svg/mobile_manipulator.svg 12 | svg/nodes_tree.svg 13 | svg/question_mark.svg 14 | svg/repeat.svg 15 | svg/retry.svg 16 | svg/robot.svg 17 | svg/robot_talk.svg 18 | svg/target_radar.svg 19 | svg/tree.svg 20 | svg/subtree.svg 21 | svg/not_equal.svg 22 | svg/letter_C.svg 23 | svg/letter_A.svg 24 | svg/logo_splashscreen.svg 25 | svg/list_add.svg 26 | svg/settings.svg 27 | svg/files.svg 28 | svg/download.svg 29 | svg/upload.svg 30 | svg/lock.svg 31 | svg/lock_open.svg 32 | svg/fallback.svg 33 | svg/fallback_star.svg 34 | svg/sequence.svg 35 | svg/sequence_star.svg 36 | svg/timeout.svg 37 | green-circle.png 38 | red-circle.png 39 | svg/magic-wand.svg 40 | BT-horizontal.png 41 | BT-vertical.png 42 | svg/zoom_home.svg 43 | svg/save_dark.svg 44 | svg/save_white.svg 45 | BT-edit.png 46 | BT-log.png 47 | BT-monitor.png 48 | svg/folder.svg 49 | svg/connect.svg 50 | svg/server_download.svg 51 | BT.png 52 | close_x.png 53 | icons.qrc 54 | play.png 55 | svg/star.svg 56 | green_star.png 57 | svg/asterix.svg 58 | svg/letter_i.svg 59 | svg/letter_o.svg 60 | svg/fallback_reactive.svg 61 | svg/sequence_reactive.svg 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /installer/org.eurecat.Groot/meta/installscript.qs: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2017 The Qt Company Ltd. 4 | ** Contact: https://www.qt.io/licensing/ 5 | ** 6 | ** This file is part of the FOO module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and The Qt Company. For licensing terms 14 | ** and conditions see https://www.qt.io/terms-conditions. For further 15 | ** information use the contact form at https://www.qt.io/contact-us. 16 | ** 17 | ** GNU General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU 19 | ** General Public License version 3 as published by the Free Software 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT 21 | ** included in the packaging of this file. Please review the following 22 | ** information to ensure the GNU General Public License requirements will 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. 24 | ** 25 | ** $QT_END_LICENSE$ 26 | ** 27 | ****************************************************************************/ 28 | 29 | function Component() 30 | { 31 | // constructor 32 | component.loaded.connect(this, Component.prototype.loaded); 33 | if (!installer.addWizardPage(component, "Page", QInstaller.TargetDirectory)) 34 | console.log("Could not add the dynamic page."); 35 | } 36 | 37 | Component.prototype.isDefault = function() 38 | { 39 | // select the component by default 40 | return true; 41 | } 42 | 43 | Component.prototype.createOperations = function() 44 | { 45 | try { 46 | // call the base create operations function 47 | component.createOperations(); 48 | } catch (e) { 49 | console.log(e); 50 | } 51 | } 52 | 53 | Component.prototype.loaded = function () 54 | { 55 | var page = gui.pageByObjectName("DynamicPage"); 56 | if (page != null) { 57 | console.log("Connecting the dynamic page entered signal."); 58 | page.entered.connect(Component.prototype.dynamicPageEntered); 59 | } 60 | } 61 | 62 | Component.prototype.dynamicPageEntered = function () 63 | { 64 | var pageWidget = gui.pageWidgetByObjectName("DynamicPage"); 65 | if (pageWidget != null) { 66 | console.log("Setting the widgets label text.") 67 | pageWidget.m_pageLabel.text = "This is a dynamically created page."; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /QtNodeEditor/include/nodes/internal/Node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "PortType.hpp" 10 | 11 | #include "Export.hpp" 12 | #include "NodeState.hpp" 13 | #include "NodeGeometry.hpp" 14 | #include "NodeData.hpp" 15 | #include "NodeGraphicsObject.hpp" 16 | #include "ConnectionGraphicsObject.hpp" 17 | #include "Serializable.hpp" 18 | #include "memory.hpp" 19 | 20 | namespace QtNodes 21 | { 22 | 23 | class Connection; 24 | class ConnectionState; 25 | class NodeGraphicsObject; 26 | class NodeDataModel; 27 | 28 | class NODE_EDITOR_PUBLIC Node 29 | : public QObject 30 | , public Serializable 31 | { 32 | Q_OBJECT 33 | 34 | public: 35 | 36 | /// NodeDataModel should be an rvalue and is moved into the Node 37 | Node(std::unique_ptr && dataModel); 38 | 39 | virtual 40 | ~Node(); 41 | 42 | public: 43 | 44 | QJsonObject 45 | save() const override; 46 | 47 | void 48 | restore(QJsonObject const &json) override; 49 | 50 | public: 51 | 52 | QUuid 53 | id() const; 54 | 55 | void reactToPossibleConnection(PortType, 56 | NodeDataType const &, 57 | QPointF const & scenePoint); 58 | 59 | void 60 | resetReactionToConnection(); 61 | 62 | public: 63 | 64 | NodeGraphicsObject const & 65 | nodeGraphicsObject() const; 66 | 67 | NodeGraphicsObject & 68 | nodeGraphicsObject(); 69 | 70 | void 71 | setGraphicsObject(std::unique_ptr&& graphics); 72 | 73 | NodeGeometry& 74 | nodeGeometry(); 75 | 76 | NodeGeometry const& 77 | nodeGeometry() const; 78 | 79 | NodeState const & 80 | nodeState() const; 81 | 82 | NodeState & 83 | nodeState(); 84 | 85 | NodeDataModel* 86 | nodeDataModel() const; 87 | 88 | public slots: // data propagation 89 | 90 | /// Propagates incoming data to the underlying model. 91 | void 92 | propagateData(std::shared_ptr nodeData, 93 | PortIndex inPortIndex) const; 94 | 95 | /// Fetches data from model's OUT #index port 96 | /// and propagates it to the connection 97 | void 98 | onDataUpdated(PortIndex index); 99 | 100 | /// update the graphic part if the size of the embeddedwidget changes 101 | void 102 | onNodeSizeUpdated(); 103 | 104 | private: 105 | 106 | // addressing 107 | 108 | QUuid _uid; 109 | 110 | // data 111 | 112 | std::unique_ptr _nodeDataModel; 113 | 114 | NodeState _nodeState; 115 | 116 | // painting 117 | 118 | NodeGeometry _nodeGeometry; 119 | 120 | std::unique_ptr _nodeGraphicsObject; 121 | }; 122 | } 123 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/target_radar.svg: -------------------------------------------------------------------------------- 1 | Created by Eucalypfrom the Noun Project -------------------------------------------------------------------------------- /bt_editor/resources/svg/lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 53 | 56 | 60 | 61 | 66 | 67 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/maze_path.svg: -------------------------------------------------------------------------------- 1 | Created by Chameleon Designfrom the Noun Project -------------------------------------------------------------------------------- /bt_editor/resources/svg/letter_i.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 41 | 43 | 44 | 46 | image/svg+xml 47 | 49 | 50 | 51 | 52 | 53 | 58 | I 70 | 71 | 72 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/letter_o.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 41 | 43 | 44 | 46 | image/svg+xml 47 | 49 | 50 | 51 | 52 | 53 | 58 | O 70 | 71 | 72 | -------------------------------------------------------------------------------- /QtNodeEditor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | # version 3.4 is required as other do not work with C++14 and clang 3 | 4 | project(QtNodeEditor CXX) 5 | 6 | set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) 7 | set(CMAKE_DISABLE_SOURCE_CHANGES ON) 8 | 9 | 10 | # Find the QtWidgets library 11 | find_package(Qt5 COMPONENTS 12 | Core 13 | Widgets 14 | Xml 15 | Gui 16 | Svg) 17 | 18 | qt5_add_resources(RESOURCES ./resources/resources.qrc) 19 | 20 | # Unfortunately, as we have a split include/src, AUTOMOC doesn't work. 21 | # We'll have to manually specify some files 22 | set(CMAKE_AUTOMOC ON) 23 | 24 | set(CPP_SOURCE_FILES 25 | src/Connection.cpp 26 | src/ConnectionBlurEffect.cpp 27 | src/ConnectionGeometry.cpp 28 | src/ConnectionGraphicsObject.cpp 29 | src/ConnectionPainter.cpp 30 | src/ConnectionState.cpp 31 | src/ConnectionStyle.cpp 32 | src/DataModelRegistry.cpp 33 | src/FlowScene.cpp 34 | src/FlowView.cpp 35 | src/FlowViewStyle.cpp 36 | src/Node.cpp 37 | src/NodeConnectionInteraction.cpp 38 | src/NodeDataModel.cpp 39 | src/NodeGeometry.cpp 40 | src/NodeGraphicsObject.cpp 41 | src/NodePainter.cpp 42 | src/NodeState.cpp 43 | src/NodeStyle.cpp 44 | src/Properties.cpp 45 | src/StyleCollection.cpp 46 | ) 47 | 48 | add_library(QtNodeEditor STATIC 49 | ${CPP_SOURCE_FILES} 50 | ${RESOURCES} 51 | ) 52 | 53 | target_include_directories(QtNodeEditor 54 | PUBLIC 55 | $ 56 | $ 57 | PRIVATE 58 | $ 59 | $ 60 | ) 61 | 62 | target_link_libraries(QtNodeEditor 63 | PUBLIC 64 | Qt5::Core 65 | Qt5::Widgets 66 | Qt5::Gui 67 | Qt5::Svg 68 | Qt5::Xml 69 | ) 70 | 71 | target_compile_definitions(QtNodeEditor 72 | PUBLIC 73 | ${Qt5Widgets_DEFINITIONS} 74 | PRIVATE 75 | NODE_EDITOR_EXPORTS 76 | #NODE_DEBUG_DRAWING 77 | ) 78 | 79 | target_compile_options(QtNodeEditor 80 | PRIVATE 81 | $<$:/W4 /wd4127 /EHsc> 82 | $<$:-Wall -Wextra -std=c++11> 83 | $<$:-Wall -Wextra -std=c++11> 84 | ) 85 | 86 | set_target_properties(QtNodeEditor 87 | PROPERTIES 88 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib 89 | LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib 90 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin 91 | ) 92 | 93 | ###### 94 | # Moc 95 | ## 96 | 97 | file(GLOB_RECURSE HEADERS_TO_MOC include/nodes/internal/*.hpp) 98 | 99 | qt5_wrap_cpp(nodes_moc 100 | ${HEADERS_TO_MOC} 101 | TARGET QtNodeEditor 102 | OPTIONS --no-notes # Don't display a note for the headers which don't produce a moc_*.cpp 103 | ) 104 | 105 | target_sources(QtNodeEditor PRIVATE ${nodes_moc}) 106 | 107 | 108 | -------------------------------------------------------------------------------- /test/groot_test_base.cpp: -------------------------------------------------------------------------------- 1 | #include "groot_test_base.h" 2 | #include 3 | #include 4 | 5 | QByteArray GrootTestBase::readFile(const char *name) 6 | { 7 | QString fileName(name); 8 | QFile file(fileName); 9 | bool ret = file.open(QIODevice::ReadOnly); 10 | QByteArray data = file.readAll(); 11 | file.close(); 12 | if( !ret ){ 13 | QTest::qFail("can't load file", __FILE__, __LINE__); 14 | } 15 | return data; 16 | } 17 | 18 | void GrootTestBase::sleepAndRefresh(int ms) 19 | { 20 | QApplication::processEvents(); 21 | QTest::qSleep ( ms ); 22 | QApplication::processEvents(); 23 | } 24 | 25 | void GrootTestBase::testMouseEvent(QGraphicsView *view, QEvent::Type type, QPoint pos, Qt::MouseButton button, 26 | Qt::KeyboardModifier modifier) 27 | { 28 | auto event = new QMouseEvent(type, pos, view->viewport()->mapToGlobal(pos), 29 | button, button, modifier); 30 | 31 | QApplication::postEvent(view->viewport(), event); 32 | QApplication::processEvents(); 33 | } 34 | 35 | void GrootTestBase::testDragObject(QGraphicsView *view, const QPoint &screen_pos, const QPoint &pos_offset) 36 | { 37 | testMouseEvent(view, QEvent::MouseButtonPress, screen_pos , Qt::LeftButton); 38 | testMouseEvent(view, QEvent::MouseMove, screen_pos + pos_offset, Qt::LeftButton); 39 | testMouseEvent(view, QEvent::MouseButtonRelease, screen_pos + pos_offset, Qt::LeftButton); 40 | } 41 | 42 | AbsBehaviorTree GrootTestBase::getAbstractTree(const QString &name) 43 | { 44 | if(name.isEmpty() ) 45 | return BuildTreeFromScene( main_win->currentTabInfo()->scene() ); 46 | else 47 | return BuildTreeFromScene( main_win->getTabByName(name)->scene() ); 48 | } 49 | 50 | void GrootTestBase::testMessageBox(int deplay_ms, TestLocation location, 51 | std::function callable_action, 52 | QMessageBox::StandardButton button_to_press) 53 | { 54 | QMutex semaphore; 55 | semaphore.lock(); 56 | 57 | QTimer::singleShot(deplay_ms, [&]() 58 | { 59 | QWidget* widget = QApplication::activeModalWidget(); 60 | if (!widget){ 61 | QTest::qFail("no modal widget", location.file, location.line); 62 | } 63 | auto message_box = dynamic_cast(widget); 64 | if (!message_box){ 65 | QTest::qFail("no QMessageBox", location.file, location.line); 66 | } 67 | if( button_to_press == QMessageBox::Default || button_to_press == QMessageBox::NoButton) 68 | { 69 | QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); 70 | QCoreApplication::postEvent(widget, event); 71 | } 72 | else{ 73 | emit message_box->button(button_to_press)->clicked(); 74 | } 75 | semaphore.unlock(); 76 | }); 77 | callable_action(); 78 | semaphore.tryLock( deplay_ms * 2 ); 79 | semaphore.unlock(); 80 | } 81 | -------------------------------------------------------------------------------- /QtNodeEditor/src/FlowViewStyle.cpp: -------------------------------------------------------------------------------- 1 | #include "FlowViewStyle.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "StyleCollection.hpp" 12 | 13 | using QtNodes::FlowViewStyle; 14 | 15 | inline void initResources() { Q_INIT_RESOURCE(resources); } 16 | 17 | FlowViewStyle:: 18 | FlowViewStyle() 19 | { 20 | // Explicit resources inialization for preventing the static initialization 21 | // order fiasco: https://isocpp.org/wiki/faq/ctors#static-init-order 22 | initResources(); 23 | 24 | // This configuration is stored inside the compiled unit and is loaded statically 25 | loadJsonFile(":DefaultStyle.json"); 26 | } 27 | 28 | 29 | FlowViewStyle:: 30 | FlowViewStyle(QString jsonText) 31 | { 32 | loadJsonText(jsonText); 33 | } 34 | 35 | 36 | void 37 | FlowViewStyle:: 38 | setStyle(QString jsonText) 39 | { 40 | FlowViewStyle style(jsonText); 41 | 42 | StyleCollection::setFlowViewStyle(style); 43 | } 44 | 45 | 46 | #ifdef STYLE_DEBUG 47 | #define FLOW_VIEW_STYLE_CHECK_UNDEFINED_VALUE(v, variable) { \ 48 | if (v.type() == QJsonValue::Undefined || \ 49 | v.type() == QJsonValue::Null) \ 50 | qWarning() << "Undefined value for parameter:" << #variable; \ 51 | } 52 | #else 53 | #define FLOW_VIEW_STYLE_CHECK_UNDEFINED_VALUE(v, variable) 54 | #endif 55 | 56 | #define FLOW_VIEW_STYLE_READ_COLOR(values, variable) { \ 57 | auto valueRef = values[#variable]; \ 58 | FLOW_VIEW_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ 59 | if (valueRef.isArray()) { \ 60 | auto colorArray = valueRef.toArray(); \ 61 | std::vector rgb; rgb.reserve(3); \ 62 | for (auto it = colorArray.begin(); it != colorArray.end(); ++it) { \ 63 | rgb.push_back((*it).toInt()); \ 64 | } \ 65 | variable = QColor(rgb[0], rgb[1], rgb[2]); \ 66 | } else { \ 67 | variable = QColor(valueRef.toString()); \ 68 | } \ 69 | } 70 | 71 | void 72 | FlowViewStyle:: 73 | loadJsonFile(QString styleFile) 74 | { 75 | QFile file(styleFile); 76 | 77 | if (!file.open(QIODevice::ReadOnly)) 78 | { 79 | qWarning() << "Couldn't open file " << styleFile; 80 | 81 | return; 82 | } 83 | 84 | loadJsonFromByteArray(file.readAll()); 85 | } 86 | 87 | 88 | void 89 | FlowViewStyle:: 90 | loadJsonText(QString jsonText) 91 | { 92 | loadJsonFromByteArray(jsonText.toUtf8()); 93 | } 94 | 95 | 96 | void 97 | FlowViewStyle:: 98 | loadJsonFromByteArray(QByteArray const &byteArray) 99 | { 100 | QJsonDocument json(QJsonDocument::fromJson(byteArray)); 101 | 102 | QJsonObject topLevelObject = json.object(); 103 | 104 | QJsonValueRef nodeStyleValues = topLevelObject["FlowViewStyle"]; 105 | 106 | QJsonObject obj = nodeStyleValues.toObject(); 107 | 108 | FLOW_VIEW_STYLE_READ_COLOR(obj, BackgroundColor); 109 | FLOW_VIEW_STYLE_READ_COLOR(obj, FineGridColor); 110 | FLOW_VIEW_STYLE_READ_COLOR(obj, CoarseGridColor); 111 | } 112 | -------------------------------------------------------------------------------- /QtNodeEditor/src/NodeState.cpp: -------------------------------------------------------------------------------- 1 | #include "NodeState.hpp" 2 | 3 | #include "NodeDataModel.hpp" 4 | 5 | #include "Connection.hpp" 6 | 7 | using QtNodes::NodeState; 8 | using QtNodes::NodeDataType; 9 | using QtNodes::NodeDataModel; 10 | using QtNodes::PortType; 11 | using QtNodes::PortIndex; 12 | using QtNodes::Connection; 13 | 14 | NodeState:: 15 | NodeState(std::unique_ptr const &model) 16 | : _inConnections(model->nPorts(PortType::In)) 17 | , _outConnections(model->nPorts(PortType::Out)) 18 | , _reaction(NOT_REACTING) 19 | , _reactingPortType(PortType::None) 20 | , _resizing(false) 21 | {} 22 | 23 | 24 | std::vector const & 25 | NodeState:: 26 | getEntries(PortType portType) const 27 | { 28 | if (portType == PortType::In) 29 | return _inConnections; 30 | else 31 | return _outConnections; 32 | } 33 | 34 | 35 | std::vector & 36 | NodeState:: 37 | getEntries(PortType portType) 38 | { 39 | if (portType == PortType::In) 40 | return _inConnections; 41 | else 42 | return _outConnections; 43 | } 44 | 45 | 46 | NodeState::ConnectionPtrSet 47 | NodeState:: 48 | connections(PortType portType, PortIndex portIndex) const 49 | { 50 | auto const &connections = getEntries(portType); 51 | if( portIndex < 0 || static_cast(portIndex) >= connections.size() ) 52 | { 53 | return NodeState::ConnectionPtrSet(); 54 | } 55 | return connections[portIndex]; 56 | } 57 | 58 | 59 | void 60 | NodeState:: 61 | setConnection(PortType portType, 62 | PortIndex portIndex, 63 | Connection& connection) 64 | { 65 | auto &connections = getEntries(portType); 66 | 67 | connections.at(portIndex).insert(std::make_pair(connection.id(), 68 | &connection)); 69 | } 70 | 71 | 72 | void 73 | NodeState:: 74 | eraseConnection(PortType portType, 75 | PortIndex portIndex, 76 | QUuid id) 77 | { 78 | getEntries(portType)[portIndex].erase(id); 79 | } 80 | 81 | 82 | NodeState::ReactToConnectionState 83 | NodeState:: 84 | reaction() const 85 | { 86 | return _reaction; 87 | } 88 | 89 | 90 | PortType 91 | NodeState:: 92 | reactingPortType() const 93 | { 94 | return _reactingPortType; 95 | } 96 | 97 | 98 | NodeDataType 99 | NodeState:: 100 | reactingDataType() const 101 | { 102 | return _reactingDataType; 103 | } 104 | 105 | 106 | void 107 | NodeState:: 108 | setReaction(ReactToConnectionState reaction, 109 | PortType reactingPortType, 110 | NodeDataType reactingDataType) 111 | { 112 | _reaction = reaction; 113 | 114 | _reactingPortType = reactingPortType; 115 | 116 | _reactingDataType = std::move(reactingDataType); 117 | } 118 | 119 | 120 | bool 121 | NodeState:: 122 | isReacting() const 123 | { 124 | return _reaction == REACTING; 125 | } 126 | 127 | 128 | void 129 | NodeState:: 130 | setResizing(bool resizing) 131 | { 132 | _resizing = resizing; 133 | } 134 | 135 | 136 | bool 137 | NodeState:: 138 | resizing() const 139 | { 140 | return _resizing; 141 | } 142 | -------------------------------------------------------------------------------- /QtNodeEditor/README.md: -------------------------------------------------------------------------------- 1 | ### Purpose 2 | 3 | **NodeEditor** is conceived as a general-purpose Qt-based library aimed at graph-controlled data processing. Nodes 4 | represent algorithms with certain inputs and outputs. Connections transfer data from the output (source) of the first 5 | node to the input (sink) of the second one. 6 | 7 | **NodeEditor** framework is a Visual [Dataflow Programming](https://en.wikipedia.org/wiki/Dataflow_programming) tool. 8 | A library client defines models and registers them in the data model registry. 9 | Further work is driven by events taking place in DataModels and Nodes. 10 | The model computing is triggered upon arriving of any new input data. The computed result is propagated to the output 11 | connections. Each new connection fetches available data and propagates is further. 12 | 13 | Each change in the source node is immediately propagated through all the connections updating the whole graph. 14 | 15 | ### Platforms 16 | 17 | * OSX (Apple Clang - LLVM 3.6), Linux (x64, gcc-5.0, clang-3.8): [![Build Status](https://travis-ci.org/paceholder/nodeeditor.svg?branch=master)](https://travis-ci.org/paceholder/nodeeditor) 18 | * Windows (Win32, x64, msvc2015, MinGW 5.3): [![Build status](https://ci.appveyor.com/api/projects/status/wxp47wv3uyyiujjw/branch/master?svg=true)](https://ci.appveyor.com/project/paceholder/nodeeditor/branch/master) 19 | 20 | 21 | ### Dependencies 22 | 23 | * Qt >5.2 24 | * CMake 3.2 25 | 26 | ### Current state 27 | 28 | * Model-based nodes 29 | * Automatic data propagation 30 | * Datatype-aware connections 31 | * Embedded Qt widgets 32 | * One-output to many-input connections 33 | * JSON-based interface styles 34 | * Saving scenes to JSON files 35 | 36 | ### Roadmap 37 | 38 | 1. Extend set of examples 39 | 2. GUI: fix scrolling for scene view window scrolling 40 | 3. Implement grouping nodes 41 | 4. Split graph and GUI parts 42 | 5. Build data propagation on top of the graph code 43 | 44 | ### Citing 45 | 46 | Dmitry Pinaev et al, Qt5 Node Editor, (2017), GitHub repository, https://github.com/paceholder/nodeeditor 47 | 48 | BibTeX 49 | 50 | @misc{Pinaev2017, 51 | author = {Dmitry Pinaev et al}, 52 | title = {Qt5 Node Editor}, 53 | year = {2017}, 54 | publisher = {GitHub}, 55 | journal = {GitHub repository}, 56 | howpublished = {\url{https://github.com/paceholder/nodeeditor}}, 57 | commit = {e89ff3ffbdd8c6245c4c1f7e9f73276bf15c3e88} 58 | } 59 | 60 | 61 | ### Youtube video: 62 | 63 | [![Youtube demonstration](https://bitbucket.org/paceholder/nodeeditor/raw/master/pictures/vid1.png)](https://www.youtube.com/watch?v=pxMXjSvlOFw) 64 | 65 | ### Now with styles 66 | 67 | 68 | [![Styles](https://bitbucket.org/paceholder/nodeeditor/raw/master/pictures/style_example.png)](https://www.youtube.com/watch?v=i_pB-Y0hCYQ) 69 | 70 | 71 | ### Buy me a beer 72 | 73 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/DmitryPinaev) 74 | 75 | ### Showcase 76 | 77 | #### [Chigraph](https://github.com/chigraph/chigraph) 78 | 79 | Chigraph is a programming language for beginners that is unique in that it is an intuitive flow graph: 80 | 81 | ![chigraph screenshot](pictures/chigraph.png) 82 | 83 | It features easy bindings to C/C++, package management, and a cool interface. 84 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/letter_A.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 25 | 29 | 33 | 34 | 43 | 44 | 63 | 65 | 66 | 68 | image/svg+xml 69 | 71 | 72 | 73 | 74 | 75 | 80 | A: 91 | 92 | 93 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/manipulator.svg: -------------------------------------------------------------------------------- 1 | Created by H Alberto Gongorafrom the Noun Project -------------------------------------------------------------------------------- /bt_editor/graphic_container.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAPHIC_CONTAINER_H 2 | #define GRAPHIC_CONTAINER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "bt_editor_base.h" 9 | #include "editor_flowscene.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class GraphicContainer : public QObject 18 | { 19 | Q_OBJECT 20 | public: 21 | explicit GraphicContainer(std::shared_ptr registry, 22 | QWidget *parent = nullptr); 23 | 24 | EditorFlowScene* scene() { return _scene; } 25 | QtNodes::FlowView* view() { return _view; } 26 | 27 | const EditorFlowScene* scene() const{ return _scene; } 28 | const QtNodes::FlowView* view() const { return _view; } 29 | 30 | void lockEditing(bool locked); 31 | 32 | void lockSubtreeEditing(QtNodes::Node& node, bool locked, bool change_style); 33 | 34 | void nodeReorder(); 35 | 36 | void saveSvgFile(const QString path); 37 | 38 | void zoomHomeView(); 39 | 40 | bool containsValidTree() const; 41 | 42 | void clearScene(); 43 | 44 | AbsBehaviorTree loadedTree() const; 45 | 46 | void loadSceneFromTree(const AbsBehaviorTree &tree); 47 | 48 | void appendTreeToNode(QtNodes::Node& node, AbsBehaviorTree &subtree); 49 | 50 | void loadFromJson(const QByteArray& data); 51 | 52 | QtNodes::Node* substituteNode(QtNodes::Node* old_node, const QString& new_node_ID); 53 | 54 | void deleteSubTreeRecursively(QtNodes::Node& node); 55 | 56 | std::set getSubtreeNodesRecursively(QtNodes::Node &root_node); 57 | 58 | void createSubtree(QtNodes::Node& root_node, QString subtree_name = QString()); 59 | 60 | public slots: 61 | 62 | void onNodeDoubleClicked(QtNodes::Node& root_node); 63 | 64 | void onPortValueDoubleClicked(QLineEdit* edit_value); 65 | 66 | void onNodeCreated(QtNodes::Node &node); 67 | 68 | void onNodeContextMenu(QtNodes::Node& node, const QPointF& pos); 69 | 70 | void onConnectionContextMenu(QtNodes::Connection &connection, const QPointF&); 71 | 72 | void onSmartRemove(QtNodes::Node* node); 73 | 74 | signals: 75 | 76 | void addNewModel( const NodeModel &new_model ); 77 | 78 | void undoableChange(); 79 | 80 | void requestSubTreeExpand(GraphicContainer& container, 81 | QtNodes::Node& node); 82 | 83 | void requestSubTreeCreate(AbsBehaviorTree tree, QString name); 84 | 85 | private: 86 | EditorFlowScene* _scene; 87 | QtNodes::FlowView* _view; 88 | 89 | void createMorphSubMenu(QtNodes::Node &node, QMenu *nodeMenu); 90 | 91 | void createSmartRemoveAction(QtNodes::Node &node, QMenu *nodeMenu); 92 | 93 | void insertNodeInConnection(QtNodes::Connection &connection, QString node_name); 94 | 95 | void recursiveLoadStep(QPointF &cursor, AbsBehaviorTree &tree, 96 | AbstractTreeNode *abs_node, 97 | QtNodes::Node* parent_node, int nest_level); 98 | 99 | std::shared_ptr _model_registry; 100 | 101 | bool _signal_was_blocked; 102 | 103 | }; 104 | 105 | #endif // GRAPHIC_CONTAINER_H 106 | -------------------------------------------------------------------------------- /QtNodeEditor/src/ConnectionGeometry.cpp: -------------------------------------------------------------------------------- 1 | #include "ConnectionGeometry.hpp" 2 | 3 | #include 4 | 5 | #include "StyleCollection.hpp" 6 | 7 | using QtNodes::ConnectionGeometry; 8 | using QtNodes::PortType; 9 | using QtNodes::PortLayout; 10 | 11 | ConnectionGeometry:: 12 | ConnectionGeometry() 13 | : _in(0, 0) 14 | , _out(0, 0) 15 | //, _animationPhase(0) 16 | , _lineWidth(3.0) 17 | , _hovered(false) 18 | , _ports_layout( PortLayout::Horizontal ) 19 | { } 20 | 21 | QPointF const& 22 | ConnectionGeometry:: 23 | getEndPoint(PortType portType) const 24 | { 25 | Q_ASSERT(portType != PortType::None); 26 | 27 | return (portType == PortType::Out ? 28 | _out : 29 | _in); 30 | } 31 | 32 | 33 | void 34 | ConnectionGeometry:: 35 | setEndPoint(PortType portType, QPointF const& point) 36 | { 37 | switch (portType) 38 | { 39 | case PortType::Out: 40 | _out = point; 41 | break; 42 | 43 | case PortType::In: 44 | _in = point; 45 | break; 46 | 47 | default: 48 | break; 49 | } 50 | } 51 | 52 | 53 | void 54 | ConnectionGeometry:: 55 | moveEndPoint(PortType portType, QPointF const &offset) 56 | { 57 | switch (portType) 58 | { 59 | case PortType::Out: 60 | _out += offset; 61 | break; 62 | 63 | case PortType::In: 64 | _in += offset; 65 | break; 66 | 67 | default: 68 | break; 69 | } 70 | } 71 | 72 | 73 | QRectF 74 | ConnectionGeometry:: 75 | boundingRect() const 76 | { 77 | auto points = pointsC1C2(); 78 | 79 | QRectF basicRect = QRectF(_out, _in).normalized(); 80 | 81 | QRectF c1c2Rect = QRectF(points.first, points.second).normalized(); 82 | 83 | auto const &connectionStyle = 84 | StyleCollection::connectionStyle(); 85 | 86 | float const diam = connectionStyle.pointDiameter(); 87 | 88 | QRectF commonRect = basicRect.united(c1c2Rect); 89 | 90 | QPointF const cornerOffset(diam, diam); 91 | 92 | commonRect.setTopLeft(commonRect.topLeft() - cornerOffset); 93 | commonRect.setBottomRight(commonRect.bottomRight() + 2 * cornerOffset); 94 | 95 | return commonRect; 96 | } 97 | 98 | 99 | std::pair 100 | ConnectionGeometry:: 101 | pointsC1C2() const 102 | { 103 | double distance = ( _ports_layout == PortLayout::Horizontal ) ? 104 | (_in.x() - _out.x()) : 105 | (_in.y() - _out.y()); 106 | 107 | double defaultOffset = 50; 108 | 109 | double minimum = qMin(defaultOffset, std::abs(distance)); 110 | double offset = 0; 111 | double ratio1 = 0.5; 112 | 113 | if (distance <= 0) 114 | { 115 | offset = -minimum; 116 | ratio1 = 1.0; 117 | } 118 | 119 | QPointF c1,c2; 120 | if( _ports_layout == PortLayout::Horizontal ) 121 | { 122 | c1 = QPointF(_out.x() + minimum * ratio1, 123 | _out.y() + offset); 124 | 125 | c2 = QPointF(_in.x() - minimum * ratio1, 126 | _in.y() + offset); 127 | } 128 | else 129 | { 130 | c1 = QPointF(_out.x() + offset, 131 | _out.y() + minimum * ratio1); 132 | 133 | c2 = QPointF(_in.x() + offset, 134 | _in.y() - minimum * ratio1); 135 | } 136 | return std::make_pair(c1, c2); 137 | } 138 | 139 | void ConnectionGeometry::setPortLayout(QtNodes::PortLayout layout) 140 | { 141 | _ports_layout = layout; 142 | } 143 | -------------------------------------------------------------------------------- /bt_editor/sidepanel_monitor.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SidepanelMonitor 4 | 5 | 6 | 7 | 0 8 | 0 9 | 271 10 | 516 11 | 12 | 13 | 14 | Frame 15 | 16 | 17 | 18 | 4 19 | 20 | 21 | 4 22 | 23 | 24 | 4 25 | 26 | 27 | 4 28 | 29 | 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | Server IP: 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 16777215 46 | 16777215 47 | 48 | 49 | 50 | 51 | 52 | 53 | localhost 54 | 55 | 56 | true 57 | 58 | 59 | 60 | 61 | 62 | 63 | Publisher Port: 64 | 65 | 66 | 67 | 68 | 69 | 70 | 1666 71 | 72 | 73 | true 74 | 75 | 76 | 77 | 78 | 79 | 80 | Server Port: 81 | 82 | 83 | 84 | 85 | 86 | 87 | 1667 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | Messages Received: 0 97 | 98 | 99 | 100 | 101 | 102 | 103 | Qt::Vertical 104 | 105 | 106 | 107 | 20 108 | 474 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /bt_editor/models/BehaviorTreeNodeModel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "bt_editor/bt_editor_base.h" 17 | #include "bt_editor/utils.h" 18 | 19 | using QtNodes::PortType; 20 | using QtNodes::PortIndex; 21 | using QtNodes::NodeData; 22 | using QtNodes::NodeDataType; 23 | using QtNodes::NodeDataModel; 24 | 25 | class BehaviorTreeDataModel : public NodeDataModel 26 | { 27 | Q_OBJECT 28 | 29 | public: 30 | BehaviorTreeDataModel(const NodeModel &model ); 31 | 32 | ~BehaviorTreeDataModel() override; 33 | 34 | public: 35 | 36 | NodeType nodeType() const; 37 | 38 | virtual void setInstanceName(const QString& name); 39 | 40 | public: 41 | 42 | void initWidget(); 43 | 44 | virtual unsigned int nPorts(PortType portType) const override; 45 | 46 | ConnectionPolicy portOutConnectionPolicy(PortIndex) const final; 47 | 48 | NodeDataType dataType(PortType , PortIndex ) const final; 49 | 50 | std::shared_ptr outData(PortIndex port) final; 51 | 52 | void setInData(std::shared_ptr, int) final {} 53 | 54 | const QString ®istrationName() const; 55 | 56 | const NodeModel &model() const { return _model; } 57 | 58 | QString name() const final { return registrationName(); } 59 | 60 | const QString& instanceName() const; 61 | 62 | PortsMapping getCurrentPortMapping() const; 63 | 64 | QWidget *embeddedWidget() final { return _main_widget; } 65 | 66 | QWidget *parametersWidget() { return _params_widget; } 67 | 68 | QJsonObject save() const override; 69 | 70 | void restore(QJsonObject const &) override; 71 | 72 | void lock(bool locked); 73 | 74 | void setPortMapping(const QString& port_name, const QString& value); 75 | 76 | int UID() const { return _uid; } 77 | 78 | bool eventFilter(QObject *obj, QEvent *event) override; 79 | 80 | 81 | public slots: 82 | 83 | void updateNodeSize(); 84 | 85 | void onHighlightPortValue(QString value); 86 | 87 | protected: 88 | 89 | QFrame* _main_widget; 90 | QFrame* _params_widget; 91 | 92 | QLineEdit* _line_edit_name; 93 | 94 | std::map _ports_widgets; 95 | int16_t _uid; 96 | 97 | QFormLayout* _form_layout; 98 | QVBoxLayout* _main_layout; 99 | QLabel* _caption_label; 100 | QFrame* _caption_logo_left; 101 | QFrame* _caption_logo_right; 102 | 103 | private: 104 | const NodeModel _model; 105 | QString _instance_name; 106 | QSvgRenderer* _icon_renderer; 107 | 108 | void readStyle(); 109 | QString _style_icon; 110 | QColor _style_caption_color; 111 | QString _style_caption_alias; 112 | 113 | signals: 114 | 115 | void parameterUpdated(QString, QWidget*); 116 | 117 | void instanceNameChanged(); 118 | 119 | void portValueDoubleChicked(QLineEdit* value_port); 120 | 121 | }; 122 | 123 | 124 | class GrootLineEdit: public QLineEdit 125 | { 126 | Q_OBJECT 127 | public: 128 | GrootLineEdit(QWidget* parent = nullptr): QLineEdit(parent) {} 129 | 130 | void mouseDoubleClickEvent(QMouseEvent *ev) override; 131 | void focusOutEvent(QFocusEvent* ev) override; 132 | signals: 133 | void doubleClicked(); 134 | void lostFocus(); 135 | }; 136 | 137 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/asterix.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 25 | 29 | 33 | 34 | 43 | 44 | 63 | 65 | 66 | 68 | image/svg+xml 69 | 71 | 72 | 73 | 74 | 75 | 80 | * 92 | 93 | 94 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/goto_map.svg: -------------------------------------------------------------------------------- 1 | Created by AFY Studiofrom the Noun Project -------------------------------------------------------------------------------- /bt_editor/resources/svg/settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 52 | 56 | 61 | 62 | -------------------------------------------------------------------------------- /bt_editor/resources/svg/not_equal.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /bt_editor/resources/svg/question_mark.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /bt_editor/resources/svg/robot.svg: -------------------------------------------------------------------------------- 1 | Created by Oksana Latyshevafrom the Noun Project -------------------------------------------------------------------------------- /test_data/test_xml_key_reordering_issue.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | --------------------------------------------------------------------------------