From 947e253bf9130a7835da7046b6beb1f707d013fc Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Fri, 12 Jan 2024 23:20:39 +0100 Subject: [PATCH] Fix infinite call recursion crash due to virtual function workaround --- hsm/limbo_hsm.cpp | 46 +++++++++++++++++++++++---------------------- hsm/limbo_hsm.h | 9 +++++---- hsm/limbo_state.cpp | 22 +++++++++++----------- hsm/limbo_state.h | 5 +++++ 4 files changed, 45 insertions(+), 37 deletions(-) diff --git a/hsm/limbo_hsm.cpp b/hsm/limbo_hsm.cpp index 8b700c1..cb8badb 100644 --- a/hsm/limbo_hsm.cpp +++ b/hsm/limbo_hsm.cpp @@ -49,9 +49,9 @@ void LimboHSM::set_active(bool p_active) { set_process_input(p_active); if (active) { - _enter(); + _do_enter(); } else { - _exit(); + _do_exit(); } } @@ -60,45 +60,43 @@ void LimboHSM::_change_state(LimboState *p_state) { ERR_FAIL_COND(p_state->get_parent() != this); if (active_state) { - active_state->_exit(); + active_state->_do_exit(); } active_state = p_state; - active_state->_enter(); + active_state->_do_enter(); emit_signal(LimboStringNames::get_singleton()->state_changed, active_state); } -void LimboHSM::_enter() { +void LimboHSM::_do_enter() { ERR_FAIL_COND_MSG(get_child_count() == 0, "LimboHSM has no candidate for initial substate."); ERR_FAIL_COND(active_state != nullptr); + ERR_FAIL_COND_MSG(initial_state == nullptr, "LimboHSM: Initial state is not set."); - LimboState::_enter(); - - if (initial_state == nullptr) { - initial_state = Object::cast_to(get_child(0)); - } - - ERR_FAIL_COND_MSG(initial_state == nullptr, "LimboHSM: Failed to acquire initial state."); - + LimboState::_do_enter(); _change_state(initial_state); } -void LimboHSM::_exit() { +void LimboHSM::_do_exit() { ERR_FAIL_COND(active_state == nullptr); - active_state->_exit(); + active_state->_do_exit(); active_state = nullptr; - LimboState::_exit(); + LimboState::_do_exit(); } -void LimboHSM::_update(double p_delta) { +void LimboHSM::_do_update(double p_delta) { if (active) { ERR_FAIL_COND(active_state == nullptr); - LimboState::_update(p_delta); - active_state->_update(p_delta); + LimboState::_do_update(p_delta); + active_state->_do_update(p_delta); } } +void LimboHSM::update(double p_delta) { + _do_update(p_delta); +} + void LimboHSM::add_transition(Node *p_from_state, Node *p_to_state, const String &p_event) { // ERR_FAIL_COND(p_from_state == nullptr); ERR_FAIL_COND(p_from_state != nullptr && p_from_state->get_parent() != this); @@ -186,7 +184,7 @@ bool LimboHSM::dispatch(const String &p_event, const Variant &p_cargo) { } if (!event_consumed && p_event == LW_NAME(EVENT_FINISHED) && !(get_parent() && get_parent()->is_class("LimboState"))) { - _exit(); + _do_exit(); } return event_consumed; @@ -198,6 +196,10 @@ void LimboHSM::initialize(Node *p_agent, const Ref &p_parent_scope) blackboard->set_parent_scope(p_parent_scope); } _initialize(p_agent, nullptr); + + if (initial_state == nullptr) { + initial_state = Object::cast_to(get_child(0)); + } } void LimboHSM::_initialize(Node *p_agent, const Ref &p_blackboard) { @@ -227,10 +229,10 @@ void LimboHSM::_notification(int p_what) { case NOTIFICATION_POST_ENTER_TREE: { } break; case NOTIFICATION_PROCESS: { - _update(get_process_delta_time()); + _do_update(get_process_delta_time()); } break; case NOTIFICATION_PHYSICS_PROCESS: { - _update(get_physics_process_delta_time()); + _do_update(get_physics_process_delta_time()); } break; } } diff --git a/hsm/limbo_hsm.h b/hsm/limbo_hsm.h index 8248d73..0e3e461 100644 --- a/hsm/limbo_hsm.h +++ b/hsm/limbo_hsm.h @@ -43,9 +43,10 @@ protected: void _notification(int p_what); virtual void _initialize(Node *p_agent, const Ref &p_blackboard) override; - virtual void _enter() override; - virtual void _exit() override; - virtual void _update(double p_delta) override; + + virtual void _do_enter() override; + virtual void _do_exit() override; + virtual void _do_update(double p_delta) override; void _change_state(LimboState *p_state); @@ -63,7 +64,7 @@ public: virtual void initialize(Node *p_agent, const Ref &p_parent_scope = nullptr); virtual bool dispatch(const String &p_event, const Variant &p_cargo = Variant()) override; - void update(double p_delta) { _update(p_delta); } + void update(double p_delta); void add_transition(Node *p_from_state, Node *p_to_state, const String &p_event); // void add_transition_from_any_state(Node *p_to_state, const String &p_event); LimboState *anystate() const { return nullptr; }; diff --git a/hsm/limbo_state.cpp b/hsm/limbo_state.cpp index fc7de49..a2b9bef 100644 --- a/hsm/limbo_state.cpp +++ b/hsm/limbo_state.cpp @@ -39,18 +39,13 @@ LimboState *LimboState::named(String p_name) { return this; }; -void LimboState::_setup() { - VCALL(_setup); - emit_signal(LimboStringNames::get_singleton()->setup); -}; - -void LimboState::_enter() { +void LimboState::_do_enter() { active = true; VCALL(_enter); emit_signal(LimboStringNames::get_singleton()->entered); }; -void LimboState::_exit() { +void LimboState::_do_exit() { if (!active) { return; } @@ -59,14 +54,13 @@ void LimboState::_exit() { active = false; }; -void LimboState::_update(double p_delta) { +void LimboState::_do_update(double p_delta) { VCALL_ARGS(_update, p_delta); emit_signal(LimboStringNames::get_singleton()->updated, p_delta); }; void LimboState::_initialize(Node *p_agent, const Ref &p_blackboard) { ERR_FAIL_COND(p_agent == nullptr); - agent = p_agent; if (!p_blackboard.is_null()) { @@ -77,8 +71,14 @@ void LimboState::_initialize(Node *p_agent, const Ref &p_blackboard) } } - _setup(); -}; + VCALL(_setup); + emit_signal(LimboStringNames::get_singleton()->setup); +} + +void LimboState::_setup() {} +void LimboState::_enter() {} +void LimboState::_exit() {} +void LimboState::_update(double p_delta) {} bool LimboState::dispatch(const String &p_event, const Variant &p_cargo) { ERR_FAIL_COND_V(p_event.is_empty(), false); diff --git a/hsm/limbo_state.h b/hsm/limbo_state.h index ff6bc47..d0d4310 100644 --- a/hsm/limbo_state.h +++ b/hsm/limbo_state.h @@ -56,6 +56,7 @@ protected: virtual void _initialize(Node *p_agent, const Ref &p_blackboard); + // Implemented in GDScript: virtual void _setup(); virtual void _enter(); virtual void _exit(); @@ -68,6 +69,10 @@ protected: GDVIRTUAL1(_update, double); #endif // LIMBOAI_MODULE + virtual void _do_enter(); + virtual void _do_exit(); + virtual void _do_update(double p_delta); + void add_event_handler(const String &p_event, const Callable &p_handler); public: