diff --git a/libs/util/include/psemek/util/behavior_tree.hpp b/libs/util/include/psemek/util/behavior_tree.hpp index ac3d9ff4..cf4b5ccd 100644 --- a/libs/util/include/psemek/util/behavior_tree.hpp +++ b/libs/util/include/psemek/util/behavior_tree.hpp @@ -183,6 +183,30 @@ namespace psemek::util } }; + template + struct action + { + ActionFn actionFn; + + action(ActionFn actionFn) + : actionFn(std::move(actionFn)) + {} + + void start(Args ...) + {} + + status update(Time, Args ... args) + { + actionFn(args...); + return finished{true}; + } + + bool event(Event const &) + { + return false; + } + }; + template struct wait { @@ -225,7 +249,7 @@ namespace psemek::util void start(Args ...) {} - status update(Time dt, Args ... args) + status update(Time, Args ... args) { return finished{condFn(args...)}; } @@ -454,6 +478,99 @@ namespace psemek::util } } }; + + template + struct selector + { + std::tuple children; + bool current_started = false; + size_t current = 0; + + selector(Children ... children) + : children{std::move(children)...} + {} + + void start(Args ...) + { + if constexpr (sizeof...(Children) == 0) + { + current = 1; + } + else + { + current = 0; + current_started = false; + } + } + + status update(Time dt, Args ... args) + { + return update_impl<0>(dt, args...); + } + + bool event(Event const & e) + { + return event_impl<0>(e); + } + + private: + template + status update_impl(Time dt, Args ... args) + { + if constexpr (I == sizeof...(Children)) + { + return finished{false}; + } + else + { + if (current != I) + { + return update_impl(dt, args...); + } + else + { + if (!current_started) + { + std::get(children).start(args...); + current_started = true; + } + auto result = std::get(children).update(dt, args...); + if (auto f = std::get_if(&result)) + { + if (!(f->result)) + { + current_started = false; + ++current; + return update_impl(dt, args...); + } + else + return finished{true}; + } + return result; + } + } + } + + template + bool event_impl(Event const & e) + { + if constexpr (I == sizeof...(Children)) + { + return false; + } + else + { + if (current == I) + { + return std::get(children).event(e); + } + else + { + return event_impl(e); + } + } + } + }; }; }