Implement guard func

This commit is contained in:
Serhii Snitsaruk 2022-09-29 22:44:51 +02:00
parent b7ea9145df
commit eecf27fdf5
3 changed files with 44 additions and 5 deletions

View File

@ -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;
}
}
}

View File

@ -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);

View File

@ -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> blackboard;
Map<String, StringName> 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();
};