2023-07-21 09:50:06 +00:00
/**
* bt_task . 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-28 10:54:34 +00:00
# include "bt_task.h"
2024-01-06 20:04:34 +00:00
2024-01-13 16:10:42 +00:00
# include "../../blackboard/blackboard.h"
# include "../../util/limbo_string_names.h"
# include "../../util/limbo_utility.h"
2024-05-14 09:39:32 +00:00
# include "../behavior_tree.h"
2023-08-19 10:19:58 +00:00
# include "bt_comment.h"
2023-07-20 16:35:36 +00:00
2024-01-13 16:10:42 +00:00
# ifdef LIMBOAI_MODULE
2022-12-15 07:26:52 +00:00
# include "core/error/error_macros.h"
# include "core/io/resource.h"
# include "core/object/class_db.h"
# include "core/object/object.h"
# include "core/object/ref_counted.h"
# include "core/object/script_language.h"
# include "core/string/ustring.h"
# include "core/templates/hash_map.h"
# include "core/variant/variant.h"
2024-01-06 20:04:34 +00:00
# endif // LIMBOAI_MODULE
# ifdef LIMBOAI_GDEXTENSION
2024-01-09 20:47:22 +00:00
# include "godot_cpp/classes/global_constants.hpp"
# include "godot_cpp/core/class_db.hpp"
# include "godot_cpp/variant/dictionary.hpp"
# include "godot_cpp/variant/string_name.hpp"
# include "godot_cpp/variant/typed_array.hpp"
# include "godot_cpp/variant/utility_functions.hpp"
# include "godot_cpp/variant/variant.hpp"
2024-01-06 20:04:34 +00:00
# include <godot_cpp/classes/ref.hpp>
2024-01-13 16:10:42 +00:00
# include <godot_cpp/classes/script.hpp>
2024-01-06 20:04:34 +00:00
# endif // LIMBOAI_GDEXTENSION
2022-08-28 10:54:34 +00:00
2023-09-19 11:43:26 +00:00
void BT : : _bind_methods ( ) {
BIND_ENUM_CONSTANT ( FRESH ) ;
BIND_ENUM_CONSTANT ( RUNNING ) ;
BIND_ENUM_CONSTANT ( FAILURE ) ;
BIND_ENUM_CONSTANT ( SUCCESS ) ;
}
2024-01-06 20:04:34 +00:00
String BTTask : : _generate_name ( ) {
2024-01-13 12:35:16 +00:00
String ret ;
// Generate name based on script path.
Ref < Script > sc = GET_SCRIPT ( this ) ;
if ( sc . is_valid ( ) & & sc - > get_path ( ) . is_absolute_path ( ) ) {
ret = sc - > get_path ( ) . get_basename ( ) . get_file ( ) . to_pascal_case ( ) ;
2022-08-28 10:54:34 +00:00
}
2024-01-06 20:04:34 +00:00
2024-01-13 12:35:16 +00:00
// Generate name based on core class name.
if ( ret . is_empty ( ) ) {
ret = get_class ( ) ;
2024-01-06 20:04:34 +00:00
}
2024-01-13 12:35:16 +00:00
return ret . trim_prefix ( " BT " ) ;
2022-08-28 10:54:34 +00:00
}
Array BTTask : : _get_children ( ) const {
Array arr ;
int num_children = get_child_count ( ) ;
arr . resize ( num_children ) ;
for ( int i = 0 ; i < num_children ; i + + ) {
arr [ i ] = get_child ( i ) . ptr ( ) ;
}
return arr ;
}
void BTTask : : _set_children ( Array p_children ) {
const int num_children = p_children . size ( ) ;
2024-02-08 16:10:31 +00:00
int num_null = 0 ;
data . children . clear ( ) ;
2023-07-20 18:10:02 +00:00
data . children . resize ( num_children ) ;
2024-02-08 16:10:31 +00:00
2022-08-28 10:54:34 +00:00
for ( int i = 0 ; i < num_children ; i + + ) {
2024-02-08 16:10:31 +00:00
Ref < BTTask > task = p_children [ i ] ;
if ( task . is_null ( ) ) {
ERR_PRINT ( " Invalid BTTask reference. " ) ;
num_null + = 1 ;
continue ;
}
if ( task - > data . parent ! = nullptr & & task - > data . parent ! = this ) {
task = task - > clone ( ) ;
if ( task . is_null ( ) ) {
// * BTComment::clone() returns nullptr at runtime - we omit those.
num_null + = 1 ;
continue ;
}
}
int idx = i - num_null ;
task - > data . parent = this ;
task - > data . index = idx ;
data . children . set ( idx , task ) ;
}
if ( num_null > 0 ) {
data . children . resize ( num_children - num_null ) ;
2022-08-28 10:54:34 +00:00
}
}
2024-02-02 15:46:26 +00:00
void BTTask : : set_display_collapsed ( bool p_display_collapsed ) {
data . display_collapsed = p_display_collapsed ;
}
bool BTTask : : is_displayed_collapsed ( ) const {
return data . display_collapsed ;
}
2024-01-06 20:04:34 +00:00
String BTTask : : get_task_name ( ) {
2024-06-02 19:59:55 +00:00
if ( ! data . custom_name . is_empty ( ) ) {
return data . custom_name ;
}
Ref < Script > task_script = get_script ( ) ;
if ( task_script . is_valid ( ) ) {
2024-08-21 18:04:35 +00:00
// ! CURSED: Currently, has_method() doesn't return true for ClassDB-registered native virtual methods. This may break in the future.
2024-06-02 19:59:55 +00:00
bool has_generate_method = has_method ( LW_NAME ( _generate_name ) ) ;
ERR_FAIL_COND_V_MSG ( has_generate_method & & ! task_script - > is_tool ( ) , _generate_name ( ) , vformat ( " BTTask: @tool annotation is required if _generate_name is defined: %s " , task_script - > get_path ( ) ) ) ;
if ( task_script - > is_tool ( ) & & has_generate_method ) {
String call_result ;
2024-06-30 10:34:06 +00:00
GDVIRTUAL_CALL ( _generate_name , call_result ) ;
2024-06-02 19:59:55 +00:00
if ( call_result . is_empty ( ) | | call_result = = " <null> " ) {
// Force reset script instance.
set_script ( Variant ( ) ) ;
set_script ( task_script ) ;
// Retry.
2024-06-30 10:34:06 +00:00
GDVIRTUAL_CALL ( _generate_name , call_result ) ;
2024-01-13 12:35:16 +00:00
}
2024-06-02 19:59:55 +00:00
ERR_FAIL_COND_V_MSG ( call_result . is_empty ( ) | | call_result = = " <null> " , _generate_name ( ) , vformat ( " BTTask: _generate_name() failed to return a proper name string (%s) " , task_script - > get_path ( ) ) ) ;
return call_result ;
2024-01-13 12:35:16 +00:00
}
2022-08-28 10:54:34 +00:00
}
2024-06-02 19:59:55 +00:00
return _generate_name ( ) ;
2022-08-28 10:54:34 +00:00
}
Ref < BTTask > BTTask : : get_root ( ) const {
const BTTask * task = this ;
while ( ! task - > is_root ( ) ) {
2023-07-20 18:10:02 +00:00
task = task - > data . parent ;
2022-08-28 10:54:34 +00:00
}
return Ref < BTTask > ( task ) ;
}
void BTTask : : set_custom_name ( const String & p_name ) {
2023-07-20 18:10:02 +00:00
if ( data . custom_name ! = p_name ) {
data . custom_name = p_name ;
2022-08-28 10:54:34 +00:00
emit_changed ( ) ;
}
} ;
2024-05-01 21:20:17 +00:00
void BTTask : : initialize ( Node * p_agent , const Ref < Blackboard > & p_blackboard , Node * p_scene_root ) {
ERR_FAIL_NULL ( p_agent ) ;
2024-11-03 03:53:56 +00:00
ERR_FAIL_COND ( p_blackboard . is_null ( ) ) ;
2024-05-01 21:20:17 +00:00
ERR_FAIL_NULL ( p_scene_root ) ;
2023-07-20 18:10:02 +00:00
data . agent = p_agent ;
data . blackboard = p_blackboard ;
2024-05-01 21:20:17 +00:00
data . scene_root = p_scene_root ;
2023-07-20 18:10:02 +00:00
for ( int i = 0 ; i < data . children . size ( ) ; i + + ) {
2024-05-01 21:20:17 +00:00
get_child ( i ) - > initialize ( p_agent , p_blackboard , p_scene_root ) ;
2022-08-28 10:54:34 +00:00
}
2022-12-15 07:26:52 +00:00
2024-09-22 12:49:46 +00:00
_setup ( ) ;
GDVIRTUAL_CALL ( _setup ) ;
2022-08-28 10:54:34 +00:00
}
Ref < BTTask > BTTask : : clone ( ) const {
2022-09-02 22:08:10 +00:00
Ref < BTTask > inst = duplicate ( false ) ;
2024-02-08 16:10:31 +00:00
// * Children are duplicated via children property. See _set_children().
2022-10-21 14:15:13 +00:00
2024-10-28 13:51:42 +00:00
// * Make BBParam properties unique.
HashMap < Ref < Resource > , Ref < Resource > > duplicates ;
2024-01-06 20:04:34 +00:00
# ifdef LIMBOAI_MODULE
2022-10-21 14:15:13 +00:00
List < PropertyInfo > props ;
inst - > get_property_list ( & props ) ;
for ( List < PropertyInfo > : : Element * E = props . front ( ) ; E ; E = E - > next ( ) ) {
2024-10-28 13:51:42 +00:00
PropertyInfo prop = E - > get ( ) ;
2024-01-13 16:10:42 +00:00
# elif LIMBOAI_GDEXTENSION
2024-01-06 20:04:34 +00:00
TypedArray < Dictionary > props = inst - > get_property_list ( ) ;
for ( int i = 0 ; i < props . size ( ) ; i + + ) {
2024-10-28 13:51:42 +00:00
PropertyInfo prop = PropertyInfo : : from_dict ( props [ i ] ) ;
# endif
if ( ! ( prop . usage & PROPERTY_USAGE_STORAGE ) ) {
2024-01-06 20:04:34 +00:00
continue ;
}
2024-10-28 13:51:42 +00:00
Variant prop_value = inst - > get ( prop . name ) ;
Ref < Resource > res = prop_value ;
if ( res . is_valid ( ) & & res - > is_class ( " BBParam " ) ) {
// Duplicate BBParam
if ( ! duplicates . has ( res ) ) {
duplicates [ res ] = res - > duplicate ( ) ;
}
res = duplicates [ res ] ;
inst - > set ( prop . name , res ) ;
} else if ( prop_value . get_type ( ) = = Variant : : ARRAY ) {
// Duplicate BBParams instances inside an array.
// - This code doesn't handle arrays of arrays.
// - A partial workaround for: https://github.com/godotengine/godot/issues/74918
// - We actually don't want to duplicate resources in clone() except for BBParam subtypes.
Array arr = prop_value ;
if ( arr . is_typed ( ) & & ClassDB : : is_parent_class ( arr . get_typed_class_name ( ) , LW_NAME ( BBParam ) ) ) {
for ( int j = 0 ; j < arr . size ( ) ; j + + ) {
Ref < Resource > bb_param = arr [ j ] ;
if ( bb_param . is_valid ( ) ) {
arr [ j ] = bb_param - > duplicate ( ) ;
2024-01-06 20:04:34 +00:00
}
}
}
}
}
2022-10-21 14:15:13 +00:00
2022-08-28 10:54:34 +00:00
return inst ;
}
2023-09-19 11:43:26 +00:00
BT : : Status BTTask : : execute ( double p_delta ) {
2023-07-20 18:10:02 +00:00
if ( data . status ! = RUNNING ) {
2023-04-14 08:16:26 +00:00
// Reset children status.
2023-07-20 18:10:02 +00:00
if ( data . status ! = FRESH ) {
2023-04-14 08:16:26 +00:00
for ( int i = 0 ; i < get_child_count ( ) ; i + + ) {
2023-10-26 14:20:33 +00:00
data . children . get ( i ) - > abort ( ) ;
2023-04-14 08:16:26 +00:00
}
}
2024-11-01 12:50:08 +00:00
// First native, then script.
_enter ( ) ;
GDVIRTUAL_CALL ( _enter ) ;
2023-04-14 08:16:26 +00:00
} else {
2023-07-20 18:10:02 +00:00
data . elapsed + = p_delta ;
2022-08-28 10:54:34 +00:00
}
2022-08-31 15:05:25 +00:00
2024-06-30 10:34:06 +00:00
if ( ! GDVIRTUAL_CALL ( _tick , p_delta , data . status ) ) {
data . status = _tick ( p_delta ) ;
}
2022-08-28 10:54:34 +00:00
2023-07-20 18:10:02 +00:00
if ( data . status ! = RUNNING ) {
2024-11-01 12:50:08 +00:00
// First script, then native.
GDVIRTUAL_CALL ( _exit ) ;
_exit ( ) ;
2023-07-20 18:10:02 +00:00
data . elapsed = 0.0 ;
2022-08-28 10:54:34 +00:00
}
2023-07-20 18:10:02 +00:00
return data . status ;
2022-08-28 10:54:34 +00:00
}
2023-10-26 14:20:33 +00:00
void BTTask : : abort ( ) {
2023-07-20 18:10:02 +00:00
for ( int i = 0 ; i < data . children . size ( ) ; i + + ) {
2023-10-26 14:20:33 +00:00
get_child ( i ) - > abort ( ) ;
2022-08-28 10:54:34 +00:00
}
2023-07-20 18:10:02 +00:00
if ( data . status = = RUNNING ) {
2024-11-01 12:50:08 +00:00
// First script, then native.
GDVIRTUAL_CALL ( _exit ) ;
_exit ( ) ;
2022-08-28 10:54:34 +00:00
}
2023-07-20 18:10:02 +00:00
data . status = FRESH ;
data . elapsed = 0.0 ;
2022-08-28 10:54:34 +00:00
}
2023-08-19 10:19:58 +00:00
int BTTask : : get_child_count_excluding_comments ( ) const {
int count = 0 ;
for ( int i = 0 ; i < data . children . size ( ) ; i + + ) {
2024-01-06 23:47:46 +00:00
if ( ! IS_CLASS ( data . children [ i ] , BTComment ) ) {
2024-01-06 20:04:34 +00:00
count + = 1 ;
}
2023-08-19 10:19:58 +00:00
}
return count ;
}
2022-08-28 10:54:34 +00:00
void BTTask : : add_child ( Ref < BTTask > p_child ) {
2022-08-30 16:48:49 +00:00
ERR_FAIL_COND_MSG ( p_child - > get_parent ( ) . is_valid ( ) , " p_child already has a parent! " ) ;
2023-07-20 18:10:02 +00:00
p_child - > data . parent = this ;
2023-11-22 12:05:55 +00:00
p_child - > data . index = data . children . size ( ) ;
2023-07-20 18:10:02 +00:00
data . children . push_back ( p_child ) ;
2022-08-28 10:54:34 +00:00
emit_changed ( ) ;
}
void BTTask : : add_child_at_index ( Ref < BTTask > p_child , int p_idx ) {
2022-08-30 16:48:49 +00:00
ERR_FAIL_COND_MSG ( p_child - > get_parent ( ) . is_valid ( ) , " p_child already has a parent! " ) ;
2023-07-20 18:10:02 +00:00
if ( p_idx < 0 | | p_idx > data . children . size ( ) ) {
p_idx = data . children . size ( ) ;
2022-08-28 10:54:34 +00:00
}
2023-07-20 18:10:02 +00:00
p_child - > data . parent = this ;
2023-11-22 12:05:55 +00:00
p_child - > data . index = p_idx ;
2024-02-08 16:10:31 +00:00
data . children . insert ( p_idx , p_child ) ;
2023-11-22 12:05:55 +00:00
for ( int i = p_idx + 1 ; i < data . children . size ( ) ; i + + ) {
get_child ( i ) - > data . index = i ;
}
2022-08-28 10:54:34 +00:00
emit_changed ( ) ;
}
void BTTask : : remove_child ( Ref < BTTask > p_child ) {
2023-07-20 18:10:02 +00:00
int idx = data . children . find ( p_child ) ;
2023-11-22 12:05:55 +00:00
ERR_FAIL_COND_MSG ( idx = = - 1 , " p_child not found! " ) ;
data . children . remove_at ( idx ) ;
p_child - > data . parent = nullptr ;
p_child - > data . index = - 1 ;
for ( int i = idx ; i < data . children . size ( ) ; i + + ) {
get_child ( i ) - > data . index = i ;
2022-08-28 10:54:34 +00:00
}
2023-11-22 12:05:55 +00:00
emit_changed ( ) ;
2022-08-28 10:54:34 +00:00
}
2022-09-21 14:13:17 +00:00
void BTTask : : remove_child_at_index ( int p_idx ) {
ERR_FAIL_INDEX ( p_idx , get_child_count ( ) ) ;
2023-11-22 12:05:55 +00:00
data . children [ p_idx ] - > data . parent = nullptr ;
data . children [ p_idx ] - > data . index = - 1 ;
2023-07-20 18:10:02 +00:00
data . children . remove_at ( p_idx ) ;
2023-11-22 12:05:55 +00:00
for ( int i = p_idx ; i < data . children . size ( ) ; i + + ) {
get_child ( i ) - > data . index = i ;
}
emit_changed ( ) ;
2022-09-21 14:13:17 +00:00
}
2022-09-03 15:00:20 +00:00
bool BTTask : : is_descendant_of ( const Ref < BTTask > & p_task ) const {
const BTTask * task = this ;
while ( task ! = nullptr ) {
2023-07-20 18:10:02 +00:00
task = task - > data . parent ;
2022-09-03 15:00:20 +00:00
if ( task = = p_task . ptr ( ) ) {
return true ;
}
}
return false ;
}
2022-08-28 10:54:34 +00:00
Ref < BTTask > BTTask : : next_sibling ( ) const {
2023-07-20 18:10:02 +00:00
if ( data . parent ! = nullptr ) {
2023-11-22 12:05:55 +00:00
if ( get_index ( ) ! = - 1 & & data . parent - > get_child_count ( ) > ( get_index ( ) + 1 ) ) {
return data . parent - > get_child ( get_index ( ) + 1 ) ;
2022-08-28 10:54:34 +00:00
}
}
return Ref < BTTask > ( ) ;
}
2024-01-13 16:10:42 +00:00
PackedStringArray BTTask : : _get_configuration_warnings ( ) {
return PackedStringArray ( ) ;
}
2024-01-06 20:04:34 +00:00
PackedStringArray BTTask : : get_configuration_warnings ( ) {
2023-08-15 15:05:30 +00:00
PackedStringArray ret ;
2022-12-15 07:26:52 +00:00
2023-08-15 15:05:30 +00:00
PackedStringArray warnings ;
2024-02-10 14:05:50 +00:00
Ref < Script > task_script = get_script ( ) ;
if ( task_script . is_valid ( ) & & task_script - > is_tool ( ) ) {
2024-06-30 10:34:06 +00:00
GDVIRTUAL_CALL ( _get_configuration_warnings , warnings ) ; // Get script warnings.
2024-02-10 14:05:50 +00:00
}
2024-01-06 20:04:34 +00:00
ret . append_array ( warnings ) ;
2024-01-17 21:46:48 +00:00
ret . append_array ( _get_configuration_warnings ( ) ) ;
2022-12-15 07:26:52 +00:00
2023-08-15 15:05:30 +00:00
return ret ;
2022-08-28 10:54:34 +00:00
}
2024-01-06 20:04:34 +00:00
void BTTask : : print_tree ( int p_initial_tabs ) {
2022-08-28 10:54:34 +00:00
String tabs = " -- " ;
for ( int i = 0 ; i < p_initial_tabs ; i + + ) {
tabs + = " -- " ;
}
2024-01-06 20:04:34 +00:00
2024-01-09 12:34:24 +00:00
PRINT_LINE ( vformat ( " %s Name: %s Instance: %s " , tabs , get_task_name ( ) , Ref < BTTask > ( this ) ) ) ;
2024-01-06 20:04:34 +00:00
2022-08-28 10:54:34 +00:00
for ( int i = 0 ; i < get_child_count ( ) ; i + + ) {
get_child ( i ) - > print_tree ( p_initial_tabs + 1 ) ;
}
}
2024-05-14 09:39:32 +00:00
Ref < BehaviorTree > BTTask : : editor_get_behavior_tree ( ) {
2024-08-06 16:17:55 +00:00
# ifdef TOOLS_ENABLED
2024-05-14 09:39:32 +00:00
BTTask * task = this ;
2024-05-14 20:03:29 +00:00
while ( task - > data . behavior_tree_id . is_null ( ) & & task - > get_parent ( ) . is_valid ( ) ) {
2024-05-14 09:39:32 +00:00
task = task - > data . parent ;
}
2024-05-14 20:03:29 +00:00
return Object : : cast_to < BehaviorTree > ( ObjectDB : : get_instance ( task - > data . behavior_tree_id ) ) ;
2024-08-06 16:17:55 +00:00
# else
ERR_PRINT ( " BTTask::editor_get_behavior_tree: Not available in release builds. " ) ;
return Ref < BehaviorTree > ( ) ;
# endif
2024-05-14 09:39:32 +00:00
}
2024-08-06 16:17:55 +00:00
# ifdef TOOLS_ENABLED
2024-05-14 09:39:32 +00:00
void BTTask : : editor_set_behavior_tree ( const Ref < BehaviorTree > & p_bt ) {
2024-05-14 20:03:29 +00:00
data . behavior_tree_id = p_bt - > get_instance_id ( ) ;
2024-05-14 09:39:32 +00:00
}
2024-05-14 20:03:29 +00:00
# endif // TOOLS_ENABLED
2022-08-28 10:54:34 +00:00
void BTTask : : _bind_methods ( ) {
2022-12-17 07:33:18 +00:00
// Public Methods.
ClassDB : : bind_method ( D_METHOD ( " is_root " ) , & BTTask : : is_root ) ;
ClassDB : : bind_method ( D_METHOD ( " get_root " ) , & BTTask : : get_root ) ;
2024-05-01 23:27:14 +00:00
ClassDB : : bind_method ( D_METHOD ( " initialize " , " agent " , " blackboard " , " scene_root " ) , & BTTask : : initialize ) ;
2022-12-17 07:33:18 +00:00
ClassDB : : bind_method ( D_METHOD ( " clone " ) , & BTTask : : clone ) ;
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " execute " , " delta " ) , & BTTask : : execute ) ;
ClassDB : : bind_method ( D_METHOD ( " get_child " , " idx " ) , & BTTask : : get_child ) ;
2022-12-17 07:33:18 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_child_count " ) , & BTTask : : get_child_count ) ;
2023-08-19 10:19:58 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_child_count_excluding_comments " ) , & BTTask : : get_child_count_excluding_comments ) ;
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " add_child " , " task " ) , & BTTask : : add_child ) ;
ClassDB : : bind_method ( D_METHOD ( " add_child_at_index " , " task " , " idx " ) , & BTTask : : add_child_at_index ) ;
ClassDB : : bind_method ( D_METHOD ( " remove_child " , " task " ) , & BTTask : : remove_child ) ;
ClassDB : : bind_method ( D_METHOD ( " remove_child_at_index " , " idx " ) , & BTTask : : remove_child_at_index ) ;
ClassDB : : bind_method ( D_METHOD ( " has_child " , " task " ) , & BTTask : : has_child ) ;
ClassDB : : bind_method ( D_METHOD ( " is_descendant_of " , " task " ) , & BTTask : : is_descendant_of ) ;
2023-11-22 12:05:55 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_index " ) , & BTTask : : get_index ) ;
2022-12-17 07:33:18 +00:00
ClassDB : : bind_method ( D_METHOD ( " next_sibling " ) , & BTTask : : next_sibling ) ;
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " print_tree " , " initial_tabs " ) , & BTTask : : print_tree , Variant ( 0 ) ) ;
2022-12-17 07:33:18 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_task_name " ) , & BTTask : : get_task_name ) ;
2023-10-26 14:20:33 +00:00
ClassDB : : bind_method ( D_METHOD ( " abort " ) , & BTTask : : abort ) ;
2024-05-14 09:39:32 +00:00
ClassDB : : bind_method ( D_METHOD ( " editor_get_behavior_tree " ) , & BTTask : : editor_get_behavior_tree ) ;
2022-10-24 22:47:22 +00:00
2022-12-17 07:33:18 +00:00
// Properties, setters and getters.
2022-08-28 10:54:34 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_agent " ) , & BTTask : : get_agent ) ;
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_agent " , " agent " ) , & BTTask : : set_agent ) ;
2024-05-01 21:20:17 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_scene_root " ) , & BTTask : : get_scene_root ) ;
2022-11-02 16:47:07 +00:00
ClassDB : : bind_method ( D_METHOD ( " _get_children " ) , & BTTask : : _get_children ) ;
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " _set_children " , " children " ) , & BTTask : : _set_children ) ;
2022-08-28 10:54:34 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_blackboard " ) , & BTTask : : get_blackboard ) ;
ClassDB : : bind_method ( D_METHOD ( " get_parent " ) , & BTTask : : get_parent ) ;
2022-10-24 22:47:22 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_status " ) , & BTTask : : get_status ) ;
2023-04-14 08:16:26 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_elapsed_time " ) , & BTTask : : get_elapsed_time ) ;
2023-10-26 14:20:33 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_custom_name " ) , & BTTask : : get_custom_name ) ;
2024-03-04 20:36:16 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_custom_name " , " name " ) , & BTTask : : set_custom_name ) ;
2022-10-24 22:47:22 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " custom_name " ) , " set_custom_name " , " get_custom_name " ) ;
2023-07-27 11:52:29 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " agent " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , PROPERTY_USAGE_NONE ) , " set_agent " , " get_agent " ) ;
2024-05-01 21:20:17 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " scene_root " , PROPERTY_HINT_NODE_TYPE , " Node " , PROPERTY_USAGE_NONE ) , " " , " get_scene_root " ) ;
2023-07-27 11:52:29 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " blackboard " , PROPERTY_HINT_RESOURCE_TYPE , " Blackboard " , PROPERTY_USAGE_NONE ) , " " , " get_blackboard " ) ;
2022-12-15 07:26:52 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : ARRAY , " children " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL ) , " _set_children " , " _get_children " ) ;
2023-07-27 11:52:29 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " status " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NONE ) , " " , " get_status " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " elapsed_time " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NONE ) , " " , " get_elapsed_time " ) ;
2022-08-28 10:54:34 +00:00
2022-12-15 07:26:52 +00:00
GDVIRTUAL_BIND ( _setup ) ;
GDVIRTUAL_BIND ( _enter ) ;
GDVIRTUAL_BIND ( _exit ) ;
2024-03-04 20:36:16 +00:00
GDVIRTUAL_BIND ( _tick , " delta " ) ;
2022-12-15 07:26:52 +00:00
GDVIRTUAL_BIND ( _generate_name ) ;
2024-01-13 16:10:42 +00:00
GDVIRTUAL_BIND ( _get_configuration_warnings ) ;
2022-08-28 10:54:34 +00:00
}
BTTask : : BTTask ( ) {
2022-08-30 16:48:49 +00:00
}
BTTask : : ~ BTTask ( ) {
for ( int i = 0 ; i < get_child_count ( ) ; i + + ) {
ERR_FAIL_COND ( ! get_child ( i ) . is_valid ( ) ) ;
2023-07-20 18:10:02 +00:00
get_child ( i ) - > data . parent = nullptr ;
2022-08-30 16:48:49 +00:00
get_child ( i ) . unref ( ) ;
}
2022-11-02 16:47:07 +00:00
}