Behavior trees: implement events in updater & include node arguments in event handler

This commit is contained in:
Nikita Lisitsa 2021-10-23 10:29:30 +03:00
parent 73bf540967
commit 9641703375

View file

@ -4,6 +4,7 @@
#include <tuple> #include <tuple>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <optional>
namespace psemek::util namespace psemek::util
{ {
@ -30,7 +31,7 @@ namespace psemek::util
{ {
virtual void start(Args ...) = 0; virtual void start(Args ...) = 0;
virtual status update(Time, Args ...) = 0; virtual status update(Time, Args ...) = 0;
virtual bool event(Event const &) = 0; virtual bool event(Event const &, Args ...) = 0;
virtual ~any_node_base() {} virtual ~any_node_base() {}
}; };
@ -55,9 +56,9 @@ namespace psemek::util
return node.update(dt, args...); return node.update(dt, args...);
} }
bool event(Event const & e) override bool event(Event const & e, Args ... args) override
{ {
return node.event(e); return node.event(e, args...);
} }
}; };
@ -78,9 +79,9 @@ namespace psemek::util
return impl_->update(dt, args...); return impl_->update(dt, args...);
} }
bool event(Event const & e) bool event(Event const & e, Args ... args)
{ {
return impl_->event(e); return impl_->event(e, args...);
} }
private: private:
@ -103,6 +104,27 @@ namespace psemek::util
new_.push_back(node_data{std::move(node), {args...}, 0, 0}); new_.push_back(node_data{std::move(node), {args...}, 0, 0});
} }
template <typename Filter>
void event(Event const & e, Filter && filter)
{
for (node_data & n : active_)
{
if (std::apply(filter, n.args))
std::apply([&](Args ... args){ n.node.event(e, args...); }, n.args);
}
for (node_data & n : suspended_)
{
if (std::apply(filter, n.args))
{
if (std::apply([&](Args ... args){ return n.node.event(e, args...); }, n.args))
{
n.duration = n.elapsed;
}
}
}
}
struct update_statistics struct update_statistics
{ {
int active_count = 0; int active_count = 0;
@ -202,7 +224,7 @@ namespace psemek::util
return finished{true}; return finished{true};
} }
bool event(Event const &) bool event(Event const &, Args ...)
{ {
return false; return false;
} }
@ -232,7 +254,7 @@ namespace psemek::util
return suspended{remaining_time}; return suspended{remaining_time};
} }
bool event(Event const &) bool event(Event const &, Args ...)
{ {
return false; return false;
} }
@ -255,12 +277,49 @@ namespace psemek::util
return finished{condFn(args...)}; return finished{condFn(args...)};
} }
bool event(Event const &) bool event(Event const &, Args ...)
{ {
return false; return false;
} }
}; };
template <typename EventFn, typename Child>
struct on_event
{
EventFn eventFn;
Child child;
std::optional<status> cached_status;
on_event(EventFn eventFn, Child child)
: eventFn(std::move(eventFn))
, child(std::move(child))
{}
void start(Args ... args)
{
child.start(args...);
}
status update(Time dt, Args ... args)
{
if (cached_status)
{
auto result = *cached_status;
cached_status = std::nullopt;
return result;
}
return child.update(dt, std::forward<Args>(args)...);
}
bool event(Event const & e, Args ... args)
{
cached_status = eventFn(e, args...);
return static_cast<bool>(cached_status);
}
};
template <typename Child> template <typename Child>
struct success struct success
{ {
@ -283,9 +342,9 @@ namespace psemek::util
return child_status; return child_status;
} }
bool event(Event const & e) bool event(Event const & e, Args ... args)
{ {
return child.event(e); return child.event(e, args...);
} }
}; };
@ -311,9 +370,9 @@ namespace psemek::util
return child_status; return child_status;
} }
bool event(Event const & e) bool event(Event const & e, Args ... args)
{ {
return child.event(e); return child.event(e, args...);
} }
}; };
@ -347,9 +406,9 @@ namespace psemek::util
return result; return result;
} }
bool event(Event const & e) bool event(Event const & e, Args ... args)
{ {
return child.event(e); return child.event(e, args...);
} }
}; };
@ -383,9 +442,9 @@ namespace psemek::util
return result; return result;
} }
bool event(Event const & e) bool event(Event const & e, Args ... args)
{ {
return child.event(e); return child.event(e, args...);
} }
}; };
@ -418,9 +477,9 @@ namespace psemek::util
return update_impl<0>(dt, args...); return update_impl<0>(dt, args...);
} }
bool event(Event const & e) bool event(Event const & e, Args ... args)
{ {
return event_impl<0>(e); return event_impl<0>(e, args...);
} }
private: private:
@ -461,7 +520,7 @@ namespace psemek::util
} }
template <size_t I> template <size_t I>
bool event_impl(Event const & e) bool event_impl(Event const & e, Args ... args)
{ {
if constexpr (I == sizeof...(Children)) if constexpr (I == sizeof...(Children))
{ {
@ -471,11 +530,11 @@ namespace psemek::util
{ {
if (current == I) if (current == I)
{ {
return std::get<I>(children).event(e); return std::get<I>(children).event(e, args...);
} }
else else
{ {
return event_impl<I + 1>(e); return event_impl<I + 1>(e, args...);
} }
} }
} }
@ -510,9 +569,9 @@ namespace psemek::util
return update_impl<0>(dt, args...); return update_impl<0>(dt, args...);
} }
bool event(Event const & e) bool event(Event const & e, Args ... args)
{ {
return event_impl<0>(e); return event_impl<0>(e, args...);
} }
private: private:
@ -555,7 +614,7 @@ namespace psemek::util
} }
template <size_t I> template <size_t I>
bool event_impl(Event const & e) bool event_impl(Event const & e, Args ... args)
{ {
if constexpr (I == sizeof...(Children)) if constexpr (I == sizeof...(Children))
{ {
@ -565,11 +624,11 @@ namespace psemek::util
{ {
if (current == I) if (current == I)
{ {
return std::get<I>(children).event(e); return std::get<I>(children).event(e, args...);
} }
else else
{ {
return event_impl<I + 1>(e); return event_impl<I + 1>(e, args...);
} }
} }
} }