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 <memory>
#include <vector>
#include <optional>
namespace psemek::util
{
@ -30,7 +31,7 @@ namespace psemek::util
{
virtual void start(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() {}
};
@ -55,9 +56,9 @@ namespace psemek::util
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...);
}
bool event(Event const & e)
bool event(Event const & e, Args ... args)
{
return impl_->event(e);
return impl_->event(e, args...);
}
private:
@ -103,6 +104,27 @@ namespace psemek::util
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
{
int active_count = 0;
@ -202,7 +224,7 @@ namespace psemek::util
return finished{true};
}
bool event(Event const &)
bool event(Event const &, Args ...)
{
return false;
}
@ -232,7 +254,7 @@ namespace psemek::util
return suspended{remaining_time};
}
bool event(Event const &)
bool event(Event const &, Args ...)
{
return false;
}
@ -255,12 +277,49 @@ namespace psemek::util
return finished{condFn(args...)};
}
bool event(Event const &)
bool event(Event const &, Args ...)
{
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>
struct success
{
@ -283,9 +342,9 @@ namespace psemek::util
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;
}
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;
}
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;
}
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...);
}
bool event(Event const & e)
bool event(Event const & e, Args ... args)
{
return event_impl<0>(e);
return event_impl<0>(e, args...);
}
private:
@ -461,7 +520,7 @@ namespace psemek::util
}
template <size_t I>
bool event_impl(Event const & e)
bool event_impl(Event const & e, Args ... args)
{
if constexpr (I == sizeof...(Children))
{
@ -471,11 +530,11 @@ namespace psemek::util
{
if (current == I)
{
return std::get<I>(children).event(e);
return std::get<I>(children).event(e, args...);
}
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...);
}
bool event(Event const & e)
bool event(Event const & e, Args ... args)
{
return event_impl<0>(e);
return event_impl<0>(e, args...);
}
private:
@ -555,7 +614,7 @@ namespace psemek::util
}
template <size_t I>
bool event_impl(Event const & e)
bool event_impl(Event const & e, Args ... args)
{
if constexpr (I == sizeof...(Children))
{
@ -565,11 +624,11 @@ namespace psemek::util
{
if (current == I)
{
return std::get<I>(children).event(e);
return std::get<I>(children).event(e, args...);
}
else
{
return event_impl<I + 1>(e);
return event_impl<I + 1>(e, args...);
}
}
}