diff --git a/libs/bt/include/psemek/bt/conditional.hpp b/libs/bt/include/psemek/bt/conditional.hpp new file mode 100644 index 00000000..fa2b8b8b --- /dev/null +++ b/libs/bt/include/psemek/bt/conditional.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include +#include + +#include + +namespace psemek::bt +{ + + template + struct conditional_node; + + template + struct conditional_node> + : node> + { + using tree_type = tree; + using node_type = node; + using typename node_type::running; + using typename node_type::finished; + using typename node_type::status; + + conditional_node(node_ptr condition, node_ptr true_branch, node_ptr false_branch) + : condition_(std::move(condition)) + , true_branch_(std::move(true_branch)) + , false_branch_(std::move(false_branch)) + {} + + void start(Args ... args) override + { + condition_result_ = std::nullopt; + condition_->start(args...); + } + + status update(Time dt, Args ... args) override + { + if (condition_result_) + { + if (*condition_result_) + return true_branch_->update(dt, args...); + else + return false_branch_->update(dt, args...); + } + else + { + auto result = condition_->update(dt, args...); + + if (auto finished = std::get_if(&result)) + { + condition_result_ = finished->result; + return running{}; + } + + return result; + } + } + + bool event(Event const & event, Args ... args) override + { + if (condition_result_) + { + if (*condition_result_) + return true_branch_->event(event, args...); + else + return false_branch_->event(event, args...); + } + else + return condition_->event(event, args...); + } + + private: + node_ptr condition_; + node_ptr true_branch_; + node_ptr false_branch_; + std::optional condition_result_; + }; + + template + node_ptr conditional(node_ptr condition, node_ptr true_branch, node_ptr false_branch) + { + return std::make_unique>(std::move(condition), std::move(true_branch), std::move(false_branch)); + } + +}