2023-07-21 09:50:06 +00:00
/**
* behavior_tree . cpp
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2024-03-04 20:36:16 +00:00
* Copyright 2021 - 2024 Serhii Snitsaruk
2023-07-21 09:50:06 +00:00
*
* Use of this source code is governed by an MIT - style
* license that can be found in the LICENSE file or at
* https : //opensource.org/licenses/MIT.
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2022-08-30 16:48:49 +00:00
# include "behavior_tree.h"
2023-07-20 16:35:36 +00:00
2024-01-26 13:35:33 +00:00
# include "../util/limbo_string_names.h"
2024-01-06 23:47:46 +00:00
# ifdef LIMBOAI_MODULE
2022-12-15 07:26:52 +00:00
# include "core/error/error_macros.h"
# include "core/object/class_db.h"
# include "core/templates/list.h"
# include "core/variant/variant.h"
2024-01-09 12:34:24 +00:00
# endif // ! LIMBOAI_MODULE
2024-01-06 23:47:46 +00:00
# ifdef LIMBOAI_GDEXTENSION
2024-01-09 12:34:24 +00:00
# include "godot_cpp/core/error_macros.hpp"
# endif // ! LIMBOAI_GDEXTENSION
2022-08-30 16:48:49 +00:00
2024-01-25 13:27:14 +00:00
void BehaviorTree : : set_description ( const String & p_value ) {
description = p_value ;
emit_changed ( ) ;
}
2024-01-23 19:02:23 +00:00
void BehaviorTree : : set_blackboard_plan ( const Ref < BlackboardPlan > & p_plan ) {
2024-01-26 13:35:33 +00:00
if ( blackboard_plan = = p_plan ) {
return ;
}
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) & & blackboard_plan . is_valid ( ) & &
blackboard_plan - > is_connected ( LW_NAME ( changed ) , callable_mp ( this , & BehaviorTree : : _plan_changed ) ) ) {
blackboard_plan - > disconnect ( LW_NAME ( changed ) , callable_mp ( this , & BehaviorTree : : _plan_changed ) ) ;
}
2024-01-23 19:02:23 +00:00
blackboard_plan = p_plan ;
if ( blackboard_plan . is_null ( ) ) {
blackboard_plan = Ref < BlackboardPlan > ( memnew ( BlackboardPlan ) ) ;
2024-01-23 14:56:30 +00:00
}
2024-01-26 13:35:33 +00:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
blackboard_plan - > connect ( LW_NAME ( changed ) , callable_mp ( this , & BehaviorTree : : _plan_changed ) ) ;
}
2024-04-01 14:34:36 +00:00
_plan_changed ( ) ;
2024-01-23 14:56:30 +00:00
}
2024-01-25 13:27:14 +00:00
void BehaviorTree : : set_root_task ( const Ref < BTTask > & p_value ) {
2024-05-14 20:03:29 +00:00
# ifdef TOOLS_ENABLED
2024-05-14 09:39:32 +00:00
_unset_editor_behavior_tree_hint ( ) ;
2024-05-14 20:03:29 +00:00
# endif // TOOLS_ENABLED
2024-01-25 13:27:14 +00:00
root_task = p_value ;
2024-05-14 20:03:29 +00:00
# ifdef TOOLS_ENABLED
2024-05-14 09:39:32 +00:00
_set_editor_behavior_tree_hint ( ) ;
2024-05-14 20:03:29 +00:00
# endif // TOOLS_ENABLED
2024-01-25 13:27:14 +00:00
emit_changed ( ) ;
}
2022-08-30 16:48:49 +00:00
Ref < BehaviorTree > BehaviorTree : : clone ( ) const {
Ref < BehaviorTree > copy = duplicate ( false ) ;
copy - > set_path ( " " ) ;
if ( root_task . is_valid ( ) ) {
copy - > root_task = root_task - > clone ( ) ;
}
return copy ;
}
2024-01-10 21:45:42 +00:00
void BehaviorTree : : copy_other ( const Ref < BehaviorTree > & p_other ) {
2024-01-09 12:34:24 +00:00
ERR_FAIL_COND ( p_other . is_null ( ) ) ;
description = p_other - > get_description ( ) ;
root_task = p_other - > get_root_task ( ) ;
}
2024-08-03 09:07:06 +00:00
Ref < BTInstance > BehaviorTree : : instantiate ( Node * p_agent , const Ref < Blackboard > & p_blackboard , Node * p_instance_owner ) const {
ERR_FAIL_COND_V_MSG ( root_task = = nullptr , nullptr , " BehaviorTree: Instantiation failed - BT has no valid root task. " ) ;
ERR_FAIL_NULL_V_MSG ( p_agent , nullptr , " BehaviorTree: Instantiation failed - agent can't be null. " ) ;
ERR_FAIL_NULL_V_MSG ( p_instance_owner , nullptr , " BehaviorTree: Instantiation failed -- instance owner can't be null. " ) ;
Node * scene_root = p_instance_owner - > get_owner ( ) ;
ERR_FAIL_NULL_V_MSG ( scene_root , nullptr , " BehaviorTree: Instantiation failed - can't get scene root, because instance_owner not owned by a scene node. Hint: Try my_player.set_owner(get_owner()). " ) ;
Ref < BTTask > root_copy = root_task - > clone ( ) ;
root_copy - > initialize ( p_agent , p_blackboard , scene_root ) ;
return BTInstance : : create ( root_copy , get_path ( ) , p_instance_owner ) ;
2022-09-21 14:13:17 +00:00
}
2024-01-26 13:35:33 +00:00
void BehaviorTree : : _plan_changed ( ) {
2024-04-01 14:34:36 +00:00
emit_signal ( LW_NAME ( plan_changed ) ) ;
2024-01-26 13:35:33 +00:00
emit_changed ( ) ;
}
2024-05-14 20:03:29 +00:00
# ifdef TOOLS_ENABLED
2024-05-14 09:39:32 +00:00
void BehaviorTree : : _set_editor_behavior_tree_hint ( ) {
if ( root_task . is_valid ( ) ) {
2024-05-14 20:03:29 +00:00
root_task - > data . behavior_tree_id = this - > get_instance_id ( ) ;
2024-05-14 09:39:32 +00:00
}
}
void BehaviorTree : : _unset_editor_behavior_tree_hint ( ) {
if ( root_task . is_valid ( ) ) {
2024-05-14 20:03:29 +00:00
root_task - > data . behavior_tree_id = ObjectID ( ) ;
2024-05-14 09:39:32 +00:00
}
}
2024-05-14 20:03:29 +00:00
# endif // TOOLS_ENABLED
2022-08-30 16:48:49 +00:00
void BehaviorTree : : _bind_methods ( ) {
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_description " , " description " ) , & BehaviorTree : : set_description ) ;
2022-08-30 16:48:49 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_description " ) , & BehaviorTree : : get_description ) ;
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_blackboard_plan " , " plan " ) , & BehaviorTree : : set_blackboard_plan ) ;
2024-01-23 19:02:23 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_blackboard_plan " ) , & BehaviorTree : : get_blackboard_plan ) ;
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_root_task " , " task " ) , & BehaviorTree : : set_root_task ) ;
2022-08-30 16:48:49 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_root_task " ) , & BehaviorTree : : get_root_task ) ;
ClassDB : : bind_method ( D_METHOD ( " clone " ) , & BehaviorTree : : clone ) ;
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " copy_other " , " other " ) , & BehaviorTree : : copy_other ) ;
2024-08-03 12:26:40 +00:00
ClassDB : : bind_method ( D_METHOD ( " instantiate " , " agent " , " blackboard " , " instance_owner " ) , & BehaviorTree : : instantiate ) ;
2022-08-30 16:48:49 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " description " , PROPERTY_HINT_MULTILINE_TEXT ) , " set_description " , " get_description " ) ;
2024-01-23 19:02:23 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " blackboard_plan " , PROPERTY_HINT_RESOURCE_TYPE , " BlackboardPlan " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT ) , " set_blackboard_plan " , " get_blackboard_plan " ) ;
2024-01-25 13:27:14 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " root_task " , PROPERTY_HINT_RESOURCE_TYPE , " BTTask " , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL ) , " set_root_task " , " get_root_task " ) ;
2024-04-01 14:34:36 +00:00
ADD_SIGNAL ( MethodInfo ( " plan_changed " ) ) ;
2024-01-23 14:31:56 +00:00
}
BehaviorTree : : BehaviorTree ( ) {
2024-01-13 16:10:42 +00:00
}
2024-01-26 13:35:33 +00:00
BehaviorTree : : ~ BehaviorTree ( ) {
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) & & blackboard_plan . is_valid ( ) & &
blackboard_plan - > is_connected ( LW_NAME ( changed ) , callable_mp ( this , & BehaviorTree : : _plan_changed ) ) ) {
blackboard_plan - > disconnect ( LW_NAME ( changed ) , callable_mp ( this , & BehaviorTree : : _plan_changed ) ) ;
}
}