├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── addons
└── behav_tree_for_groups
│ ├── Reaction.gd
│ ├── action.svg
│ ├── action.svg.import
│ ├── action_2d.svg
│ ├── action_2d.svg.import
│ ├── action_3d.svg
│ ├── action_3d.svg.import
│ ├── add_agent.gd
│ ├── add_agent_at_pos_2d.gd
│ ├── add_agent_at_pos_3d.gd
│ ├── add_spring_on_contact.gd
│ ├── behavior.gd
│ ├── behavior.svg
│ ├── behavior.svg.import
│ ├── behavior_tree_for_groups.gd
│ ├── behavior_tree_for_groups.svg
│ ├── behavior_tree_for_groups.svg.import
│ ├── behavior_tree_for_groups_plugin.gd
│ ├── btfg_tools.gd
│ ├── change_color.gd
│ ├── change_color_random.gd
│ ├── clone_agent.gd
│ ├── clone_agent_at_pos_2d.gd
│ ├── clone_agent_at_pos_3d.gd
│ ├── condition.svg
│ ├── condition.svg.import
│ ├── condition_2d.svg
│ ├── condition_2d.svg.import
│ ├── condition_3d.svg
│ ├── condition_3d.svg.import
│ ├── data_plus.gd
│ ├── data_set.gd
│ ├── delete.gd
│ ├── fallback.gd
│ ├── fallback.svg
│ ├── fallback.svg.import
│ ├── field.gd
│ ├── force_angular_z.gd
│ ├── force_forward.gd
│ ├── force_global.gd
│ ├── force_radial.gd
│ ├── force_random.gd
│ ├── force_to_grid_value.gd
│ ├── global_data_plus.gd
│ ├── global_data_set.gd
│ ├── grid2d.gd
│ ├── icon.png
│ ├── icon.png.import
│ ├── if_age_between.gd
│ ├── if_age_equals.gd
│ ├── if_age_equals_periodic_values.gd
│ ├── if_age_equals_values.gd
│ ├── if_age_inf.gd
│ ├── if_age_sup.gd
│ ├── if_collision.gd
│ ├── if_data_between.gd
│ ├── if_data_equals.gd
│ ├── if_data_equals_periodic_values.gd
│ ├── if_data_equals_values.gd
│ ├── if_data_inf.gd
│ ├── if_data_sup.gd
│ ├── if_global_data_between.gd
│ ├── if_global_data_equals.gd
│ ├── if_global_data_inf.gd
│ ├── if_global_data_sup.gd
│ ├── if_grid_2d_value_inf.gd
│ ├── if_grid_2d_value_sup.gd
│ ├── if_in_box.gd
│ ├── if_mouse_click.gd
│ ├── if_no_contact.gd
│ ├── if_no_contact_with.gd
│ ├── if_proba.gd
│ ├── if_state_equals.gd
│ ├── if_step_between.gd
│ ├── if_time_between.gd
│ ├── if_time_inf.gd
│ ├── if_time_sup.gd
│ ├── new_agent_2d.gd
│ ├── new_agent_3d.gd
│ ├── new_grid_2d.gd
│ ├── parallel.gd
│ ├── parallel.svg
│ ├── parallel.svg.import
│ ├── plugin.cfg
│ ├── print_message.gd
│ ├── prompt_dialog.gd
│ ├── sequential.gd
│ ├── sequential.svg
│ ├── sequential.svg.import
│ ├── set_age.gd
│ ├── set_grid_value_2d.gd
│ ├── set_state.gd
│ ├── stay_in_box.gd
│ ├── torque_global.gd
│ ├── torque_random.gd
│ └── translate_random.gd
├── doc
└── behavior_tree_for_groups.pdf
├── examples
├── 2d_tutorial
│ ├── agent_2d_0.tscn
│ └── main.tscn
├── bacteria_colony
│ ├── bact.tscn
│ ├── gluc.tscn
│ ├── ker.tscn
│ ├── main.tscn
│ ├── main2.tscn
│ └── main3.tscn
├── coag
│ ├── coag.tscn
│ ├── fibro.tscn
│ └── ma_grille.tscn
├── coagulation
│ ├── CoaB82.tmp
│ ├── CoaFB45.tmp
│ ├── FA.tscn
│ ├── Thumbs.db
│ ├── factors.tscn
│ ├── grid_2d_0.tscn
│ ├── lesion.png
│ ├── lesion.png.import
│ ├── lesion.tscn
│ ├── main.tscn
│ ├── platelet.tscn
│ ├── sphere_64x64.png
│ └── sphere_64x64.png.import
├── flow_2d
│ ├── cell.tscn
│ └── main.tscn
├── flow_3d
│ ├── .DS_Store
│ ├── cell.tscn
│ └── main.tscn
├── forest_fire
│ ├── fire.tscn
│ ├── main.tscn
│ ├── tree.tscn
│ ├── tree_burned.tscn
│ └── tree_in_fire.tscn
├── grid2d
│ ├── Agt.tscn
│ ├── follower.tscn
│ ├── my_ADF0.tmp
│ ├── my_grid.tscn
│ ├── reaction-diffusion.tscn
│ └── reaction_diffusion.tscn
└── various
│ ├── agent_2d.tscn
│ ├── agent_a.tscn
│ ├── agent_b.tscn
│ ├── agent_c.tscn
│ ├── boilings.tscn
│ ├── cell_tissue.tscn
│ ├── cells_adhesion.tscn
│ ├── cicatrisation.tscn
│ ├── crowd_circular_mvt.tscn
│ ├── crowd_opposite_mvt.tscn
│ ├── curie_therapy.tscn
│ ├── grid_2d.tscn
│ ├── molecule_adhesion.tscn
│ ├── mouse_click.tscn
│ ├── prey_pred.tscn
│ └── test_generic_6dof_joint_3d.tscn
├── project.godot
└── screenshots
├── .gdignore
├── BTFG_documentation_front_page.png
├── BTFG_documentation_front_page.png.import
├── behav_tree_for_groups_flow.png
├── behav_tree_for_groups_flow_th.png
├── behav_tree_tor_groups_coag.png
├── behav_tree_tor_groups_coag_th.png
├── behavior_tree_for_groups_forest.png
├── behavior_tree_for_groups_forest_th.png
└── icon_big.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Godot 4+ specific ignores
2 | .godot/
3 |
4 | # Godot-specific ignores
5 | .import/
6 | export.cfg
7 | export_presets.cfg
8 |
9 | # Imported translations (automatically generated from CSV files)
10 | *.translation
11 |
12 | # Mono-specific ignores
13 | .mono/
14 | data_*/
15 | mono_crash.*.json
16 |
17 | # Mac specific
18 | .DS_Store/
19 | .DS_Store
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Pascal Ballet
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BehaviorTreeForGroups
2 | 
3 |
4 | **[Behavior Tree For Groups](doc/behavior_tree_for_groups.pdf) is an addon for Godot Engine that enables you to create swarms, flocks and multiagent systems using a single behavior tree.**
5 |
6 | **You can easily design collective behaviors without any code by adding groups to your nodes.**
7 |
8 | **Several examples, in 2D or 3D, are available: test them to understand how they work and what can be done**
9 |
10 | [](doc/behavior_tree_for_groups.pdf)
11 |
12 | ## Simple 2D tutorial
13 | ### First, create a new 2D scene
14 | * save it as *main*
15 | ### Second, create a new Agent2D
16 | * Click the + button in your scene tree and Select *NewAgent2D* (you can also create your own RigidBody2D)
17 | * Open the *Agent2D.tscn* automatically generated, and select the *RigidBody* at the root of this scene
18 | * In the inspector, go to the *Node Tab* then go to *Group* and add a new group called *test group*
19 | * Save the *Agent2D* scene
20 | * Go back to your *main* scene
21 | ### Third, create a simple behavior tree
22 | * Click the *plus button* in your *main* scene, then select the node *BehavTreeForGroups*
23 | * Then, add a new child node called *Behavior*
24 | * In the inspector of the newly created node *Behavior*, in the *Group* property, write *test_group*. That means all the nodes having the Group *test_group* will be treated.
25 | * Then, as child of the node *Behavior*, add a new node called *TranslateRandom*
26 | ### Finally, put about 10 *Agent2D* in your *main* scene
27 | * Drag & drop the file *Agent2D* inside your *main* scene
28 | * Execute your program: all the agents having the group *test_group* will move at random
29 | ### Many other nodes exists to create many different behaviors
30 |
31 | ## Simple 3D tutorial
32 | ### Very simple : replace 2D by 3D in the previous example!
33 | * And do not forget to put a camera and a light then execute your program
34 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/Reaction.gd:
--------------------------------------------------------------------------------
1 | extends Resource
2 | class_name Reaction
3 |
4 | var coef_r1:int = 0
5 | @export var reactive_1:String = ""
6 | var coef_r2:int = 0
7 | @export var reactive_2:String = ""
8 | var coef_r3:int = 0
9 | @export var reactive_3:String = ""
10 |
11 | @export var speed:float = 0.01
12 |
13 | var coef_p1:int = 0
14 | @export var product_1:String = ""
15 | var coef_p2:int = 0
16 | @export var product_2:String = ""
17 | var coef_p3:int = 0
18 | @export var product_3:String = ""
19 |
20 | func extract_coef_field():
21 |
22 | # reactives
23 | var lst_r1 = reactive_1.split(" ")
24 | if lst_r1.size() == 1:
25 | coef_r1 = 1
26 | reactive_1 = lst_r1[0]
27 | if lst_r1.size() == 2:
28 | coef_r1 = int(lst_r1[0])
29 | reactive_1 = lst_r1[1]
30 |
31 | var lst_r2 = reactive_2.split(" ")
32 | if lst_r2.size() == 1:
33 | coef_r2 = 1
34 | reactive_2 = lst_r2[0]
35 | if lst_r2.size() == 2:
36 | coef_r2 = int(lst_r2[0])
37 | reactive_2 = lst_r2[1]
38 |
39 | var lst_r3 = reactive_3.split(" ")
40 | if lst_r3.size() == 1:
41 | coef_r3 = 1
42 | reactive_3 = lst_r3[0]
43 | if lst_r3.size() == 2:
44 | coef_r3 = int(lst_r3[0])
45 | reactive_3 = lst_r3[1]
46 |
47 | # products
48 | var lst_p1 = product_1.split(" ")
49 | if lst_p1.size() == 1:
50 | coef_p1 = 1
51 | product_1 = lst_p1[0]
52 | if lst_p1.size() == 2:
53 | coef_p1 = int(lst_p1[0])
54 | product_1 = lst_p1[1]
55 |
56 | var lst_p2 = product_2.split(" ")
57 | if lst_p2.size() == 1:
58 | coef_p2 = 1
59 | product_2 = lst_p2[0]
60 | if lst_p2.size() == 2:
61 | coef_p2 = int(lst_p2[0])
62 | product_2 = lst_p2[1]
63 |
64 | var lst_p3 = product_3.split(" ")
65 | if lst_p3.size() == 1:
66 | coef_p3 = 1
67 | product_3 = lst_p3[0]
68 | if lst_p3.size() == 2:
69 | coef_p3 = int(lst_p3[0])
70 | product_3 = lst_p3[1]
71 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/action.svg:
--------------------------------------------------------------------------------
1 |
2 |
66 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/action.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://c0b5hrdrav62w"
6 | path="res://.godot/imported/action.svg-82397c85d2e85f7b3df5f9f676b99e24.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/action.svg"
14 | dest_files=["res://.godot/imported/action.svg-82397c85d2e85f7b3df5f9f676b99e24.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/action_2d.svg:
--------------------------------------------------------------------------------
1 |
2 |
64 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/action_2d.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cxykedgwukq8c"
6 | path="res://.godot/imported/action_2d.svg-0b5cd9faeb36f82b227527f4596f388d.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/action_2d.svg"
14 | dest_files=["res://.godot/imported/action_2d.svg-0b5cd9faeb36f82b227527f4596f388d.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/action_3d.svg:
--------------------------------------------------------------------------------
1 |
2 |
66 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/action_3d.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dm6qvndrqaw2b"
6 | path="res://.godot/imported/action_3d.svg-eec895205d47be25d61382570512377b.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/action_3d.svg"
14 | dest_files=["res://.godot/imported/action_3d.svg-eec895205d47be25d61382570512377b.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/add_agent.gd:
--------------------------------------------------------------------------------
1 | ## Dynamically add a new node/agent in the scene
2 | ## at the location of the current node/agent
3 |
4 | @icon("action.svg")
5 |
6 | class_name AddAgent
7 | extends BehaviorTreeForGroups
8 |
9 | #@export var agent_path:String = ""
10 | @export_file("*.tscn") var agent_tscn: String
11 |
12 | var root:Node = null
13 | var new_agent_scene:Resource = null
14 | var new_agent_behaviors:Array = []
15 | var new_agent_prototype:Node = null
16 |
17 | var btfg:BehaviorTreeForGroups = null
18 |
19 | func biodyn_process(agent) -> bool:
20 | #if agent_tscn.ends_with("_in_fire.tscn") == true:
21 | # print("TOUCH")
22 |
23 | if agent_tscn != "":
24 | # Initilize the Agent to clone
25 | if new_agent_scene == null:
26 | if root == null:
27 | root = get_tree().current_scene
28 | # Get the new Agent
29 | new_agent_scene = load(agent_tscn)
30 | new_agent_prototype = new_agent_scene.instantiate()
31 | # Find ALL its behaviors and put them in the new_agent_behaviors Array
32 | btfg = BTFG.btfg_root
33 |
34 | for b in btfg.get_children(): # Get ALL the behaviors of BehaviorTreeForGroups
35 | if b is Behavior and b.applies_on_agent(new_agent_prototype): #new_agent_prototype.is_in_group(b.on_group):
36 | # Copy the current behavior to the new_agent_prototype
37 | var behav_clone:Behavior = b.duplicate(15) # Duplicate the Behavior recursively
38 | behav_clone.process_mode = Node.PROCESS_MODE_INHERIT # We can do it because its agent (proto) is NEVER in the scene tree
39 | new_agent_prototype.add_child(behav_clone) # Add the Behavior to the prototype agent
40 |
41 | # Add of an Agent to the Scene
42 | var nb_agents:int = root.get_child_count()
43 | if new_agent_scene != null and nb_agents < BehaviorTreeForGroups.max_agents:
44 | var spawn = new_agent_prototype.duplicate()
45 | # Put and translate the spawn in the scene
46 | root.add_child(spawn)
47 | if agent.get("transform"):
48 | spawn.translate ( agent.transform.origin )
49 | else:
50 | spawn.translate ( agent.position )
51 | return true
52 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/add_agent_at_pos_2d.gd:
--------------------------------------------------------------------------------
1 | ## Dynamically add a new node/agent in the scene
2 | ## at a location chosen
3 |
4 | @icon("action_2d.svg")
5 |
6 | class_name AddAgentAtPos2D
7 | extends BehaviorTreeForGroups
8 |
9 | # exports
10 | @export_file("*.tscn") var agent_tscn: String
11 | @export var relative:bool = true
12 | @export var x:float = 0
13 | @export var y:float = 0
14 |
15 | var root:Node = null
16 | var new_agent_scene:Resource = null
17 | var new_agent_behaviors:Array = []
18 | var new_agent_prototype:Node = null
19 |
20 | var btfg:BehaviorTreeForGroups = null
21 |
22 | var newpos : Vector2
23 | var rx : float
24 | var ry : float
25 |
26 | func biodyn_process(agent) -> bool:
27 | if agent_tscn != "":
28 | # Initilize the Agent to clone
29 | if new_agent_scene == null:
30 | if root == null:
31 | root = get_tree().current_scene
32 | # Get the new Agent
33 | new_agent_scene = load(agent_tscn)
34 | new_agent_prototype = new_agent_scene.instantiate()
35 | # Find ALL its behaviors and put them in the new_agent_behaviors Array
36 | btfg = BTFG.btfg_root
37 |
38 | for b in btfg.get_children(): # Get ALL the behaviors of BehaviorTreeForGroups
39 | if b is Behavior and new_agent_prototype.is_in_group(b.on_group):
40 | # Copy the current behavior to the new_agent_prototype
41 | var behav_clone:Behavior = b.duplicate(15) # Duplicate the Behavior recursively
42 | behav_clone.process_mode = Node.PROCESS_MODE_INHERIT # We can do it because its agent (proto) is NEVER in the scene tree
43 | new_agent_prototype.add_child(behav_clone) # Add the Behavior to the prototype agent
44 |
45 | if relative == true:
46 | rx = x+agent.position.x
47 | ry = y+agent.position.y
48 | newpos = Vector2(rx, ry)
49 | else :
50 | newpos = Vector2(x, y)
51 | # Add of an Agent to the Scene
52 | var nb_agents:int = root.get_child_count()
53 | if new_agent_scene != null and nb_agents < BehaviorTreeForGroups.max_agents:
54 | var spawn = new_agent_prototype.duplicate()
55 | spawn.position = newpos
56 | # Put and translate the spawn in the scene
57 | root.add_child(spawn)
58 | if agent.get("transform"):
59 | spawn.translate ( Vector2(0,0))
60 | else:
61 | spawn.translate ( agent.position )
62 | return true
63 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/add_agent_at_pos_3d.gd:
--------------------------------------------------------------------------------
1 | ## Dynamically add a new node/agent in the scene
2 | ## at a location chosen
3 |
4 | @icon("action_3d.svg")
5 |
6 | class_name AddAgentAtPos3D
7 | extends BehaviorTreeForGroups
8 |
9 | #exports
10 | @export_file("*.tscn") var agent_tscn: String
11 | @export var relative:bool = true
12 | @export var x :float = 1
13 | @export var y :float = 1
14 | @export var z :float = 1
15 |
16 |
17 | var root:Node = null
18 | var new_agent_scene:Resource = null
19 | var new_agent_behaviors:Array = []
20 | var new_agent_prototype:Node = null
21 |
22 | var btfg:BehaviorTreeForGroups = null
23 |
24 | var newpos : Vector3
25 | var rx : float
26 | var ry : float
27 | var rz : float
28 |
29 |
30 |
31 |
32 | func biodyn_process(agent) -> bool:
33 | if agent is RigidBody3D :
34 |
35 |
36 | if agent_tscn != "":
37 | # Initilize the Agent to clone
38 | if new_agent_scene == null:
39 | if root == null:
40 | root = get_tree().current_scene
41 | # Get the new Agent
42 | new_agent_scene = load(agent_tscn)
43 | new_agent_prototype = new_agent_scene.instantiate()
44 | # Find ALL its behaviors and put them in the new_agent_behaviors Array
45 | btfg = BTFG.btfg_root
46 |
47 | for b in btfg.get_children(): # Get ALL the behaviors of BehaviorTreeForGroups
48 | if b is Behavior and new_agent_prototype.is_in_group(b.on_group):
49 | # Copy the current behavior to the new_agent_prototype
50 | var behav_clone:Behavior = b.duplicate(15) # Duplicate the Behavior recursively
51 | behav_clone.process_mode = Node.PROCESS_MODE_INHERIT # We can do it because its agent (proto) is NEVER in the scene tree
52 | new_agent_prototype.add_child(behav_clone) # Add the Behavior to the prototype agent
53 |
54 | if relative == true:
55 | rx = x+agent.position.x
56 | ry = y+agent.position.y
57 | rz = z+agent.position.z
58 | newpos = Vector3(rx, ry, rz)
59 | else :
60 | newpos = Vector3(x, y, z)
61 | # Add of an Agent to the Scene
62 | var nb_agents:int = root.get_child_count()
63 | if new_agent_scene != null and nb_agents < BehaviorTreeForGroups.max_agents:
64 | var spawn = new_agent_prototype.duplicate()
65 | spawn.position = newpos
66 | # Put and translate the spawn in the scene
67 | root.add_child(spawn)
68 | if agent.get("transform"):
69 | spawn.translate ( Vector3(0,0,0))
70 | else:
71 | spawn.translate ( agent.position )
72 | return true
73 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/behavior.gd:
--------------------------------------------------------------------------------
1 | ## Behavior root node.
2 | ## MUST be a DIRECT child of the BehaviorTreeForGroups Node
3 | ## Works on one specific group
4 | ## Execute all its children, always
5 | ## like a Parallel Node
6 |
7 | @icon("behavior.svg")
8 |
9 | class_name Behavior
10 | extends BehaviorTreeForGroups
11 |
12 | @export var activated:bool = true
13 | #@export var on_group = ""
14 |
15 | func _process(delta):
16 | biodyn_process(get_parent())
17 |
18 | func biodyn_process(agent:Node)->bool:
19 | # The Behavior Node is a Parallel Node
20 | # It executes all its children, stops after ALL children execution
21 | # Returns True when at least ONE child returns True
22 | if activated == false:
23 | return false
24 | var overall_success:bool = false
25 | for behav in get_children():
26 | var success = behav.biodyn_process(agent)
27 | if success == true:
28 | overall_success = true
29 |
30 | return overall_success
31 |
32 | func applies_on_agent(n:Node) -> bool:
33 | for gp in self.get_groups():
34 | if n.is_in_group(gp):
35 | return true
36 | return false
37 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/behavior.svg:
--------------------------------------------------------------------------------
1 |
2 |
52 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/behavior.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b8vs3hmibsimo"
6 | path="res://.godot/imported/behavior.svg-ac6cd31274dd65cc3e8e145a25b33e4b.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/behavior.svg"
14 | dest_files=["res://.godot/imported/behavior.svg-ac6cd31274dd65cc3e8e145a25b33e4b.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/behavior_tree_for_groups.gd:
--------------------------------------------------------------------------------
1 | ## Root node of the BehavTreeForGroups plugin.
2 | ## Its DIRECT children MUST be Behavior nodes
3 |
4 | @icon("behavior_tree_for_groups.svg")
5 |
6 | class_name BehaviorTreeForGroups
7 | extends Node
8 |
9 | ## Max number of created agents
10 | static var max_agents:int = 3000
11 | ##Number of agents
12 | static var nb_agents:int = 0
13 | ## Current simulation step
14 | static var simulation_step:int = 0
15 |
16 | var init:bool = false
17 |
18 | func get_class() -> String:
19 | return "BehaviorTreeForGroups"
20 |
21 | func put_all_behaviors():
22 | # The user will NOT execute BioDyn plugin
23 | if self.process_mode == Node.PROCESS_MODE_DISABLED:
24 | return
25 |
26 | # Put the behaviors INTO ALL agents according to their groups
27 | var root:Node = get_tree().current_scene
28 | for behav in get_children(): # Try to put the current behavior into the right agents
29 | if behav is Behavior and behav.process_mode != Node.PROCESS_MODE_DISABLED:
30 | for agt in root.get_children(): # Test the groups of ALL agents
31 | behav.process_mode = Node.PROCESS_MODE_DISABLED # It becomes Disabled in BioDyn behaviors (attached to no Agent)
32 | var apply_behav:bool = is_behavior_applicable(agt, behav)
33 | if apply_behav == true: #agt.is_in_group(behav.on_group): # the behav is for the agt
34 | var behav_clone:Behavior = behav.duplicate(15)
35 | behav_clone.process_mode = Node.PROCESS_MODE_INHERIT
36 | agt.add_child(behav_clone) #we add the behavior into the agent
37 | if agt.get("btfg_root"):
38 | agt.btfg_root = self
39 |
40 | func is_behavior_applicable(agt, behav)->bool:
41 | for b in behav.get_groups():
42 | if agt.is_in_group(b):
43 | return true
44 | return false
45 |
46 | func _ready():
47 | if BTFG.btfg_root == null:
48 | var the_script:Script = get_script()
49 | var script_name:String = ""
50 | if the_script != null:
51 | var script_path:NodePath = the_script.get_path()
52 | var sub:String = script_path.get_concatenated_subnames()
53 | script_name = sub.get_file()
54 |
55 | if script_name == "behavior_tree_for_groups.gd":
56 | BTFG.btfg_root = self
57 |
58 | func _process(delta):
59 | if init == true: # All behaviors have been put into Agents
60 | simulation_step += 1
61 | else:
62 | put_all_behaviors()
63 | init = true
64 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/behavior_tree_for_groups.svg:
--------------------------------------------------------------------------------
1 |
2 |
79 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/behavior_tree_for_groups.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cor7dp8jswgqk"
6 | path="res://.godot/imported/behavior_tree_for_groups.svg-333b37a8e7effe0f4965d4e8e34b9393.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/behavior_tree_for_groups.svg"
14 | dest_files=["res://.godot/imported/behavior_tree_for_groups.svg-333b37a8e7effe0f4965d4e8e34b9393.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/btfg_tools.gd:
--------------------------------------------------------------------------------
1 | extends Node
2 |
3 | class_name BTFG
4 | ## BehavTreeForGroups main node
5 | static var btfg_root:BehaviorTreeForGroups = null
6 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/change_color.gd:
--------------------------------------------------------------------------------
1 | ## Change the color of a node/agent.
2 |
3 | @icon("action.svg")
4 | class_name ChangeColor
5 | extends BehaviorTreeForGroups
6 |
7 | @export var color:Color = Color.CHARTREUSE
8 |
9 | func biodyn_process(agent)->bool:
10 | if agent is RigidBody3D:
11 | # New material
12 | var mat:StandardMaterial3D = StandardMaterial3D.new()
13 | mat.albedo_color = color
14 | # Put the new material
15 | var msh:MeshInstance3D = agent.get_node("MeshInstance3D")
16 | msh.material_override = mat
17 | return true
18 |
19 | if agent is RigidBody2D:
20 | var poly:Polygon2D = agent.get_node("Polygon2D")
21 | poly.color = color
22 | return true
23 |
24 | return false
25 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/change_color_random.gd:
--------------------------------------------------------------------------------
1 | ## Change the color of a node/agent randomly.
2 |
3 | @icon("action.svg")
4 | class_name ChangeColorRandom
5 | extends BehaviorTreeForGroups
6 |
7 |
8 | func biodyn_process(agent)->bool:
9 | if agent is RigidBody3D:
10 | # New material
11 | var mat:StandardMaterial3D = StandardMaterial3D.new()
12 | mat.albedo_color = Color(randf_range(0,1),randf_range(0,1),randf_range(0,1))
13 | # Put the new material
14 | var msh:MeshInstance3D = agent.get_node("MeshInstance3D")
15 | msh.material_override = mat
16 | return true
17 |
18 | if agent is RigidBody2D:
19 | var poly:Polygon2D = agent.get_node("Polygon2D")
20 | poly.color = Color(randf_range(0,1),randf_range(0,1),randf_range(0,1))
21 | return true
22 |
23 | return false
24 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/clone_agent.gd:
--------------------------------------------------------------------------------
1 | ## Duplicate the current node/agent
2 |
3 | @icon("action.svg")
4 |
5 | class_name CloneAgent
6 | extends BehaviorTreeForGroups
7 |
8 | func biodyn_process(agent) -> bool:
9 | # Clone agent to the Scene
10 | var nb_agents:int = get_tree().current_scene.get_child_count()
11 | if nb_agents < BehaviorTreeForGroups.max_agents:
12 | var spawn = agent.duplicate(15)
13 | # Put and translate the spawn in the scene
14 | get_tree().current_scene.add_child(spawn)
15 |
16 | return true
17 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/clone_agent_at_pos_2d.gd:
--------------------------------------------------------------------------------
1 | ## Duplicate the current node/agent in a position chosen
2 |
3 | @icon("action_2d.svg")
4 |
5 | class_name CloneAgentAtPos2D
6 | extends BehaviorTreeForGroups
7 |
8 | @export var relative:bool = true
9 | @export var x:float = 0
10 | @export var y:float = 0
11 |
12 | #position
13 | var newpos : Vector2
14 | var rx : float
15 | var ry : float
16 |
17 | func biodyn_process(agent) -> bool:
18 | #create the position of the clone
19 | if agent is RigidBody2D :
20 | if relative == true:
21 | rx = x+agent.position.x
22 | ry = y+agent.position.y
23 | newpos = Vector2(rx, ry)
24 | else :
25 | newpos = Vector2(x, y)
26 | #print(newpos)
27 | # Clone agent to the Scene
28 | var nb_agents:int = get_tree().current_scene.get_child_count()
29 | if nb_agents < BehaviorTreeForGroups.max_agents:
30 | var spawn = agent.duplicate(15)
31 | #assign the position
32 | spawn.position = newpos
33 | # Put and translate the spawn in the scene
34 | get_tree().current_scene.add_child(spawn)
35 | return true
36 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/clone_agent_at_pos_3d.gd:
--------------------------------------------------------------------------------
1 | ## Duplicate the current node/agent in a position chosen
2 |
3 | @icon("action_3d.svg")
4 |
5 | class_name CloneAgentAtPos3D
6 | extends BehaviorTreeForGroups
7 |
8 | @export var relative:bool = true
9 | @export var x :float = 1
10 | @export var y :float = 1
11 | @export var z :float = 1
12 |
13 | #position
14 | var newpos : Vector3
15 | var rx : float
16 | var ry : float
17 | var rz : float
18 |
19 | func biodyn_process(agent) -> bool:
20 | #create the position of the clone
21 | if agent is RigidBody3D :
22 | if relative == true :
23 | rx = x+agent.position.x
24 | ry = y+agent.position.y
25 | rz = z+agent.position.z
26 | newpos = Vector3(rx, ry, rz)
27 | else :
28 | newpos = Vector3(x, y, z)
29 | var nb_agents:int = get_tree().current_scene.get_child_count()
30 | if nb_agents < BehaviorTreeForGroups.max_agents:
31 | var spawn = agent.duplicate(15)
32 | #assign the position
33 | spawn.position = newpos
34 | # Put and translate the spawn in the scene
35 | get_tree().current_scene.add_child(spawn)
36 | return true
37 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/condition.svg:
--------------------------------------------------------------------------------
1 |
2 |
46 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/condition.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://di6h3i6wutt1a"
6 | path="res://.godot/imported/condition.svg-be15db2fc4b79447b8f91834a6bcaf0b.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/condition.svg"
14 | dest_files=["res://.godot/imported/condition.svg-be15db2fc4b79447b8f91834a6bcaf0b.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/condition_2d.svg:
--------------------------------------------------------------------------------
1 |
2 |
46 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/condition_2d.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dbas35fjgsbwv"
6 | path="res://.godot/imported/condition_2d.svg-74b4e16627102cb24d295cbf3e6d313c.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/condition_2d.svg"
14 | dest_files=["res://.godot/imported/condition_2d.svg-74b4e16627102cb24d295cbf3e6d313c.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/condition_3d.svg:
--------------------------------------------------------------------------------
1 |
2 |
46 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/condition_3d.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://be71n6y4vjmpc"
6 | path="res://.godot/imported/condition_3d.svg-dfa75c275f007577f1438903b09d3242.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/condition_3d.svg"
14 | dest_files=["res://.godot/imported/condition_3d.svg-dfa75c275f007577f1438903b09d3242.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/data_plus.gd:
--------------------------------------------------------------------------------
1 | ## Add a float to a current agent's data
2 |
3 | @icon("action.svg")
4 | class_name DataPlus
5 | extends BehaviorTreeForGroups
6 |
7 | @export var data_name:String = ""
8 | @export var add_value:float = 0
9 |
10 | func biodyn_process(agent:Node)->bool:
11 | if data_name != "":
12 | if agent.has_meta(data_name):
13 | var val:float = 0
14 | val = agent.get_meta(data_name)
15 | val = val + add_value
16 | agent.set_meta(data_name, val)
17 | return true
18 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/data_set.gd:
--------------------------------------------------------------------------------
1 | ## Set a float to a current agent's data
2 |
3 | @icon("action.svg")
4 | class_name DataSet
5 | extends BehaviorTreeForGroups
6 |
7 | @export var data_name:String = ""
8 | @export var set_to_value:float = 0
9 |
10 | func biodyn_process(agent:Node)->bool:
11 | if data_name != "":
12 | agent.set_meta(data_name, set_to_value)
13 | return true
14 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/delete.gd:
--------------------------------------------------------------------------------
1 | ## Remove the current agent from the scene
2 |
3 | @icon("action.svg")
4 | class_name Delete
5 | extends BehaviorTreeForGroups
6 |
7 | func biodyn_process(agent)->bool:
8 | agent.queue_free()
9 | return true
10 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/fallback.gd:
--------------------------------------------------------------------------------
1 | ## Execute its children nodes
2 | ## upto one of them succeed
3 |
4 | @icon("fallback.svg")
5 | class_name Fallback
6 | extends BehaviorTreeForGroups
7 |
8 | @export var activated:bool = true
9 |
10 | # Called every frame. 'delta' is the elapsed time since the previous frame.
11 | func biodyn_process(agent)->bool:
12 | # Fallback Node
13 | # Execute its children, stops when :
14 | # a) one succeeded (=> return success)
15 | # b) or all failed (=> return failure)
16 | if activated == false:
17 | return false
18 | var overall_success:bool = false
19 | for behav in self.get_children():
20 | var success = behav.biodyn_process(agent)
21 | if success == true:
22 | return true
23 | return false
24 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/fallback.svg:
--------------------------------------------------------------------------------
1 |
2 |
57 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/fallback.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://7swuq7wv1mja"
6 | path="res://.godot/imported/fallback.svg-70c42f61285363b7207b30c252a557ca.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/fallback.svg"
14 | dest_files=["res://.godot/imported/fallback.svg-70c42f61285363b7207b30c252a557ca.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/field.gd:
--------------------------------------------------------------------------------
1 | extends Resource
2 |
3 | class_name Field
4 |
5 | @export var name:String = "Field"
6 | @export var color:Color = Color.BLUE
7 | @export_range(0.0, 1.0) var diffusion_speed:float = 0.3
8 | @export var degradation_speed:float = 0.001
9 | @export_enum("0", "1", "Random") var initialisation: String = "0"
10 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/force_angular_z.gd:
--------------------------------------------------------------------------------
1 | ## Applies an angular force to the current agent
2 | ## relating to the center
3 |
4 | @icon("action.svg")
5 | class_name ForceAngularZ
6 | extends BehaviorTreeForGroups
7 |
8 | ## Center of the force field (vortex)
9 | @export var center:Vector3
10 | ##Intensity of the force field (vortex)
11 | @export var intensity:float = 1.0
12 |
13 | func biodyn_process(agent)->bool:
14 | if agent is RigidBody3D:
15 | var dv:Vector3 = center - agent.position.normalized()
16 | var du:Vector3 = Vector3(-dv.y, dv.x, 0)
17 | agent.apply_central_impulse ( intensity*du )
18 | return true
19 | if agent is RigidBody2D:
20 | var dv:Vector2 = Vector2(center.x, center.y) - agent.position.normalized()
21 | var du:Vector2 = Vector2(-dv.y, dv.x)
22 | agent.apply_central_impulse ( intensity*du )
23 | return true
24 |
25 | return false
26 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/force_forward.gd:
--------------------------------------------------------------------------------
1 | ## Applies a forward force to the current agent
2 |
3 | @icon("action.svg")
4 | class_name ForceForward
5 | extends BehaviorTreeForGroups
6 |
7 | @export var fx:float = 0.0
8 |
9 | func biodyn_process(agent)->bool:
10 | if agent is RigidBody3D:
11 | agent.apply_central_impulse(agent.transform.basis.x * fx)
12 | return true
13 |
14 | if agent is RigidBody2D:
15 | agent.apply_central_impulse(agent.transform.basis.x * fx)
16 | return true
17 |
18 | return false
19 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/force_global.gd:
--------------------------------------------------------------------------------
1 | ## Applies a force to the current agent
2 | ## relating to the absolute axis reference
3 |
4 | @icon("action.svg")
5 | class_name ForceGlobal
6 | extends BehaviorTreeForGroups
7 |
8 | @export var fx:float = 0.0
9 | @export var fy:float = 0.0
10 | @export var fz:float = 0.0
11 |
12 | func biodyn_process(agent)->bool:
13 | if agent is RigidBody3D:
14 | agent.apply_central_impulse ( Vector3 (fx, fy, fz) )
15 | return true
16 | if agent is RigidBody2D:
17 | agent.apply_central_impulse ( Vector2 (fx, fy) )
18 | return true
19 | return false
20 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/force_radial.gd:
--------------------------------------------------------------------------------
1 | ## Applies a centrifuge or centripet force to the current agent
2 | ## relating to the center
3 |
4 | @icon("action.svg")
5 | class_name ForceRadial
6 | extends BehaviorTreeForGroups
7 |
8 | ## Center of the force field
9 | @export var center:Vector3
10 | ## Intensity of the force field
11 | @export var intensity:float = 1.0
12 |
13 | func biodyn_process(agent)->bool:
14 | if agent is RigidBody3D:
15 | var dv:Vector3 = center - agent.position.normalized()
16 | agent.apply_central_impulse ( intensity*dv )
17 | return true
18 |
19 | if agent is RigidBody2D:
20 | var dv:Vector2 = Vector2(center.x, center.y) - agent.position.normalized()
21 | agent.apply_central_impulse ( intensity*dv )
22 | return true
23 |
24 | return false
25 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/force_random.gd:
--------------------------------------------------------------------------------
1 | ## Applies a random force to the current agent
2 |
3 | @icon("action.svg")
4 | class_name ForceRandom
5 | extends BehaviorTreeForGroups
6 |
7 | @export var F:Vector3 = Vector3(1,1,1)
8 |
9 | func biodyn_process(agent)->bool:
10 | if agent is RigidBody3D:
11 | var ffx:float = F.x * (randf() - 0.5)
12 | var ffy:float = F.y * (randf() - 0.5)
13 | var ffz:float = F.z * (randf() - 0.5)
14 | #call_deferred("agent.apply_central_force", Vector3 (ffx, ffy, ffz) )
15 | agent.apply_central_impulse ( Vector3 (ffx, ffy, ffz) )
16 | return true
17 |
18 | if agent is RigidBody2D:
19 | var ffx:float = F.x * (randf() - 0.5)
20 | var ffy:float = F.y * (randf() - 0.5)
21 | #call_deferred("agent.apply_central_force", Vector3 (ffx, ffy, ffz) )
22 | agent.apply_central_impulse ( Vector2 (ffx, ffy) )
23 | return true
24 |
25 | return false
26 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/force_to_grid_value.gd:
--------------------------------------------------------------------------------
1 | ## Applies a force to the current agent
2 | ## toward the value the agent has to reach
3 | ## inside a Grid of values
4 |
5 | @icon("action.svg")
6 | class_name ForceToGridValue
7 | extends BehaviorTreeForGroups
8 |
9 | @export var on_grid_group:String = ""
10 | @export var for_field:String = ""
11 | @export var target_value:float = 0
12 | @export var force:float = 0
13 |
14 | var grids:Array = Array()
15 |
16 | func _ready():
17 | grids = get_tree().get_nodes_in_group(on_grid_group)
18 | pass
19 |
20 | func biodyn_process(agent)->bool:
21 | for grid in grids:
22 | # 2D
23 | var F:Vector2 = Vector2(0,0)
24 | if agent is RigidBody2D and "values_t0" in grid:
25 | var ax:float = agent.position.x
26 | var ay:float = agent.position.y
27 | var gx_min:float = grid.position.x
28 | var gx_max:float = gx_min+grid.size.x
29 | var gy_min:float = grid.position.y
30 | var gy_max:float = gy_min+grid.size.y
31 | if ax >= gx_min && ax < gx_max:
32 | if ay >= gy_min && ay < gy_max:
33 | var px:int = ((ax - gx_min) / grid.size.x) * grid.SX
34 | var py:int = ((ay - gy_min) / grid.size.y) * grid.SY
35 | var p:int = px+py*grid.SX
36 | var fx:float = 0
37 | var fy:float = 0
38 | if grid.fields_dico.has(for_field) == true:
39 | var p0:float = grid.values_t0[(p+1)%(grid.SX*grid.SY)].values[grid.fields_dico[for_field]]
40 | var p1:float = grid.values_t0[(p-grid.SX+grid.SX*grid.SY)%(grid.SX*grid.SY)].values[grid.fields_dico[for_field]]
41 | var p2:float = grid.values_t0[(p-1+grid.SX*grid.SY)%(grid.SX*grid.SY)].values[grid.fields_dico[for_field]]
42 | var p3:float = grid.values_t0[(p+grid.SX)%(grid.SX*grid.SY)].values[grid.fields_dico[for_field]]
43 | if grid.values_t0[p].values[grid.fields_dico[for_field]] >= target_value:
44 | # Go to the lowest value arround
45 | if p0 <= p1 && p0 <= p2 && p0 <= p3:
46 | fx = force
47 | elif p1 <= p2 && p1 <= p3:
48 | fy = -force
49 | elif p2 <= p3:
50 | fx = -force
51 | else:
52 | fy = force
53 | if grid.values_t0[p].values[grid.fields_dico[for_field]] < target_value:
54 | # Go to the highest value arround
55 | if p0 >= p1 && p0 >= p2 && p0 >= p3:
56 | fx = force
57 | elif p1 >= p2 && p1 >= p3:
58 | fy = -force
59 | elif p2 >= p3:
60 | fx = -force
61 | else:
62 | fy = force
63 | F = F + Vector2(fx,fy)
64 | agent.apply_impulse(F)
65 | return true
66 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/global_data_plus.gd:
--------------------------------------------------------------------------------
1 | ## Add a float to a current global's data
2 |
3 | @icon("action.svg")
4 | class_name GlobalDataPlus
5 | extends BehaviorTreeForGroups
6 |
7 | @export var global_data_name:String = ""
8 | @export var add_value:float = 0
9 |
10 | func biodyn_process(agent:Node)->bool:
11 | if global_data_name != "":
12 | if BTFG.btfg_root.has_meta(global_data_name):
13 | var val:float = 0
14 | val = BTFG.btfg_root.get_meta(global_data_name)
15 | val = val + add_value
16 | BTFG.btfg_root.set_meta(global_data_name, val)
17 | return true
18 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/global_data_set.gd:
--------------------------------------------------------------------------------
1 | ## Set a float to global scene's data
2 |
3 | @icon("action.svg")
4 | class_name GlobalDataSet
5 | extends BehaviorTreeForGroups
6 |
7 | @export var global_data_name:String = ""
8 | @export var set_to_value:float = 0
9 |
10 | func biodyn_process(agent:Node)->bool:
11 | if global_data_name != "":
12 | BTFG.btfg_root.set_meta(global_data_name, set_to_value)
13 | return true
14 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/grid2d.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends TextureRect
3 |
4 | @export var SX:int = 64
5 | @export var SY:int = 32
6 | @export var loop_x:bool = false
7 | @export var loop_y:bool = false
8 |
9 | @export var fields:Array[Field] = []
10 | @export var reactions:Array[Reaction] = []
11 |
12 | @export var opacity:float = 1.0
13 | #@export var show_iso:bool = false
14 | @export var print_values:bool = false
15 |
16 | @export var state:int = 0
17 | @export var age:int = 0
18 |
19 | var values_t0:Array[data] = []
20 | var values_t1:Array[data] = []
21 |
22 | var xmin:float; var xmax:float; var ymin:float;var ymax:float
23 |
24 | # Store the values of each field for ONE position in the matrix
25 | # Each data stores one qte of all the Fields
26 | class data:
27 | var values:Array[float] = []
28 | func _init(fields:Array[Field], i:int, j:int, SX:int, SY:int, loop_x:bool, loop_y:bool):
29 | values.resize(fields.size())
30 | for f in fields.size():
31 | if fields[f] != null:
32 | if fields[f].initialisation == "0":
33 | values[f] = 0.0
34 | elif fields[f].initialisation == "1":
35 | values[f] = 1.0
36 | elif fields[f].initialisation == "Random":
37 | values[f] = randf()
38 | if loop_x == false and (i == 0 or i == SX-1) : # borders are exluded if non toric matrix
39 | values[f] = 0.0
40 | if loop_y == false and (j == 0 or j == SY-1):
41 | values[f] = 0.0
42 | var fields_dico:Dictionary
43 |
44 | func _ready():
45 | # loop or not loop
46 | if loop_x == true:
47 | xmin = 0
48 | xmax = SX
49 | else:
50 | xmin = 1
51 | xmax = SX-1
52 | if loop_y == true:
53 | ymin = 0
54 | ymax = SY
55 | else:
56 | ymin = 1
57 | ymax = SY-1
58 |
59 | # Init matrix values
60 | values_t0.resize(SX*SY)
61 | values_t1.resize(SX*SY)
62 | for i in SX:
63 | for j in SY:
64 | values_t0[i+j*SX] = data.new(fields, i, j, SX, SY, loop_x, loop_y) # Call the constructor (_init)
65 | values_t1[i+j*SX] = data.new(fields, i, j, SX, SY, loop_x, loop_y)
66 |
67 | # fields names => id: allow a quick access of fields names during reactions
68 | var id:int = 0
69 | fields_dico["-"]=-1
70 | for f in fields:
71 | if f!= null:
72 | fields_dico[f.name]=id
73 | id += 1
74 |
75 | # reactions init
76 | for r in reactions:
77 | if r!=null:
78 | r.extract_coef_field()
79 | if fields_dico.has(r.reactive_1) == false:
80 | r.reactive_1 = "-"
81 | if fields_dico.has(r.reactive_2) == false:
82 | r.reactive_2 = "-"
83 | if fields_dico.has(r.reactive_3) == false:
84 | r.reactive_3 = "-"
85 | if fields_dico.has(r.product_1) == false:
86 | r.product_1 = "-"
87 | if fields_dico.has(r.product_2) == false:
88 | r.product_2 = "-"
89 | if fields_dico.has(r.product_3) == false:
90 | r.product_3 = "-"
91 |
92 | func _process(_delta):
93 | if not Engine.is_editor_hint():
94 | reaction_diffusion()
95 | #if show_iso == false:
96 | display_values()
97 | #else:
98 | # display_iso()
99 | if print_values == true:
100 | print_all_values()
101 | age += 1
102 |
103 | func reaction_diffusion():
104 | # Reaction
105 | var r1 : int
106 | var r2 : int
107 | var r3 : int
108 | var s : float
109 | var p1 : int
110 | var p2 : int
111 | var p3 : int
112 |
113 | for r in reactions:
114 | if r != null:
115 | for i in range(xmin,xmax):
116 | for j in range(ymin,ymax):
117 | var p:int = i+j*SX
118 | r1 = fields_dico[r.reactive_1]
119 | r2 = fields_dico[r.reactive_2]
120 | r3 = fields_dico[r.reactive_3]
121 | p1 = fields_dico[r.product_1]
122 | p2 = fields_dico[r.product_2]
123 | p3 = fields_dico[r.product_3]
124 | s = r.speed
125 |
126 | # NO reactive
127 | if r1 < 0 and r2 < 0 and r3 < 0:
128 | # if product
129 | if p1 >= 0:
130 | values_t0[p].values[p1] += s*r.coef_p1
131 | if p2 >= 0:
132 | values_t0[p].values[p2] += s*r.coef_p2
133 | if p3 >= 0:
134 | values_t0[p].values[p3] += s*r.coef_p3
135 | # Only ONE reactive (r1)
136 | if r1 >= 0 and r2 < 0 and r3 < 0:
137 | var d_qte:float = s * values_t0[p].values[r1]
138 | values_t0[p].values[r1] -= d_qte*r.coef_r1
139 | # if product
140 | if p1 >= 0:
141 | values_t0[p].values[p1] += d_qte*r.coef_p1
142 | if p2 >= 0:
143 | values_t0[p].values[p2] += d_qte*r.coef_p2
144 | if p3 >= 0:
145 | values_t0[p].values[p3] += d_qte*r.coef_p3
146 | # Only ONE reactive (r2)
147 | if r1 < 0 and r2 >= 0 and r3 < 0:
148 | var d_qte:float = s * values_t0[p].values[r2]
149 | values_t0[p].values[r2] -= d_qte*r.coef_r2
150 | # if product
151 | if p1 >= 0:
152 | values_t0[p].values[p1] += d_qte*r.coef_p1
153 | if p2 >= 0:
154 | values_t0[p].values[p2] += d_qte*r.coef_p2
155 | if p3 >= 0:
156 | values_t0[p].values[p3] += d_qte*r.coef_p3
157 | # Only ONE reactive (r3)
158 | if r1 < 0 and r2 < 0 and r3 >= 0:
159 | var d_qte:float = s * values_t0[p].values[r3]
160 | values_t0[p].values[r3] -= d_qte*r.coef_r3
161 | # if product
162 | if p1 >= 0:
163 | values_t0[p].values[p1] += d_qte*r.coef_p1
164 | if p2 >= 0:
165 | values_t0[p].values[p2] += d_qte*r.coef_p2
166 | if p3 >= 0:
167 | values_t0[p].values[p3] += d_qte*r.coef_p3
168 | # TWO reactives (r1+r2)
169 | if r1 >=0 and r2 >= 0 and r3 < 0:
170 | var d_qte:float = s * values_t0[p].values[r1] * values_t0[p].values[r2]
171 | values_t0[p].values[r1] -= d_qte*r.coef_r1
172 | values_t0[p].values[r2] -= d_qte*r.coef_r2
173 | # if product
174 | if p1 >= 0:
175 | values_t0[p].values[p1] += d_qte*r.coef_p1
176 | if p2 >= 0:
177 | values_t0[p].values[p2] += d_qte*r.coef_p2
178 | if p3 >= 0:
179 | values_t0[p].values[p3] += d_qte*r.coef_p3
180 | # TWO reactives (r1+r3)
181 | if r1 >=0 and r2 < 0 and r3 >= 0:
182 | var d_qte:float = s * values_t0[p].values[r1] * values_t0[p].values[r3]
183 | values_t0[p].values[r1] -= d_qte*r.coef_r1
184 | values_t0[p].values[r3] -= d_qte*r.coef_r3
185 | # if product
186 | if p1 >= 0:
187 | values_t0[p].values[p1] += d_qte*r.coef_p1
188 | if p2 >= 0:
189 | values_t0[p].values[p2] += d_qte*r.coef_p2
190 | if p3 >= 0:
191 | values_t0[p].values[p3] += d_qte*r.coef_p3
192 | # TWO reactives (r1+r3)
193 | if r1 < 0 and r2 >= 0 and r3 >= 0:
194 | var d_qte:float = s * values_t0[p].values[r2] * values_t0[p].values[r3]
195 | values_t0[p].values[r2] -= d_qte*r.coef_r2
196 | values_t0[p].values[r3] -= d_qte*r.coef_r3
197 | # if product
198 | if p1 >= 0:
199 | values_t0[p].values[p1] += d_qte*r.coef_p1
200 | if p2 >= 0:
201 | values_t0[p].values[p2] += d_qte*r.coef_p2
202 | if p3 >= 0:
203 | values_t0[p].values[p3] += d_qte*r.coef_p3
204 | # THREE reactives (r1+r2+r3)
205 | if r1 >= 0 and r2 >= 0 and r3 >= 0:
206 | var d_qte:float = s * values_t0[p].values[r1] * values_t0[p].values[r2] * values_t0[p].values[r3]
207 | values_t0[p].values[r1] -= d_qte*r.coef_r1
208 | values_t0[p].values[r2] -= d_qte*r.coef_r2
209 | values_t0[p].values[r3] -= d_qte*r.coef_r3
210 | # if product
211 | if p1 >= 0:
212 | values_t0[p].values[p1] += d_qte*r.coef_p1
213 | if p2 >= 0:
214 | values_t0[p].values[p2] += d_qte*r.coef_p2
215 | if p3 >= 0:
216 | values_t0[p].values[p3] += d_qte*r.coef_p3
217 |
218 | # Diffusion
219 | for f in fields.size():
220 | if fields[f] != null:
221 | var degrad:float = fields[f].degradation_speed
222 | var diffus:float = fields[f].diffusion_speed
223 | for i in range(xmin,xmax):
224 | for j in range(ymin,ymax):
225 | var p:int = i+j*SX
226 | var v0:float = values_t0[ (i+1)%SX+j*SX].values[f]
227 | var v1:float = values_t0[ (i-1+SX)%SX+j*SX].values[f]
228 | var v2:float = values_t0[ i%SX+((j+1)%SY)*SX].values[f]
229 | var v3:float = values_t0[ i%SX+((j-1+SY)%SY)*SX].values[f]
230 | values_t1[p].values[f] = (1.0-degrad)*(1.0-diffus)*values_t0[p].values[f] + diffus*(v0+v1+v2+v3)*0.25
231 |
232 | for i in range(SX*SY):
233 | values_t0[i].values[f] = values_t1[i].values[f]
234 |
235 |
236 | func display_values():
237 | var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8)
238 | for f in fields.size():
239 | if fields[f] != null:
240 | for i in range(SX):
241 | for j in range(SY):
242 | var p:int = i+j*SX
243 | var v:float = values_t0[p].values[f]
244 | var col:Color = img.get_pixel(i,j)
245 | var baseColor:Color = fields[f].color
246 | var R = max(0.1, min(v*baseColor.r+col.r,0.9))
247 | var G = max(0.1, min(v*baseColor.g+col.g,0.9))
248 | var B = max(0.1, min(v*baseColor.b+col.b,0.9))
249 | img.set_pixel(i,j,Color(R,G,B,opacity) )
250 | set_texture(ImageTexture.create_from_image(img))
251 |
252 |
253 | func print_all_values():
254 | var i:int = randi_range(0, SX-1)
255 | var j:int = randi_range(0, SY-1)
256 | for f in fields.size():
257 | var v:float = values_t0[i+j*SX].values[f]
258 | print("At (" + str(i) + "," + str(j) + ")=" + str(num_zeros(v)) + "<=" + str(v) )
259 |
260 | func num_zeros(val:float) -> int:
261 | var n:int = 0
262 | if val != 0:
263 | n = -floor( log(abs(val)) / log(10) ) - 1
264 | return n
265 |
266 | func display_iso():
267 | return
268 | #var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8)
269 | #var r:float; var g:float; var b:float
270 | #for i in range(1,SX-2):
271 | #for j in range(1,SY-2):
272 | #var p:int = i+j*SX
273 | #var v0:float = num_zeros(values_t0[p])
274 | #var vg:float = num_zeros(values_t0[p-1])
275 | #var vd:float = num_zeros(values_t0[p+1])
276 | #var vh:float = num_zeros(values_t0[p-SX])
277 | #var vb:float = num_zeros(values_t0[p+SX])
278 | #var e:float = 1.0
279 | #if vg>v0 || vd>v0 || vh>v0 || vb>v0:
280 | #e = 0.5
281 | #img.set_pixel(i,j,Color(e*baseColor.r,e*baseColor.g,e*baseColor.b,baseColor.a) )
282 | #set_texture(ImageTexture.create_from_image(img))
283 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/addons/behav_tree_for_groups/icon.png
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/icon.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://y1248e31lb2p"
6 | path="res://.godot/imported/icon.png-73f6b8b1eff28052e2c7e3d863afda88.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/icon.png"
14 | dest_files=["res://.godot/imported/icon.png-73f6b8b1eff28052e2c7e3d863afda88.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_age_between.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the agent's age
2 | ## is between 2 given integer numbers.
3 |
4 | @icon("condition.svg")
5 | class_name IfAgeBetween
6 | extends BehaviorTreeForGroups
7 |
8 | ## Initial simulation/execution step
9 | @export var age_start:int = 0
10 | ## Final simulation/execution step
11 | @export var age_end:int = 100
12 |
13 | func _ready():
14 | pass
15 |
16 | # Called every frame. 'delta' is the elapsed time since the previous frame.
17 | func biodyn_process(agent)->bool:
18 | var age:int = agent.age
19 | if age >= age_start and age <= age_end:
20 | return true
21 | else:
22 | return false
23 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_age_equals.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the agent's age
2 | ## is equal to the given integer number.
3 |
4 | @icon("condition.svg")
5 | class_name IfAgeEquals
6 | extends BehaviorTreeForGroups
7 |
8 | @export var age_equals:int = 0
9 |
10 | func _ready():
11 | pass
12 |
13 | # Called every frame. 'delta' is the elapsed time since the previous frame.
14 | func biodyn_process(agent)->bool:
15 | var age:int = agent.age
16 | if age == age_equals :
17 | return true
18 | else:
19 | return false
20 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_age_equals_periodic_values.gd:
--------------------------------------------------------------------------------
1 | ## Return true when age reaches
2 | ## specified periodic values
3 |
4 | @icon("condition.svg")
5 | class_name IfAgeEqualsPeriodicValues
6 | extends BehaviorTreeForGroups
7 |
8 |
9 | ## Size of each step
10 | @export var period: int =0
11 | @export var min_age: int =0
12 | ## Put -1 for infinite max age
13 | @export var max_age: int = -1
14 |
15 | func biodyn_process(agent)->bool:
16 | var age:int =agent.age
17 | if max_age == -1 :
18 | if age >= min_age :
19 | if (age-min_age)%period == 0 :
20 | return true
21 | else :
22 | return false
23 | else :
24 | return false
25 | elif age >= min_age and age <= max_age:
26 | if (age-min_age)%period == 0 :
27 | return true
28 | else :
29 | return false
30 | else :
31 | return false
32 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_age_equals_values.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the age equals
2 | ## one of the given values.
3 |
4 | @icon("condition.svg")
5 | class_name IfAgeEqualsValues
6 | extends BehaviorTreeForGroups
7 |
8 | @export var values:Array[int] = [10,20,25]
9 |
10 | # Called every frame. 'delta' is the elapsed time since the previous frame.
11 | func biodyn_process(agent)->bool:
12 | var age:int = agent.age
13 | if values.find(age, 0) >= 0 :
14 | return true
15 | else:
16 | return false
17 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_age_inf.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the agent's age
2 | ## is inf to the given integer number.
3 |
4 | @icon("condition.svg")
5 | class_name IfAgeInf
6 | extends BehaviorTreeForGroups
7 |
8 | @export var age_inferior_to:int = 0
9 |
10 | # Called every frame. 'delta' is the elapsed time since the previous frame.
11 | func biodyn_process(agent)->bool:
12 | if agent.age <= age_inferior_to :
13 | return true
14 | else:
15 | return false
16 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_age_sup.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the agent's age
2 | ## is equal to the given integer number.
3 |
4 | @icon("condition.svg")
5 | class_name IfAgeSup
6 | extends BehaviorTreeForGroups
7 |
8 | @export var age_superior_to:int = 0
9 |
10 | # Called every frame. 'delta' is the elapsed time since the previous frame.
11 | func biodyn_process(agent)->bool:
12 | if agent.age >= age_superior_to :
13 | return true
14 | else:
15 | return false
16 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_collision.gd:
--------------------------------------------------------------------------------
1 | ## Returns true if a collision occurs
2 | ## for the current agent
3 |
4 | @icon("condition.svg")
5 | class_name IfCollision
6 | extends BehaviorTreeForGroups
7 |
8 | ## Collider's group
9 | @export var with_group:String = ""
10 | ## Group's state (-1 = any state)
11 | @export var in_state:int = -1
12 | ## Collider's reference into the common blackboard
13 | var collider_reference:String = "collider"
14 |
15 | func biodyn_process(agent)->bool:
16 | var bodies = agent.get_colliding_bodies()
17 | if bodies.size() > 0:
18 | for b in bodies:
19 | if b.is_in_group(with_group):
20 | if "state" in b:
21 | if b.state == in_state || in_state == -1:
22 | if collider_reference != "":
23 | get_tree().current_scene.set_meta(collider_reference, b)
24 | return true
25 | else: # Not an agent from BehavTreeForGroups
26 | return true
27 | return false
28 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_data_between.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the agent's data
2 | ## is between 2 given float values.
3 |
4 | @icon("condition.svg")
5 | class_name IfDataBetween
6 | extends BehaviorTreeForGroups
7 |
8 | @export var data_name:String = ""
9 | @export var data_min:float = 0
10 | @export var data_max:float = 0
11 |
12 | func biodyn_process(agent:Node)->bool:
13 | if data_name != "":
14 | if agent.has_meta(data_name):
15 | var val:float = 0
16 | val = agent.get_meta(data_name)
17 | if val >= data_min and val <= data_max:
18 | return true
19 | return false
20 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_data_equals.gd:
--------------------------------------------------------------------------------
1 | ## Return true if an agent's data
2 | ## equals a specific float value
3 |
4 | @icon("condition.svg")
5 | class_name IfDataEquals
6 | extends BehaviorTreeForGroups
7 |
8 | @export var data_name:String = ""
9 | @export var is_equal_to:float = 0
10 |
11 | func biodyn_process(agent:Node)->bool:
12 | if data_name != "":
13 | if agent.has_meta(data_name):
14 | var val:float = 0
15 | val = agent.get_meta(data_name)
16 | if val == is_equal_to:
17 | return true
18 | return false
19 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_data_equals_periodic_values.gd:
--------------------------------------------------------------------------------
1 | ## Return true when the data's value is
2 | ## inside the specified interval and
3 | ## periodically for each gap of the step size.
4 |
5 | @icon("condition.svg")
6 | class_name IfDataEqualsPeriodicValues
7 | extends BehaviorTreeForGroups
8 |
9 |
10 |
11 | @export var data_name:String = ""
12 | ## Size of each step
13 | @export var period: float = 0
14 | @export var min_data: float = 0
15 | ## Put -1 for infinite
16 | @export var max_data: float = -1
17 |
18 | # Called every frame. 'delta' is the elapsed time since the previous frame.
19 | func biodyn_process(agent)->bool:
20 | if data_name != "":
21 | if agent.has_meta(data_name):
22 | var data_value:float = agent.get_meta(data_name)
23 | if max_data == -1 :
24 | if data_value >= min_data :
25 | if modulo( (data_value-min_data), period) == true :
26 | return true
27 | else :
28 | return false
29 | else :
30 | return false
31 | elif data_value >= min_data and data_value <= max_data:
32 | if modulo( (data_value-min_data), period) == true :
33 | return true
34 | else :
35 | return false
36 | else:
37 | return false
38 | else :
39 | return false
40 | else :
41 | return false
42 |
43 | func modulo(val:float, period:float) -> bool:
44 | var rest:int = val / period
45 | if (val / period) == rest:
46 | return true
47 | else:
48 | return false
49 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_data_equals_values.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the data's value
2 | ## equals one of the given values.
3 |
4 | @icon("condition.svg")
5 | class_name IfDataEqualsValues
6 | extends BehaviorTreeForGroups
7 | @export var data_name:String = ""
8 | @export var values:Array[float] = [10,20,25]
9 |
10 | # Called every frame. 'delta' is the elapsed time since the previous frame.
11 | func biodyn_process(agent)->bool:
12 | if data_name != "":
13 | if agent.has_meta(data_name):
14 | var data_value:float = agent.get_meta(data_name)
15 | if values.find(data_value) >= 0 :
16 | return true
17 | else:
18 | return false
19 | else :
20 | return false
21 | else :
22 | return false
23 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_data_inf.gd:
--------------------------------------------------------------------------------
1 | ## Return true if an agent's data
2 | ## is inferior to a float value
3 |
4 | @icon("condition.svg")
5 | class_name IfDataInf
6 | extends BehaviorTreeForGroups
7 |
8 | @export var data_name:String = ""
9 | @export var is_inf_to:float = 0
10 |
11 | func biodyn_process(agent:Node)->bool:
12 | if data_name != "":
13 | if agent.has_meta(data_name):
14 | var val:float = 0
15 | val = agent.get_meta(data_name)
16 | if val < is_inf_to:
17 | return true
18 | return false
19 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_data_sup.gd:
--------------------------------------------------------------------------------
1 | ## Return true if an agent's data
2 | ## is superior to a float value
3 |
4 | @icon("condition.svg")
5 | class_name IfDataSup
6 | extends BehaviorTreeForGroups
7 |
8 | @export var data_name:String = ""
9 | @export var is_sup_to:float = 0
10 |
11 | func biodyn_process(agent:Node)->bool:
12 | if data_name != "":
13 | if agent.has_meta(data_name):
14 | var val:float = 0
15 | val = agent.get_meta(data_name)
16 | if val > is_sup_to:
17 | return true
18 | return false
19 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_global_data_between.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the global's data
2 | ## is between 2 given float values.
3 |
4 | @icon("condition.svg")
5 | class_name IfGlobalDataBetween
6 | extends BehaviorTreeForGroups
7 |
8 | @export var global_data_name:String = ""
9 | @export var min:float = 0
10 | @export var max:float = 0
11 |
12 | func biodyn_process(agent:Node)->bool:
13 | if global_data_name != "":
14 | if BTFG.btfg_root.has_meta(global_data_name):
15 | var val:float = BTFG.btfg_root.get_meta(global_data_name)
16 | if val >= min and val <= max:
17 | return true
18 | return false
19 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_global_data_equals.gd:
--------------------------------------------------------------------------------
1 | ## Return true if a global's data
2 | ## equals a specific float value
3 |
4 | @icon("condition.svg")
5 | class_name IfGlobalDataEquals
6 | extends BehaviorTreeForGroups
7 |
8 | @export var global_data_name:String = ""
9 | @export var is_equal_to:float = 0
10 |
11 | func biodyn_process(agent:Node)->bool:
12 | if global_data_name != "":
13 | if BTFG.btfg_root.has_meta(global_data_name):
14 | var val:float = BTFG.btfg_root.get_meta(global_data_name)
15 | if val == is_equal_to:
16 | return true
17 | return false
18 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_global_data_inf.gd:
--------------------------------------------------------------------------------
1 | ## Return true if a global's data
2 | ## is inferior to a float value
3 |
4 | @icon("condition.svg")
5 | class_name IfGlobalDataInf
6 | extends BehaviorTreeForGroups
7 |
8 | @export var global_data_name:String = ""
9 | @export var is_inf_to:float = 0
10 |
11 | func biodyn_process(agent:Node)->bool:
12 | if global_data_name != "":
13 | if BTFG.btfg_root.has_meta(global_data_name):
14 | var val:float = BTFG.btfg_root.get_meta(global_data_name)
15 | if val <= is_inf_to:
16 | return true
17 | return false
18 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_global_data_sup.gd:
--------------------------------------------------------------------------------
1 | ## Return true if a global's data
2 | ## is superior to a float value
3 |
4 | @icon("condition.svg")
5 | class_name IfGlobalDataSup
6 | extends BehaviorTreeForGroups
7 |
8 | @export var global_data_name:String = ""
9 | @export var is_sup_to:float = 0
10 |
11 | func biodyn_process(agent:Node)->bool:
12 | if global_data_name != "":
13 | if BTFG.btfg_root.has_meta(global_data_name):
14 | var val:float = BTFG.btfg_root.get_meta(global_data_name)
15 | if val >= is_sup_to:
16 | return true
17 | return false
18 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_grid_2d_value_inf.gd:
--------------------------------------------------------------------------------
1 | ## Return true if an agent
2 | ## is inside a grid having a value
3 | ## inferior to a float number
4 |
5 | @icon("condition_2d.svg")
6 | class_name IfGrid2DValueInf
7 | extends BehaviorTreeForGroups
8 |
9 | ## Name of the Grid's group
10 | ## Value to test (in Magnitude: 1=1/10, 2=1/100, 3=1/1000, etc)
11 | @export var is_inf_to:float = 0
12 |
13 | var grids:Array = Array()
14 |
15 | func _ready():
16 | for gp in self.get_groups():
17 | var sous_grids = get_tree().get_nodes_in_group(gp)
18 | for sg in sous_grids:
19 | grids.push_back(sg)
20 |
21 | func biodyn_process(agent)->bool:
22 | var cdt:bool = false
23 | for grid in grids:
24 | # 2D
25 | if agent is Node2D:
26 | var ax:float = agent.position.x
27 | var ay:float = agent.position.y
28 | var gx_min:float = grid.position.x
29 | var gx_max:float = gx_min+grid.size.x
30 | var gy_min:float = grid.position.y
31 | var gy_max:float = gy_min+grid.size.y
32 | if ax >= gx_min && ax < gx_max:
33 | if ay >= gy_min && ay < gy_max:
34 | var px:int = ((ax - gx_min) / grid.size.x) * grid.SX
35 | var py:int = ((ay - gy_min) / grid.size.y) * grid.SY
36 | var p:int = px+py*grid.SX
37 | var val:float = grid.values_t0[p]
38 | if val <= pow(10, -is_inf_to):
39 | cdt = true
40 | return cdt
41 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_grid_2d_value_sup.gd:
--------------------------------------------------------------------------------
1 | ## Return true if an agent
2 | ## is inside a grid having a value
3 | ## superior to a float number
4 |
5 | @icon("condition_2d.svg")
6 | class_name IfGrid2DValueSup
7 | extends BehaviorTreeForGroups
8 |
9 | ## Name of the Grid's group
10 | ## Value to test (in Magnitude: 1=1/10, 2=1/100, 3=1/1000, etc)
11 | @export var is_sup_to:float = 0
12 |
13 | var grids:Array = Array()
14 |
15 | func _ready():
16 | for gp in self.get_groups():
17 | var sous_grids = get_tree().get_nodes_in_group(gp)
18 | for sg in sous_grids:
19 | grids.push_back(sg)
20 |
21 | func biodyn_process(agent)->bool:
22 | var cdt:bool = false
23 | for grid in grids:
24 | # 2D
25 | if agent is Node2D:
26 | var ax:float = agent.position.x
27 | var ay:float = agent.position.y
28 | var gx_min:float = grid.position.x
29 | var gx_max:float = gx_min+grid.size.x
30 | var gy_min:float = grid.position.y
31 | var gy_max:float = gy_min+grid.size.y
32 | if ax >= gx_min && ax < gx_max:
33 | if ay >= gy_min && ay < gy_max:
34 | var px:int = ((ax - gx_min) / grid.size.x) * grid.SX
35 | var py:int = ((ay - gy_min) / grid.size.y) * grid.SY
36 | var p:int = px+py*grid.SX
37 | var val:float = grid.values_t0[p]
38 | if val >= pow(10, -is_sup_to):
39 | cdt = true
40 | return cdt
41 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_in_box.gd:
--------------------------------------------------------------------------------
1 | ## Return true if an agent
2 | ## is inside box
3 |
4 | @icon("condition.svg")
5 | class_name IfInBox
6 | extends BehaviorTreeForGroups
7 |
8 | @export var min:Vector3 = Vector3(-5,-5,-5)
9 | @export var max:Vector3 = Vector3(5,5,5)
10 |
11 | func biodyn_process(agent:Node) -> bool:
12 | if agent is Node3D:
13 | var x:float = agent.position.x
14 | var y:float = agent.position.y
15 | var z:float = agent.position.z
16 |
17 | # X Axis
18 | if x < min.x:
19 | return false
20 | if x > max.x:
21 | return false
22 | # Y Axis
23 | if y < min.y:
24 | return false
25 | if y > max.y:
26 | return false
27 | # Z Axis
28 | if z < min.z:
29 | return false
30 | if z > max.z:
31 | return false
32 |
33 | return true
34 |
35 | if agent is Node2D:
36 | var x:float = agent.position.x
37 | var y:float = agent.position.y
38 |
39 | # X Axis
40 | if x < min.x:
41 | return false
42 | if x > max.x:
43 | return false
44 | # Y Axis
45 | if y < min.y:
46 | return false
47 | if y > max.y:
48 | return false
49 |
50 | return true
51 |
52 | return false
53 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_mouse_click.gd:
--------------------------------------------------------------------------------
1 | ## Return true if an agent
2 | ## is clicked by the mouse cursor.
3 |
4 | @icon("condition.svg")
5 | class_name IfMouseClick
6 | extends BehaviorTreeForGroups
7 |
8 | @export_enum("Left:1","Right:2","Middle:3") var mouse_button = 1
9 | @export var playerCamera:Camera3D
10 | var btn:int = MOUSE_BUTTON_LEFT
11 |
12 | func _ready():
13 | if mouse_button == 1:
14 | btn = MOUSE_BUTTON_LEFT
15 | if mouse_button == 2:
16 | btn = MOUSE_BUTTON_RIGHT
17 | if mouse_button == 3:
18 | btn = MOUSE_BUTTON_MIDDLE
19 |
20 | # Called every frame. 'delta' is the elapsed time since the previous frame.
21 | func biodyn_process(agent)->bool:
22 | if agent is CollisionObject3D:
23 | if Input.is_mouse_button_pressed(btn):
24 | if playerCamera == null:
25 | playerCamera = get_tree().root.find_child("Camera3D", true, false)
26 | if playerCamera == null:
27 | print("Camera3D not found")
28 | return false
29 | var spaceState = agent.get_world_3d().direct_space_state
30 | var mousePosition = agent.get_viewport().get_mouse_position()
31 | var raycastOrigin = playerCamera.project_ray_origin(mousePosition)
32 | var rayLength = 1000
33 | var raycastTarget = raycastOrigin + playerCamera.project_ray_normal(mousePosition) * rayLength
34 | var physicsRaycastQuery = PhysicsRayQueryParameters3D.create(raycastOrigin, raycastTarget)
35 | var raycastResult = spaceState.intersect_ray(physicsRaycastQuery)
36 | if raycastResult:
37 | if raycastResult.collider == agent:
38 | return true
39 |
40 | return false
41 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_no_contact.gd:
--------------------------------------------------------------------------------
1 | ## Return true if an agent
2 | ## has no collision during
3 | ## several execution steps
4 |
5 | @icon("condition.svg")
6 | class_name IfNoContact
7 | extends BehaviorTreeForGroups
8 |
9 | @export var steps_without_contact:int = 100
10 | var period_of_no_contact:int = 0
11 |
12 | func biodyn_process(agent)->bool:
13 | var bodies = agent.get_colliding_bodies()
14 | if bodies.size() == 0:
15 | period_of_no_contact = period_of_no_contact + 1
16 | else:
17 | period_of_no_contact = 0 # A contact occurs => reset
18 |
19 | if period_of_no_contact >= steps_without_contact:
20 | period_of_no_contact = steps_without_contact # avoid go back to MIN int if very very long period without contact
21 | return true
22 | else:
23 | return false
24 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_no_contact_with.gd:
--------------------------------------------------------------------------------
1 | ## Return true if an agent has no collision
2 | ## with a specific group in a designated
3 | ## state during several execution steps.
4 |
5 | @icon("condition.svg")
6 | class_name IfNoContactWith
7 | extends BehaviorTreeForGroups
8 |
9 | ## Contact's group
10 | @export var with_group:String = ""
11 | @export var steps_without_contact:int = 100
12 | var period_of_no_contact:int = 0
13 | ## Group's state (-1 = any state)
14 | @export var in_state:int = -1
15 |
16 | func biodyn_process(agent)->bool:
17 | var bodies = agent.get_colliding_bodies()
18 | var col:bool = false
19 | for b in bodies:
20 | if b.is_in_group(with_group):
21 | if "state" in b:
22 | if b.state == in_state || in_state == -1:
23 | col = true
24 |
25 | if col == false:
26 | period_of_no_contact = period_of_no_contact + 1
27 | else:
28 | period_of_no_contact = 0 # A contact occurs => reset
29 |
30 | if period_of_no_contact >= steps_without_contact:
31 | period_of_no_contact = steps_without_contact # avoid go back to MIN int if very very long period without contact
32 | return true
33 | else:
34 | return false
35 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_proba.gd:
--------------------------------------------------------------------------------
1 | ## Return true if a random float
2 | ## between 0 and 100 is inferior
3 | ## to a given float number
4 |
5 | @icon("condition.svg")
6 | class_name IfProba
7 | extends BehaviorTreeForGroups
8 |
9 | ## Probability of success
10 | @export var proba:float = 100
11 |
12 | func _ready():
13 | pass
14 |
15 | # Called every frame. 'delta' is the elapsed time since the previous frame.
16 | func biodyn_process(agent)->bool:
17 | var rnd:float = randf()
18 | if rnd < proba/100.0:
19 | return true
20 | else:
21 | return false
22 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_state_equals.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the agent's state
2 | ## equals a given integer value
3 |
4 | @icon("condition.svg")
5 | class_name IfStateEquals
6 | extends BehaviorTreeForGroups
7 |
8 | ## Test the state value (-1 for any state)
9 | @export var state_equals:int = 0
10 |
11 | func biodyn_process(agent:Node)->bool:
12 | if agent.state == state_equals || state_equals == -1:
13 | return true
14 | else:
15 | return false
16 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_step_between.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the simulation/execution step
2 | ## is between 2 given integer numbers.
3 |
4 | @icon("condition.svg")
5 | class_name IfStepBetween
6 | extends BehaviorTreeForGroups
7 |
8 | ## Initial simulation/execution step
9 | @export var step_start:int = 0
10 | ## Final simulation/execution step
11 | @export var step_end:int = 100
12 |
13 | func _ready():
14 | pass
15 |
16 | # Called every frame. 'delta' is the elapsed time since the previous frame.
17 | func biodyn_process(agent)->bool:
18 | var step:int = BehaviorTreeForGroups.simulation_step
19 | if step >= step_start and step <= step_end:
20 | return true
21 | else:
22 | return false
23 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_time_between.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the time's data
2 | ## is between 2 given float values.
3 |
4 | @icon("condition.svg")
5 | class_name IfTimeBetween
6 | extends BehaviorTreeForGroups
7 |
8 | @export var start_time_ms:int = 0
9 | @export var end_time_ms:int = 0
10 |
11 | func biodyn_process(agent:Node)->bool:
12 | var val:int = Time.get_ticks_msec()
13 | if val >= start_time_ms and val <= end_time_ms:
14 | return true
15 | return false
16 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_time_inf.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the time
2 | ## is inferior to a specific
3 | ## int value snapped by 20.
4 |
5 | @icon("condition.svg")
6 | class_name IfTimeInf
7 | extends BehaviorTreeForGroups
8 | @export var is_inferior_to_ms:int = 0
9 |
10 | func biodyn_process(agent:Node)->bool:
11 | var val:int = Time.get_ticks_msec()
12 | if val <= is_inferior_to_ms :
13 | return true
14 | else :
15 | return false
16 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/if_time_sup.gd:
--------------------------------------------------------------------------------
1 | ## Return true if the time
2 | ## is superior to a specific
3 | ## int value snapped by 20.
4 |
5 | @icon("condition.svg")
6 | class_name IfTimeSup
7 | extends BehaviorTreeForGroups
8 | @export var is_superior_to_ms:int = 0
9 |
10 | func biodyn_process(agent:Node)->bool:
11 | var val:int = Time.get_ticks_msec()
12 | if val >= is_superior_to_ms :
13 | return true
14 | else :
15 | return false
16 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/new_agent_2d.gd:
--------------------------------------------------------------------------------
1 | ## Create a new Type of 2D Agent
2 | ## into a Type Scene file (.tscn)
3 | ## This agent can be added manually
4 | ## using the Godot Editor
5 | ## or automaticaly (see AddAgent)
6 | ## into the main scene.
7 |
8 | @icon("action_2d.svg")
9 | @tool
10 |
11 | class_name NewAgent2D
12 | extends BehaviorTreeForGroups
13 |
14 | signal prompt_confirmed(input_text: String)
15 | signal prompt_canceled
16 | # Scène principale qui hérite de Node2D
17 | var prompt_instance: PromptDialog
18 |
19 | func _on_prompt_confirmed(input_text: String) -> void:
20 | print("L'utilisateur a validé la saisie : ", input_text)
21 |
22 | func _on_prompt_canceled(input_text: String) -> void:
23 | print("L'utilisateur a annulé la saisie : ", input_text)
24 | queue_free()
25 |
26 | func _enter_tree():
27 | print("Agent2D : _enter_tree")
28 |
29 | # Creation of the PromptDialog
30 | prompt_instance = PromptDialog.new()
31 |
32 | print("Agent2D : prompt_instance created")
33 |
34 | # Ajout de la scène du prompt comme enfant
35 | #add_child(prompt_instance)
36 | #get_editor_interface().get_base_control().add_child(prompt_instance)
37 | var editor_root = get_tree().root.get_child(0) # Accède à la fenêtre principale de l'éditeur
38 | editor_root.add_child(prompt_instance)
39 |
40 | prompt_instance.min_size = Vector2i(320, 80)
41 | prompt_instance.reset_size()
42 | prompt_instance.move_to_center()
43 | prompt_instance.title = "Name the new 2d agent"
44 |
45 | # Rendre la fenêtre modale pour bloquer les interactions avec l'interface principale
46 | prompt_instance.set_transient(true)
47 | prompt_instance.set_exclusive(true)
48 |
49 |
50 | prompt_instance.close_requested.connect(func():
51 | prompt_instance._on_cancel_button_pressed()
52 | )
53 |
54 | # Connexion du signal de confirmation
55 | prompt_instance.prompt_confirmed.connect(_on_prompt_confirmed)
56 | # Connexion du signal d'annulation
57 | prompt_instance.prompt_canceled.connect(_on_prompt_canceled)
58 |
59 | # Attendre que l'utilisateur confirme la fenêtre (bloque l'exécution ici)
60 | # Open the name window and apply the name to the new agent 2d
61 | var result = await prompt_instance.prompt_confirmed
62 |
63 | # The new agent is a .tscn file
64 | # It must have a valid filename
65 | var agent_name:String = result
66 | if agent_name.is_valid_filename() == false:
67 | print("Agent2D : invalid agent name => agent NOT created. Use a valid filename.")
68 | free_my_resources(null)
69 | return
70 |
71 | build_agent_2d(agent_name)
72 |
73 | func free_my_resources(rb:RigidBody2D):
74 | # Free memory resources
75 | if rb != null:
76 | rb.queue_free() # saved in the .tscn file
77 | self.queue_free() # this node is only made for creating rb
78 | print("Agent2D : Removed from Scene Tree")
79 |
80 | func build_agent_2d(agent_name:String):
81 |
82 | # Create the rigidBody2D
83 | print("Agent2D : creation of RigidBody2D")
84 | var rb:RigidBody2D = RigidBody2D.new()
85 |
86 | rb.name = agent_name
87 | rb.add_to_group(agent_name, true)
88 |
89 | # Add the collision shape 3D
90 | var col:CollisionShape2D = CollisionShape2D.new()
91 | col.name = "CollisionShape2D"
92 | var cs:CircleShape2D = CircleShape2D.new()
93 | cs.radius = 10
94 | col.set_shape(cs)
95 | rb.add_child(col)
96 | col.set_owner(rb)
97 | # Add the Polygon2D
98 | var poly:Polygon2D = Polygon2D.new()
99 | poly.name = "Polygon2D"
100 | var vertices:PackedVector2Array = PackedVector2Array(polygone2D_regular(10,6))
101 |
102 | # Attribuer les sommets au Polygon2D
103 | poly.set_polygon(vertices)
104 | #msh.scale = Vector2(20,20)
105 | #msh.set_mesh(SphereMesh.new())
106 | #msh.material = mat
107 | rb.add_child(poly)
108 | poly.set_owner(rb)
109 |
110 | # Set script to rb (if necessary,
111 | # change rb_script then uncomment below)
112 | var script = GDScript.new()
113 | script.set_source_code(rb_script())
114 | script.reload()
115 | rb.set_script(script)
116 |
117 | # Set parameters
118 | rb.set_gravity_scale(0)
119 | rb.contact_monitor = true
120 | rb.max_contacts_reported = 2
121 | rb.linear_damp = 1
122 | rb.angular_damp = 1
123 | #rb.agent_color = Color(mat.albedo_color)
124 |
125 | # Export the new Agent as scene
126 | print("Agent2D : try to save TSCN")
127 | var scene = PackedScene.new()
128 | scene.pack(rb)
129 | var scene_path:String
130 | # Still a lot (it's .tscn files, NOT instances in scene tree!)
131 | scene_path = "res://"+agent_name+".tscn" #"res://"+agent_name+str(i)+".tscn"
132 | # Check if the file already exists
133 | if ResourceLoader.exists(scene_path)==true:
134 | print("new Agent2D:agent already exists. Try a new name or remove the agent")
135 | free_my_resources(rb)
136 | return
137 | # Save the Agent in the resource file .tscn
138 | ResourceSaver.save(scene, scene_path)
139 | free_my_resources(rb)
140 |
141 |
142 |
143 | func polygone2D_regular(radius:float, n:int) -> PackedVector2Array:
144 | var arr_poly:PackedVector2Array = PackedVector2Array()
145 | for a in range(0,n):
146 | var x:float = radius * cos(deg_to_rad(a*360.0 / n))
147 | var y:float = radius * sin(deg_to_rad(a*360.0 / n))
148 | arr_poly.append(Vector2(x,y))
149 | return arr_poly
150 |
151 | func rb_script():
152 | return """
153 | @tool
154 | extends RigidBody2D
155 |
156 | @export var state:int = 0
157 | @export var age:int = 0
158 |
159 | func _process(_delta):
160 | if not Engine.is_editor_hint():
161 | age += 1
162 |
163 | """
164 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/new_agent_3d.gd:
--------------------------------------------------------------------------------
1 | ## Create a new Type of 3D Agent
2 | ## into a Type Scene file (.tscn)
3 | ## This agent can be added manually
4 | ## using the Godot Editor
5 | ## or automaticaly (see AddAgent)
6 | ## into the main scene.
7 |
8 | @icon("action_3d.svg")
9 | @tool
10 |
11 | class_name NewAgent3D
12 | extends BehaviorTreeForGroups
13 |
14 | signal prompt_confirmed(input_text: String)
15 | signal prompt_canceled
16 | # Scène principale qui hérite de Node2D
17 | var prompt_instance: PromptDialog
18 |
19 | func _on_prompt_confirmed(input_text: String) -> void:
20 | print("L'utilisateur a validé la saisie : ", input_text)
21 |
22 | func _on_prompt_canceled(input_text: String) -> void:
23 | print("L'utilisateur a annulé la saisie : ", input_text)
24 | queue_free()
25 |
26 | func _enter_tree():
27 | print("Agent3D : _enter_tree")
28 |
29 | # Creation of the PromptDialog
30 | prompt_instance = PromptDialog.new()
31 |
32 | print("Agent3D : prompt_instance created")
33 |
34 | # Ajout de la scène du prompt comme enfant
35 | #add_child(prompt_instance)
36 | #get_editor_interface().get_base_control().add_child(prompt_instance)
37 | var editor_root = get_tree().root.get_child(0) # Accède à la fenêtre principale de l'éditeur
38 | editor_root.add_child(prompt_instance)
39 |
40 | prompt_instance.min_size = Vector2i(320, 80)
41 | prompt_instance.reset_size()
42 | prompt_instance.move_to_center()
43 | prompt_instance.title = "Name the new 3d agent"
44 |
45 | # Rendre la fenêtre modale pour bloquer les interactions avec l'interface principale
46 | prompt_instance.set_transient(true)
47 | prompt_instance.set_exclusive(true)
48 |
49 |
50 | prompt_instance.close_requested.connect(func():
51 | prompt_instance._on_cancel_button_pressed()
52 | )
53 |
54 | # Connexion du signal de confirmation
55 | prompt_instance.prompt_confirmed.connect(_on_prompt_confirmed)
56 | # Connexion du signal d'annulation
57 | prompt_instance.prompt_canceled.connect(_on_prompt_canceled)
58 |
59 | # Attendre que l'utilisateur confirme la fenêtre (bloque l'exécution ici)
60 | # Open the name window and apply the name to the new agent 2d
61 | var result = await prompt_instance.prompt_confirmed
62 |
63 | # The new agent is a .tscn file
64 | # It must have a valid filename
65 | var agent_name:String = result
66 | if agent_name.is_valid_filename() == false:
67 | print("Agent3D : invalid agent name => agent NOT created. Use a valid filename.")
68 | free_my_resources(null)
69 | return
70 |
71 | build_agent_3d(agent_name)
72 |
73 | func free_my_resources(rb:RigidBody3D):
74 | # Free memory resources
75 | if rb != null:
76 | rb.queue_free() # saved in the .tscn file
77 | self.queue_free() # this node is only made for creating rb
78 | print("Agent3D : Removed from Scene Tree")
79 |
80 | func build_agent_3d(agent_name:String):
81 | # Create the rigidBody3D
82 | var rb:RigidBody3D = RigidBody3D.new()
83 | rb.name = agent_name
84 | rb.add_to_group(agent_name, true)
85 |
86 | # Add the collision shape 3D
87 | var col:CollisionShape3D = CollisionShape3D.new()
88 | col.name = "CollisionShape3D"
89 | col.set_shape(SphereShape3D.new())
90 | rb.add_child(col)
91 | col.set_owner(rb)
92 | # New mat
93 | var mat:StandardMaterial3D = StandardMaterial3D.new()
94 | mat.albedo_color = Color(randf(),randf(),randf())
95 | # Add the meshinstance 3D
96 | var msh:MeshInstance3D = MeshInstance3D.new()
97 | msh.name = "MeshInstance3D"
98 | msh.set_mesh(SphereMesh.new())
99 | msh.material_override = mat
100 | rb.add_child(msh)
101 | msh.set_owner(rb)
102 |
103 | # Set script to rb (if necessary,
104 | # change rb_script then uncomment below)
105 | var script = GDScript.new()
106 | script.set_source_code(rb_script())
107 | script.reload()
108 | rb.set_script(script)
109 |
110 | # Set parameters
111 | rb.set_gravity_scale(0)
112 | rb.contact_monitor = true
113 | rb.max_contacts_reported = 2
114 | rb.linear_damp = 5
115 | rb.angular_damp = 5
116 | #rb.agent_color = Color(mat.albedo_color)
117 |
118 | # Export the new Agent as scene
119 | print("Agent3D : try to save TSCN")
120 | var scene = PackedScene.new()
121 | scene.pack(rb)
122 | var scene_path:String
123 | # Still a lot (it's .tscn files, NOT instances in scene tree!)
124 | scene_path = "res://"+agent_name+".tscn"
125 | # Check if the file already exists
126 | if ResourceLoader.exists(scene_path)==true:
127 | print("new Agent2D:agent already exists. Try a new name or remove the agent")
128 | free_my_resources(rb)
129 | return
130 | # Save the Agent in the resource file .tscn
131 | ResourceSaver.save(scene, scene_path)
132 | free_my_resources(rb)
133 |
134 | print("Agent3D : END")
135 |
136 |
137 | func rb_script():
138 | return """
139 | @tool
140 | extends RigidBody3D
141 |
142 | @export var state:int = 0
143 | @export var age:int = 0
144 |
145 | func _process(_delta):
146 | if not Engine.is_editor_hint():
147 | age += 1
148 |
149 | func emit_changed():
150 | pass
151 |
152 | """
153 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/new_grid_2d.gd:
--------------------------------------------------------------------------------
1 | ## Create a new Type of 2D Grid
2 | ## into a Type Scene file (.tscn)
3 | ## This grid can be added manually
4 | ## using the Godot Editor
5 | ## or automaticaly (see AddAgent)
6 | ## into the main scene.
7 |
8 | @icon("action_2d.svg")
9 | @tool
10 |
11 | class_name NewGrid2D
12 | extends BehaviorTreeForGroups
13 |
14 | signal prompt_confirmed(input_text: String)
15 | signal prompt_canceled
16 | # Scène principale qui hérite de Node2D
17 | var prompt_instance: PromptDialog
18 |
19 | func _on_prompt_confirmed(input_text: String) -> void:
20 | print("L'utilisateur a validé la saisie : ", input_text)
21 |
22 | func _on_prompt_canceled(input_text: String) -> void:
23 | print("L'utilisateur a annulé la saisie : ", input_text)
24 | queue_free()
25 |
26 | func _enter_tree():
27 | print("Grid2D : _enter_tree")
28 |
29 | # Creation of the PromptDialog
30 | prompt_instance = PromptDialog.new()
31 |
32 | print("Grid2D : prompt_instance created")
33 |
34 | # Ajout de la scène du prompt comme enfant
35 | #add_child(prompt_instance)
36 | #get_editor_interface().get_base_control().add_child(prompt_instance)
37 | var editor_root = get_tree().root.get_child(0) # Accède à la fenêtre principale de l'éditeur
38 | editor_root.add_child(prompt_instance)
39 |
40 | prompt_instance.min_size = Vector2i(320, 80)
41 | prompt_instance.reset_size()
42 | prompt_instance.move_to_center()
43 | prompt_instance.title = "Name the new 2d grid"
44 |
45 | # Rendre la fenêtre modale pour bloquer les interactions avec l'interface principale
46 | prompt_instance.set_transient(true)
47 | prompt_instance.set_exclusive(true)
48 |
49 |
50 | prompt_instance.close_requested.connect(func():
51 | prompt_instance._on_cancel_button_pressed()
52 | )
53 |
54 | # Connexion du signal de confirmation
55 | prompt_instance.prompt_confirmed.connect(_on_prompt_confirmed)
56 | # Connexion du signal d'annulation
57 | prompt_instance.prompt_canceled.connect(_on_prompt_canceled)
58 |
59 | # Attendre que l'utilisateur confirme la fenêtre (bloque l'exécution ici)
60 | # Open the name window and apply the name to the new agent 2d
61 | var result = await prompt_instance.prompt_confirmed
62 |
63 | # The new agent is a .tscn file
64 | # It must have a valid filename
65 | var agent_name:String = result
66 | if agent_name.is_valid_filename() == false:
67 | print("Grid2D : invalid agent name => agent NOT created. Use a valid filename.")
68 | free_my_resources(null)
69 | return
70 |
71 | build_grid_2d(agent_name)
72 |
73 | func free_my_resources(tr:TextureRect):
74 | # Free memory resources
75 | if tr != null:
76 | tr.queue_free() # saved in the .tscn file
77 | self.queue_free() # this node is only made for creating rb
78 | print("Grid2D : Removed from Scene Tree")
79 |
80 | func build_grid_2d(agent_name:String):
81 | # Create the rigidBody3D
82 | var tr:TextureRect = TextureRect.new()
83 | tr.name = agent_name
84 | tr.add_to_group(agent_name, true)
85 |
86 | # Add the Image
87 | var SX:int = 64
88 | var SY:int = 32
89 | var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8)
90 | for x in range(SX):
91 | for y in range(SY):
92 | var rnd:float = 0#randf()
93 | if x == 0 || x == SX-1 || y == 0 || y == SY-1:
94 | img.set_pixel(x,y, Color(rnd,rnd,rnd,1))
95 | # Put the image into a texture for rendering
96 | tr.set_texture(ImageTexture.create_from_image(img))
97 |
98 | # Set script to tr
99 | var script = GDScript.new()
100 | script.set_source_code(tr_script())
101 | script.reload()
102 | tr.set_script(script)
103 |
104 | # Export the new Agent as scene
105 | print("Grid2D : try to save TSCN")
106 | var scene = PackedScene.new()
107 | scene.pack(tr)
108 | var scene_path:String
109 | # Still a lot (it's .tscn files, NOT instances in scene tree!)
110 | scene_path = "res://"+agent_name+".tscn"
111 | # Check if the file already exists
112 | if ResourceLoader.exists(scene_path)==true:
113 | print("new Grid2D:agent already exists. Try a new name or remove the agent")
114 | free_my_resources(tr)
115 | return
116 | # Save the Agent in the resource file .tscn
117 | ResourceSaver.save(scene, scene_path)
118 | free_my_resources(tr)
119 |
120 | print("Grid2D : END")
121 |
122 | func tr_script() -> String:
123 | var scp:Script = load("res://addons/behav_tree_for_groups/grid2d.gd")
124 | return scp.source_code
125 | #return """
126 | #@tool
127 | #extends TextureRect
128 | #class_name Grid2D
129 | #
130 | #@export var baseColor:Color = Color(0.5,0.5,0.5,0.5)
131 | #@export var diffusionRate = 0.3
132 | #@export var degradationRate = 0.001
133 | #@export var display_value:bool = false
134 | #@export var show_iso:bool = false
135 | #
136 | #@export var SX:int = 64
137 | #@export var SY:int = 32
138 | #@export var loop_x:bool = false
139 | #@export var loop_y:bool = false
140 | #
141 | #@export var state:int = 0
142 | #@export var age:int = 0
143 | #
144 | #var values_t0:PackedFloat32Array = PackedFloat32Array()
145 | #var values_t1:PackedFloat32Array = PackedFloat32Array()
146 | #
147 | #var xmin:float; var xmax:float; var ymin:float;var ymax:float
148 | #
149 | #func _ready():
150 | #values_t0.resize(SX*SY)
151 | #values_t1.resize(SX*SY)
152 | #for i in range(SX*SY):
153 | #values_t0[i] = 0
154 | #
155 | #if loop_x == true:
156 | #xmin = 0
157 | #xmax = SX
158 | #else:
159 | #xmin = 1
160 | #xmax = SX-1
161 | #
162 | #if loop_y == true:
163 | #ymin = 0
164 | #ymax = SY
165 | #else:
166 | #ymin = 1
167 | #ymax = SY-1
168 | #
169 | #
170 | #func _process(_delta):
171 | #if not Engine.is_editor_hint():
172 | #diffusion()
173 | #if show_iso == false:
174 | #display_values()
175 | #else:
176 | #display_iso()
177 | #if display_value == true:
178 | #print_value()
179 | #age += 1
180 | #
181 | #func diffusion():
182 | #for i in range(xmin,xmax):
183 | #for j in range(ymin,ymax):
184 | #var p:int = i+j*SX
185 | #var v0:float = values_t0[ (i+1)%SX+j*SX]
186 | #var v1:float = values_t0[ (i-1+SX)%SX+j*SX]
187 | #var v2:float = values_t0[ i%SX+((j+1)%SY)*SX]
188 | #var v3:float = values_t0[ i%SX+((j-1+SY)%SY)*SX]
189 | #values_t1[p] = (1.0-degradationRate)*(1.0-diffusionRate)*values_t0[p] + diffusionRate*(v0+v1+v2+v3)*0.25
190 | #
191 | #for i in range(SX*SY):
192 | #values_t0[i] = values_t1[i]
193 | #
194 | #func display_values():
195 | #var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8)
196 | #for i in range(SX):
197 | #for j in range(SY):
198 | #var p:int = i+j*SX
199 | #var v:float = values_t0[p]
200 | #img.set_pixel(i,j,Color(v*baseColor.r,v*baseColor.g,v*baseColor.b,baseColor.a) )
201 | #set_texture(ImageTexture.create_from_image(img))
202 | #
203 | #func print_value():
204 | #var i:int = randi_range(0, SX-1)
205 | #var j:int = randi_range(0, SY-1)
206 | #var v:float = values_t0[i+j*SX]
207 | #print("At (" + str(i) + "," + str(j) + ")=" + str(num_zeros(v)) + "<=" + str(v) )
208 | #
209 | #func num_zeros(val:float) -> int:
210 | #var n:int = 0
211 | #if val != 0:
212 | #n = -floor( log(abs(val)) / log(10) ) - 1
213 | #return n
214 | #
215 | #func display_iso():
216 | #var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8)
217 | #var r:float; var g:float; var b:float
218 | #for i in range(1,SX-2):
219 | #for j in range(1,SY-2):
220 | #var p:int = i+j*SX
221 | #var v0:float = num_zeros(values_t0[p])
222 | #var vg:float = num_zeros(values_t0[p-1])
223 | #var vd:float = num_zeros(values_t0[p+1])
224 | #var vh:float = num_zeros(values_t0[p-SX])
225 | #var vb:float = num_zeros(values_t0[p+SX])
226 | #var e:float = 1.0
227 | #if vg>v0 || vd>v0 || vh>v0 || vb>v0:
228 | #e = 0.5
229 | #img.set_pixel(i,j,Color(e*baseColor.r,e*baseColor.g,e*baseColor.b,baseColor.a) )
230 | #set_texture(ImageTexture.create_from_image(img))
231 | #
232 | #"""
233 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/parallel.gd:
--------------------------------------------------------------------------------
1 | ## Execute all its children
2 |
3 | @icon("parallel.svg")
4 | class_name Parallel
5 | extends BehaviorTreeForGroups
6 |
7 | @export var activated:bool = true
8 |
9 | # Called every frame. 'delta' is the elapsed time since the previous frame.
10 | func biodyn_process(agent)->bool:
11 | # Parallel Node
12 | # Execute all its children, stops after ALL children execution
13 | # Return True when at leat ONE child returns True
14 | if activated == false:
15 | return false
16 | var overall_success:bool = false
17 | for behav in self.get_children():
18 | var success = behav.biodyn_process(agent)
19 | if success == true:
20 | overall_success = true
21 | return overall_success
22 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/parallel.svg:
--------------------------------------------------------------------------------
1 |
2 |
64 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/parallel.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://c5i55nkua68w6"
6 | path="res://.godot/imported/parallel.svg-bb539307c1dace5e872ffa4400740c3d.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/parallel.svg"
14 | dest_files=["res://.godot/imported/parallel.svg-bb539307c1dace5e872ffa4400740c3d.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/plugin.cfg:
--------------------------------------------------------------------------------
1 | [plugin]
2 |
3 | name="Behavior Tree for Groups"
4 | description="Add a behavior tree to node's groups and create swarms, flocks and multiagent systems."
5 | author="Pascal Ballet"
6 | version="2.0"
7 | script="behavior_tree_for_groups_plugin.gd"
8 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/print_message.gd:
--------------------------------------------------------------------------------
1 | ## Print a message into
2 | ## the Godot Output Window.
3 |
4 | @icon("action.svg")
5 | class_name PrintMessage
6 | extends BehaviorTreeForGroups
7 |
8 | ## Message to print
9 | @export var message:String = ""
10 | ## Data to print
11 | @export var data:String = ""
12 | ## Blackboard reference to print
13 | @export var reference:String = ""
14 |
15 | func biodyn_process(agent)->bool:
16 | var msg:String = message
17 | if agent.has_meta(data):
18 | msg += ":"+data+" = " + agent.get_meta(data)
19 | var root:Node = get_tree().current_scene
20 | if root.has_meta(reference):
21 | msg += ":"+reference+" = " + root.get_meta(reference)
22 |
23 | print(msg)
24 | return true
25 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/prompt_dialog.gd:
--------------------------------------------------------------------------------
1 | ## PromptDialog class asking for the name of a new agent
2 |
3 | extends Window
4 |
5 | class_name PromptDialog
6 |
7 | var input_field: LineEdit
8 |
9 | signal prompt_confirmed(input_text: String)
10 | signal prompt_canceled
11 |
12 | func _init():
13 | pass
14 |
15 | func _ready() -> void:
16 | # Vertical Box Container to put the Line Edit
17 | # and the OK and CANCEL buttons
18 | var vbox:VBoxContainer = VBoxContainer.new()
19 | vbox.set_anchors_preset(Control.PRESET_FULL_RECT)
20 | # Set light grey background color
21 | var style = StyleBoxFlat.new()
22 | style.bg_color = Color(0.9, 0.0, 0.9, 1.0) # Light grey color
23 | vbox.add_theme_stylebox_override("panel", style)
24 | # Add a MarginContainer for better spacing
25 | var margin = MarginContainer.new()
26 | margin.add_theme_constant_override("margin_left", 16)
27 | margin.add_theme_constant_override("margin_right", 16)
28 | vbox.add_child(margin)
29 |
30 | # LineEdit creation to enter the 2d agent name
31 | input_field = LineEdit.new()
32 | input_field.alignment = HorizontalAlignment.HORIZONTAL_ALIGNMENT_CENTER
33 | input_field.expand_to_text_length = true
34 | input_field.placeholder_text = "agent_name"
35 | vbox.add_child(input_field)
36 |
37 | # HBox creation to put Buttons OK and CANCEL
38 | var hbox:HBoxContainer = HBoxContainer.new()
39 | hbox.set_anchors_preset(Control.PRESET_FULL_RECT)
40 | hbox.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
41 | hbox.add_theme_constant_override("separation", 10) # Space between buttons
42 | vbox.add_child(hbox)
43 |
44 | # OK button creation
45 | var ok_button = Button.new()
46 | ok_button.text = "OK"
47 | ok_button.pressed.connect(self._on_ok_button_pressed)
48 | ok_button.size_flags_horizontal = Control.SIZE_FILL
49 | set_button_style(ok_button, Color(0.0, 0.6, 0.0, 1.0))
50 | hbox.add_child(ok_button)
51 |
52 | # CANCEL button creation
53 | var cancel_button = Button.new()
54 | cancel_button.text = "CANCEL"
55 | cancel_button.pressed.connect(self._on_cancel_button_pressed)
56 | set_button_style(cancel_button, Color(0.6, 0.0, 0.0, 1.0))
57 | hbox.add_child(cancel_button)
58 |
59 | # Add the VBox to the modal prompt Window
60 | add_child(vbox)
61 |
62 | # Set the style of a given button
63 | func set_button_style(button:Button, text_color:Color):
64 | # Create button styles
65 | var normal_style = StyleBoxFlat.new()
66 | normal_style.bg_color = Color(0.6, 0.6, 0.6, 1.0)
67 | normal_style.corner_radius_top_left = 4
68 | normal_style.corner_radius_top_right = 4
69 | normal_style.corner_radius_bottom_left = 4
70 | normal_style.corner_radius_bottom_right = 4
71 |
72 | var hover_style = StyleBoxFlat.new()
73 | hover_style.bg_color = Color(0.8, 0.8, 0.8, 1.0)
74 | hover_style.corner_radius_top_left = 4
75 | hover_style.corner_radius_top_right = 4
76 | hover_style.corner_radius_bottom_left = 4
77 | hover_style.corner_radius_bottom_right = 4
78 |
79 | var pressed_style = StyleBoxFlat.new()
80 | pressed_style.bg_color = Color(0.85, 0.85, 0.85, 1.0)
81 | pressed_style.corner_radius_top_left = 4
82 | pressed_style.corner_radius_top_right = 4
83 | pressed_style.corner_radius_bottom_left = 4
84 | pressed_style.corner_radius_bottom_right = 4
85 |
86 | # Apply styles to button
87 | button.add_theme_stylebox_override("normal", normal_style)
88 | button.add_theme_stylebox_override("hover", hover_style)
89 | button.add_theme_stylebox_override("pressed", pressed_style)
90 |
91 | # Add padding to button
92 | button.custom_minimum_size.x = 100
93 | button.custom_minimum_size.y = 30
94 |
95 | # Set button text color
96 | button.add_theme_color_override("font_color", Color.WHITE)
97 | button.add_theme_color_override("font_hover_color", text_color)
98 |
99 | # Events from the buttons
100 | func _on_ok_button_pressed() -> void:
101 | emit_signal("prompt_confirmed", input_field.text)
102 | hide()
103 | print("PromptDialog : _on_ok_button_pressed")
104 |
105 | func _on_cancel_button_pressed() -> void:
106 | emit_signal("prompt_canceled", "")
107 | hide()
108 | print("PromptDialog : _on_cancel_button_pressed")
109 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/sequential.gd:
--------------------------------------------------------------------------------
1 | ## Execute its children
2 | ## upto one of them fails
3 | ## (return false)
4 |
5 | @icon("sequential.svg")
6 | class_name Sequential
7 | extends BehaviorTreeForGroups
8 |
9 | ## Activate / unactivate this sequence
10 | @export var activated:bool = true
11 |
12 | func biodyn_process(agent)->bool:
13 | # Sequential Node
14 | # Execute all its children, stops
15 | # a) after the 1st Failed
16 | # b) or after ALL children execution succeded
17 | # Return False if ONE of its children fail.
18 | # Returns True if all succeeded
19 | if activated == false:
20 | return false
21 | for behav in self.get_children():
22 | var success = behav.biodyn_process(agent)
23 | if success == false:
24 | return false
25 | return true
26 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/sequential.svg:
--------------------------------------------------------------------------------
1 |
2 |
53 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/sequential.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b1djd0cc1vk3h"
6 | path="res://.godot/imported/sequential.svg-44b8b3071cabbf19b9116d22a23d7582.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/behav_tree_for_groups/sequential.svg"
14 | dest_files=["res://.godot/imported/sequential.svg-44b8b3071cabbf19b9116d22a23d7582.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/set_age.gd:
--------------------------------------------------------------------------------
1 | ## Set an int to a current agent's age
2 |
3 | @icon("action.svg")
4 | class_name SetAge
5 | extends BehaviorTreeForGroups
6 |
7 | ## New agent's age value
8 | @export var age:int = 0
9 |
10 | func biodyn_process(agent:Node)->bool:
11 | agent.age = age
12 | return true
13 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/set_grid_value_2d.gd:
--------------------------------------------------------------------------------
1 | ## Set a float value inside a Grid2D
2 | ## at the location of the current agent
3 |
4 | @icon("action_2d.svg")
5 | class_name SetGridValue2D
6 | extends BehaviorTreeForGroups
7 |
8 | @export var field:String = ""
9 | @export var set_value:float = 0.5
10 |
11 | var grids:Array = Array()
12 |
13 | func _ready():
14 | for gp in self.get_groups():
15 | var sous_grids = get_tree().get_nodes_in_group(gp)
16 | for sg in sous_grids:
17 | if "fields" in sg:
18 | grids.push_back(sg)
19 |
20 | func biodyn_process(agent)->bool:
21 | for grid in grids:
22 | # 2D
23 | if agent is Node2D and "values_t0" in grid:
24 | var ax:float = agent.position.x
25 | var ay:float = agent.position.y
26 | var gx_min:float = grid.position.x
27 | var gx_max:float = gx_min+grid.size.x
28 | var gy_min:float = grid.position.y
29 | var gy_max:float = gy_min+grid.size.y
30 | if ax >= gx_min && ax < gx_max:
31 | if ay >= gy_min && ay < gy_max:
32 | var px:int = ((ax - gx_min) / grid.size.x) * grid.SX
33 | var py:int = ((ay - gy_min) / grid.size.y) * grid.SY
34 | var p:int = px+py*grid.SX
35 | if grid.fields_dico.has(field) == true:
36 | grid.values_t0[p].values[grid.fields_dico[field]] = set_value
37 | return true
38 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/set_state.gd:
--------------------------------------------------------------------------------
1 | ## Set the state of the current agent
2 |
3 | @icon("action.svg")
4 | class_name SetState
5 | extends BehaviorTreeForGroups
6 |
7 | ## New agent's state value
8 | @export var set_to_value:int = 0
9 | var update_state_at_age:int = -1
10 | var agt:Node = null
11 |
12 | func biodyn_process(agent:Node)->bool:
13 | try_update_state()
14 | if agent.state != set_to_value:
15 | update_state_at_age = agent.age+1
16 | agt = agent
17 |
18 | return true
19 |
20 | func _process(_delta):
21 | try_update_state()
22 |
23 | func try_update_state():
24 | if update_state_at_age != -1:
25 | if is_instance_valid(agt):
26 | if update_state_at_age <= agt.age:
27 | agt.state = set_to_value
28 | update_state_at_age = -1
29 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/stay_in_box.gd:
--------------------------------------------------------------------------------
1 | ## Force the current agent
2 | ## to stay inside a 2D or 3D box
3 |
4 | @tool
5 | @icon("action.svg")
6 |
7 | class_name StayInBox
8 | extends BehaviorTreeForGroups
9 |
10 | @export var min:Vector3 = Vector3(-5,-5,-5)
11 | @export var max:Vector3 = Vector3( 5, 5, 5)
12 | @export var loop_x:bool = false
13 | @export var loop_y:bool = false
14 | @export var loop_z:bool = false
15 |
16 | func biodyn_process(agent:Node) -> bool:
17 | if agent is Node3D:
18 | var x:float = agent.position.x
19 | var y:float = agent.position.y
20 | var z:float = agent.position.z
21 |
22 | var new_x:float = x
23 | var new_y:float = y
24 | var new_z:float = z
25 |
26 | var out_of_box = false
27 |
28 | # X Axis
29 | if x < min.x:
30 | out_of_box = true
31 | if loop_x == true:
32 | new_x = max.x
33 | else:
34 | new_x = min.x
35 | if agent is RigidBody3D:
36 | (agent as RigidBody3D).linear_velocity.x = - (agent as RigidBody3D).linear_velocity.x
37 |
38 | if x > max.x:
39 | out_of_box = true
40 | if loop_x == true:
41 | new_x = min.x
42 | else:
43 | new_x = max.x
44 | if agent is RigidBody3D:
45 | (agent as RigidBody3D).linear_velocity.x = - (agent as RigidBody3D).linear_velocity.x
46 |
47 | # Y Axis
48 | if y < min.y:
49 | out_of_box = true
50 | if loop_y == true:
51 | new_y = max.y
52 | else:
53 | new_y = min.y
54 | if agent is RigidBody3D:
55 | (agent as RigidBody3D).linear_velocity.y = - (agent as RigidBody3D).linear_velocity.y
56 |
57 | if y > max.y:
58 | out_of_box = true
59 | if loop_y == true:
60 | new_y = min.y
61 | else:
62 | new_y = max.y
63 | if agent is RigidBody3D:
64 | (agent as RigidBody3D).linear_velocity.y = - (agent as RigidBody3D).linear_velocity.y
65 |
66 | # Z Axis
67 | if z < min.z:
68 | out_of_box = true
69 | if loop_z == true:
70 | new_z = max.z
71 | else:
72 | new_z = min.z
73 | if agent is RigidBody3D:
74 | (agent as RigidBody3D).linear_velocity.z = - (agent as RigidBody3D).linear_velocity.z
75 |
76 | if z > max.z:
77 | out_of_box = true
78 | if loop_z == true:
79 | new_z = min.z
80 | else:
81 | new_z = max.z
82 | if agent is RigidBody3D:
83 | (agent as RigidBody3D).linear_velocity.z = - (agent as RigidBody3D).linear_velocity.z
84 |
85 | if out_of_box == true:
86 | #agent.position = Vector3(new_x,new_y,new_z)
87 | agent.global_transform.origin = Vector3(new_x,new_y,new_z)
88 | return true
89 |
90 | if agent is Node2D:
91 | var x:float = agent.position.x
92 | var y:float = agent.position.y
93 |
94 | var new_x:float = x
95 | var new_y:float = y
96 |
97 | var out_of_box = false
98 |
99 | # X Axis
100 | if x < min.x:
101 | out_of_box = true
102 | if loop_x == true:
103 | new_x = max.x
104 | else:
105 | new_x = min.x
106 | if agent is RigidBody2D:
107 | (agent as RigidBody2D).linear_velocity.x = - (agent as RigidBody2D).linear_velocity.x
108 |
109 | if x > max.x:
110 | out_of_box = true
111 | if loop_x == true:
112 | new_x = min.x
113 | else:
114 | new_x = max.x
115 | if agent is RigidBody2D:
116 | (agent as RigidBody2D).linear_velocity.x = - (agent as RigidBody2D).linear_velocity.x
117 |
118 | # Y Axis
119 | if y < min.y:
120 | out_of_box = true
121 | if loop_y == true:
122 | new_y = max.y
123 | else:
124 | new_y = min.y
125 | if agent is RigidBody2D:
126 | (agent as RigidBody2D).linear_velocity.y = - (agent as RigidBody2D).linear_velocity.y
127 |
128 | if y > max.y:
129 | out_of_box = true
130 | if loop_y == true:
131 | new_y = min.y
132 | else:
133 | new_y = max.y
134 | if agent is RigidBody2D:
135 | (agent as RigidBody2D).linear_velocity.y = - (agent as RigidBody2D).linear_velocity.y
136 |
137 | if out_of_box == true:
138 | agent.global_transform.origin = Vector2(new_x,new_y)
139 | # agent.position.x = new_x
140 | # agent.position.y = new_y
141 | return true
142 |
143 | return false
144 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/torque_global.gd:
--------------------------------------------------------------------------------
1 | ## Apply a torque on the current agent
2 | ## according to the absolute axis reference
3 |
4 | @icon("action.svg")
5 | class_name TorqueGlobal
6 | extends BehaviorTreeForGroups
7 |
8 | @export var rx:float = 0.0
9 | @export var ry:float = 0.0
10 | @export var rz:float = 0.0
11 |
12 | func biodyn_process(agent)->bool:
13 | if agent is RigidBody3D:
14 | agent.apply_torque_impulse ( Vector3 (rx, ry, rz) )
15 | return true
16 |
17 | if agent is RigidBody2D:
18 | agent.apply_torque_impulse ( rz )
19 | return true
20 |
21 | return false
22 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/torque_random.gd:
--------------------------------------------------------------------------------
1 | ## Apply a random torque on the current agent.
2 |
3 | @icon("action.svg")
4 | class_name TorqueRandom
5 | extends BehaviorTreeForGroups
6 |
7 | @export var rx:float = 1.0
8 | @export var ry:float = 1.0
9 | @export var rz:float = 1.0
10 |
11 | func biodyn_process(agent)->bool:
12 | if agent is Node3D:
13 | var rrx:float = rx * (randf() - 0.5)
14 | var rry:float = ry * (randf() - 0.5)
15 | var rrz:float = rz * (randf() - 0.5)
16 | #call_deferred("agent.apply_central_force", Vector3 (ffx, ffy, ffz) )
17 | agent.apply_torque_impulse ( Vector3 (rrx, rry, rrz) )
18 | return true
19 |
20 | if agent is Node2D:
21 | var rrz:float = rz * (randf() - 0.5)
22 | #call_deferred("agent.apply_central_force", Vector3 (ffx, ffy, ffz) )
23 | agent.apply_torque_impulse ( rrz )
24 | return true
25 |
26 | return false
27 |
--------------------------------------------------------------------------------
/addons/behav_tree_for_groups/translate_random.gd:
--------------------------------------------------------------------------------
1 | ## Apply a random translation
2 | ## on the current agent.
3 |
4 | @icon("action.svg")
5 | class_name TranslateRandom
6 | extends BehaviorTreeForGroups
7 |
8 | ## Maximum sizes of the random vector
9 | @export var delta:Vector3 = Vector3(1,1,1)
10 |
11 | func biodyn_process(agent)->bool:
12 | if agent is Node3D:
13 | var ddx:float = randf()*delta.x - delta.x / 2.0
14 | var ddy:float = randf()*delta.y - delta.y / 2.0
15 | var ddz:float = randf()*delta.z - delta.z / 2.0
16 | agent.translate ( Vector3 (ddx, ddy, ddz) )
17 | return true
18 |
19 | if agent is Node2D:
20 | var ddx:float = randf()*delta.x - delta.x / 2.0
21 | var ddy:float = randf()*delta.y - delta.y / 2.0
22 | agent.translate ( Vector2 (ddx, ddy) )
23 | return true
24 |
25 | return false
26 |
--------------------------------------------------------------------------------
/doc/behavior_tree_for_groups.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/doc/behavior_tree_for_groups.pdf
--------------------------------------------------------------------------------
/examples/2d_tutorial/agent_2d_0.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://dsdilworfnl1q"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_3rvo1"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _process(_delta):
12 | if not Engine.is_editor_hint():
13 | age += 1
14 |
15 | func _enter_tree():
16 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\")
17 | set_name.call_deferred(new_name)
18 | "
19 |
20 | [sub_resource type="CircleShape2D" id="CircleShape2D_qmo1i"]
21 |
22 | [node name="agent_2d_0" type="RigidBody2D" groups=["test_group"]]
23 | gravity_scale = 0.0
24 | contact_monitor = true
25 | max_contacts_reported = 2
26 | linear_damp = 1.0
27 | angular_damp = 1.0
28 | script = SubResource("GDScript_3rvo1")
29 |
30 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
31 | shape = SubResource("CircleShape2D_qmo1i")
32 |
33 | [node name="Polygon2D" type="Polygon2D" parent="."]
34 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
35 |
--------------------------------------------------------------------------------
/examples/2d_tutorial/main.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=5 format=3 uid="uid://b43rx2enqvlnj"]
2 |
3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_8qv0k"]
4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_vp25h"]
5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/translate_random.gd" id="3_pbt64"]
6 | [ext_resource type="PackedScene" uid="uid://dsdilworfnl1q" path="res://examples/2d_tutorial/agent_2d_0.tscn" id="4_7458n"]
7 |
8 | [node name="main" type="Node2D"]
9 |
10 | [node name="BehaviorTreeForGroups" type="Node" parent="."]
11 | script = ExtResource("1_8qv0k")
12 |
13 | [node name="Behavior" type="Node" parent="BehaviorTreeForGroups" groups=["test_group"]]
14 | script = ExtResource("2_vp25h")
15 |
16 | [node name="TranslateRandom" type="Node" parent="BehaviorTreeForGroups/Behavior"]
17 | script = ExtResource("3_pbt64")
18 | delta = Vector3(3, 3, 3)
19 |
20 | [node name="agent_2d_0" parent="." instance=ExtResource("4_7458n")]
21 | position = Vector2(146, 276)
22 |
23 | [node name="agent_2d_1" parent="." instance=ExtResource("4_7458n")]
24 | position = Vector2(160, 225)
25 |
26 | [node name="agent_2d_2" parent="." instance=ExtResource("4_7458n")]
27 | position = Vector2(107, 246)
28 |
29 | [node name="agent_2d_3" parent="." instance=ExtResource("4_7458n")]
30 | position = Vector2(249, 253)
31 |
32 | [node name="agent_2d_4" parent="." instance=ExtResource("4_7458n")]
33 | position = Vector2(207, 212)
34 |
35 | [node name="agent_2d_5" parent="." instance=ExtResource("4_7458n")]
36 | position = Vector2(196, 250)
37 |
38 | [node name="agent_2d_6" parent="." instance=ExtResource("4_7458n")]
39 | position = Vector2(214, 282)
40 |
41 | [node name="agent_2d_7" parent="." instance=ExtResource("4_7458n")]
42 | position = Vector2(129, 202)
43 |
--------------------------------------------------------------------------------
/examples/bacteria_colony/bact.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://bh4ftosmek2wy"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_oxsuj"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _process(_delta):
12 | if not Engine.is_editor_hint():
13 | age += 1
14 | "
15 |
16 | [sub_resource type="CircleShape2D" id="CircleShape2D_deou3"]
17 |
18 | [node name="Bact" type="RigidBody2D" groups=["bact"]]
19 | mass = 100.0
20 | gravity_scale = 0.0
21 | contact_monitor = true
22 | max_contacts_reported = 2
23 | linear_damp = 1.0
24 | angular_damp = 1.0
25 | script = SubResource("GDScript_oxsuj")
26 |
27 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
28 | shape = SubResource("CircleShape2D_deou3")
29 |
30 | [node name="Polygon2D" type="Polygon2D" parent="."]
31 | color = Color(1, 0, 0.0431373, 1)
32 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
33 |
--------------------------------------------------------------------------------
/examples/bacteria_colony/gluc.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://bx4xylu7e1eag"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_oxsuj"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _process(_delta):
12 | if not Engine.is_editor_hint():
13 | age += 1
14 | "
15 |
16 | [sub_resource type="CircleShape2D" id="CircleShape2D_deou3"]
17 |
18 | [node name="Gluc" type="RigidBody2D" groups=["gluc"]]
19 | gravity_scale = 0.0
20 | contact_monitor = true
21 | max_contacts_reported = 2
22 | linear_damp = 1.0
23 | angular_damp = 1.0
24 | script = SubResource("GDScript_oxsuj")
25 |
26 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
27 | shape = SubResource("CircleShape2D_deou3")
28 |
29 | [node name="Polygon2D" type="Polygon2D" parent="."]
30 | color = Color(0, 1, 0.0666667, 1)
31 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
32 |
--------------------------------------------------------------------------------
/examples/bacteria_colony/ker.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://3evit7hlnoq3"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_oxsuj"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _process(_delta):
12 | if not Engine.is_editor_hint():
13 | age += 1
14 | "
15 |
16 | [sub_resource type="CircleShape2D" id="CircleShape2D_deou3"]
17 |
18 | [node name="Ker" type="RigidBody2D"]
19 | mass = 1000.0
20 | gravity_scale = 0.0
21 | contact_monitor = true
22 | max_contacts_reported = 2
23 | linear_damp = 1.0
24 | angular_damp = 1.0
25 | script = SubResource("GDScript_oxsuj")
26 |
27 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
28 | scale = Vector2(10, 10)
29 | shape = SubResource("CircleShape2D_deou3")
30 |
31 | [node name="Polygon2D" type="Polygon2D" parent="."]
32 | scale = Vector2(10, 10)
33 | color = Color(1, 0.482353, 0, 1)
34 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
35 |
--------------------------------------------------------------------------------
/examples/coag/coag.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=17 format=3 uid="uid://dfu0f4ml38di0"]
2 |
3 | [ext_resource type="PackedScene" uid="uid://dl1mi18kqpcki" path="res://examples/coag/ma_grille.tscn" id="1_2thtx"]
4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_q4mpb"]
5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/field.gd" id="2_2xt6c"]
6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_mfvur"]
7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/reaction.gd" id="3_4oj5n"]
8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/set_grid_value_2d.gd" id="3_k5ybw"]
9 | [ext_resource type="PackedScene" uid="uid://m6hkrylkreko" path="res://examples/coag/fibro.tscn" id="4_a54p3"]
10 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="4_kqs1l"]
11 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/sequential.gd" id="5_n2l44"]
12 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_grid_2d_value_sup.gd" id="6_pl66x"]
13 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/add_agent.gd" id="7_n45if"]
14 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/delete.gd" id="8_duvfc"]
15 |
16 | [sub_resource type="Resource" id="Resource_q6ab2"]
17 | script = ExtResource("2_2xt6c")
18 | name = "A"
19 | color = Color(0, 0, 1, 1)
20 | diffusion_speed = 0.001
21 | degradation_speed = 0.01
22 | initialisation = "Random"
23 |
24 | [sub_resource type="Resource" id="Resource_dhys0"]
25 | script = ExtResource("2_2xt6c")
26 | name = "Field"
27 | color = Color(0, 1, 0, 1)
28 | diffusion_speed = 0.001
29 | degradation_speed = 0.01
30 | initialisation = "Random"
31 |
32 | [sub_resource type="Resource" id="Resource_lb84g"]
33 | script = ExtResource("2_2xt6c")
34 | name = "C"
35 | color = Color(1, 0.205149, 0.393126, 1)
36 | diffusion_speed = 0.3
37 | degradation_speed = 0.001
38 | initialisation = "0"
39 |
40 | [sub_resource type="Resource" id="Resource_p1nvq"]
41 | script = ExtResource("3_4oj5n")
42 | reactive_1 = "A"
43 | reactive_2 = "B"
44 | reactive_3 = ""
45 | speed = 0.01
46 | product_1 = "C"
47 | product_2 = ""
48 | product_3 = ""
49 |
50 | [node name="coag" type="Node2D"]
51 |
52 | [node name="BehaviorTreeForGroups" type="Node" parent="."]
53 | script = ExtResource("1_q4mpb")
54 |
55 | [node name="Secretion" type="Node" parent="BehaviorTreeForGroups" groups=["Fibro"]]
56 | script = ExtResource("2_mfvur")
57 |
58 | [node name="SetGridValue2D" type="Node" parent="BehaviorTreeForGroups/Secretion"]
59 | script = ExtResource("3_k5ybw")
60 | on_grid_group = "ma_grille"
61 | for_field = "A"
62 | set_value = 1.0
63 |
64 | [node name="ForceRandom" type="Node" parent="BehaviorTreeForGroups/Secretion"]
65 | script = ExtResource("4_kqs1l")
66 | F = Vector3(10, 10, 0)
67 |
68 | [node name="ActivationMacrophage" type="Node" parent="BehaviorTreeForGroups"]
69 | script = ExtResource("2_mfvur")
70 |
71 | [node name="Sequential" type="Node" parent="BehaviorTreeForGroups/ActivationMacrophage"]
72 | script = ExtResource("5_n2l44")
73 |
74 | [node name="IfGrid2DValueSup" type="Node" parent="BehaviorTreeForGroups/ActivationMacrophage/Sequential"]
75 | script = ExtResource("6_pl66x")
76 |
77 | [node name="AddAgent" type="Node" parent="BehaviorTreeForGroups/ActivationMacrophage/Sequential"]
78 | script = ExtResource("7_n45if")
79 |
80 | [node name="Delete" type="Node" parent="BehaviorTreeForGroups/ActivationMacrophage/Sequential"]
81 | script = ExtResource("8_duvfc")
82 |
83 | [node name="ma_grille" parent="." instance=ExtResource("1_2thtx")]
84 | offset_left = 110.0
85 | offset_top = 80.0
86 | offset_right = 1060.0
87 | offset_bottom = 596.0
88 | fields = Array[ExtResource("2_2xt6c")]([SubResource("Resource_q6ab2"), SubResource("Resource_dhys0"), SubResource("Resource_lb84g")])
89 | reactions = Array[ExtResource("3_4oj5n")]([SubResource("Resource_p1nvq")])
90 |
91 | [node name="Fibro" parent="." instance=ExtResource("4_a54p3")]
92 | position = Vector2(383, 361)
93 |
--------------------------------------------------------------------------------
/examples/coag/fibro.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://m6hkrylkreko"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_80yq4"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _process(_delta):
12 | if not Engine.is_editor_hint():
13 | age += 1
14 |
15 | "
16 |
17 | [sub_resource type="CircleShape2D" id="CircleShape2D_up5f6"]
18 |
19 | [node name="Fibro" type="RigidBody2D" groups=["Fibro"]]
20 | gravity_scale = 0.0
21 | contact_monitor = true
22 | max_contacts_reported = 2
23 | linear_damp = 1.0
24 | angular_damp = 1.0
25 | script = SubResource("GDScript_80yq4")
26 |
27 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
28 | shape = SubResource("CircleShape2D_up5f6")
29 |
30 | [node name="Polygon2D" type="Polygon2D" parent="."]
31 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
32 |
--------------------------------------------------------------------------------
/examples/coagulation/FA.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://bw71fvacgc6sk"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_6aa4s"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _process(_delta):
12 | if not Engine.is_editor_hint():
13 | age += 1
14 | "
15 |
16 | [sub_resource type="CircleShape2D" id="CircleShape2D_whlnq"]
17 |
18 | [node name="FA" type="RigidBody2D" groups=["FA", "circulating"]]
19 | gravity_scale = 0.0
20 | contact_monitor = true
21 | max_contacts_reported = 2
22 | linear_damp = 1.0
23 | angular_damp = 1.0
24 | script = SubResource("GDScript_6aa4s")
25 |
26 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
27 | scale = Vector2(0.5, 0.5)
28 | shape = SubResource("CircleShape2D_whlnq")
29 |
30 | [node name="Polygon2D" type="Polygon2D" parent="."]
31 | scale = Vector2(0.5, 0.5)
32 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
33 |
--------------------------------------------------------------------------------
/examples/coagulation/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/examples/coagulation/Thumbs.db
--------------------------------------------------------------------------------
/examples/coagulation/factors.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://weluiq846o2x"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_g40xn"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _enter_tree():
12 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\")
13 | set_name.call_deferred(new_name)
14 |
15 | "
16 |
17 | [sub_resource type="CircleShape2D" id="CircleShape2D_xyohc"]
18 | radius = 4.0
19 |
20 | [node name="Factors" type="RigidBody2D" groups=["factors"]]
21 | collision_layer = 2
22 | collision_mask = 2
23 | mass = 0.1
24 | gravity_scale = 0.0
25 | max_contacts_reported = 2
26 | contact_monitor = true
27 | linear_damp = 1.0
28 | angular_damp = 1.0
29 | script = SubResource("GDScript_g40xn")
30 |
31 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
32 | shape = SubResource("CircleShape2D_xyohc")
33 |
34 | [node name="Polygon2D" type="Polygon2D" parent="."]
35 | scale = Vector2(0.4, 0.404145)
36 | color = Color(1, 0.290196, 0, 1)
37 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
38 |
--------------------------------------------------------------------------------
/examples/coagulation/lesion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/examples/coagulation/lesion.png
--------------------------------------------------------------------------------
/examples/coagulation/lesion.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dsnumjw110fjy"
6 | path="res://.godot/imported/lesion.png-a04a2f0deb9866341dcc73d994083952.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://examples/coagulation/lesion.png"
14 | dest_files=["res://.godot/imported/lesion.png-a04a2f0deb9866341dcc73d994083952.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/examples/coagulation/lesion.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://8d1mmxxnxnxy"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_nyy48"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _enter_tree():
12 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\")
13 | set_name.call_deferred(new_name)
14 |
15 |
16 | func _process(_delta):
17 | if not Engine.is_editor_hint():
18 | age += 1
19 |
20 | "
21 |
22 | [sub_resource type="CircleShape2D" id="CircleShape2D_ikg3t"]
23 |
24 | [node name="lesion" type="RigidBody2D" groups=["fibro"]]
25 | gravity_scale = 0.0
26 | freeze = true
27 | freeze_mode = 1
28 | max_contacts_reported = 5
29 | contact_monitor = true
30 | linear_damp = 1.0
31 | angular_damp = 1.0
32 | script = SubResource("GDScript_nyy48")
33 | state = 1
34 | age = 3678
35 |
36 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
37 | shape = SubResource("CircleShape2D_ikg3t")
38 |
39 | [node name="Polygon2D" type="Polygon2D" parent="."]
40 | color = Color(1, 0.368627, 0.690196, 1)
41 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
42 |
--------------------------------------------------------------------------------
/examples/coagulation/platelet.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://c7hylydq3sl81"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_oq8p4"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _enter_tree():
12 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\")
13 | set_name.call_deferred(new_name)
14 |
15 |
16 | func _process(_delta):
17 | if not Engine.is_editor_hint():
18 | age += 1
19 |
20 | "
21 |
22 | [sub_resource type="CircleShape2D" id="CircleShape2D_rgg7l"]
23 |
24 | [node name="platelet" type="RigidBody2D" groups=["circulating", "platelet"]]
25 | collision_mask = 3
26 | gravity_scale = 0.0
27 | max_contacts_reported = 4
28 | contact_monitor = true
29 | linear_damp = 1.0
30 | angular_damp = 1.0
31 | script = SubResource("GDScript_oq8p4")
32 | age = 15724
33 |
34 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
35 | shape = SubResource("CircleShape2D_rgg7l")
36 |
37 | [node name="Polygon2D" type="Polygon2D" parent="."]
38 | color = Color(0.564706, 0.603922, 1, 1)
39 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
40 |
--------------------------------------------------------------------------------
/examples/coagulation/sphere_64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/examples/coagulation/sphere_64x64.png
--------------------------------------------------------------------------------
/examples/coagulation/sphere_64x64.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b7wtmuys4ctgj"
6 | path="res://.godot/imported/sphere_64x64.png-7405549ae7fa038ee7fb77f228b2c7a3.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://examples/coagulation/sphere_64x64.png"
14 | dest_files=["res://.godot/imported/sphere_64x64.png-7405549ae7fa038ee7fb77f228b2c7a3.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/examples/flow_2d/cell.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://i28u32im7gm4"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_kww5j"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | func _enter_tree():
9 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\")
10 | set_name.call_deferred(new_name)
11 |
12 | "
13 |
14 | [sub_resource type="CircleShape2D" id="CircleShape2D_n3lcf"]
15 |
16 | [node name="Cell" type="RigidBody2D" groups=["cell"]]
17 | gravity_scale = 0.0
18 | max_contacts_reported = 2
19 | contact_monitor = true
20 | linear_damp = 1.0
21 | angular_damp = 1.0
22 | script = SubResource("GDScript_kww5j")
23 |
24 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
25 | shape = SubResource("CircleShape2D_n3lcf")
26 |
27 | [node name="Polygon2D" type="Polygon2D" parent="."]
28 | color = Color(1, 0.0509804, 0.45098, 1)
29 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
30 |
--------------------------------------------------------------------------------
/examples/flow_2d/main.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=7 format=3 uid="uid://dpaaye4b1ct5e"]
2 |
3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_qevbp"]
4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_21fqr"]
5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="3_rck85"]
6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="4_q10aq"]
7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_global.gd" id="5_hquvo"]
8 | [ext_resource type="PackedScene" uid="uid://i28u32im7gm4" path="res://examples/flow_2d/cell.tscn" id="6_ko71e"]
9 |
10 | [node name="Flow2D" type="Node2D"]
11 |
12 | [node name="BehavTreeForGroups" type="Node" parent="."]
13 | script = ExtResource("1_qevbp")
14 |
15 | [node name="Behavior" type="Node" parent="BehavTreeForGroups" groups=["cell"]]
16 | script = ExtResource("2_21fqr")
17 |
18 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Behavior"]
19 | script = ExtResource("3_rck85")
20 |
21 | [node name="ForceGlobal" type="Node" parent="BehavTreeForGroups/Behavior"]
22 | script = ExtResource("5_hquvo")
23 | fx = 2.0
24 |
25 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Behavior"]
26 | script = ExtResource("4_q10aq")
27 | min = Vector3(200, 100, 0)
28 | max = Vector3(600, 200, 0)
29 | loop_x = true
30 |
31 | [node name="ColorRect" type="ColorRect" parent="."]
32 | offset_left = 200.0
33 | offset_top = 100.0
34 | offset_right = 600.0
35 | offset_bottom = 200.0
36 | color = Color(0.313726, 0.258824, 1, 0.290196)
37 |
38 | [node name="cell" parent="." instance=ExtResource("6_ko71e")]
39 | position = Vector2(259, 161)
40 |
41 | [node name="cell2" parent="." instance=ExtResource("6_ko71e")]
42 | position = Vector2(281, 146)
43 |
44 | [node name="cell3" parent="." instance=ExtResource("6_ko71e")]
45 | position = Vector2(236, 137)
46 |
47 | [node name="cell4" parent="." instance=ExtResource("6_ko71e")]
48 | position = Vector2(258, 122)
49 |
50 | [node name="cell5" parent="." instance=ExtResource("6_ko71e")]
51 | position = Vector2(328, 187)
52 |
53 | [node name="cell6" parent="." instance=ExtResource("6_ko71e")]
54 | position = Vector2(350, 172)
55 |
56 | [node name="cell7" parent="." instance=ExtResource("6_ko71e")]
57 | position = Vector2(305, 163)
58 |
59 | [node name="cell8" parent="." instance=ExtResource("6_ko71e")]
60 | position = Vector2(327, 148)
61 |
62 | [node name="cell9" parent="." instance=ExtResource("6_ko71e")]
63 | position = Vector2(391, 151)
64 |
65 | [node name="cell10" parent="." instance=ExtResource("6_ko71e")]
66 | position = Vector2(413, 136)
67 |
68 | [node name="cell11" parent="." instance=ExtResource("6_ko71e")]
69 | position = Vector2(368, 127)
70 |
71 | [node name="cell12" parent="." instance=ExtResource("6_ko71e")]
72 | position = Vector2(390, 112)
73 |
74 | [node name="cell13" parent="." instance=ExtResource("6_ko71e")]
75 | position = Vector2(460, 177)
76 |
77 | [node name="cell14" parent="." instance=ExtResource("6_ko71e")]
78 | position = Vector2(482, 162)
79 |
80 | [node name="cell15" parent="." instance=ExtResource("6_ko71e")]
81 | position = Vector2(437, 153)
82 |
83 | [node name="cell16" parent="." instance=ExtResource("6_ko71e")]
84 | position = Vector2(459, 138)
85 |
86 | [node name="cell17" parent="." instance=ExtResource("6_ko71e")]
87 | position = Vector2(497, 147)
88 |
89 | [node name="cell18" parent="." instance=ExtResource("6_ko71e")]
90 | position = Vector2(519, 132)
91 |
92 | [node name="cell19" parent="." instance=ExtResource("6_ko71e")]
93 | position = Vector2(474, 123)
94 |
95 | [node name="cell20" parent="." instance=ExtResource("6_ko71e")]
96 | position = Vector2(496, 108)
97 |
98 | [node name="cell21" parent="." instance=ExtResource("6_ko71e")]
99 | position = Vector2(566, 173)
100 |
101 | [node name="cell22" parent="." instance=ExtResource("6_ko71e")]
102 | position = Vector2(588, 158)
103 |
104 | [node name="cell23" parent="." instance=ExtResource("6_ko71e")]
105 | position = Vector2(543, 149)
106 |
107 | [node name="cell24" parent="." instance=ExtResource("6_ko71e")]
108 | position = Vector2(565, 134)
109 |
--------------------------------------------------------------------------------
/examples/flow_3d/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/examples/flow_3d/.DS_Store
--------------------------------------------------------------------------------
/examples/flow_3d/cell.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=5 format=3 uid="uid://doydn5x6x37xu"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_yh41y"]
4 | script/source = "
5 | @tool
6 | extends RigidBody3D
7 |
8 | #@export var agent_color:Color :
9 | # get:
10 | # return agent_color
11 | # set(value):
12 | # agent_color = value
13 | # if get_child(1) != null:
14 | # get_child(1).material_override.albedo_color = agent_color
15 |
16 | func _ready():
17 | pass
18 |
19 | func _process(delta):
20 | pass
21 |
22 | func _enter_tree():
23 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\")
24 | set_name.call_deferred(new_name)
25 |
26 | func emit_changed():
27 | pass
28 |
29 | "
30 |
31 | [sub_resource type="SphereShape3D" id="SphereShape3D_tjc2m"]
32 |
33 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_o7kob"]
34 | albedo_color = Color(0.443137, 0.321569, 0.780392, 1)
35 |
36 | [sub_resource type="SphereMesh" id="SphereMesh_sw65u"]
37 |
38 | [node name="Cell" type="RigidBody3D" groups=["cell"]]
39 | gravity_scale = 0.0
40 | max_contacts_reported = 2
41 | contact_monitor = true
42 | linear_damp = 5.0
43 | angular_damp = 5.0
44 | script = SubResource("GDScript_yh41y")
45 |
46 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
47 | shape = SubResource("SphereShape3D_tjc2m")
48 |
49 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
50 | material_override = SubResource("StandardMaterial3D_o7kob")
51 | mesh = SubResource("SphereMesh_sw65u")
52 |
--------------------------------------------------------------------------------
/examples/flow_3d/main.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=7 format=3 uid="uid://dxyigr7s87t04"]
2 |
3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_4jb5r"]
4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_3ieej"]
5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="3_f64oc"]
6 | [ext_resource type="PackedScene" uid="uid://doydn5x6x37xu" path="res://examples/flow_3d/cell.tscn" id="4_x2xy5"]
7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_global.gd" id="4_yuj62"]
8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="5_4avop"]
9 |
10 | [node name="Flow" type="Node3D"]
11 |
12 | [node name="BehavTreeForGroups" type="Node" parent="."]
13 | script = ExtResource("1_4jb5r")
14 |
15 | [node name="Behavior" type="Node" parent="BehavTreeForGroups" groups=["cell"]]
16 | script = ExtResource("2_3ieej")
17 |
18 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Behavior"]
19 | script = ExtResource("3_f64oc")
20 |
21 | [node name="ForceGlobal" type="Node" parent="BehavTreeForGroups/Behavior"]
22 | script = ExtResource("4_yuj62")
23 | fx = 0.3
24 |
25 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Behavior"]
26 | script = ExtResource("5_4avop")
27 | loop_x = true
28 |
29 | [node name="Camera3D" type="Camera3D" parent="."]
30 | transform = Transform3D(1, 0, 0, 0, 0.858978, 0.512013, 0, -0.512013, 0.858978, 0, 2.59212, 5.00598)
31 |
32 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
33 | transform = Transform3D(1, 0, 0, 0, 0.867245, 0.497882, 0, -0.497882, 0.867245, 0, 3.77915, 4.85166)
34 |
35 | [node name="cell" parent="." instance=ExtResource("4_x2xy5")]
36 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, 0, -0.0886159)
37 |
38 | [node name="cell2" parent="." instance=ExtResource("4_x2xy5")]
39 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, 0, -0.0886159)
40 |
41 | [node name="cell3" parent="." instance=ExtResource("4_x2xy5")]
42 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, 0, -0.0886159)
43 |
44 | [node name="cell4" parent="." instance=ExtResource("4_x2xy5")]
45 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, 0, -0.0886159)
46 |
47 | [node name="cell5" parent="." instance=ExtResource("4_x2xy5")]
48 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, 0, -1.23198)
49 |
50 | [node name="cell6" parent="." instance=ExtResource("4_x2xy5")]
51 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, 0, -1.23198)
52 |
53 | [node name="cell7" parent="." instance=ExtResource("4_x2xy5")]
54 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, 0, -1.23198)
55 |
56 | [node name="cell8" parent="." instance=ExtResource("4_x2xy5")]
57 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, 0, -1.23198)
58 |
59 | [node name="cell9" parent="." instance=ExtResource("4_x2xy5")]
60 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, 0, -2.37579)
61 |
62 | [node name="cell10" parent="." instance=ExtResource("4_x2xy5")]
63 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, 0, -2.37579)
64 |
65 | [node name="cell11" parent="." instance=ExtResource("4_x2xy5")]
66 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, 0, -2.37579)
67 |
68 | [node name="cell12" parent="." instance=ExtResource("4_x2xy5")]
69 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, 0, -2.37579)
70 |
71 | [node name="cell13" parent="." instance=ExtResource("4_x2xy5")]
72 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, 1.09299, -1.24824)
73 |
74 | [node name="cell14" parent="." instance=ExtResource("4_x2xy5")]
75 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, 1.09299, -1.24824)
76 |
77 | [node name="cell15" parent="." instance=ExtResource("4_x2xy5")]
78 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, 1.09299, -1.24824)
79 |
80 | [node name="cell16" parent="." instance=ExtResource("4_x2xy5")]
81 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, 1.09299, -1.24824)
82 |
83 | [node name="cell17" parent="." instance=ExtResource("4_x2xy5")]
84 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, -1.07794, -1.24824)
85 |
86 | [node name="cell18" parent="." instance=ExtResource("4_x2xy5")]
87 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, -1.07794, -1.24824)
88 |
89 | [node name="cell19" parent="." instance=ExtResource("4_x2xy5")]
90 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, -1.07794, -1.24824)
91 |
92 | [node name="cell20" parent="." instance=ExtResource("4_x2xy5")]
93 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, -1.07794, -1.24824)
94 |
--------------------------------------------------------------------------------
/examples/forest_fire/fire.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://cnvya7fqx07ur"]
2 |
3 | [sub_resource type="PlaneMesh" id="PlaneMesh_2od7k"]
4 |
5 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_vcjnx"]
6 | albedo_color = Color(1, 0, 0.0509804, 1)
7 |
8 | [sub_resource type="SphereShape3D" id="SphereShape3D_q8vu0"]
9 |
10 | [node name="Fire" type="RigidBody3D" groups=["Fire"]]
11 | gravity_scale = 0.0
12 | linear_damp = 2.0
13 |
14 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
15 | transform = Transform3D(0.16, 0, 0, 0, 0.16, 0, 0, 0, 0.16, 0, 0, 0)
16 | mesh = SubResource("PlaneMesh_2od7k")
17 | surface_material_override/0 = SubResource("StandardMaterial3D_vcjnx")
18 |
19 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
20 | transform = Transform3D(0.4, 0, 0, 0, 0.4, 0, 0, 0, 0.4, 0, 0, 0)
21 | shape = SubResource("SphereShape3D_q8vu0")
22 |
--------------------------------------------------------------------------------
/examples/forest_fire/tree.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=6 format=3 uid="uid://cis6ivx1riuic"]
2 |
3 | [sub_resource type="BoxShape3D" id="BoxShape3D_7nlum"]
4 |
5 | [sub_resource type="PrismMesh" id="PrismMesh_ieixx"]
6 |
7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_rxxig"]
8 | albedo_color = Color(0, 0.45098, 0.0352941, 1)
9 |
10 | [sub_resource type="CylinderMesh" id="CylinderMesh_4d0ge"]
11 |
12 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_i5c1d"]
13 | albedo_color = Color(1, 0.498039, 0.0235294, 1)
14 |
15 | [node name="Tree" type="RigidBody3D" groups=["Tree"]]
16 | axis_lock_linear_x = true
17 | axis_lock_linear_y = true
18 | axis_lock_linear_z = true
19 | axis_lock_angular_x = true
20 | axis_lock_angular_y = true
21 | axis_lock_angular_z = true
22 | max_contacts_reported = 1
23 | contact_monitor = true
24 |
25 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
26 | transform = Transform3D(1.46, 0, 0, 0, 1.46, 0, 0, 0, 1.46, 0, -0.228769, 0)
27 | shape = SubResource("BoxShape3D_7nlum")
28 |
29 | [node name="MeshInstance3D2" type="MeshInstance3D" parent="."]
30 | transform = Transform3D(1, 0, 0, 0, 0.351, 0, 0, 0, 1, 0, 0.233011, 0)
31 | mesh = SubResource("PrismMesh_ieixx")
32 | surface_material_override/0 = SubResource("StandardMaterial3D_rxxig")
33 |
34 | [node name="MeshInstance3D3" type="MeshInstance3D" parent="."]
35 | transform = Transform3D(1.46, 0, 0, 0, 0.511543, 0, 0, 0, 1.46, 0, -0.198279, 0)
36 | mesh = SubResource("PrismMesh_ieixx")
37 | surface_material_override/0 = SubResource("StandardMaterial3D_rxxig")
38 |
39 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
40 | transform = Transform3D(0.45, 0, 0, 0, 0.757859, 0, 0, 0, 0.45, 0, -1.17152, 0)
41 | mesh = SubResource("CylinderMesh_4d0ge")
42 | surface_material_override/0 = SubResource("StandardMaterial3D_i5c1d")
43 |
--------------------------------------------------------------------------------
/examples/forest_fire/tree_burned.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://co4y4j2jfmhr1"]
2 |
3 | [sub_resource type="BoxShape3D" id="BoxShape3D_7nlum"]
4 |
5 | [sub_resource type="CylinderMesh" id="CylinderMesh_4d0ge"]
6 |
7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0da6n"]
8 | albedo_color = Color(0.152941, 0.0705882, 0, 1)
9 |
10 | [node name="TreeBurned" type="RigidBody3D" groups=["TreeBurned"]]
11 | axis_lock_linear_x = true
12 | axis_lock_linear_y = true
13 | axis_lock_linear_z = true
14 | axis_lock_angular_x = true
15 | axis_lock_angular_y = true
16 | axis_lock_angular_z = true
17 |
18 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
19 | transform = Transform3D(0.6, 0, 0, 0, 0.6, 0, 0, 0, 0.6, 0, -1.02591, 0)
20 | shape = SubResource("BoxShape3D_7nlum")
21 |
22 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
23 | transform = Transform3D(0.45, 0, 0, 0, 0.757859, 0, 0, 0, 0.45, 0, -1.09886, 0)
24 | mesh = SubResource("CylinderMesh_4d0ge")
25 | surface_material_override/0 = SubResource("StandardMaterial3D_0da6n")
26 |
--------------------------------------------------------------------------------
/examples/forest_fire/tree_in_fire.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=6 format=3 uid="uid://dsdphcvcaxhpx"]
2 |
3 | [sub_resource type="BoxShape3D" id="BoxShape3D_7nlum"]
4 |
5 | [sub_resource type="PrismMesh" id="PrismMesh_ieixx"]
6 |
7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m3v45"]
8 | albedo_color = Color(1, 0, 0.14902, 1)
9 |
10 | [sub_resource type="CylinderMesh" id="CylinderMesh_4d0ge"]
11 |
12 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0da6n"]
13 | albedo_color = Color(0.152941, 0.0705882, 0, 1)
14 |
15 | [node name="TreeInFire" type="RigidBody3D" groups=["TreeInFire"]]
16 | axis_lock_linear_x = true
17 | axis_lock_linear_y = true
18 | axis_lock_linear_z = true
19 | axis_lock_angular_x = true
20 | axis_lock_angular_y = true
21 | axis_lock_angular_z = true
22 |
23 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
24 | transform = Transform3D(1.46, 0, 0, 0, 1.46, 0, 0, 0, 1.46, 0, -0.227753, 0)
25 | shape = SubResource("BoxShape3D_7nlum")
26 |
27 | [node name="MeshInstance3D2" type="MeshInstance3D" parent="."]
28 | transform = Transform3D(1, 0, 0, 0, 0.351, 0, 0, 0, 1, 0, 0.234027, 0)
29 | mesh = SubResource("PrismMesh_ieixx")
30 | surface_material_override/0 = SubResource("StandardMaterial3D_m3v45")
31 |
32 | [node name="MeshInstance3D3" type="MeshInstance3D" parent="."]
33 | transform = Transform3D(1.46, 0, 0, 0, 0.511543, 0, 0, 0, 1.46, 0, -0.197263, 0)
34 | mesh = SubResource("PrismMesh_ieixx")
35 | surface_material_override/0 = SubResource("StandardMaterial3D_m3v45")
36 |
37 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
38 | transform = Transform3D(0.45, 0, 0, 0, 0.757859, 0, 0, 0, 0.45, 0, -1.17051, 0)
39 | mesh = SubResource("CylinderMesh_4d0ge")
40 | surface_material_override/0 = SubResource("StandardMaterial3D_0da6n")
41 |
--------------------------------------------------------------------------------
/examples/grid2d/Agt.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://ccaq3hxvxvpla"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_sbo1b"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _process(_delta):
12 | if not Engine.is_editor_hint():
13 | age += 1
14 | "
15 |
16 | [sub_resource type="CircleShape2D" id="CircleShape2D_88vdm"]
17 |
18 | [node name="Agt" type="RigidBody2D" groups=["Agt"]]
19 | gravity_scale = 0.0
20 | contact_monitor = true
21 | max_contacts_reported = 2
22 | linear_damp = 1.0
23 | angular_damp = 1.0
24 | script = SubResource("GDScript_sbo1b")
25 |
26 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
27 | shape = SubResource("CircleShape2D_88vdm")
28 |
29 | [node name="Polygon2D" type="Polygon2D" parent="."]
30 | color = Color(1, 0, 0, 1)
31 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
32 |
--------------------------------------------------------------------------------
/examples/grid2d/follower.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://d3ie2qkjhjg3d"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_8ycgr"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _process(_delta):
12 | if not Engine.is_editor_hint():
13 | age += 1
14 | "
15 |
16 | [sub_resource type="CircleShape2D" id="CircleShape2D_g4qje"]
17 |
18 | [node name="follower" type="RigidBody2D" groups=["follower"]]
19 | gravity_scale = 0.0
20 | contact_monitor = true
21 | max_contacts_reported = 2
22 | linear_damp = 1.0
23 | angular_damp = 1.0
24 | script = SubResource("GDScript_8ycgr")
25 |
26 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
27 | shape = SubResource("CircleShape2D_g4qje")
28 |
29 | [node name="Polygon2D" type="Polygon2D" parent="."]
30 | color = Color(0.521569, 1, 0, 1)
31 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025)
32 |
--------------------------------------------------------------------------------
/examples/grid2d/reaction-diffusion.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene format=3 uid="uid://uxy5nviyl5pl"]
2 |
3 | [node name="Reaction-diffusion" type="Node2D"]
4 |
--------------------------------------------------------------------------------
/examples/grid2d/reaction_diffusion.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=27 format=3 uid="uid://ba0usgva601dg"]
2 |
3 | [ext_resource type="PackedScene" uid="uid://cpe7fdfuxa1bj" path="res://examples/grid2d/my_grid.tscn" id="1_qumfy"]
4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_xt3m6"]
5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/field.gd" id="2_a7pa0"]
6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_aq2ef"]
7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="3_w5h35"]
8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/set_grid_value_2d.gd" id="4_8b4h6"]
9 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="5_4atmj"]
10 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_to_grid_value.gd" id="6_3wt0p"]
11 | [ext_resource type="PackedScene" uid="uid://d3ie2qkjhjg3d" path="res://examples/grid2d/follower.tscn" id="7_uleci"]
12 | [ext_resource type="PackedScene" uid="uid://ccaq3hxvxvpla" path="res://examples/grid2d/Agt.tscn" id="8_a4qvu"]
13 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/reaction.gd" id="9_051ld"]
14 |
15 | [sub_resource type="Resource" id="Resource_knat1"]
16 | script = ExtResource("2_a7pa0")
17 | name = "A"
18 | color = Color(0, 0.988235, 0, 1)
19 | diffusion_speed = 0.1
20 | degradation_speed = 0.001
21 | initialisation = "Random"
22 |
23 | [sub_resource type="Resource" id="Resource_4fn7p"]
24 | script = ExtResource("2_a7pa0")
25 | name = "B"
26 | color = Color(1, 0.568627, 0.733333, 1)
27 | diffusion_speed = 0.005
28 | degradation_speed = 0.001
29 | initialisation = "0"
30 |
31 | [sub_resource type="Resource" id="Resource_57mwe"]
32 | script = ExtResource("2_a7pa0")
33 | name = "B"
34 | color = Color(1, 0, 0.0588235, 1)
35 | diffusion_speed = 0.1
36 | degradation_speed = 0.001
37 | initialisation = "Random"
38 |
39 | [sub_resource type="Resource" id="Resource_r0hg5"]
40 | script = ExtResource("9_051ld")
41 | reactive_1 = "A"
42 | reactive_2 = "A"
43 | reactive_3 = ""
44 | speed = 0.01
45 | product_1 = "3 A"
46 | product_2 = ""
47 | product_3 = ""
48 |
49 | [sub_resource type="Resource" id="Resource_3pbwn"]
50 | script = ExtResource("9_051ld")
51 | reactive_1 = "B"
52 | reactive_2 = "B"
53 | reactive_3 = ""
54 | speed = 0.01
55 | product_1 = "3 B"
56 | product_2 = ""
57 | product_3 = ""
58 |
59 | [sub_resource type="Resource" id="Resource_uqhw3"]
60 | script = ExtResource("9_051ld")
61 | reactive_1 = "A"
62 | reactive_2 = "B"
63 | reactive_3 = ""
64 | speed = 0.01
65 | product_1 = "0 A"
66 | product_2 = "0 B"
67 | product_3 = ""
68 |
69 | [sub_resource type="Resource" id="Resource_5x48p"]
70 | script = ExtResource("2_a7pa0")
71 | name = "B"
72 | color = Color(0, 0, 1, 1)
73 | diffusion_speed = 0.3
74 | degradation_speed = 0.001
75 | initialisation = "Random"
76 |
77 | [sub_resource type="Resource" id="Resource_00wib"]
78 | script = ExtResource("2_a7pa0")
79 | name = "Mol2"
80 | color = Color(0.8012, 0.555211, 0.460583, 1)
81 | diffusion_speed = 0.1
82 | degradation_speed = 0.0
83 | initialisation = "Random"
84 |
85 | [sub_resource type="Resource" id="Resource_uhnse"]
86 | script = ExtResource("2_a7pa0")
87 | name = "A"
88 | color = Color(1, 0, 1, 1)
89 | diffusion_speed = 0.3
90 | degradation_speed = 0.01
91 | initialisation = "0"
92 |
93 | [sub_resource type="Resource" id="Resource_g16xq"]
94 | script = ExtResource("2_a7pa0")
95 | name = "A"
96 | color = Color(0.926313, 0.000197721, 0.794224, 1)
97 | diffusion_speed = 0.05
98 | degradation_speed = 0.001
99 | initialisation = "Random"
100 |
101 | [sub_resource type="Resource" id="Resource_qxp5o"]
102 | script = ExtResource("2_a7pa0")
103 | name = "B"
104 | color = Color(2.55093e-06, 0.69572, 0.487671, 1)
105 | diffusion_speed = 0.05
106 | degradation_speed = 0.001
107 | initialisation = "Random"
108 |
109 | [sub_resource type="Resource" id="Resource_grxcc"]
110 | script = ExtResource("2_a7pa0")
111 | name = "C"
112 | color = Color(0, 0, 1, 1)
113 | diffusion_speed = 0.05
114 | degradation_speed = 0.001
115 | initialisation = "Random"
116 |
117 | [sub_resource type="Resource" id="Resource_oe8bw"]
118 | script = ExtResource("9_051ld")
119 | reactive_1 = "A"
120 | reactive_2 = "B"
121 | reactive_3 = ""
122 | speed = 0.3
123 | product_1 = "2 B"
124 | product_2 = ""
125 | product_3 = ""
126 |
127 | [sub_resource type="Resource" id="Resource_1dlc7"]
128 | script = ExtResource("9_051ld")
129 | reactive_1 = "B"
130 | reactive_2 = "C"
131 | reactive_3 = ""
132 | speed = 0.3
133 | product_1 = "2 C"
134 | product_2 = ""
135 | product_3 = ""
136 |
137 | [sub_resource type="Resource" id="Resource_5hr6g"]
138 | script = ExtResource("9_051ld")
139 | reactive_1 = "C"
140 | reactive_2 = "A"
141 | reactive_3 = ""
142 | speed = 0.3
143 | product_1 = "2 A"
144 | product_2 = ""
145 | product_3 = ""
146 |
147 | [node name="ReactionDiffusion" type="Node2D"]
148 |
149 | [node name="BehaviorTreeForGroups" type="Node" parent="."]
150 | script = ExtResource("1_xt3m6")
151 |
152 | [node name="Agt" type="Node" parent="BehaviorTreeForGroups" groups=["Agt"]]
153 | script = ExtResource("2_aq2ef")
154 |
155 | [node name="ForceRandom" type="Node" parent="BehaviorTreeForGroups/Agt"]
156 | script = ExtResource("3_w5h35")
157 | F = Vector3(50, 50, 50)
158 |
159 | [node name="SetGridValue2D" type="Node" parent="BehaviorTreeForGroups/Agt" groups=["my_grid"]]
160 | script = ExtResource("4_8b4h6")
161 | field = "A"
162 | set_value = 1.0
163 |
164 | [node name="StayInBox" type="Node" parent="BehaviorTreeForGroups/Agt"]
165 | script = ExtResource("5_4atmj")
166 | min = Vector3(0, 0, 0)
167 | max = Vector3(1000, 500, 0)
168 |
169 | [node name="Follow" type="Node" parent="BehaviorTreeForGroups" groups=["follower"]]
170 | script = ExtResource("2_aq2ef")
171 |
172 | [node name="ForceToGridValue" type="Node" parent="BehaviorTreeForGroups/Follow"]
173 | script = ExtResource("6_3wt0p")
174 | on_grid_group = "my_grid"
175 | for_field = "A"
176 | target_value = 1.0
177 | force = 10.0
178 |
179 | [node name="ForceRandom" type="Node" parent="BehaviorTreeForGroups/Follow"]
180 | script = ExtResource("3_w5h35")
181 | F = Vector3(20, 20, 20)
182 |
183 | [node name="SetGridValue2D2" type="Node" parent="BehaviorTreeForGroups/Follow" groups=["my_grid"]]
184 | script = ExtResource("4_8b4h6")
185 | field = "A"
186 | set_value = 1.0
187 |
188 | [node name="StayInBox2" type="Node" parent="BehaviorTreeForGroups/Follow"]
189 | script = ExtResource("5_4atmj")
190 | min = Vector3(0, 0, 0)
191 | max = Vector3(1000, 500, 0)
192 |
193 | [node name="my_grid" parent="." instance=ExtResource("1_qumfy")]
194 | offset_left = 24.0
195 | offset_top = 16.0
196 | offset_right = 536.0
197 | offset_bottom = 291.0
198 | SX = 128
199 | SY = 64
200 | fields = Array[ExtResource("2_a7pa0")]([SubResource("Resource_knat1"), SubResource("Resource_4fn7p")])
201 |
202 | [node name="my_grid2" parent="." instance=ExtResource("1_qumfy")]
203 | offset_left = 595.0
204 | offset_top = 14.0
205 | offset_right = 1107.0
206 | offset_bottom = 292.0
207 | SX = 128
208 | SY = 64
209 | fields = Array[ExtResource("2_a7pa0")]([SubResource("Resource_knat1"), SubResource("Resource_57mwe")])
210 | reactions = Array[ExtResource("9_051ld")]([SubResource("Resource_r0hg5"), SubResource("Resource_3pbwn"), SubResource("Resource_uqhw3")])
211 |
212 | [node name="my_grid3" parent="." instance=ExtResource("1_qumfy")]
213 | offset_left = 30.0
214 | offset_top = 343.0
215 | offset_right = 539.0
216 | offset_bottom = 614.0
217 | loop_x = true
218 | loop_y = true
219 | fields = Array[ExtResource("2_a7pa0")]([SubResource("Resource_5x48p"), SubResource("Resource_00wib"), SubResource("Resource_uhnse")])
220 |
221 | [node name="my_grid_Belousov_Zhabotinsky" parent="." instance=ExtResource("1_qumfy")]
222 | offset_left = 599.0
223 | offset_top = 347.0
224 | offset_right = 1108.0
225 | offset_bottom = 612.0
226 | loop_x = true
227 | loop_y = true
228 | fields = Array[ExtResource("2_a7pa0")]([SubResource("Resource_g16xq"), SubResource("Resource_qxp5o"), SubResource("Resource_grxcc")])
229 | reactions = Array[ExtResource("9_051ld")]([SubResource("Resource_oe8bw"), SubResource("Resource_1dlc7"), SubResource("Resource_5hr6g")])
230 |
231 | [node name="Agt" parent="." instance=ExtResource("8_a4qvu")]
232 | position = Vector2(334, 182)
233 |
234 | [node name="Agt2" parent="." instance=ExtResource("8_a4qvu")]
235 | position = Vector2(333, 458)
236 |
237 | [node name="Agt3" parent="." instance=ExtResource("8_a4qvu")]
238 | position = Vector2(862, 308)
239 |
240 | [node name="Agt4" parent="." instance=ExtResource("8_a4qvu")]
241 | position = Vector2(799, 357)
242 |
243 | [node name="Agt5" parent="." instance=ExtResource("8_a4qvu")]
244 | position = Vector2(334, 182)
245 |
246 | [node name="Agt6" parent="." instance=ExtResource("8_a4qvu")]
247 | position = Vector2(333, 458)
248 |
249 | [node name="Agt7" parent="." instance=ExtResource("8_a4qvu")]
250 | position = Vector2(862, 308)
251 |
252 | [node name="Agt8" parent="." instance=ExtResource("8_a4qvu")]
253 | position = Vector2(799, 357)
254 |
255 | [node name="Agt9" parent="." instance=ExtResource("8_a4qvu")]
256 | position = Vector2(334, 182)
257 |
258 | [node name="Agt10" parent="." instance=ExtResource("8_a4qvu")]
259 | position = Vector2(333, 458)
260 |
261 | [node name="Agt11" parent="." instance=ExtResource("8_a4qvu")]
262 | position = Vector2(862, 308)
263 |
264 | [node name="Agt12" parent="." instance=ExtResource("8_a4qvu")]
265 | position = Vector2(799, 357)
266 |
267 | [node name="follower" parent="." instance=ExtResource("7_uleci")]
268 | position = Vector2(165, 100)
269 |
270 | [node name="follower2" parent="." instance=ExtResource("7_uleci")]
271 | position = Vector2(200, 100)
272 |
273 | [node name="follower3" parent="." instance=ExtResource("7_uleci")]
274 | position = Vector2(700, 400)
275 |
276 | [node name="follower4" parent="." instance=ExtResource("7_uleci")]
277 | position = Vector2(800, 400)
278 |
279 | [node name="follower5" parent="." instance=ExtResource("7_uleci")]
280 | position = Vector2(165, 100)
281 |
282 | [node name="follower6" parent="." instance=ExtResource("7_uleci")]
283 | position = Vector2(200, 100)
284 |
285 | [node name="follower7" parent="." instance=ExtResource("7_uleci")]
286 | position = Vector2(700, 400)
287 |
288 | [node name="follower8" parent="." instance=ExtResource("7_uleci")]
289 | position = Vector2(800, 400)
290 |
291 | [node name="follower9" parent="." instance=ExtResource("7_uleci")]
292 | position = Vector2(165, 100)
293 |
294 | [node name="follower10" parent="." instance=ExtResource("7_uleci")]
295 | position = Vector2(200, 100)
296 |
297 | [node name="follower11" parent="." instance=ExtResource("7_uleci")]
298 | position = Vector2(700, 400)
299 |
300 | [node name="follower12" parent="." instance=ExtResource("7_uleci")]
301 | position = Vector2(800, 400)
302 |
--------------------------------------------------------------------------------
/examples/various/agent_2d.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://btaurfj6abv1j"]
2 |
3 | [sub_resource type="GDScript" id="GDScript_5seel"]
4 | script/source = "
5 | @tool
6 | extends RigidBody2D
7 |
8 | @export var state:int = 0
9 | @export var age:int = 0
10 |
11 | func _process(_delta):
12 | if not Engine.is_editor_hint():
13 | age += 1
14 |
15 | func _enter_tree():
16 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\")
17 | set_name.call_deferred(new_name)
18 | "
19 |
20 | [sub_resource type="CircleShape2D" id="CircleShape2D_3k7d8"]
21 |
22 | [node name="agent_2d" type="RigidBody2D" groups=["agt"]]
23 | gravity_scale = 0.0
24 | contact_monitor = true
25 | max_contacts_reported = 2
26 | linear_damp = 1.0
27 | angular_damp = 1.0
28 | script = SubResource("GDScript_5seel")
29 |
30 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
31 | shape = SubResource("CircleShape2D_3k7d8")
32 |
33 | [node name="Polygon2D" type="Polygon2D" parent="."]
34 | color = Color(1, 0.294118, 0.533333, 1)
35 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22461e-15, -5, -8.66025, 5, -8.66025)
36 |
--------------------------------------------------------------------------------
/examples/various/agent_a.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://c0socp63xfqt7"]
2 |
3 | [sub_resource type="BoxShape3D" id="BoxShape3D_obgbv"]
4 | size = Vector3(1, 0.3, 0.3)
5 |
6 | [sub_resource type="BoxMesh" id="BoxMesh_q4tn4"]
7 |
8 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_6w1qo"]
9 | albedo_color = Color(1, 0.745098, 0, 1)
10 |
11 | [node name="Agent-A" type="RigidBody3D" groups=["Agent-A"]]
12 | contact_monitor = true
13 | max_contacts_reported = 1
14 | metadata/Age = 0
15 |
16 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
17 | shape = SubResource("BoxShape3D_obgbv")
18 |
19 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
20 | transform = Transform3D(1, 0, 0, 0, 0.3, 0, 0, 0, 0.3, 0, 0, 0)
21 | mesh = SubResource("BoxMesh_q4tn4")
22 | surface_material_override/0 = SubResource("StandardMaterial3D_6w1qo")
23 |
--------------------------------------------------------------------------------
/examples/various/agent_b.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://cmh2j5wto6rrp"]
2 |
3 | [sub_resource type="SphereShape3D" id="SphereShape3D_f7ebv"]
4 |
5 | [sub_resource type="SphereMesh" id="SphereMesh_owuwi"]
6 |
7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_t20g3"]
8 | albedo_color = Color(1, 0.666667, 0.984314, 1)
9 |
10 | [node name="Agent-B" type="RigidBody3D" groups=["Agent-B"]]
11 | contact_monitor = true
12 | max_contacts_reported = 1
13 | metadata/Age = 0
14 |
15 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
16 | transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0)
17 | shape = SubResource("SphereShape3D_f7ebv")
18 |
19 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
20 | transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0)
21 | mesh = SubResource("SphereMesh_owuwi")
22 | surface_material_override/0 = SubResource("StandardMaterial3D_t20g3")
23 |
--------------------------------------------------------------------------------
/examples/various/agent_c.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://cnp1sb4hijc2o"]
2 |
3 | [sub_resource type="SphereShape3D" id="SphereShape3D_f7ebv"]
4 |
5 | [sub_resource type="SphereMesh" id="SphereMesh_owuwi"]
6 |
7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8mr6m"]
8 | albedo_color = Color(0.972549, 1, 0, 1)
9 |
10 | [node name="Agent-C" type="RigidBody3D" groups=["Agent-C"]]
11 | contact_monitor = true
12 | max_contacts_reported = 1
13 | metadata/Age = 0
14 |
15 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
16 | transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0)
17 | shape = SubResource("SphereShape3D_f7ebv")
18 |
19 | [node name="MeshInstance3D" type="MeshInstance3D" parent="." groups=["Agent-C"]]
20 | transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0)
21 | mesh = SubResource("SphereMesh_owuwi")
22 | surface_material_override/0 = SubResource("StandardMaterial3D_8mr6m")
23 |
--------------------------------------------------------------------------------
/examples/various/curie_therapy.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene format=3 uid="uid://bxd6dtmcpy2h4"]
2 |
3 | [node name="CurieTherapy" type="Node2D"]
4 |
5 | [node name="Label" type="Label" parent="."]
6 | offset_right = 40.0
7 | offset_bottom = 23.0
8 | text = "Work in progress..."
9 |
--------------------------------------------------------------------------------
/examples/various/molecule_adhesion.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=13 format=3 uid="uid://gbfhv38mowje"]
2 |
3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_ty85y"]
4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_r87fs"]
5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/sequential.gd" id="3_1a2m6"]
6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_step_between.gd" id="4_t67sr"]
7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/add_spring_on_contact.gd" id="4_u81ky"]
8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="4_wcjs1"]
9 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="4_xxsde"]
10 | [ext_resource type="PackedScene" uid="uid://cmh2j5wto6rrp" path="res://examples/various/agent_b.tscn" id="5_di58j"]
11 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_proba.gd" id="6_q137f"]
12 | [ext_resource type="PackedScene" uid="uid://cnp1sb4hijc2o" path="res://examples/various/agent_c.tscn" id="6_qqbgm"]
13 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/delete.gd" id="7_3e5lb"]
14 |
15 | [sub_resource type="BoxMesh" id="BoxMesh_ccvj4"]
16 | flip_faces = true
17 |
18 | [node name="ExampleAdhesion" type="Node3D"]
19 |
20 | [node name="BehavTreeForGroups" type="Node" parent="."]
21 | script = ExtResource("1_ty85y")
22 |
23 | [node name="Agent-B" type="Node" parent="BehavTreeForGroups" groups=["Agent-B"]]
24 | script = ExtResource("2_r87fs")
25 |
26 | [node name="MvtRandom" type="Node" parent="BehavTreeForGroups/Agent-B"]
27 | script = ExtResource("3_1a2m6")
28 |
29 | [node name="IfStepBetween" type="Node" parent="BehavTreeForGroups/Agent-B/MvtRandom"]
30 | script = ExtResource("4_t67sr")
31 | step_end = 100000
32 |
33 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Agent-B/MvtRandom"]
34 | script = ExtResource("4_xxsde")
35 |
36 | [node name="DeathRandom" type="Node" parent="BehavTreeForGroups/Agent-B"]
37 | script = ExtResource("3_1a2m6")
38 |
39 | [node name="IfStepBetween" type="Node" parent="BehavTreeForGroups/Agent-B/DeathRandom"]
40 | script = ExtResource("4_t67sr")
41 | step_start = 100000
42 | step_end = 100000000
43 |
44 | [node name="IfProba" type="Node" parent="BehavTreeForGroups/Agent-B/DeathRandom"]
45 | script = ExtResource("6_q137f")
46 | proba = 0.001
47 |
48 | [node name="Delete" type="Node" parent="BehavTreeForGroups/Agent-B/DeathRandom"]
49 | script = ExtResource("7_3e5lb")
50 |
51 | [node name="AddSpringOnContact" type="Node" parent="BehavTreeForGroups/Agent-B"]
52 | script = ExtResource("4_u81ky")
53 | with_group = "Agent-C"
54 |
55 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Agent-B"]
56 | script = ExtResource("4_wcjs1")
57 | min = Vector3(-1, -1, -1)
58 | max = Vector3(1, 1, 1)
59 |
60 | [node name="Agent-C" type="Node" parent="BehavTreeForGroups" groups=["Agent-C"]]
61 | script = ExtResource("2_r87fs")
62 |
63 | [node name="Sequential" type="Node" parent="BehavTreeForGroups/Agent-C"]
64 | script = ExtResource("3_1a2m6")
65 |
66 | [node name="IfStepBetween" type="Node" parent="BehavTreeForGroups/Agent-C/Sequential"]
67 | script = ExtResource("4_t67sr")
68 | step_end = 100000
69 |
70 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Agent-C/Sequential"]
71 | script = ExtResource("4_xxsde")
72 |
73 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Agent-C"]
74 | script = ExtResource("4_wcjs1")
75 | min = Vector3(-1, -1, -1)
76 | max = Vector3(1, 1, 1)
77 |
78 | [node name="Agent-B" parent="." instance=ExtResource("5_di58j")]
79 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0)
80 | gravity_scale = 0.0
81 |
82 | [node name="Agent-B2" parent="." instance=ExtResource("5_di58j")]
83 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0)
84 | gravity_scale = 0.0
85 |
86 | [node name="Agent-B3" parent="." instance=ExtResource("5_di58j")]
87 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0)
88 | gravity_scale = 0.0
89 |
90 | [node name="Agent-B4" parent="." instance=ExtResource("5_di58j")]
91 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0)
92 | gravity_scale = 0.0
93 |
94 | [node name="Agent-B5" parent="." instance=ExtResource("5_di58j")]
95 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0)
96 | gravity_scale = 0.0
97 |
98 | [node name="Agent-B6" parent="." instance=ExtResource("5_di58j")]
99 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0)
100 | gravity_scale = 0.0
101 |
102 | [node name="Agent-B7" parent="." instance=ExtResource("5_di58j")]
103 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0)
104 | gravity_scale = 0.0
105 |
106 | [node name="Agent-B8" parent="." instance=ExtResource("5_di58j")]
107 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0)
108 | gravity_scale = 0.0
109 |
110 | [node name="Agent-C" parent="." instance=ExtResource("6_qqbgm")]
111 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0)
112 | gravity_scale = 0.0
113 |
114 | [node name="Agent-C2" parent="." instance=ExtResource("6_qqbgm")]
115 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0)
116 | gravity_scale = 0.0
117 |
118 | [node name="Agent-C3" parent="." instance=ExtResource("6_qqbgm")]
119 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0)
120 | gravity_scale = 0.0
121 |
122 | [node name="Agent-C4" parent="." instance=ExtResource("6_qqbgm")]
123 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0)
124 | gravity_scale = 0.0
125 |
126 | [node name="Agent-C5" parent="." instance=ExtResource("6_qqbgm")]
127 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0)
128 | gravity_scale = 0.0
129 |
130 | [node name="Agent-C6" parent="." instance=ExtResource("6_qqbgm")]
131 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0)
132 | gravity_scale = 0.0
133 |
134 | [node name="Agent-C7" parent="." instance=ExtResource("6_qqbgm")]
135 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0)
136 | gravity_scale = 0.0
137 |
138 | [node name="Agent-C8" parent="." instance=ExtResource("6_qqbgm")]
139 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0)
140 | gravity_scale = 0.0
141 |
142 | [node name="Camera3D" type="Camera3D" parent="."]
143 | transform = Transform3D(1, 0, 0, 0, 0.890372, 0.455234, 0, -0.455234, 0.890372, 0, 1.04184, 2.29168)
144 |
145 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
146 | transform = Transform3D(1, 0, 0, 0, 0.180794, 0.983521, 0, -0.983521, 0.180794, 0, 0, 10.7686)
147 |
148 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
149 | transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0)
150 | mesh = SubResource("BoxMesh_ccvj4")
151 |
--------------------------------------------------------------------------------
/examples/various/prey_pred.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=14 format=3 uid="uid://cjttehav3absk"]
2 |
3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_bbgsd"]
4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_ydp6m"]
5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="3_n8pv4"]
6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/sequential.gd" id="4_52da3"]
7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_proba.gd" id="5_jmidm"]
8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/add_agent.gd" id="6_6wxfy"]
9 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_collision.gd" id="7_3pti1"]
10 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/delete.gd" id="8_bqvrh"]
11 | [ext_resource type="PackedScene" uid="uid://cmh2j5wto6rrp" path="res://examples/various/agent_b.tscn" id="9_1gvab"]
12 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="9_maaon"]
13 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_global.gd" id="10_ahpm3"]
14 | [ext_resource type="PackedScene" uid="uid://cnp1sb4hijc2o" path="res://examples/various/agent_c.tscn" id="10_sbjrl"]
15 |
16 | [sub_resource type="BoxMesh" id="BoxMesh_h8i4e"]
17 | flip_faces = true
18 |
19 | [node name="ExamplePreyPred" type="Node3D"]
20 |
21 | [node name="BehavTreeForGroups" type="Node" parent="."]
22 | script = ExtResource("1_bbgsd")
23 |
24 | [node name="Preys" type="Node" parent="BehavTreeForGroups" groups=["Agent-B"]]
25 | script = ExtResource("2_ydp6m")
26 |
27 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Preys"]
28 | script = ExtResource("3_n8pv4")
29 |
30 | [node name="Reproduce" type="Node" parent="BehavTreeForGroups/Preys"]
31 | script = ExtResource("4_52da3")
32 |
33 | [node name="IfProba" type="Node" parent="BehavTreeForGroups/Preys/Reproduce"]
34 | script = ExtResource("5_jmidm")
35 | proba = 1.0
36 |
37 | [node name="AddAgent" type="Node" parent="BehavTreeForGroups/Preys/Reproduce"]
38 | script = ExtResource("6_6wxfy")
39 | agent_tscn = "res://examples/various/agent_b.tscn"
40 |
41 | [node name="Eaten" type="Node" parent="BehavTreeForGroups/Preys"]
42 | script = ExtResource("4_52da3")
43 |
44 | [node name="IfContact" type="Node" parent="BehavTreeForGroups/Preys/Eaten"]
45 | script = ExtResource("7_3pti1")
46 | with_group = "Agent-C"
47 |
48 | [node name="Delete" type="Node" parent="BehavTreeForGroups/Preys/Eaten"]
49 | script = ExtResource("8_bqvrh")
50 |
51 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Preys"]
52 | script = ExtResource("9_maaon")
53 |
54 | [node name="Jump" type="Node" parent="BehavTreeForGroups/Preys"]
55 | script = ExtResource("4_52da3")
56 |
57 | [node name="IfProba" type="Node" parent="BehavTreeForGroups/Preys/Jump"]
58 | script = ExtResource("5_jmidm")
59 | proba = 0.1
60 |
61 | [node name="ForceGlobal" type="Node" parent="BehavTreeForGroups/Preys/Jump"]
62 | script = ExtResource("10_ahpm3")
63 | fy = 5.0
64 |
65 | [node name="Predators" type="Node" parent="BehavTreeForGroups" groups=["Agent-C"]]
66 | script = ExtResource("2_ydp6m")
67 |
68 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Predators"]
69 | script = ExtResource("3_n8pv4")
70 |
71 | [node name="Eat" type="Node" parent="BehavTreeForGroups/Predators"]
72 | script = ExtResource("4_52da3")
73 |
74 | [node name="IfContact" type="Node" parent="BehavTreeForGroups/Predators/Eat"]
75 | script = ExtResource("7_3pti1")
76 | with_group = "Agent-B"
77 |
78 | [node name="AddAgent" type="Node" parent="BehavTreeForGroups/Predators/Eat"]
79 | script = ExtResource("6_6wxfy")
80 | agent_tscn = "res://Examples/various/agent_c.tscn"
81 |
82 | [node name="Death" type="Node" parent="BehavTreeForGroups/Predators"]
83 | script = ExtResource("4_52da3")
84 |
85 | [node name="IfProba" type="Node" parent="BehavTreeForGroups/Predators/Death"]
86 | script = ExtResource("5_jmidm")
87 | proba = 0.3
88 |
89 | [node name="Delete" type="Node" parent="BehavTreeForGroups/Predators/Death"]
90 | script = ExtResource("8_bqvrh")
91 |
92 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Predators"]
93 | script = ExtResource("9_maaon")
94 |
95 | [node name="Camera3D" type="Camera3D" parent="."]
96 | transform = Transform3D(1, 0, 0, 0, 0.723714, 0.6901, 0, -0.6901, 0.723714, 0.0294014, 2.78409, 6.53686)
97 |
98 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
99 | transform = Transform3D(1, 0, 0, 0, 0.883782, 0.467899, 0, -0.467899, 0.883782, 0, 6.90312, 11.0244)
100 |
101 | [node name="Predator1" parent="." instance=ExtResource("10_sbjrl")]
102 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.48761, 0.7, -1.11156)
103 |
104 | [node name="Predator2" parent="." instance=ExtResource("10_sbjrl")]
105 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.19409, 0.7, -0.695615)
106 |
107 | [node name="Predator3" parent="." instance=ExtResource("10_sbjrl")]
108 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.968706, 0.7, -1.29503)
109 |
110 | [node name="Predator4" parent="." instance=ExtResource("10_sbjrl")]
111 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.02174, 0.7, -0.901522)
112 |
113 | [node name="Prey1" parent="." instance=ExtResource("9_1gvab")]
114 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.507974, 0.7, -0.246305)
115 |
116 | [node name="Prey2" parent="." instance=ExtResource("9_1gvab")]
117 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.01165, 0.7, -0.246305)
118 |
119 | [node name="Prey3" parent="." instance=ExtResource("9_1gvab")]
120 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.507974, 0.7, -0.959407)
121 |
122 | [node name="Prey4" parent="." instance=ExtResource("9_1gvab")]
123 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.01165, 0.7, -0.959407)
124 |
125 | [node name="Prey5" parent="." instance=ExtResource("9_1gvab")]
126 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.44594, 0.7, -0.246305)
127 |
128 | [node name="Prey6" parent="." instance=ExtResource("9_1gvab")]
129 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.94961, 0.7, -0.246305)
130 |
131 | [node name="Prey7" parent="." instance=ExtResource("9_1gvab")]
132 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.44594, 0.7, -0.959407)
133 |
134 | [node name="Prey8" parent="." instance=ExtResource("9_1gvab")]
135 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.94961, 0.7, -0.959407)
136 |
137 | [node name="Prey9" parent="." instance=ExtResource("9_1gvab")]
138 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.772096, 0.7, -0.735504)
139 |
140 | [node name="Prey10" parent="." instance=ExtResource("9_1gvab")]
141 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.27577, 0.7, -0.735504)
142 |
143 | [node name="Prey11" parent="." instance=ExtResource("9_1gvab")]
144 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.772096, 0.7, -1.44861)
145 |
146 | [node name="Prey12" parent="." instance=ExtResource("9_1gvab")]
147 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.27577, 0.7, -1.44861)
148 |
149 | [node name="Prey13" parent="." instance=ExtResource("9_1gvab")]
150 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.71006, 0.7, -0.735504)
151 |
152 | [node name="Prey14" parent="." instance=ExtResource("9_1gvab")]
153 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.21374, 0.7, -0.735504)
154 |
155 | [node name="Prey15" parent="." instance=ExtResource("9_1gvab")]
156 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.71006, 0.7, -1.44861)
157 |
158 | [node name="Prey16" parent="." instance=ExtResource("9_1gvab")]
159 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.21374, 0.7, -1.44861)
160 |
161 | [node name="Prey17" parent="." instance=ExtResource("9_1gvab")]
162 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.203144, 0.7, -0.0964099)
163 |
164 | [node name="Prey18" parent="." instance=ExtResource("9_1gvab")]
165 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.70682, 0.7, -0.0964099)
166 |
167 | [node name="Prey19" parent="." instance=ExtResource("9_1gvab")]
168 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.203144, 0.7, -0.809512)
169 |
170 | [node name="Prey20" parent="." instance=ExtResource("9_1gvab")]
171 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.70682, 0.7, -0.809512)
172 |
173 | [node name="Prey21" parent="." instance=ExtResource("9_1gvab")]
174 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.14111, 0.7, -0.0964099)
175 |
176 | [node name="Prey22" parent="." instance=ExtResource("9_1gvab")]
177 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.64478, 0.7, -0.0964099)
178 |
179 | [node name="Prey23" parent="." instance=ExtResource("9_1gvab")]
180 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.14111, 0.7, -0.809512)
181 |
182 | [node name="Prey24" parent="." instance=ExtResource("9_1gvab")]
183 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.64478, 0.7, -0.809512)
184 |
185 | [node name="Prey25" parent="." instance=ExtResource("9_1gvab")]
186 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.467266, 0.7, -0.585609)
187 |
188 | [node name="Prey26" parent="." instance=ExtResource("9_1gvab")]
189 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.97094, 0.7, -0.585609)
190 |
191 | [node name="Prey27" parent="." instance=ExtResource("9_1gvab")]
192 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.467266, 0.7, -1.29871)
193 |
194 | [node name="Prey28" parent="." instance=ExtResource("9_1gvab")]
195 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.97094, 0.7, -1.29871)
196 |
197 | [node name="Prey29" parent="." instance=ExtResource("9_1gvab")]
198 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.40523, 0.7, -0.585609)
199 |
200 | [node name="Prey30" parent="." instance=ExtResource("9_1gvab")]
201 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.90891, 0.7, -0.585609)
202 |
203 | [node name="Prey31" parent="." instance=ExtResource("9_1gvab")]
204 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.40523, 0.7, -1.29871)
205 |
206 | [node name="Prey32" parent="." instance=ExtResource("9_1gvab")]
207 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.90891, 0.7, -1.29871)
208 |
209 | [node name="Environment" type="MeshInstance3D" parent="."]
210 | transform = Transform3D(10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0)
211 | mesh = SubResource("BoxMesh_h8i4e")
212 |
--------------------------------------------------------------------------------
/examples/various/test_generic_6dof_joint_3d.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=6 format=3 uid="uid://cki3e4t2gcdqr"]
2 |
3 | [sub_resource type="SphereShape3D" id="SphereShape3D_d8nr6"]
4 |
5 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_pexjg"]
6 | albedo_color = Color(1, 0.584314, 0.552941, 1)
7 |
8 | [sub_resource type="BoxMesh" id="BoxMesh_3ci86"]
9 |
10 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_4soa8"]
11 | albedo_color = Color(0.666667, 1, 0.682353, 1)
12 |
13 | [sub_resource type="BoxMesh" id="BoxMesh_xulsm"]
14 |
15 | [node name="TestGeneric6DOFJoint3D" type="Node3D"]
16 |
17 | [node name="Generic6DOFJoint3D" type="Generic6DOFJoint3D" parent="."]
18 | node_a = NodePath("../Fixed")
19 | node_b = NodePath("../Moves")
20 | linear_spring_x/stiffness = 0.001
21 | linear_spring_x/damping = 0.1
22 | linear_spring_x/equilibrium_point = 1.0
23 | linear_spring_y/stiffness = 0.001
24 | linear_spring_y/damping = 0.1
25 | linear_spring_y/equilibrium_point = 1.0
26 | linear_spring_z/stiffness = 0.001
27 | linear_spring_z/damping = 0.1
28 | linear_spring_z/equilibrium_point = 1.0
29 | angular_limit_x/restitution = 10.0
30 | angular_limit_y/restitution = 10.0
31 | angular_limit_z/restitution = 10.0
32 |
33 | [node name="Fixed" type="RigidBody3D" parent="."]
34 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
35 | axis_lock_linear_x = true
36 | axis_lock_linear_y = true
37 | axis_lock_linear_z = true
38 | axis_lock_angular_x = true
39 | axis_lock_angular_y = true
40 | axis_lock_angular_z = true
41 | gravity_scale = 0.0
42 |
43 | [node name="CollisionShape3D" type="CollisionShape3D" parent="Fixed"]
44 | shape = SubResource("SphereShape3D_d8nr6")
45 |
46 | [node name="MeshInstance3D" type="MeshInstance3D" parent="Fixed"]
47 | material_override = SubResource("StandardMaterial3D_pexjg")
48 | mesh = SubResource("BoxMesh_3ci86")
49 |
50 | [node name="Moves" type="RigidBody3D" parent="."]
51 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.7, 2, 0)
52 |
53 | [node name="CollisionShape3D" type="CollisionShape3D" parent="Moves"]
54 | shape = SubResource("SphereShape3D_d8nr6")
55 |
56 | [node name="MeshInstance3D" type="MeshInstance3D" parent="Moves"]
57 | material_override = SubResource("StandardMaterial3D_4soa8")
58 | mesh = SubResource("BoxMesh_xulsm")
59 |
60 | [node name="Camera3D" type="Camera3D" parent="."]
61 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.767151, 4.75228)
62 |
63 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
64 | transform = Transform3D(1, 0, 0, 0, 0.866025, 0.5, 0, -0.5, 0.866025, 0, 5, 8)
65 |
--------------------------------------------------------------------------------
/project.godot:
--------------------------------------------------------------------------------
1 | ; Engine configuration file.
2 | ; It's best edited using the editor UI and not directly,
3 | ; since the parameters that go here are not all obvious.
4 | ;
5 | ; Format:
6 | ; [section] ; section goes between []
7 | ; param=value ; assign values to parameters
8 |
9 | config_version=5
10 |
11 | [application]
12 |
13 | config/name="behavior_tree_for_groups"
14 | config/description="A Behavior Tree to create swarm and multiagent systems based on Node's Groups."
15 | run/main_scene="res://examples/various/crowd_opposite_mvt.tscn"
16 | config/features=PackedStringArray("4.3", "Forward Plus")
17 | config/icon="res://addons/behav_tree_for_groups/icon.png"
18 |
19 | [display]
20 |
21 | window/stretch/mode="viewport"
22 |
23 | [editor_plugins]
24 |
25 | enabled=PackedStringArray("res://addons/behav_tree_for_groups/plugin.cfg")
26 |
--------------------------------------------------------------------------------
/screenshots/.gdignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/.gdignore
--------------------------------------------------------------------------------
/screenshots/BTFG_documentation_front_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/BTFG_documentation_front_page.png
--------------------------------------------------------------------------------
/screenshots/BTFG_documentation_front_page.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://d0or1opyfy513"
6 | path="res://.godot/imported/BTFG_documentation_front_page.png-ee3c8157e44908e447dc44db304e4256.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://screenshots/BTFG_documentation_front_page.png"
14 | dest_files=["res://.godot/imported/BTFG_documentation_front_page.png-ee3c8157e44908e447dc44db304e4256.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/screenshots/behav_tree_for_groups_flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behav_tree_for_groups_flow.png
--------------------------------------------------------------------------------
/screenshots/behav_tree_for_groups_flow_th.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behav_tree_for_groups_flow_th.png
--------------------------------------------------------------------------------
/screenshots/behav_tree_tor_groups_coag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behav_tree_tor_groups_coag.png
--------------------------------------------------------------------------------
/screenshots/behav_tree_tor_groups_coag_th.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behav_tree_tor_groups_coag_th.png
--------------------------------------------------------------------------------
/screenshots/behavior_tree_for_groups_forest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behavior_tree_for_groups_forest.png
--------------------------------------------------------------------------------
/screenshots/behavior_tree_for_groups_forest_th.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behavior_tree_for_groups_forest_th.png
--------------------------------------------------------------------------------
/screenshots/icon_big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/icon_big.png
--------------------------------------------------------------------------------