From eecf27fdf5de5d3e7bee4a47f5ce4d1628fc0c90 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Thu, 29 Sep 2022 22:44:51 +0200 Subject: [PATCH] Implement guard func --- limbo_hsm.cpp | 15 +++++++++++++-- limbo_state.cpp | 19 +++++++++++++++++++ limbo_state.h | 15 ++++++++++++--- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/limbo_hsm.cpp b/limbo_hsm.cpp index 491a6ff..4fd4e8e 100644 --- a/limbo_hsm.cpp +++ b/limbo_hsm.cpp @@ -129,8 +129,19 @@ bool LimboHSM::dispatch(const String &p_event, const Variant &p_cargo) { uint64_t key = _get_transition_key(active_state, p_event); if (transitions.has(key)) { LimboState *to_state = transitions[key]; - _change_state(to_state); - event_consumed = true; + bool permitted = true; + if (to_state->guard.obj != nullptr) { + Variant result = to_state->guard.obj->callv(to_state->guard.func, to_state->guard.binds); + if (unlikely(result.get_type() != Variant::BOOL)) { + ERR_PRINT_ONCE(vformat("State guard func \"%s()\" returned non-boolean value (%s).", to_state->guard.func, to_state)); + } else { + permitted = bool(result); + } + } + if (permitted) { + _change_state(to_state); + event_consumed = true; + } } } diff --git a/limbo_state.cpp b/limbo_state.cpp index 4eb854a..78ce1be 100644 --- a/limbo_state.cpp +++ b/limbo_state.cpp @@ -109,6 +109,21 @@ LimboState *LimboState::call_on_update(Object *p_object, const StringName &p_met return this; } +void LimboState::set_guard_func(Object *p_object, const StringName &p_func, const Array &p_binds) { + ERR_FAIL_COND(p_object == nullptr); + ERR_FAIL_COND(!p_object->has_method(p_func)); + + guard.obj = p_object; + guard.func = p_func; + guard.binds = p_binds; +} + +void LimboState::clear_guard_func() { + guard.obj = nullptr; + guard.func = ""; + guard.binds.clear(); +} + void LimboState::_notification(int p_what) { switch (p_what) { case NOTIFICATION_EXIT_TREE: { @@ -134,6 +149,8 @@ void LimboState::_bind_methods() { ClassDB::bind_method(D_METHOD("call_on_enter", "p_object", "p_method"), &LimboState::call_on_enter); ClassDB::bind_method(D_METHOD("call_on_exit", "p_object", "p_method"), &LimboState::call_on_exit); ClassDB::bind_method(D_METHOD("call_on_update", "p_object", "p_method"), &LimboState::call_on_update); + ClassDB::bind_method(D_METHOD("set_guard_func", "p_object", "p_func", "p_binds"), &LimboState::set_guard_func, Array()); + ClassDB::bind_method(D_METHOD("clear_guard_func"), &LimboState::clear_guard_func); BIND_VMETHOD(MethodInfo("_setup")); BIND_VMETHOD(MethodInfo("_enter")); @@ -150,6 +167,8 @@ LimboState::LimboState() { agent = nullptr; active = false; + guard.obj = nullptr; + set_process(false); set_physics_process(false); set_process_input(false); diff --git a/limbo_state.h b/limbo_state.h index fa9dee9..fefd4ac 100644 --- a/limbo_state.h +++ b/limbo_state.h @@ -4,22 +4,29 @@ #define LIMBO_STATE_H #include "blackboard.h" +#include "core/class_db.h" +#include "core/object.h" #include "core/string_name.h" #include "core/ustring.h" #include "core/variant.h" #include "scene/main/node.h" -// TODO Implement guards class LimboHSM; class LimboState : public Node { GDCLASS(LimboState, Node); private: + struct GuardCallback { + Object *obj = nullptr; + StringName func; + Array binds; + }; + Object *agent; Ref blackboard; Map handlers; - // Guard *guard; + GuardCallback guard; protected: friend LimboHSM; @@ -51,7 +58,9 @@ public: String event_finished() const { return EVENT_FINISHED; } LimboState *get_root() const; bool is_active() const { return active; } - uint32_t hash() const; + + void set_guard_func(Object *p_object, const StringName &p_func, const Array &p_binds = Array()); + void clear_guard_func(); LimboState(); };