Add a behavior tree to the enemy

Add the Beehave addon.
Make the enemy do the same thing as before but with a behavior tree.
This commit is contained in:
Mathilde Grapin 2023-06-12 16:48:35 +02:00
parent 09f6925a00
commit 1aed988149
92 changed files with 4025 additions and 25 deletions

21
addons/beehave/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 bitbrain
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,33 @@
## The blackboard is an object that can be used to store and access data between
## multiple nodes of the behavior tree.
@icon("icons/blackboard.svg")
class_name Blackboard extends Node
var blackboard: Dictionary = {}
func keys() -> Array[String]:
var keys: Array[String]
keys.assign(blackboard.keys().duplicate())
return keys
func set_value(key: Variant, value: Variant, blackboard_name: String = 'default') -> void:
if not blackboard.has(blackboard_name):
blackboard[blackboard_name] = {}
blackboard[blackboard_name][key] = value
func get_value(key: Variant, default_value: Variant = null, blackboard_name: String = 'default') -> Variant:
if has_value(key, blackboard_name):
return blackboard[blackboard_name].get(key, default_value)
return default_value
func has_value(key: Variant, blackboard_name: String = 'default') -> bool:
return blackboard.has(blackboard_name) and blackboard[blackboard_name].has(key) and blackboard[blackboard_name][key] != null
func erase_value(key: Variant, blackboard_name: String = 'default') -> void:
if blackboard.has(blackboard_name):
blackboard[blackboard_name][key] = null

View file

@ -0,0 +1,91 @@
@tool
extends EditorDebuggerPlugin
const DebuggerTab := preload("debugger_tab.gd")
var debugger_tab := DebuggerTab.new()
var floating_window: Window
var session: EditorDebuggerSession
func _has_capture(prefix: String) -> bool:
return prefix == "beehave"
func _capture(message: String, data: Array, session_id: int) -> bool:
# in case the behavior tree has invalid setup this might be null
if debugger_tab == null:
return false
if message == "beehave:register_tree":
debugger_tab.register_tree(data[0])
return true
if message == "beehave:unregister_tree":
debugger_tab.unregister_tree(data[0])
return true
if message == "beehave:process_tick":
debugger_tab.graph.process_tick(data[0], data[1])
return true
if message == "beehave:process_begin":
debugger_tab.graph.process_begin(data[0])
return true
if message == "beehave:process_end":
debugger_tab.graph.process_end(data[0])
return true
return false
func _setup_session(session_id: int) -> void:
session = get_session(session_id)
session.started.connect(debugger_tab.start)
session.stopped.connect(debugger_tab.stop)
debugger_tab.name = "🐝 Beehave"
debugger_tab.make_floating.connect(_on_make_floating)
debugger_tab.session = session
session.add_session_tab(debugger_tab)
func _on_make_floating() -> void:
var plugin := BeehaveUtils.get_plugin()
if not plugin:
return
if floating_window:
_on_window_close_requested()
return
var border_size := Vector2(4, 4) * BeehaveUtils.get_editor_scale()
var editor_interface: EditorInterface = plugin.get_editor_interface()
var editor_main_screen = editor_interface.get_editor_main_screen()
debugger_tab.get_parent().remove_child(debugger_tab)
floating_window = Window.new()
var panel := Panel.new()
panel.add_theme_stylebox_override("panel", editor_interface.get_base_control().get_theme_stylebox("PanelForeground", "EditorStyles"))
panel.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
floating_window.add_child(panel)
var margin := MarginContainer.new()
margin.add_child(debugger_tab)
margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
margin.add_theme_constant_override("margin_right", border_size.x)
margin.add_theme_constant_override("margin_left", border_size.x)
margin.add_theme_constant_override("margin_top", border_size.y)
margin.add_theme_constant_override("margin_bottom", border_size.y)
panel.add_child(margin)
floating_window.title = "🐝 Beehave"
floating_window.wrap_controls = true
floating_window.min_size = Vector2i(600, 350)
floating_window.size = debugger_tab.size
floating_window.position = editor_main_screen.global_position
floating_window.transient = true
floating_window.close_requested.connect(_on_window_close_requested)
editor_interface.get_base_control().add_child(floating_window)
func _on_window_close_requested() -> void:
debugger_tab.get_parent().remove_child(debugger_tab)
session.add_session_tab(debugger_tab)
floating_window.queue_free()
floating_window = null

View file

@ -0,0 +1,31 @@
class_name BeehaveDebuggerMessages
static func can_send_message() -> bool:
return not Engine.is_editor_hint() and OS.has_feature("editor")
static func register_tree(beehave_tree: Dictionary) -> void:
if can_send_message():
EngineDebugger.send_message("beehave:register_tree", [beehave_tree])
static func unregister_tree(instance_id: int) -> void:
if can_send_message():
EngineDebugger.send_message("beehave:unregister_tree", [instance_id])
static func process_tick(instance_id: int, status: int) -> void:
if can_send_message():
EngineDebugger.send_message("beehave:process_tick", [instance_id, status])
static func process_begin(instance_id: int) -> void:
if can_send_message():
EngineDebugger.send_message("beehave:process_begin", [instance_id])
static func process_end(instance_id: int) -> void:
if can_send_message():
EngineDebugger.send_message("beehave:process_end", [instance_id])

View file

@ -0,0 +1,107 @@
@tool
extends PanelContainer
signal make_floating()
const BeehaveGraphEdit := preload("graph_edit.gd")
const TREE_ICON := preload("../icons/tree.svg")
var container: HSplitContainer
var item_list: ItemList
var graph: BeehaveGraphEdit
var message: Label
var active_trees: Dictionary
var active_tree_id: int = -1
var session: EditorDebuggerSession
func _ready() -> void:
container = HSplitContainer.new()
add_child(container)
item_list = ItemList.new()
item_list.custom_minimum_size = Vector2(200, 0)
item_list.item_selected.connect(_on_item_selected)
container.add_child(item_list)
graph = BeehaveGraphEdit.new()
container.add_child(graph)
message = Label.new()
message.text = "Run Project for debugging"
message.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
message.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
message.set_anchors_preset(Control.PRESET_CENTER)
add_child(message)
var button := Button.new()
button.flat = true
button.icon = get_theme_icon(&"ExternalLink", &"EditorIcons")
button.pressed.connect(func(): make_floating.emit())
button.tooltip_text = "Make floating"
button.focus_mode = Control.FOCUS_NONE
graph.get_zoom_hbox().add_child(button)
var toggle_button := Button.new()
toggle_button.flat = true
toggle_button.icon = get_theme_icon(&"Back", &"EditorIcons")
toggle_button.pressed.connect(_on_toggle_button_pressed.bind(toggle_button))
toggle_button.tooltip_text = "Toggle Panel"
toggle_button.focus_mode = Control.FOCUS_NONE
graph.get_zoom_hbox().add_child(toggle_button)
graph.get_zoom_hbox().move_child(toggle_button, 0)
stop()
visibility_changed.connect(_on_visibility_changed)
func start() -> void:
container.visible = true
message.visible = false
func stop() -> void:
container.visible = false
message.visible = true
active_trees.clear()
item_list.clear()
graph.beehave_tree = {}
func register_tree(data: Dictionary) -> void:
var idx := item_list.add_item(data.name, TREE_ICON)
item_list.set_item_tooltip(idx, data.path)
item_list.set_item_metadata(idx, data.id)
active_trees[data.id] = data
func unregister_tree(instance_id: int) -> void:
var id := str(instance_id)
for i in item_list.item_count:
if item_list.get_item_metadata(i) == id:
item_list.remove_item(i)
break
active_trees.erase(id)
if graph.beehave_tree.get("id", "") == id:
graph.beehave_tree = {}
func _on_toggle_button_pressed(toggle_button: Button) -> void:
item_list.visible = !item_list.visible
toggle_button.icon = get_theme_icon(&"Back" if item_list.visible else &"Forward", &"EditorIcons")
func _on_item_selected(idx: int) -> void:
var id: StringName = item_list.get_item_metadata(idx)
graph.beehave_tree = active_trees.get(id, {})
active_tree_id = id.to_int()
session.send_message("beehave:activate_tree", [active_tree_id])
func _on_visibility_changed() -> void:
session.send_message("beehave:visibility_changed", [visible and is_visible_in_tree()])

View file

@ -0,0 +1,33 @@
@tool
extends RefCounted
const SUCCESS_COLOR := Color("#009944c8")
const NORMAL_COLOR := Color("#15181e")
const FAILURE_COLOR := Color("#cf000f80")
const RUNNING_COLOR := Color("#ffcc00c8")
var empty: StyleBoxEmpty
var normal: StyleBoxFlat
var success: StyleBoxFlat
var failure: StyleBoxFlat
var running: StyleBoxFlat
func _init() -> void:
var plugin := BeehaveUtils.get_plugin()
if not plugin:
return
var editor_scale := BeehaveUtils.get_editor_scale()
empty = StyleBoxEmpty.new()
normal = plugin.get_editor_interface().get_base_control().get_theme_stylebox(&"frame", &"GraphNode").duplicate()
success = plugin.get_editor_interface().get_base_control().get_theme_stylebox(&"selected_frame", &"GraphNode").duplicate()
failure = success.duplicate()
running = success.duplicate()
success.border_color = SUCCESS_COLOR
failure.border_color = FAILURE_COLOR
running.border_color = RUNNING_COLOR

View file

@ -0,0 +1,38 @@
extends Node
var _registered_trees: Dictionary
var _active_tree: BeehaveTree
func _enter_tree() -> void:
EngineDebugger.register_message_capture("beehave", _on_debug_message)
func _on_debug_message(message: String, data: Array) -> bool:
if message == "activate_tree":
_set_active_tree(data[0])
return true
if message == "visibility_changed":
if _active_tree:
_active_tree._can_send_message = data[0]
return true
return false
func _set_active_tree(tree_id: int) -> void:
var tree: BeehaveTree = _registered_trees.get(tree_id, null)
if not tree:
return
if _active_tree:
_active_tree._can_send_message = false
_active_tree = tree
_active_tree._can_send_message = true
func register_tree(tree: BeehaveTree) -> void:
_registered_trees[tree.get_instance_id()] = tree
func unregister_tree(tree: BeehaveTree) -> void:
_registered_trees.erase(tree.get_instance_id())

View file

@ -0,0 +1,259 @@
@tool
extends GraphEdit
const BeehaveGraphNode := preload("graph_node.gd")
const HORIZONTAL_LAYOUT_ICON := preload("icons/horizontal_layout.svg")
const VERTICAL_LAYOUT_ICON := preload("icons/vertical_layout.svg")
const PROGRESS_SHIFT: int = 50
const INACTIVE_COLOR: Color = Color("#898989aa")
const ACTIVE_COLOR: Color = Color("#ffcc00c8")
const SUCCESS_COLOR: Color = Color("#009944c8")
var updating_graph: bool = false
var arraging_nodes: bool = false
var beehave_tree: Dictionary:
set(value):
if beehave_tree == value:
return
beehave_tree = value
active_nodes.clear()
_update_graph()
var horizontal_layout: bool = false:
set(value):
if updating_graph or arraging_nodes:
return
if horizontal_layout == value:
return
horizontal_layout = value
_update_layout_button()
_update_graph()
var active_nodes: Array[String]
var progress: int = 0
var layout_button: Button
func _ready() -> void:
custom_minimum_size = Vector2(100, 300)
arrange_nodes_button_hidden = true
minimap_enabled = false
layout_button = Button.new()
layout_button.flat = true
layout_button.focus_mode = Control.FOCUS_NONE
layout_button.pressed.connect(func(): horizontal_layout = not horizontal_layout)
get_zoom_hbox().add_child(layout_button)
_update_layout_button()
func _update_graph() -> void:
if updating_graph:
return
updating_graph = true
clear_connections()
for child in get_children():
remove_child(child)
child.queue_free()
if not beehave_tree.is_empty():
_add_nodes(beehave_tree)
_connect_nodes(beehave_tree)
_arrange_nodes.call_deferred(beehave_tree)
updating_graph = false
func _add_nodes(node: Dictionary) -> void:
if node.is_empty():
return
var gnode := BeehaveGraphNode.new(horizontal_layout)
add_child(gnode)
gnode.title_text = node.name
gnode.name = node.id
gnode.icon = _get_icon(node.type.back())
if node.type.has(&"BeehaveTree"):
gnode.set_slots(false, true)
elif node.type.has(&"Leaf"):
gnode.set_slots(true, false)
elif node.type.has(&"Composite") or node.type.has(&"Decorator"):
gnode.set_slots(true, true)
for child in node.get("children", []):
_add_nodes(child)
func _connect_nodes(node: Dictionary) -> void:
for child in node.get("children", []):
connect_node(node.id, 0, child.id, 0)
_connect_nodes(child)
func _arrange_nodes(node: Dictionary) -> void:
if arraging_nodes:
return
arraging_nodes = true
var tree_node := _create_tree_nodes(node)
tree_node.update_positions(horizontal_layout)
_place_nodes(tree_node)
arraging_nodes = false
func _create_tree_nodes(node: Dictionary, root: TreeNode = null) -> TreeNode:
var tree_node := TreeNode.new(get_node(node.id), root)
for child in node.get("children", []):
var child_node := _create_tree_nodes(child, tree_node)
tree_node.children.push_back(child_node)
return tree_node
func _place_nodes(node: TreeNode) -> void:
node.item.position_offset = Vector2(node.x, node.y)
for child in node.children:
_place_nodes(child)
func _get_icon(type: StringName) -> Texture2D:
var classes := ProjectSettings.get_global_class_list()
for c in classes:
if c["class"] == type:
var icon_path := c.get("icon", String())
if not icon_path.is_empty():
return load(icon_path)
return null
func get_status(status: int) -> String:
if status == 0:
return "SUCCESS"
elif status == 1:
return "FAILURE"
return "RUNNING"
func process_begin(instance_id: int) -> void:
if not _is_same_tree(instance_id):
return
for child in get_children():
child.set_meta("status", -1)
func process_tick(instance_id: int, status: int) -> void:
var node := get_node_or_null(str(instance_id))
if node:
node.text = "Status: %s" % get_status(status)
node.set_status(status)
node.set_meta("status", status)
if status == 0 or status == 2:
if not active_nodes.has(node.name):
active_nodes.push_back(node.name)
func process_end(instance_id: int) -> void:
if not _is_same_tree(instance_id):
return
for child in get_children():
var status := child.get_meta("status", -1)
match status:
0:
active_nodes.erase(child.name)
child.set_color(SUCCESS_COLOR)
1:
active_nodes.erase(child.name)
child.set_color(INACTIVE_COLOR)
2:
child.set_color(ACTIVE_COLOR)
_:
child.text = " "
child.set_status(status)
child.set_color(INACTIVE_COLOR)
func _is_same_tree(instance_id: int) -> bool:
return str(instance_id) == beehave_tree.get("id", "")
func _get_connection_line(from_position: Vector2, to_position: Vector2) -> PackedVector2Array:
var points: PackedVector2Array
from_position = from_position.round()
to_position = to_position.round()
points.push_back(from_position)
var mid_position := ((to_position + from_position) / 2).round()
if horizontal_layout:
points.push_back(Vector2(mid_position.x, from_position.y))
points.push_back(Vector2(mid_position.x, to_position.y))
else:
points.push_back(Vector2(from_position.x, mid_position.y))
points.push_back(Vector2(to_position.x, mid_position.y))
points.push_back(to_position)
return points
func _process(delta: float) -> void:
if not active_nodes.is_empty():
progress += 10 if delta >= 0.05 else 1
if progress >= 1000:
progress = 0
queue_redraw()
func _draw() -> void:
if active_nodes.is_empty():
return
var circle_size: float = max(3, 6 * zoom)
var progress_shift: float = PROGRESS_SHIFT * zoom
var connections := get_connection_list()
for c in connections:
if not c.from in active_nodes or not c.to in active_nodes:
continue
var from := get_node(String(c.from))
var to := get_node(String(c.to))
if from.get_meta("status", -1) < 0 or to.get_meta("status", -1) < 0:
return
var line := _get_connection_line(from.position + from.get_connection_output_position(c.from_port), to.position + to.get_connection_input_position(c.to_port))
var curve = Curve2D.new()
for l in line:
curve.add_point(l)
var max_steps := int(curve.get_baked_length())
var current_shift := progress % max_steps
var p := curve.sample_baked(current_shift)
draw_circle(p, circle_size, ACTIVE_COLOR)
var shift := current_shift - progress_shift
while shift >= 0:
draw_circle(curve.sample_baked(shift), circle_size, ACTIVE_COLOR)
shift -= progress_shift
shift = current_shift + progress_shift
while shift <= curve.get_baked_length():
draw_circle(curve.sample_baked(shift), circle_size, ACTIVE_COLOR)
shift += progress_shift
func _update_layout_button() -> void:
layout_button.icon = VERTICAL_LAYOUT_ICON if horizontal_layout else HORIZONTAL_LAYOUT_ICON
layout_button.tooltip_text = "Switch to Vertical layout" if horizontal_layout else "Switch to Horizontal layout"

View file

@ -0,0 +1,145 @@
@tool
extends GraphNode
const DEFAULT_COLOR := Color("#dad4cb")
const PORT_TOP_ICON := preload("icons/port_top.svg")
const PORT_BOTTOM_ICON := preload("icons/port_bottom.svg")
const PORT_LEFT_ICON := preload("icons/port_left.svg")
const PORT_RIGHT_ICON := preload("icons/port_right.svg")
@export var title_text: String:
set(value):
title_text = value
if title_label:
title_label.text = value
@export var text: String:
set(value):
text = value
if label:
label.text = " " if text.is_empty() else text
@export var icon: Texture2D:
set(value):
icon = value
if icon_rect:
icon_rect.texture = value
var layout_size: float:
get:
return size.y if horizontal else size.x
var panel: PanelContainer
var icon_rect: TextureRect
var title_label: Label
var container: VBoxContainer
var label: Label
var frames: RefCounted = BeehaveUtils.get_frames()
var horizontal: bool = false
func _init(horizontal: bool = false) -> void:
self.horizontal = horizontal
func _ready() -> void:
custom_minimum_size = Vector2(50, 50) * BeehaveUtils.get_editor_scale()
draggable = false
add_theme_stylebox_override("frame", frames.empty)
add_theme_stylebox_override("selected_frame", frames.empty)
add_theme_color_override("close_color", Color.TRANSPARENT)
add_theme_icon_override("close", ImageTexture.new())
# For top port
add_child(Control.new())
panel = PanelContainer.new()
panel.mouse_filter = Control.MOUSE_FILTER_PASS
panel.add_theme_stylebox_override("panel", frames.normal)
add_child(panel)
var vbox_container := VBoxContainer.new()
panel.add_child(vbox_container)
var title_size := 24 * BeehaveUtils.get_editor_scale()
var margin_container := MarginContainer.new()
margin_container.add_theme_constant_override("margin_top", -title_size - 2 * BeehaveUtils.get_editor_scale())
margin_container.mouse_filter = Control.MOUSE_FILTER_PASS
vbox_container.add_child(margin_container)
var title_container := HBoxContainer.new()
title_container.add_child(Control.new())
title_container.mouse_filter = Control.MOUSE_FILTER_PASS
title_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
margin_container.add_child(title_container)
icon_rect = TextureRect.new()
icon_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
title_container.add_child(icon_rect)
title_label = Label.new()
title_label.add_theme_color_override("font_color", DEFAULT_COLOR)
title_label.add_theme_font_override("font", get_theme_font("title_font"))
title_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
title_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
title_label.text = title_text
title_container.add_child(title_label)
title_container.add_child(Control.new())
container = VBoxContainer.new()
container.size_flags_vertical = Control.SIZE_EXPAND_FILL
container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
panel.add_child(container)
label = Label.new()
label.text = " " if text.is_empty() else text
container.add_child(label)
# For bottom port
add_child(Control.new())
minimum_size_changed.connect(_on_size_changed)
_on_size_changed.call_deferred()
func set_status(status: int) -> void:
panel.add_theme_stylebox_override("panel", _get_stylebox(status))
func _get_stylebox(status: int) -> StyleBox:
match status:
0: return frames.success
1: return frames.failure
2: return frames.running
_: return frames.normal
func set_slots(left_enabled: bool, right_enabled: bool) -> void:
if horizontal:
set_slot(1, left_enabled, 0, Color.WHITE, right_enabled, 0, Color.WHITE, PORT_LEFT_ICON, PORT_RIGHT_ICON)
else:
set_slot(0, left_enabled, 0, Color.WHITE, false, -2, Color.TRANSPARENT, PORT_TOP_ICON, null)
set_slot(2, false, -1, Color.TRANSPARENT, right_enabled, 0, Color.WHITE, null, PORT_BOTTOM_ICON)
func set_color(color: Color) -> void:
set_input_color(color)
set_output_color(color)
func set_input_color(color: Color) -> void:
set_slot_color_left(1 if horizontal else 0, color)
func set_output_color(color: Color) -> void:
set_slot_color_right(1 if horizontal else 2, color)
func _on_size_changed():
add_theme_constant_override("port_offset", 12 * BeehaveUtils.get_editor_scale() if horizontal else round(size.x / 2.0))

View file

@ -0,0 +1 @@
<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="matrix(0 -1 1 0 0 16)"><rect height="6" rx="1" stroke-width=".6" width="6" y="10"/><rect height="6" rx="1" stroke-width=".780723" width="6" x="5"/><rect height="6" rx="1" stroke-width=".780723" width="6" x="10" y="10"/><path d="m7 5h2v4h-2z" stroke-width=".768491"/><rect height="4" rx="1" ry="0" stroke-width=".768491" width="2" x="12" y="7"/><rect height="5" rx="1" stroke-width=".859" width="2" x="2" y="7"/><path d="m3 7h10v2h-10z" stroke-width="1.09113"/></g></svg>

After

Width:  |  Height:  |  Size: 562 B

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b4xw25mue1ktm"
path="res://.godot/imported/horizontal_layout.svg-d2a7af351e44f9bf61d0c938b6f47fac.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/debug/icons/horizontal_layout.svg"
dest_files=["res://.godot/imported/horizontal_layout.svg-d2a7af351e44f9bf61d0c938b6f47fac.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1 @@
<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><path d="m10 4a5 5 0 0 1 -2.5000001 4.3301271 5 5 0 0 1 -5-.0000002 5 5 0 0 1 -2.4999999-4.3301269" fill="#fff" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 222 B

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bdivs6ajl6yo8"
path="res://.godot/imported/port_bottom.svg-e5c5c61b642a79ab9c2b66ff56603d34.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/debug/icons/port_bottom.svg"
dest_files=["res://.godot/imported/port_bottom.svg-e5c5c61b642a79ab9c2b66ff56603d34.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1 @@
<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><path d="m5 0a5 5 0 0 0 -4.33012712 2.5000001 5 5 0 0 0 .0000002 5 5 5 0 0 0 4.33012692 2.4999999" fill="#fff" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 221 B

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cppwynbk7b67r"
path="res://.godot/imported/port_left.svg-69cd927c4db555f1edbb8d1f553ea2fd.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/debug/icons/port_left.svg"
dest_files=["res://.godot/imported/port_left.svg-69cd927c4db555f1edbb8d1f553ea2fd.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1 @@
<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><path d="m4.5 10a5 5 0 0 0 4.3301271-2.5000002 5 5 0 0 0 -.0000002-4.9999999 5 5 0 0 0 -4.3301269-2.4999999" fill="#fff" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 231 B

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b5tp0xrmqa42x"
path="res://.godot/imported/port_right.svg-f760bd8be2dd613d0d3848c998c92a2a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/debug/icons/port_right.svg"
dest_files=["res://.godot/imported/port_right.svg-f760bd8be2dd613d0d3848c998c92a2a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1 @@
<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><path d="m10-6a5 5 0 0 1 -2.5000001 4.3301271 5 5 0 0 1 -5-.0000002 5 5 0 0 1 -2.4999999-4.3301269" fill="#fff" fill-rule="evenodd" transform="scale(1 -1)"/></svg>

After

Width:  |  Height:  |  Size: 246 B

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bky8qt47hmp65"
path="res://.godot/imported/port_top.svg-d1b336cdc6a0dd570305782a1e56f61d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/debug/icons/port_top.svg"
dest_files=["res://.godot/imported/port_top.svg-d1b336cdc6a0dd570305782a1e56f61d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1 @@
<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><rect height="6" rx="1" stroke-width=".6" width="6" y="10"/><rect height="6" rx="1" stroke-width=".780723" width="6" x="5"/><rect height="6" rx="1" stroke-width=".780723" width="6" x="10" y="10"/><path d="m7 5h2v4h-2z" stroke-width=".768491"/><rect height="4" rx="1" ry="0" stroke-width=".768491" width="2" x="12" y="7"/><rect height="5" rx="1" stroke-width=".859" width="2" x="2" y="7"/><path d="m3 7h10v2h-10z" stroke-width="1.09113"/></g></svg>

After

Width:  |  Height:  |  Size: 528 B

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://clb3m3iitw3hw"
path="res://.godot/imported/vertical_layout.svg-1a08fee4b09812a05bcf3defb8afcc4c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/debug/icons/vertical_layout.svg"
dest_files=["res://.godot/imported/vertical_layout.svg-1a08fee4b09812a05bcf3defb8afcc4c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,255 @@
class_name TreeNode
extends RefCounted
# Based on https://rachel53461.wordpress.com/2014/04/20/algorithm-for-drawing-trees/
const SIBLING_DISTANCE: float = 20.0
const LEVEL_DISTANCE: float = 40.0
var x: float
var y: float
var mod: float
var parent: TreeNode
var children: Array[TreeNode]
var item: GraphNode
func _init(p_item: GraphNode = null, p_parent: TreeNode = null) -> void:
parent = p_parent
item = p_item
func is_leaf() -> bool:
return children.is_empty()
func is_most_left() -> bool:
if not parent:
return true
return parent.children.front() == self
func is_most_right() -> bool:
if not parent:
return true
return parent.children.back() == self
func get_previous_sibling() -> TreeNode:
if not parent or is_most_left():
return null
return parent.children[parent.children.find(self) - 1]
func get_next_sibling() -> TreeNode:
if not parent or is_most_right():
return null
return parent.children[parent.children.find(self) + 1]
func get_most_left_sibling() -> TreeNode:
if not parent:
return null
if is_most_left():
return self
return parent.children.front()
func get_most_left_child() -> TreeNode:
if children.is_empty():
return null
return children.front()
func get_most_right_child() -> TreeNode:
if children.is_empty():
return null
return children.back()
func update_positions(horizontally: bool = false) -> void:
_initialize_nodes(self, 0)
_calculate_initial_x(self)
_check_all_children_on_screen(self)
_calculate_final_positions(self, 0)
if horizontally:
_swap_x_y(self)
_calculate_x(self, 0)
else:
_calculate_y(self, 0)
func _initialize_nodes(node: TreeNode, depth: int) -> void:
node.x = -1
node.y = depth
node.mod = 0
for child in node.children:
_initialize_nodes(child, depth + 1)
func _calculate_initial_x(node: TreeNode) -> void:
for child in node.children:
_calculate_initial_x(child)
if node.is_leaf():
if not node.is_most_left():
node.x = node.get_previous_sibling().x + node.get_previous_sibling().item.layout_size + SIBLING_DISTANCE
else:
node.x = 0
else:
var mid: float
if node.children.size() == 1:
var offset: float = (node.children.front().item.layout_size - node.item.layout_size) / 2
mid = node.children.front().x + offset
else:
var left_child := node.get_most_left_child()
var right_child := node.get_most_right_child()
mid = (left_child.x + right_child.x + right_child.item.layout_size - node.item.layout_size) / 2
if node.is_most_left():
node.x = mid
else:
node.x = node.get_previous_sibling().x + node.get_previous_sibling().item.layout_size + SIBLING_DISTANCE
node.mod = node.x - mid
if not node.is_leaf() and not node.is_most_left():
_check_for_conflicts(node)
func _calculate_final_positions(node: TreeNode, mod_sum: float) -> void:
node.x += mod_sum
mod_sum += node.mod
for child in node.children:
_calculate_final_positions(child, mod_sum)
func _check_all_children_on_screen(node: TreeNode) -> void:
var node_contour: Dictionary = {}
_get_left_contour(node, 0, node_contour)
var shift_amount: float = 0
for y in node_contour.keys():
if node_contour[y] + shift_amount < 0:
shift_amount = (node_contour[y] * -1)
if shift_amount > 0:
node.x += shift_amount
node.mod += shift_amount
func _check_for_conflicts(node: TreeNode) -> void:
var min_distance := SIBLING_DISTANCE
var shift_value: float = 0
var shift_sibling: TreeNode = null
var node_contour: Dictionary = {}# { int, float }
_get_left_contour(node, 0, node_contour)
var sibling := node.get_most_left_sibling()
while sibling != null and sibling != node:
var sibling_contour: Dictionary = {}
_get_right_contour(sibling, 0, sibling_contour)
for level in range(node.y + 1, min(sibling_contour.keys().max(), node_contour.keys().max()) + 1):
var distance: float = node_contour[level] - sibling_contour[level]
if distance + shift_value < min_distance:
shift_value = min_distance - distance
shift_sibling = sibling
sibling = sibling.get_next_sibling()
if shift_value > 0:
node.x += shift_value
node.mod += shift_value
_center_nodes_between(shift_sibling, node)
func _center_nodes_between(left_node: TreeNode, right_node: TreeNode) -> void:
var left_index := left_node.parent.children.find(left_node)
var right_index := left_node.parent.children.find(right_node)
var num_nodes_between: int = (right_index - left_index) - 1
if num_nodes_between > 0:
# The extra distance that needs to be split into num_nodes_between + 1
# in order to find the new node spacing so that nodes are equally spaced
var distance_to_allocate: float = right_node.x - left_node.x - left_node.item.layout_size
# Subtract sizes on nodes in between
for i in range(left_index + 1, right_index):
distance_to_allocate -= left_node.parent.children[i].item.layout_size
# Divide space equally
var distance_between_nodes: float = distance_to_allocate / (num_nodes_between + 1)
var prev_node := left_node
var middle_node := left_node.get_next_sibling()
while middle_node != right_node:
var desire_x: float = prev_node.x + prev_node.item.layout_size + distance_between_nodes
var offset := desire_x - middle_node.x
middle_node.x += offset
middle_node.mod += offset
prev_node = middle_node
middle_node = middle_node.get_next_sibling()
func _get_left_contour(node: TreeNode, mod_sum: float, values: Dictionary) -> void:
var node_left: float = node.x + mod_sum
var depth := int(node.y)
if not values.has(depth):
values[depth] = node_left
else:
values[depth] = min(values[depth], node_left)
mod_sum += node.mod
for child in node.children:
_get_left_contour(child, mod_sum, values)
func _get_right_contour(node: TreeNode, mod_sum: float, values: Dictionary) -> void:
var node_right: float = node.x + mod_sum + node.item.layout_size
var depth := int(node.y)
if not values.has(depth):
values[depth] = node_right
else:
values[depth] = max(values[depth], node_right)
mod_sum += node.mod
for child in node.children:
_get_right_contour(child, mod_sum, values)
func _swap_x_y(node: TreeNode) -> void:
for child in node.children:
_swap_x_y(child)
var temp := node.x
node.x = node.y
node.y = temp
func _calculate_x(node: TreeNode, offset: int) -> void:
node.x = offset
var sibling := node.get_most_left_sibling()
var max_size: int = node.item.size.x
while sibling != null:
max_size = max(sibling.item.size.x, max_size)
sibling = sibling.get_next_sibling()
for child in node.children:
_calculate_x(child, max_size + offset + LEVEL_DISTANCE * BeehaveUtils.get_editor_scale())
func _calculate_y(node: TreeNode, offset: int) -> void:
node.y = offset
var sibling := node.get_most_left_sibling()
var max_size: int = node.item.size.y
while sibling != null:
max_size = max(sibling.item.size.y, max_size)
sibling = sibling.get_next_sibling()
for child in node.children:
_calculate_y(child, max_size + offset + LEVEL_DISTANCE * BeehaveUtils.get_editor_scale())

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="18.512016"
width="14.055721"
version="1.1"
id="svg8741"
sodipodi:docname="action.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8745" />
<sodipodi:namedview
id="namedview8743"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="7.6367532"
inkscape:cx="-17.284833"
inkscape:cy="19.183545"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg8741" />
<path
d="M 10.176432,3.6912688 Q 9.4137999,3.5779847 8.9573199,2.9622304 8.5018279,2.346623 8.6151119,1.5839909 q 0.113137,-0.76164287 0.727903,-1.21827047 0.615754,-0.45648072 1.3783861,-0.34319658 0.762632,0.1132841 1.218124,0.72889148 0.45648,0.61575427 0.343343,1.37739717 -0.113284,0.7626321 -0.729038,1.2191128 -0.614766,0.4566276 -1.377398,0.3433435 z M 8.3557339,18.50048 q -0.412474,-0.06127 -0.675246,-0.415727 -0.263613,-0.355592 -0.2024895,-0.767077 l 0.5938965,-3.998131 -1.1673025,-1.499791 -0.492278,1.19059 Q 6.067908,13.906466 5.2412215,14.299263 4.4143881,14.693049 3.5141916,14.369273 L 0.68012778,13.316428 q -0.3971933,-0.164141 -0.5825748,-0.549563 -0.1843923,-0.385274 -0.0202507,-0.782468 0.1463082,-0.420062 0.5218382,-0.606912 0.3753831,-0.185862 0.79544492,-0.03955 L 4.2327238,12.370146 6.3483399,6.4922013 5.1950516,6.7424632 4.9226408,8.5763411 Q 4.8584317,9.0085983 4.5028393,9.2722113 4.1483829,9.534983 3.7359088,9.473712 3.3234346,9.412442 3.0497828,9.0563693 2.7772671,8.6994546 2.8414761,8.2671975 L 3.0925819,6.5767458 Q 3.1935238,5.897202 3.6684284,5.3884589 4.1443222,4.8798627 4.8023572,4.703636 L 6.9923039,4.1443377 q 0.743073,-0.1838143 1.140791,-0.2409975 0.398708,-0.057036 0.728094,-0.00811 0.515345,0.076551 0.87859,0.3943727 0.3633911,0.3168322 0.5670941,0.7898969 l 0.629089,1.4410733 q 0.295795,0.6970267 0.885176,1.2688312 0.589381,0.5718045 1.447044,0.8892676 0.421051,0.1464552 0.62705,0.4611386 0.205852,0.3156725 0.147667,0.7073745 -0.07347,0.494573 -0.448694,0.754259 -0.376218,0.259539 -0.813966,0.08937 Q 11.753166,10.370427 10.957563,9.778099 10.159981,9.1854775 9.5990659,8.4288493 l -0.661707,1.9024227 0.845301,1.115306 q 0.2835431,0.357542 0.3859911,0.804445 0.102448,0.446903 0.03501,0.900921 l -0.6642771,4.471933 q -0.06112,0.411485 -0.416716,0.675098 -0.355445,0.262624 -0.76693,0.201501 z"
id="path8739"
style="fill:#ffb649;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cjeip5yvvptwj"
path="res://.godot/imported/action.svg-e8a91246d0ba9ba3cf84290d65648f06.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/action.svg"
dest_files=["res://.godot/imported/action.svg-e8a91246d0ba9ba3cf84290d65648f06.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="14.416"
width="15.416"
version="1.1"
id="svg1061"
sodipodi:docname="blackboard.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1065" />
<sodipodi:namedview
id="namedview1063"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="30.547013"
inkscape:cx="-0.42557352"
inkscape:cy="10.62297"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg1061" />
<path
d="M 0,4.333 V 1.937 Q 0,1.125 0.573,0.562 1.146,0 1.937,0 h 11.542 q 0.791,0 1.364,0.562 0.573,0.563 0.573,1.375 v 2.396 z m 4.354,1.396 v 8.687 H 1.937 q -0.791,0 -1.364,-0.573 Q 0,13.27 0,12.479 v -6.75 z m 6.708,0 h 4.354 v 6.75 q 0,0.791 -0.573,1.364 -0.573,0.573 -1.364,0.573 h -2.417 z m -1.396,0 v 8.687 H 5.75 V 5.729 Z"
id="path1059"
style="fill:#c689ff;fill-opacity:1;stroke:none;stroke-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cd8ge6anm44wd"
path="res://.godot/imported/blackboard.svg-18d4dfd4f6de558de250b67251ff1e69.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/blackboard.svg"
dest_files=["res://.godot/imported/blackboard.svg-18d4dfd4f6de558de250b67251ff1e69.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="16.375999"
width="14.126321"
version="1.1"
id="svg4"
sodipodi:docname="category_bt.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="15.273506"
inkscape:cx="7.071068"
inkscape:cy="10.377447"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="m 11.48968,7.688 q -0.354,0 -0.76,-0.219 -0.406,-0.219 -0.552,-0.51 L 9.5736798,6 q -0.167,-0.291 -0.167,-0.729 0,-0.437 0.167,-0.729 L 10.07368,3.667 q 0.146,-0.291 0.552,-0.531 0.406,-0.24 0.76,-0.24 h 0.875 q 0.375,0 0.792,0.219 0.417,0.219 0.562,0.552 l 0.355,0.854 q 0.145,0.334 0.156,0.761 0.01,0.427 -0.136,0.76 l -0.396,0.875 q -0.145,0.333 -0.552,0.552 -0.406,0.219 -0.781,0.219 z m -4.8120002,2.917 q -0.354,0 -0.761,-0.219 -0.406,-0.219 -0.573,-0.531 l -0.374,-0.917 q -0.146,-0.312 -0.146,-0.75 0,-0.438 0.146,-0.75 l 0.374,-0.917 q 0.167,-0.312 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.219 0.552,0.531 l 0.396,0.917 q 0.146,0.312 0.146,0.75 0,0.438 -0.146,0.75 l -0.396,0.917 q -0.146,0.312 -0.552,0.531 -0.406,0.219 -0.781,0.219 z m 0,-5.813 q -0.354,0 -0.761,-0.219 -0.406,-0.218 -0.573,-0.531 l -0.374,-0.875 q -0.146,-0.333 -0.146,-0.771 0,-0.437 0.146,-0.75 l 0.374,-0.896 q 0.167,-0.312 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.219 0.552,0.531 l 0.396,0.896 q 0.146,0.313 0.146,0.75 0,0.438 -0.146,0.771 l -0.396,0.875 q -0.146,0.313 -0.552,0.531 -0.406,0.219 -0.781,0.219 z m -4.813,2.896 q -0.375,0 -0.771,-0.219 Q 0.69867978,7.25 0.53167978,6.917 l -0.375,-0.875 Q -0.01032022,5.709 6.7977528e-4,5.282 0.01067978,4.855 0.17767978,4.521 l 0.333,-0.854 q 0.167,-0.333 0.57300002,-0.552 0.406,-0.219 0.781,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.407,0.219 0.573,0.552 l 0.334,0.854 q 0.166,0.334 0.177,0.761 0.01,0.427 -0.157,0.76 l -0.374,0.875 q -0.167,0.333 -0.563,0.552 -0.396,0.219 -0.771,0.219 z m 0,5.75 q -0.375,0 -0.781,-0.219 Q 0.67767978,13 0.51067978,12.667 l -0.333,-0.854 Q 0.01067978,11.48 6.7977528e-4,11.053 -0.01032022,10.626 0.15667978,10.292 l 0.375,-0.875 q 0.167,-0.333 0.56200002,-0.552 0.396,-0.219 0.771,-0.219 h 0.771 q 0.375,0 0.771,0.219 0.396,0.219 0.563,0.552 l 0.374,0.875 q 0.167,0.334 0.157,0.761 -0.011,0.427 -0.177,0.76 l -0.334,0.854 q -0.166,0.333 -0.573,0.552 -0.406,0.219 -0.781,0.219 z m 4.855,2.938 q -0.355,0 -0.761,-0.219 -0.406,-0.219 -0.594,-0.531 l -0.375,-0.896 q -0.166,-0.313 -0.166,-0.75 0,-0.438 0.146,-0.771 l 0.374,-0.875 q 0.167,-0.313 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.218 0.552,0.531 l 0.396,0.875 q 0.146,0.333 0.146,0.771 0,0.437 -0.146,0.75 l -0.396,0.896 q -0.146,0.312 -0.552,0.531 -0.406,0.219 -0.781,0.219 z M 11.48968,13.438 q -0.354,0 -0.77,-0.219 -0.417,-0.219 -0.563,-0.51 L 9.5936798,11.771 q -0.166,-0.291 -0.177,-0.718 -0.01,-0.427 0.157,-0.719 L 10.17768,9.376 q 0.146,-0.292 0.552,-0.511 0.406,-0.219 0.76,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.407,0.219 0.552,0.552 l 0.396,0.875 q 0.146,0.334 0.136,0.761 -0.011,0.427 -0.156,0.76 l -0.355,0.854 q -0.145,0.333 -0.562,0.552 -0.417,0.219 -0.792,0.219 z"
id="path2"
style="fill:#c689ff;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bqda5kd75gtko"
path="res://.godot/imported/category_bt.svg-8537bebd1c5f62dca3d7ee7f17efeed4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/category_bt.svg"
dest_files=["res://.godot/imported/category_bt.svg-8537bebd1c5f62dca3d7ee7f17efeed4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="16.375999"
width="14.126321"
version="1.1"
id="svg4"
sodipodi:docname="category_composite.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="15.273506"
inkscape:cx="7.071068"
inkscape:cy="10.377447"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="m 11.48968,7.688 q -0.354,0 -0.76,-0.219 -0.406,-0.219 -0.552,-0.51 L 9.5736798,6 q -0.167,-0.291 -0.167,-0.729 0,-0.437 0.167,-0.729 L 10.07368,3.667 q 0.146,-0.291 0.552,-0.531 0.406,-0.24 0.76,-0.24 h 0.875 q 0.375,0 0.792,0.219 0.417,0.219 0.562,0.552 l 0.355,0.854 q 0.145,0.334 0.156,0.761 0.01,0.427 -0.136,0.76 l -0.396,0.875 q -0.145,0.333 -0.552,0.552 -0.406,0.219 -0.781,0.219 z m -4.8120002,2.917 q -0.354,0 -0.761,-0.219 -0.406,-0.219 -0.573,-0.531 l -0.374,-0.917 q -0.146,-0.312 -0.146,-0.75 0,-0.438 0.146,-0.75 l 0.374,-0.917 q 0.167,-0.312 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.219 0.552,0.531 l 0.396,0.917 q 0.146,0.312 0.146,0.75 0,0.438 -0.146,0.75 l -0.396,0.917 q -0.146,0.312 -0.552,0.531 -0.406,0.219 -0.781,0.219 z m 0,-5.813 q -0.354,0 -0.761,-0.219 -0.406,-0.218 -0.573,-0.531 l -0.374,-0.875 q -0.146,-0.333 -0.146,-0.771 0,-0.437 0.146,-0.75 l 0.374,-0.896 q 0.167,-0.312 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.219 0.552,0.531 l 0.396,0.896 q 0.146,0.313 0.146,0.75 0,0.438 -0.146,0.771 l -0.396,0.875 q -0.146,0.313 -0.552,0.531 -0.406,0.219 -0.781,0.219 z m -4.813,2.896 q -0.375,0 -0.771,-0.219 Q 0.69867978,7.25 0.53167978,6.917 l -0.375,-0.875 Q -0.01032022,5.709 6.7977528e-4,5.282 0.01067978,4.855 0.17767978,4.521 l 0.333,-0.854 q 0.167,-0.333 0.57300002,-0.552 0.406,-0.219 0.781,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.407,0.219 0.573,0.552 l 0.334,0.854 q 0.166,0.334 0.177,0.761 0.01,0.427 -0.157,0.76 l -0.374,0.875 q -0.167,0.333 -0.563,0.552 -0.396,0.219 -0.771,0.219 z m 0,5.75 q -0.375,0 -0.781,-0.219 Q 0.67767978,13 0.51067978,12.667 l -0.333,-0.854 Q 0.01067978,11.48 6.7977528e-4,11.053 -0.01032022,10.626 0.15667978,10.292 l 0.375,-0.875 q 0.167,-0.333 0.56200002,-0.552 0.396,-0.219 0.771,-0.219 h 0.771 q 0.375,0 0.771,0.219 0.396,0.219 0.563,0.552 l 0.374,0.875 q 0.167,0.334 0.157,0.761 -0.011,0.427 -0.177,0.76 l -0.334,0.854 q -0.166,0.333 -0.573,0.552 -0.406,0.219 -0.781,0.219 z m 4.855,2.938 q -0.355,0 -0.761,-0.219 -0.406,-0.219 -0.594,-0.531 l -0.375,-0.896 q -0.166,-0.313 -0.166,-0.75 0,-0.438 0.146,-0.771 l 0.374,-0.875 q 0.167,-0.313 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.218 0.552,0.531 l 0.396,0.875 q 0.146,0.333 0.146,0.771 0,0.437 -0.146,0.75 l -0.396,0.896 q -0.146,0.312 -0.552,0.531 -0.406,0.219 -0.781,0.219 z M 11.48968,13.438 q -0.354,0 -0.77,-0.219 -0.417,-0.219 -0.563,-0.51 L 9.5936798,11.771 q -0.166,-0.291 -0.177,-0.718 -0.01,-0.427 0.157,-0.719 L 10.17768,9.376 q 0.146,-0.292 0.552,-0.511 0.406,-0.219 0.76,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.407,0.219 0.552,0.552 l 0.396,0.875 q 0.146,0.334 0.136,0.761 -0.011,0.427 -0.156,0.76 l -0.355,0.854 q -0.145,0.333 -0.562,0.552 -0.417,0.219 -0.792,0.219 z"
id="path2"
style="fill:#40d29f;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://tw8ql5cxqeo4"
path="res://.godot/imported/category_composite.svg-43f66e63a7ccfa5ac8ec6da0583b3246.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/category_composite.svg"
dest_files=["res://.godot/imported/category_composite.svg-43f66e63a7ccfa5ac8ec6da0583b3246.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="16.375999"
width="14.126321"
version="1.1"
id="svg4"
sodipodi:docname="category_decorator.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="15.273506"
inkscape:cx="7.071068"
inkscape:cy="10.377447"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="m 11.48968,7.688 q -0.354,0 -0.76,-0.219 -0.406,-0.219 -0.552,-0.51 L 9.5736798,6 q -0.167,-0.291 -0.167,-0.729 0,-0.437 0.167,-0.729 L 10.07368,3.667 q 0.146,-0.291 0.552,-0.531 0.406,-0.24 0.76,-0.24 h 0.875 q 0.375,0 0.792,0.219 0.417,0.219 0.562,0.552 l 0.355,0.854 q 0.145,0.334 0.156,0.761 0.01,0.427 -0.136,0.76 l -0.396,0.875 q -0.145,0.333 -0.552,0.552 -0.406,0.219 -0.781,0.219 z m -4.8120002,2.917 q -0.354,0 -0.761,-0.219 -0.406,-0.219 -0.573,-0.531 l -0.374,-0.917 q -0.146,-0.312 -0.146,-0.75 0,-0.438 0.146,-0.75 l 0.374,-0.917 q 0.167,-0.312 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.219 0.552,0.531 l 0.396,0.917 q 0.146,0.312 0.146,0.75 0,0.438 -0.146,0.75 l -0.396,0.917 q -0.146,0.312 -0.552,0.531 -0.406,0.219 -0.781,0.219 z m 0,-5.813 q -0.354,0 -0.761,-0.219 -0.406,-0.218 -0.573,-0.531 l -0.374,-0.875 q -0.146,-0.333 -0.146,-0.771 0,-0.437 0.146,-0.75 l 0.374,-0.896 q 0.167,-0.312 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.219 0.552,0.531 l 0.396,0.896 q 0.146,0.313 0.146,0.75 0,0.438 -0.146,0.771 l -0.396,0.875 q -0.146,0.313 -0.552,0.531 -0.406,0.219 -0.781,0.219 z m -4.813,2.896 q -0.375,0 -0.771,-0.219 Q 0.69867978,7.25 0.53167978,6.917 l -0.375,-0.875 Q -0.01032022,5.709 6.7977528e-4,5.282 0.01067978,4.855 0.17767978,4.521 l 0.333,-0.854 q 0.167,-0.333 0.57300002,-0.552 0.406,-0.219 0.781,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.407,0.219 0.573,0.552 l 0.334,0.854 q 0.166,0.334 0.177,0.761 0.01,0.427 -0.157,0.76 l -0.374,0.875 q -0.167,0.333 -0.563,0.552 -0.396,0.219 -0.771,0.219 z m 0,5.75 q -0.375,0 -0.781,-0.219 Q 0.67767978,13 0.51067978,12.667 l -0.333,-0.854 Q 0.01067978,11.48 6.7977528e-4,11.053 -0.01032022,10.626 0.15667978,10.292 l 0.375,-0.875 q 0.167,-0.333 0.56200002,-0.552 0.396,-0.219 0.771,-0.219 h 0.771 q 0.375,0 0.771,0.219 0.396,0.219 0.563,0.552 l 0.374,0.875 q 0.167,0.334 0.157,0.761 -0.011,0.427 -0.177,0.76 l -0.334,0.854 q -0.166,0.333 -0.573,0.552 -0.406,0.219 -0.781,0.219 z m 4.855,2.938 q -0.355,0 -0.761,-0.219 -0.406,-0.219 -0.594,-0.531 l -0.375,-0.896 q -0.166,-0.313 -0.166,-0.75 0,-0.438 0.146,-0.771 l 0.374,-0.875 q 0.167,-0.313 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.218 0.552,0.531 l 0.396,0.875 q 0.146,0.333 0.146,0.771 0,0.437 -0.146,0.75 l -0.396,0.896 q -0.146,0.312 -0.552,0.531 -0.406,0.219 -0.781,0.219 z M 11.48968,13.438 q -0.354,0 -0.77,-0.219 -0.417,-0.219 -0.563,-0.51 L 9.5936798,11.771 q -0.166,-0.291 -0.177,-0.718 -0.01,-0.427 0.157,-0.719 L 10.17768,9.376 q 0.146,-0.292 0.552,-0.511 0.406,-0.219 0.76,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.407,0.219 0.552,0.552 l 0.396,0.875 q 0.146,0.334 0.136,0.761 -0.011,0.427 -0.156,0.76 l -0.355,0.854 q -0.145,0.333 -0.562,0.552 -0.417,0.219 -0.792,0.219 z"
id="path2"
style="fill:#46c0e1;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cpe6ntmjqkl2n"
path="res://.godot/imported/category_decorator.svg-79d598d6456f32724156248e09d6eaf3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/category_decorator.svg"
dest_files=["res://.godot/imported/category_decorator.svg-79d598d6456f32724156248e09d6eaf3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="16.375999"
width="14.126321"
version="1.1"
id="svg4"
sodipodi:docname="category_leaf.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="15.273506"
inkscape:cx="7.071068"
inkscape:cy="10.377447"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="m 11.48968,7.688 q -0.354,0 -0.76,-0.219 -0.406,-0.219 -0.552,-0.51 L 9.5736798,6 q -0.167,-0.291 -0.167,-0.729 0,-0.437 0.167,-0.729 L 10.07368,3.667 q 0.146,-0.291 0.552,-0.531 0.406,-0.24 0.76,-0.24 h 0.875 q 0.375,0 0.792,0.219 0.417,0.219 0.562,0.552 l 0.355,0.854 q 0.145,0.334 0.156,0.761 0.01,0.427 -0.136,0.76 l -0.396,0.875 q -0.145,0.333 -0.552,0.552 -0.406,0.219 -0.781,0.219 z m -4.8120002,2.917 q -0.354,0 -0.761,-0.219 -0.406,-0.219 -0.573,-0.531 l -0.374,-0.917 q -0.146,-0.312 -0.146,-0.75 0,-0.438 0.146,-0.75 l 0.374,-0.917 q 0.167,-0.312 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.219 0.552,0.531 l 0.396,0.917 q 0.146,0.312 0.146,0.75 0,0.438 -0.146,0.75 l -0.396,0.917 q -0.146,0.312 -0.552,0.531 -0.406,0.219 -0.781,0.219 z m 0,-5.813 q -0.354,0 -0.761,-0.219 -0.406,-0.218 -0.573,-0.531 l -0.374,-0.875 q -0.146,-0.333 -0.146,-0.771 0,-0.437 0.146,-0.75 l 0.374,-0.896 q 0.167,-0.312 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.219 0.552,0.531 l 0.396,0.896 q 0.146,0.313 0.146,0.75 0,0.438 -0.146,0.771 l -0.396,0.875 q -0.146,0.313 -0.552,0.531 -0.406,0.219 -0.781,0.219 z m -4.813,2.896 q -0.375,0 -0.771,-0.219 Q 0.69867978,7.25 0.53167978,6.917 l -0.375,-0.875 Q -0.01032022,5.709 6.7977528e-4,5.282 0.01067978,4.855 0.17767978,4.521 l 0.333,-0.854 q 0.167,-0.333 0.57300002,-0.552 0.406,-0.219 0.781,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.407,0.219 0.573,0.552 l 0.334,0.854 q 0.166,0.334 0.177,0.761 0.01,0.427 -0.157,0.76 l -0.374,0.875 q -0.167,0.333 -0.563,0.552 -0.396,0.219 -0.771,0.219 z m 0,5.75 q -0.375,0 -0.781,-0.219 Q 0.67767978,13 0.51067978,12.667 l -0.333,-0.854 Q 0.01067978,11.48 6.7977528e-4,11.053 -0.01032022,10.626 0.15667978,10.292 l 0.375,-0.875 q 0.167,-0.333 0.56200002,-0.552 0.396,-0.219 0.771,-0.219 h 0.771 q 0.375,0 0.771,0.219 0.396,0.219 0.563,0.552 l 0.374,0.875 q 0.167,0.334 0.157,0.761 -0.011,0.427 -0.177,0.76 l -0.334,0.854 q -0.166,0.333 -0.573,0.552 -0.406,0.219 -0.781,0.219 z m 4.855,2.938 q -0.355,0 -0.761,-0.219 -0.406,-0.219 -0.594,-0.531 l -0.375,-0.896 q -0.166,-0.313 -0.166,-0.75 0,-0.438 0.146,-0.771 l 0.374,-0.875 q 0.167,-0.313 0.573,-0.531 0.407,-0.219 0.761,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.406,0.218 0.552,0.531 l 0.396,0.875 q 0.146,0.333 0.146,0.771 0,0.437 -0.146,0.75 l -0.396,0.896 q -0.146,0.312 -0.552,0.531 -0.406,0.219 -0.781,0.219 z M 11.48968,13.438 q -0.354,0 -0.77,-0.219 -0.417,-0.219 -0.563,-0.51 L 9.5936798,11.771 q -0.166,-0.291 -0.177,-0.718 -0.01,-0.427 0.157,-0.719 L 10.17768,9.376 q 0.146,-0.292 0.552,-0.511 0.406,-0.219 0.76,-0.219 h 0.771 q 0.375,0 0.781,0.219 0.407,0.219 0.552,0.552 l 0.396,0.875 q 0.146,0.334 0.136,0.761 -0.011,0.427 -0.156,0.76 l -0.355,0.854 q -0.145,0.333 -0.562,0.552 -0.417,0.219 -0.792,0.219 z"
id="path2"
style="fill:#ffb649;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ceraiow5o4ssv"
path="res://.godot/imported/category_leaf.svg-c740ecab6cfae632574ca5e39e46fd2e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/category_leaf.svg"
dest_files=["res://.godot/imported/category_leaf.svg-c740ecab6cfae632574ca5e39e46fd2e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="18.084"
width="18.084"
version="1.1"
id="svg4180"
sodipodi:docname="condition.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs4184" />
<sodipodi:namedview
id="namedview4182"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="7.6367532"
inkscape:cx="-10.737547"
inkscape:cy="24.290428"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg4180" />
<path
d="m 8.938,14.063 q 0.542,0 0.927,-0.386 0.385,-0.385 0.385,-0.927 0,-0.541 -0.385,-0.916 -0.385,-0.375 -0.927,-0.375 -0.542,0 -0.927,0.375 -0.386,0.375 -0.386,0.916 0,0.542 0.386,0.927 0.385,0.386 0.927,0.386 z M 9.042,5.938 q 0.396,0 0.646,0.229 0.25,0.229 0.25,0.542 0,0.229 -0.177,0.562 Q 9.584,7.604 9.292,7.834 8.646,8.417 8.323,8.927 8,9.438 8,9.917 q 0,0.375 0.261,0.635 0.26,0.261 0.656,0.261 0.396,0 0.698,-0.24 0.302,-0.239 0.469,-0.698 0.104,-0.25 0.291,-0.51 0.188,-0.261 0.542,-0.615 0.604,-0.562 0.833,-1.073 0.23,-0.51 0.23,-1.135 0,-1.167 -0.761,-1.865 Q 10.459,3.98 9.188,3.98 8.25,3.98 7.552,4.365 6.854,4.75 6.292,5.48 6.084,5.75 6.198,6.125 6.313,6.5 6.584,6.709 6.938,6.98 7.365,6.886 7.792,6.792 8.104,6.417 8.313,6.209 8.563,6.073 8.813,5.938 9.042,5.938 Z m 0,12.146 q -1.875,0 -3.531,-0.709 Q 3.854,16.667 2.636,15.448 1.417,14.23 0.709,12.584 0,10.938 0,9.042 0,7.146 0.709,5.5 1.417,3.854 2.636,2.636 3.854,1.417 5.511,0.709 7.167,0 9.042,0 q 1.896,0 3.542,0.709 1.646,0.708 2.864,1.927 1.219,1.218 1.927,2.864 0.709,1.646 0.709,3.542 0,1.896 -0.709,3.542 -0.708,1.646 -1.927,2.864 -1.218,1.219 -2.864,1.927 -1.646,0.709 -3.542,0.709 z"
id="path4178"
style="fill:#ffb649;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dkixxh0kndfct"
path="res://.godot/imported/condition.svg-57892684b10a64086f68c09c388b17e5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/condition.svg"
dest_files=["res://.godot/imported/condition.svg-57892684b10a64086f68c09c388b17e5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="17.666"
width="17.666"
version="1.1"
id="svg6751"
sodipodi:docname="failer.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs6755" />
<sodipodi:namedview
id="namedview6753"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="30.547013"
inkscape:cx="12.308896"
inkscape:cy="5.3851419"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg6751" />
<path
d="m 8.854,9.666 q 0.5,0 0.896,-0.395 0.395,-0.396 0.395,-0.917 v -2.75 q 0,-0.5 -0.395,-0.886 Q 9.354,4.333 8.854,4.333 8.333,4.333 7.937,4.729 7.541,5.125 7.541,5.625 v 2.75 q 0,0.52 0.396,0.906 0.396,0.385 0.917,0.385 z m -0.021,3.959 q 0.583,0 1.01,-0.407 0.428,-0.406 0.428,-1.031 0,-0.583 -0.428,-1.021 -0.427,-0.437 -1.01,-0.437 -0.583,0 -1.01,0.437 -0.428,0.438 -0.428,1.021 0,0.625 0.428,1.031 0.427,0.407 1.01,0.407 z m 0,4.041 q -1.854,0 -3.458,-0.687 Q 3.771,16.291 2.573,15.093 1.375,13.895 0.687,12.291 0,10.687 0,8.833 0,6.958 0.687,5.364 1.375,3.771 2.573,2.573 3.771,1.375 5.375,0.687 6.979,0 8.833,0 q 1.875,0 3.469,0.687 1.593,0.688 2.791,1.886 1.198,1.198 1.886,2.791 0.687,1.594 0.687,3.469 0,1.854 -0.687,3.458 -0.688,1.604 -1.886,2.802 -1.198,1.198 -2.791,1.886 -1.594,0.687 -3.469,0.687 z"
id="path6749"
style="fill:#46c0e1;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b8qs25ku5wdvt"
path="res://.godot/imported/failer.svg-9a62b840e1eacc0437e7a67b14a302e4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/failer.svg"
dest_files=["res://.godot/imported/failer.svg-9a62b840e1eacc0437e7a67b14a302e4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="13.907205"
width="18.437"
version="1.1"
id="svg68"
sodipodi:docname="inverter.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs72" />
<sodipodi:namedview
id="namedview70"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="29.521708"
inkscape:cx="6.3343218"
inkscape:cy="7.8078138"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg68" />
<path
d="m 12.937,8.48 q -0.458,-0.459 -0.458,-1.032 0,-0.572 0.458,-1.031 L 13.416,5.938 H 9.812 Q 9.229,5.938 8.791,5.5 8.354,5.063 8.354,4.48 8.354,3.876 8.791,3.448 9.229,3.021 9.812,3.021 h 3.604 l -0.5,-0.5 Q 12.458,2.063 12.468,1.49 12.479,0.917 12.937,0.48 13.396,0 13.979,0 14.562,0 15,0.459 l 2.979,2.979 q 0.229,0.229 0.344,0.5 0.114,0.271 0.114,0.521 0,0.271 -0.114,0.541 -0.115,0.271 -0.344,0.5 l -3,3 Q 14.52,8.959 13.958,8.948 13.396,8.938 12.937,8.48 Z M 3.416,13.438 0.437,10.459 Q 0.229,10.25 0.114,9.98 0,9.709 0,9.438 0,9.167 0.114,8.896 0.229,8.626 0.437,8.396 l 3.021,-3 Q 3.916,4.938 4.468,4.948 5.02,4.959 5.479,5.417 5.937,5.876 5.937,6.459 5.937,7.042 5.479,7.48 L 5,7.959 h 3.604 q 0.583,0 1.021,0.437 0.437,0.438 0.437,1.021 0,0.604 -0.437,1.031 -0.438,0.428 -1.021,0.428 H 5 l 0.5,0.52 q 0.458,0.459 0.448,1.021 -0.011,0.563 -0.469,1.021 -0.459,0.458 -1.021,0.469 -0.562,0.01 -1.042,-0.469 z"
id="path66"
style="fill:#46c0e1;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://di1fnvn0j82nt"
path="res://.godot/imported/inverter.svg-1f1b976d95de42c4ad99a92fa9a6c5d0.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/inverter.svg"
dest_files=["res://.godot/imported/inverter.svg-1f1b976d95de42c4ad99a92fa9a6c5d0.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="14.75"
width="14.916"
version="1.1"
id="svg3323"
sodipodi:docname="repeater.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs3327" />
<sodipodi:namedview
id="namedview3325"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="7.6367532"
inkscape:cx="-37.057633"
inkscape:cy="27.56407"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg3323" />
<path
d="M 7.375,14.75 Q 4.312,14.75 2.156,12.594 0,10.437 0,7.375 0,4.313 2.156,2.156 4.312,0 7.375,0 8.979,0 10.385,0.646 11.791,1.292 12.833,2.5 V 1.042 q 0,-0.417 0.313,-0.729 Q 13.458,0 13.875,0 q 0.416,0 0.729,0.313 0.312,0.312 0.312,0.729 v 4.583 q 0,0.542 -0.406,0.948 -0.406,0.406 -0.948,0.406 H 8.958 Q 8.541,6.979 8.229,6.677 7.916,6.375 7.916,5.958 7.916,5.542 8.229,5.229 8.541,4.917 8.958,4.917 h 2.354 Q 10.646,3.917 9.614,3.313 8.583,2.708 7.375,2.708 q -1.938,0 -3.302,1.365 -1.365,1.364 -1.365,3.302 0,1.938 1.365,3.302 1.364,1.365 3.302,1.365 1.25,0 2.291,-0.615 1.042,-0.614 1.688,-1.677 0.208,-0.313 0.562,-0.521 0.354,-0.208 0.688,-0.208 0.854,0 1.239,0.573 0.386,0.573 0.011,1.26 -0.979,1.771 -2.698,2.833 -1.719,1.063 -3.781,1.063 z"
id="path3321"
style="fill:#46c0e1;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d0tbxe5pwd0h4"
path="res://.godot/imported/limiter.svg-b4c7646605c46f53c5e403fe21d8f584.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/limiter.svg"
dest_files=["res://.godot/imported/limiter.svg-b4c7646605c46f53c5e403fe21d8f584.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="13.906356"
width="17.791"
version="1.1"
id="svg5037"
sodipodi:docname="selector.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs5041" />
<sodipodi:namedview
id="namedview5039"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="7.6367532"
inkscape:cx="61.282588"
inkscape:cy="33.849463"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg5037" />
<path
d="M 4.52,13.645 Q 4.25,13.374 4.25,13 4.25,12.624 4.5,12.354 L 5.208,11.666 Q 2.979,11.395 1.489,9.802 0,8.208 0,5.895 0,3.437 1.718,1.718 3.437,0 5.895,0 H 7.562 Q 7.916,0 8.187,0.27 8.458,0.541 8.458,0.895 8.458,1.27 8.187,1.541 7.916,1.812 7.562,1.812 H 5.895 Q 4.187,1.812 3,3 1.812,4.187 1.812,5.895 1.812,7.437 2.76,8.52 3.708,9.604 5.187,9.916 L 4.5,9.229 Q 4.229,8.937 4.239,8.583 4.25,8.229 4.52,7.958 4.77,7.687 5.145,7.687 q 0.375,0 0.646,0.271 l 2.167,2.187 q 0.125,0.125 0.208,0.302 0.084,0.177 0.084,0.365 0,0.167 -0.084,0.344 -0.083,0.177 -0.208,0.323 L 5.75,13.645 Q 5.479,13.916 5.124,13.906 4.77,13.895 4.52,13.645 Z M 12.041,5.958 Q 11.25,5.958 10.708,5.416 10.166,4.874 10.166,4.083 V 1.874 q 0,-0.77 0.542,-1.322 Q 11.25,0 12.041,0 h 3.875 q 0.771,0 1.323,0.552 0.552,0.552 0.552,1.322 v 2.209 q 0,0.791 -0.552,1.333 -0.552,0.542 -1.323,0.542 z m 0,-1.875 h 3.875 V 1.874 h -3.875 z m 0,9.541 q -0.791,0 -1.333,-0.552 Q 10.166,12.52 10.166,11.75 V 9.541 q 0,-0.791 0.542,-1.333 0.542,-0.542 1.333,-0.542 h 3.875 q 0.771,0 1.323,0.542 0.552,0.542 0.552,1.333 v 2.209 q 0,0.77 -0.552,1.322 -0.552,0.552 -1.323,0.552 z"
id="path5035"
style="fill:#40d29f;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://vd20qqjvikmk"
path="res://.godot/imported/selector.svg-78bccfc448bd1676b5a29bfde4b08e5b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/selector.svg"
dest_files=["res://.godot/imported/selector.svg-78bccfc448bd1676b5a29bfde4b08e5b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.3 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://op2xj3wn1gv7"
path="res://.godot/imported/selector_random.svg-d52fea1352c24483ecd9dc8609cf00f3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/selector_random.svg"
dest_files=["res://.godot/imported/selector_random.svg-d52fea1352c24483ecd9dc8609cf00f3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="14.543364"
width="17.791"
version="1.1"
id="svg5037"
sodipodi:docname="selector_reactive.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs5041" /><sodipodi:namedview
id="namedview5039"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="15.273506"
inkscape:cx="18.59429"
inkscape:cy="12.014268"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg5037" /><path
style="fill:#40d29f;fill-opacity:1;color:#000000;stroke-width:1.7354;-inkscape-stroke:none;paint-order:markers stroke fill"
d="m 15.63424,18.518399 q -0.218955,0 -0.373746,-0.150649 -0.155154,-0.150651 -0.155154,-0.363746 v -1.161448 l -0.860595,0.49993 q -0.196481,0.103026 -0.400572,0.05152 -0.20373,-0.05152 -0.309582,-0.227915 l -0.181253,-0.308712 q -0.105496,-0.183813 -0.05655,-0.385972 0.04894,-0.202159 0.237805,-0.312236 l 0.868569,-0.492527 -0.883432,-0.485112 q -0.188867,-0.110433 -0.241793,-0.312236 -0.05292,-0.202161 0.05292,-0.385974 l 0.196116,-0.301299 q 0.113465,-0.183814 0.321183,-0.238852 0.207716,-0.05539 0.388971,0.05504 l 0.868208,0.492523 v -1.161448 q 0,-0.213096 0.155154,-0.363747 0.154791,-0.150648 0.373746,-0.150648 h 0.347283 q 0.218955,0 0.373747,0.150648 0.155152,0.150651 0.155152,0.363747 v 1.161448 l 0.868209,-0.499931 q 0.188867,-0.103026 0.388973,-0.04763 0.200104,0.05504 0.313568,0.224034 l 0.211343,0.323526 q 0.113466,0.183813 0.05655,0.38562 -0.05655,0.20216 -0.253031,0.312589 l -0.87582,0.477704 0.86857,0.492521 q 0.181255,0.09561 0.245418,0.304826 0.06416,0.209569 -0.0493,0.385974 l -0.196119,0.316117 q -0.113464,0.176404 -0.313569,0.235323 -0.200105,0.05857 -0.388972,-0.05151 l -0.875822,-0.50734 v 1.161449 q 0,0.213096 -0.155152,0.363745 -0.154792,0.15065 -0.373747,0.15065 z"
id="path5291"
transform="matrix(1.2719165,0,0,1.2110461,-6.1455464,-7.8832739)"
inkscape:label="asterisk" /><path
style="fill:#40d29f;fill-opacity:1"
d="M 12.041,5.958 Q 11.25,5.958 10.708,5.416 10.166,4.874 10.166,4.083 V 1.874 q 0,-0.77 0.542,-1.322 Q 11.25,0 12.041,0 h 3.875 q 0.771,0 1.323,0.552 0.552,0.552 0.552,1.322 v 2.209 q 0,0.791 -0.552,1.333 -0.552,0.542 -1.323,0.542 z m 0,-1.875 h 3.875 V 1.874 h -3.875 z"
id="path923"
inkscape:label="square" /><path
style="fill:#40d29f;fill-opacity:1"
d="M 4.52,13.645 Q 4.25,13.374 4.25,13 4.25,12.624 4.5,12.354 L 5.208,11.666 Q 2.979,11.395 1.489,9.802 0,8.208 0,5.895 0,3.437 1.718,1.718 3.437,0 5.895,0 H 7.562 Q 7.916,0 8.187,0.27 8.458,0.541 8.458,0.895 8.458,1.27 8.187,1.541 7.916,1.812 7.562,1.812 H 5.895 Q 4.187,1.812 3,3 1.812,4.187 1.812,5.895 1.812,7.437 2.76,8.52 3.708,9.604 5.187,9.916 L 4.5,9.229 Q 4.229,8.937 4.239,8.583 4.25,8.229 4.52,7.958 4.77,7.687 5.145,7.687 q 0.375,0 0.646,0.271 l 2.167,2.187 q 0.125,0.125 0.208,0.302 0.084,0.177 0.084,0.365 0,0.167 -0.084,0.344 -0.083,0.177 -0.208,0.323 L 5.75,13.645 Q 5.479,13.916 5.124,13.906 4.77,13.895 4.52,13.645 Z"
id="path5035"
inkscape:label="arrow" /></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cf6x41gdjw55"
path="res://.godot/imported/selector_reactive.svg-dd3b8fb8cd2ffe331605aaad1e021cc0.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/selector_reactive.svg"
dest_files=["res://.godot/imported/selector_reactive.svg-dd3b8fb8cd2ffe331605aaad1e021cc0.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="13.187"
width="16.583"
version="1.1"
id="svg5894"
sodipodi:docname="sequence.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs5898" />
<sodipodi:namedview
id="namedview5896"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="43.2"
inkscape:cx="13.449074"
inkscape:cy="7.974537"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg5894" />
<path
d="M 1.709,8.313 Q 1,8.313 0.5,7.823 0,7.333 0,6.604 0,5.896 0.5,5.396 q 0.5,-0.5 1.209,-0.5 0.708,0 1.208,0.5 0.5,0.5 0.5,1.229 0,0.708 -0.5,1.198 -0.5,0.49 -1.208,0.49 z m 0,-4.896 Q 1,3.417 0.5,2.927 0,2.437 0,1.708 0,1 0.5,0.5 1,0 1.709,0 q 0.708,0 1.208,0.5 0.5,0.5 0.5,1.229 0,0.708 -0.5,1.198 -0.5,0.49 -1.208,0.49 z m 0,9.77 Q 1,13.187 0.5,12.698 0,12.208 0,11.479 q 0,-0.708 0.5,-1.208 0.5,-0.5 1.209,-0.5 0.708,0 1.208,0.5 0.5,0.5 0.5,1.229 0,0.708 -0.5,1.198 -0.5,0.489 -1.208,0.489 z m 4.604,-0.395 q -0.5,0 -0.896,-0.396 Q 5.021,12 5.021,11.479 q 0,-0.5 0.396,-0.896 0.396,-0.396 0.896,-0.396 h 8.979 q 0.5,0 0.896,0.396 0.395,0.396 0.395,0.896 0,0.521 -0.395,0.917 -0.396,0.396 -0.896,0.396 z m 0,-4.875 q -0.5,0 -0.896,-0.396 -0.396,-0.396 -0.396,-0.917 0,-0.5 0.396,-0.896 0.396,-0.395 0.896,-0.395 h 8.979 q 0.5,0 0.896,0.395 0.395,0.396 0.395,0.896 0,0.521 -0.395,0.917 -0.396,0.396 -0.896,0.396 z m 0,-4.896 q -0.5,0 -0.896,-0.396 -0.396,-0.396 -0.396,-0.917 0,-0.5 0.396,-0.895 0.396,-0.396 0.896,-0.396 h 8.979 q 0.5,0 0.896,0.396 0.395,0.395 0.395,0.895 0,0.521 -0.395,0.917 -0.396,0.396 -0.896,0.396 z"
id="path5892"
style="fill:#40d29f;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://1kiyv5175ytx"
path="res://.godot/imported/sequence.svg-76e5600611900cc81e9ec286977b8c6a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/sequence.svg"
dest_files=["res://.godot/imported/sequence.svg-76e5600611900cc81e9ec286977b8c6a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="12.183594"
width="16.582031"
version="1.1"
id="svg5894"
sodipodi:docname="sequence_random.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs5898" />
<sodipodi:namedview
id="namedview5896"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="32"
inkscape:cx="-1.59375"
inkscape:cy="7.828125"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg5894" />
<path
id="path414"
style="color:#000000;fill:#40d29f;stroke-width:0.4;stroke-linecap:round;paint-order:fill markers stroke"
d="M 1.7089844,0 C 1.2363186,0 0.83333267,0.16666733 0.5,0.5 0.16666733,0.83333267 0,1.2350322 0,1.7070312 c 0,0.4859992 0.16666733,0.8940371 0.5,1.2207032 0.33333267,0.3266659 0.7363186,0.4902343 1.2089844,0.4902344 0.471999,0 0.8756516,-0.1635685 1.2089844,-0.4902344 0.3333326,-0.3266661 0.4999999,-0.7272196 0.5,-1.1992188 0,-0.485999 -0.1666674,-0.89518293 -0.5,-1.2285156 C 2.5846361,0.16666733 2.1809834,0 1.7089844,0 Z M 6.3125,0.41796875 c -0.3333327,0 -0.6305318,0.13053177 -0.8945312,0.39453125 -0.2639996,0.2633328 -0.3964844,0.5611987 -0.3964844,0.8945312 0,0.3473327 0.1324848,0.6539694 0.3964844,0.9179688 C 5.6819682,2.8889994 5.9791673,3.0214844 6.3125,3.0214844 h 8.980469 C 15.626301,3.0214844 15.9235,2.8889994 16.1875,2.625 16.450833,2.3610006 16.582031,2.0543639 16.582031,1.7070312 16.582031,1.3736987 16.450833,1.0758328 16.1875,0.8125 15.9235,0.54850052 15.626301,0.41796875 15.292969,0.41796875 Z M 9.0878906,4.3007812 c -0.2828275,0 -0.5270087,0.1055895 -0.7324218,0.3164063 -0.2050874,0.2104687 -0.3066407,0.4597345 -0.3066407,0.75 v 5.7480465 c 0,0.290266 0.101563,0.543098 0.3066407,0.753907 0.2054131,0.210442 0.4495943,0.314453 0.7324218,0.314453 h 5.6015624 c 0.282829,0 0.527005,-0.103984 0.732422,-0.314453 0.20504,-0.210809 0.310547,-0.463641 0.310547,-0.753907 V 5.3671875 c 0,-0.2902655 -0.105468,-0.5395313 -0.310547,-0.75 -0.192576,-0.1976408 -0.419166,-0.3040153 -0.679687,-0.3164063 -0.01736,-8.263e-4 -0.03505,0 -0.05274,0 z M 1.9257812,5.3535156 C 1.6720837,5.3535062 1.4450691,5.4533683 1.2441406,5.6542969 1.043212,5.8547182 0.94335938,6.0822399 0.94335938,6.3359375 c 0,0.2643529 0.0998526,0.4982903 0.30078122,0.6992187 0.2009285,0.2009285 0.4279431,0.3007813 0.6816406,0.3007813 H 6.8886719 V 5.7070312 c 0,-0.1182132 0.017785,-0.2363441 0.048828,-0.3515624 z m 11.7246098,0.041016 c 0.275278,0 0.533582,0.1086393 0.724609,0.3046876 0.191017,0.1960469 0.294922,0.4582008 0.294922,0.7363281 0,0.2781252 -0.10358,0.53844 -0.294922,0.734375 -0.191911,0.1969508 -0.45114,0.3027343 -0.724609,0.3027343 -0.273472,0 -0.532817,-0.1054585 -0.72461,-0.3027343 -0.192232,-0.1968435 -0.291015,-0.4579656 -0.291015,-0.734375 0,-0.2764085 0.09911,-0.5393695 0.291015,-0.7363281 0.190906,-0.1963654 0.449327,-0.3046876 0.72461,-0.3046876 z M 11.888672,7.203125 c 0.0068,0 0.0244,-0.00128 0.05273,0 0.256852,0.011652 0.493747,0.1218832 0.671875,0.3046875 0.191019,0.1960465 0.296876,0.4562463 0.296875,0.734375 10e-7,0.2781245 -0.105853,0.5402803 -0.296875,0.7363281 C 12.42137,9.1754773 12.162139,9.28125 11.888672,9.28125 c -0.273461,0 -0.532699,-0.1057738 -0.72461,-0.3027344 -0.191923,-0.1969574 -0.291015,-0.4599183 -0.291015,-0.7363281 0,-0.2764094 0.0991,-0.5374165 0.291015,-0.734375 0.191024,-0.1960448 0.449335,-0.3046875 0.72461,-0.3046875 z m -1.75,1.8066406 c 0.0068,0 0.0244,6.732e-4 0.05273,0.00195 0.256848,0.011652 0.49375,0.1238283 0.671875,0.3066406 0.189491,0.1948428 0.294922,0.4530828 0.294922,0.7304688 0,0.278128 -0.103894,0.538327 -0.294922,0.734375 -0.191019,0.196026 -0.449319,0.306641 -0.724609,0.306641 -0.2750313,0 -0.5324,-0.111387 -0.7226564,-0.306641 C 9.2249894,10.587155 9.1210938,10.326955 9.1210938,10.048828 9.1210937,9.7714422 9.2265406,9.5132022 9.4160156,9.3183594 9.6062729,9.1231217 9.8636398,9.0097656 10.138672,9.0097656 Z m -8.216797,0.1875 c -0.2536975,-9.4e-6 -0.478759,0.0979 -0.6796875,0.2988282 -0.2009286,0.2004212 -0.30273437,0.4279427 -0.30273438,0.6816402 0,0.264353 0.10180578,0.498291 0.30273438,0.699219 0.2009285,0.200929 0.42599,0.300781 0.6796875,0.300781 H 6.8867188 V 9.5488281 c 0,-0.1182133 0.017785,-0.2363441 0.048828,-0.3515625 z" />
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b3inan2jpcg03"
path="res://.godot/imported/sequence_random.svg-58cee9098c622ef87db941279206422a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/sequence_random.svg"
dest_files=["res://.godot/imported/sequence_random.svg-58cee9098c622ef87db941279206422a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="14.874624"
width="16.583984"
version="1.1"
id="svg5894"
sodipodi:docname="sequence_reactive.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs5898"><linearGradient
id="linearGradient3589"
inkscape:swatch="solid"><stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3587" /></linearGradient><inkscape:path-effect
effect="fill_between_many"
method="originald"
linkedpaths="#path5892,0,1|#path3531,0,1"
id="path-effect3720"
is_visible="true"
lpeversion="0"
join="true"
close="true"
autoreverse="true" /></defs><sodipodi:namedview
id="namedview5896"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="21.599999"
inkscape:cx="16.805556"
inkscape:cy="4.3287039"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg5894" /><path
d="M 0,0"
id="path3722"
class="UnoptimicedTransforms"
inkscape:original-d="M 0,0"
inkscape:path-effect="#path-effect3720"
transform="translate(-1.7285156,-3.375)" /><path
id="path5892"
style="fill:#40d29f;fill-opacity:1"
class="UnoptimicedTransforms"
d="m 3.4375,3.375 c -0.4726662,0 -0.8756514,0.166667 -1.2089844,0.5 -0.333333,0.333333 -0.5,0.7350317 -0.5,1.2070312 0,0.4859996 0.166667,0.8940368 0.5,1.2207032 0.333333,0.3266663 0.7363182,0.4902344 1.2089844,0.4902344 0.4719995,-10e-8 0.8756514,-0.1635681 1.2089844,-0.4902344 0.333333,-0.3266664 0.5,-0.7272192 0.5,-1.1992188 0,-0.4859995 -0.166667,-0.8951826 -0.5,-1.2285156 C 4.3131514,3.541667 3.9094995,3.375 3.4375,3.375 Z M 8.0429688,3.7929688 C 7.7096358,3.7929687 7.4104841,3.9235003 7.1464844,4.1875 6.8824846,4.4508331 6.75,4.7486983 6.75,5.0820312 6.75,5.4293642 6.8824846,5.7360003 7.1464844,6 7.4104841,6.2639997 7.7096358,6.3964844 8.0429688,6.3964844 H 17.021484 C 17.354817,6.3964844 17.653969,6.2639997 17.917969,6 18.181302,5.7360003 18.3125,5.4293642 18.3125,5.0820312 18.3125,4.7486983 18.181302,4.4508331 17.917969,4.1875 17.653969,3.9235003 17.354817,3.7929688 17.021484,3.7929688 Z M 3.4375,8.2714844 c -0.4726662,0 -0.8756514,0.166667 -1.2089844,0.5 -0.333333,0.333333 -0.5,0.7350317 -0.5,1.2070312 0,0.4859994 0.166667,0.8920834 0.5,1.2187504 0.333333,0.326666 0.7363182,0.490234 1.2089844,0.490234 0.4719995,0 0.8756514,-0.163568 1.2089844,-0.490234 0.333333,-0.326667 0.5,-0.725266 0.5,-1.197266 0,-0.4859995 -0.166667,-0.8951826 -0.5,-1.2285156 -0.333333,-0.333333 -0.7369849,-0.5 -1.2089844,-0.5 z M 8.0429688,8.6875 c -0.333333,0 -0.6324847,0.1311982 -0.8964844,0.3945312 C 6.8824846,9.346031 6.75,9.6451826 6.75,9.9785156 c 0,0.3473334 0.1324846,0.6539694 0.3964844,0.9179684 0.2639997,0.264 0.5631514,0.396485 0.8964844,0.396485 H 12.582031 C 12.667811,11.029759 12.810428,10.78417 13,10.615234 c 0.314158,-0.280616 0.764135,-0.439453 1.171875,-0.439453 h 0.46875 c 0.407741,0 0.855765,0.158985 1.169922,0.439453 0.189414,0.168797 0.331535,0.414214 0.416015,0.677735 h 0.794922 c 0.333333,0 0.632485,-0.132485 0.896485,-0.396485 0.263333,-0.263999 0.394531,-0.570635 0.394531,-0.9179684 0,-0.333333 -0.131198,-0.6324846 -0.394531,-0.8964844 C 17.653969,8.8186982 17.354817,8.6875 17.021484,8.6875 Z M 3.4375,13.146484 c -0.4726662,0 -0.8756514,0.166667 -1.2089844,0.5 -0.333333,0.333333 -0.5,0.735032 -0.5,1.207032 0,0.485999 0.166667,0.892083 0.5,1.21875 0.333333,0.325999 0.7363182,0.490234 1.2089844,0.490234 0.4719995,0 0.8756514,-0.164235 1.2089844,-0.490234 0.333333,-0.326667 0.5,-0.725266 0.5,-1.197266 0,-0.486 -0.166667,-0.895183 -0.5,-1.228516 -0.333333,-0.333333 -0.7369849,-0.5 -1.2089844,-0.5 z M 8.0429688,13.5625 c -0.333333,0 -0.6324847,0.130532 -0.8964844,0.394531 C 6.8824846,14.221031 6.75,14.520183 6.75,14.853516 c 0,0.347333 0.1324846,0.653969 0.3964844,0.917968 0.2639997,0.264 0.5631514,0.396485 0.8964844,0.396485 H 10.03125 C 9.985538,15.92966 9.986027,15.678358 10.04492,15.455078 10.12589,15.148084 10.389523,14.941651 10.626951,14.732422 10.380403,14.52554 10.114609,14.310259 10.025389,13.998047 9.986266,13.860916 9.972079,13.712745 9.974607,13.5625 Z m 10.2500002,1.083984 c -0.03323,0.02743 -0.06681,0.05476 -0.09961,0.08203 0.03855,0.03356 0.07792,0.06815 0.117188,0.101562 -0.0012,-0.06277 -0.007,-0.123307 -0.01758,-0.183594 z"
transform="translate(-1.7285156,-3.375)" /><path
style="color:#000000;fill:#40d29f;stroke-width:2;paint-order:stroke markers fill;fill-opacity:1"
d="m 12.442996,14.874619 q -0.295876,0 -0.505045,-0.186837 -0.209662,-0.186838 -0.209662,-0.451125 v -1.440446 l -1.16293,0.620023 q -0.265504,0.127774 -0.541296,0.06389 -0.2753016,-0.06389 -0.4183406,-0.282664 l -0.244932,-0.382867 q -0.142553,-0.227969 -0.07642,-0.47869 0.06613,-0.250722 0.321348,-0.387241 L 10.779424,11.33783 9.5856344,10.736185 q -0.255217,-0.136961 -0.326737,-0.38724 -0.07153,-0.250722 0.07153,-0.478691 l 0.265013,-0.373676 q 0.153328,-0.227967 0.4340186,-0.296228 0.28069,-0.0687 0.52562,0.06827 l 1.173216,0.610833 V 8.439007 q 0,-0.264287 0.209662,-0.451125 0.209169,-0.186837 0.505047,-0.186837 h 0.469287 q 0.295874,0 0.505047,0.186837 0.209659,0.186838 0.209659,0.451125 v 1.440446 l 1.173216,-0.620024 q 0.255218,-0.127774 0.525622,-0.05908 0.270404,0.06827 0.423731,0.277851 l 0.285589,0.401242 q 0.153327,0.227969 0.07642,0.478254 -0.07642,0.25072 -0.341923,0.387677 l -1.183505,0.592455 1.173707,0.610833 q 0.24493,0.118573 0.331635,0.378052 0.08671,0.259911 -0.06662,0.478692 l -0.265012,0.392052 q -0.153326,0.21878 -0.423729,0.291853 -0.270405,0.07263 -0.525621,-0.06389 l -1.183504,-0.629204 v 1.440446 q 0,0.264286 -0.20966,0.451125 -0.209172,0.186837 -0.505048,0.186837 z"
id="path6912" /></svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c88s6g4nixh5"
path="res://.godot/imported/sequence_reactive.svg-7d384ca290f7934adb9e17d9e7116b6c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/sequence_reactive.svg"
dest_files=["res://.godot/imported/sequence_reactive.svg-7d384ca290f7934adb9e17d9e7116b6c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="17.666"
width="17.666"
version="1.1"
id="svg7608"
sodipodi:docname="succedeer.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs7612" />
<sodipodi:namedview
id="namedview7610"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="10.8"
inkscape:cx="-0.092592592"
inkscape:cy="15.509259"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg7608" />
<path
d="M 7.666,9.479 6.479,8.271 Q 6.104,7.916 5.604,7.916 q -0.5,0 -0.875,0.375 -0.375,0.375 -0.375,0.865 0,0.489 0.375,0.865 l 2,2.02 q 0.416,0.396 0.927,0.396 0.51,0 0.906,-0.396 L 12.833,7.75 Q 13.166,7.416 13.052,6.958 12.937,6.5 12.833,6.041 12.458,5.666 11.968,5.666 q -0.489,0 -0.864,0.375 z m 1.167,8.187 q -1.854,0 -3.458,-0.687 Q 3.771,16.291 2.573,15.093 1.375,13.895 0.687,12.291 0,10.687 0,8.833 0,6.958 0.687,5.364 1.375,3.771 2.573,2.573 3.771,1.375 5.375,0.687 6.979,0 8.833,0 q 1.875,0 3.469,0.687 1.593,0.688 2.791,1.886 1.198,1.198 1.886,2.791 0.687,1.594 0.687,3.469 0,1.854 -0.687,3.458 -0.688,1.604 -1.886,2.802 -1.198,1.198 -2.791,1.886 -1.594,0.687 -3.469,0.687 z"
id="path7606"
style="fill:#46c0e1;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dyeh47y28xpax"
path="res://.godot/imported/succeeder.svg-e5cf6f6e04b9b862b82fd2cb479272aa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/succeeder.svg"
dest_files=["res://.godot/imported/succeeder.svg-e5cf6f6e04b9b862b82fd2cb479272aa.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="15.063"
width="16.875999"
version="1.1"
id="svg12"
sodipodi:docname="tree.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs16" />
<sodipodi:namedview
id="namedview14"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="10.8"
inkscape:cx="-26.481481"
inkscape:cy="9.3981481"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg12" />
<path
d="m 12.709,15.063 q -0.771,0 -1.313,-0.521 -0.541,-0.521 -0.562,-1.271 V 12.604 H 9.376 q -0.792,0 -1.344,-0.552 Q 7.48,11.5 7.48,10.73 V 4.313 H 6.021 V 4.938 Q 6.021,5.709 5.469,6.23 4.917,6.75 4.146,6.75 H 1.876 Q 1.105,6.75 0.553,6.198 0,5.646 0,4.875 v -3 Q 0,1.104 0.553,0.552 1.105,0 1.876,0 h 2.27 q 0.771,0 1.323,0.521 0.552,0.521 0.552,1.271 v 0.646 h 4.813 V 1.792 q 0,-0.75 0.552,-1.271 Q 11.938,0 12.709,0 H 15 q 0.771,0 1.323,0.552 0.553,0.552 0.553,1.323 v 3 q 0,0.771 -0.553,1.323 Q 15.771,6.75 15,6.75 H 12.709 Q 11.938,6.75 11.386,6.23 10.834,5.709 10.834,4.938 V 4.313 H 9.376 v 6.417 h 1.458 v -0.626 q 0,-0.77 0.552,-1.291 0.552,-0.521 1.323,-0.521 H 15 q 0.771,0 1.323,0.552 0.553,0.552 0.553,1.323 v 3.021 q 0,0.771 -0.553,1.323 -0.552,0.552 -1.323,0.552 z"
id="path10"
style="fill:#c689ff;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c2c881jv0gddb"
path="res://.godot/imported/tree.svg-c0b20ed88b2fe300c0296f7236049076.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/beehave/icons/tree.svg"
dest_files=["res://.godot/imported/tree.svg-c0b20ed88b2fe300c0296f7236049076.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -0,0 +1,54 @@
extends Node
var _tree_count: int = 0
var _active_tree_count: int = 0
var _registered_trees: Array[BeehaveTree] = []
func _enter_tree() -> void:
Performance.add_custom_monitor("beehave/total_trees", _get_total_trees)
Performance.add_custom_monitor("beehave/total_enabled_trees", _get_total_enabled_trees)
func register_tree(tree: BeehaveTree) -> void:
if _registered_trees.has(tree):
return
_registered_trees.append(tree)
_tree_count += 1
if tree.enabled:
_active_tree_count += 1
tree.tree_enabled.connect(_on_tree_enabled)
tree.tree_disabled.connect(_on_tree_disabled)
func unregister_tree(tree: BeehaveTree) -> void:
if not _registered_trees.has(tree):
return
_registered_trees.erase(tree)
_tree_count -= 1
if tree.enabled:
_active_tree_count -= 1
tree.tree_enabled.disconnect(_on_tree_enabled)
tree.tree_disabled.disconnect(_on_tree_disabled)
func _get_total_trees() -> int:
return _tree_count
func _get_total_enabled_trees() -> int:
return _active_tree_count
func _on_tree_enabled() -> void:
_active_tree_count += 1
func _on_tree_disabled() -> void:
_active_tree_count -= 1

View file

@ -0,0 +1,49 @@
## A node in the behavior tree. Every node must return `SUCCESS`, `FAILURE` or
## `RUNNING` when ticked.
@tool
class_name BeehaveNode extends Node
enum {
SUCCESS,
FAILURE,
RUNNING
}
func _get_configuration_warnings() -> PackedStringArray:
var warnings: PackedStringArray = []
if get_children().any(func(x): return not (x is BeehaveNode)):
warnings.append("All children of this node should inherit from BeehaveNode class.")
return warnings
## Executes this node and returns a status code.
## This method must be overwritten.
func tick(actor: Node, blackboard: Blackboard) -> int:
return SUCCESS
## Called when this node needs to be interrupted before it can return FAILURE or SUCCESS.
func interrupt(actor: Node, blackboard: Blackboard) -> void:
pass
## Called before the first time it ticks by the parent.
func before_run(actor: Node, blackboard: Blackboard) -> void:
pass
## Called after the last time it ticks and returns
## [code]SUCCESS[/code] or [code]FAILURE[/code].
func after_run(actor: Node, blackboard: Blackboard) -> void:
pass
func get_class_name() -> Array[StringName]:
return [&"BeehaveNode"]
func can_send_message(blackboard: Blackboard) -> bool:
return blackboard.get_value("can_send_message", false)

View file

@ -0,0 +1,224 @@
## Controls the flow of execution of the entire behavior tree.
@tool
@icon("../icons/tree.svg")
class_name BeehaveTree extends Node
enum {
SUCCESS,
FAILURE,
RUNNING
}
signal tree_enabled
signal tree_disabled
## Wether this behavior tree should be enabled or not.
@export var enabled: bool = true:
set(value):
enabled = value
set_physics_process(enabled)
if value:
tree_enabled.emit()
else:
interrupt()
tree_disabled.emit()
get:
return enabled
## An optional node path this behavior tree should apply to.
@export_node_path var actor_node_path : NodePath
## Custom blackboard node. An internal blackboard will be used
## if no blackboard is provided explicitly.
@export var blackboard:Blackboard:
set(b):
blackboard = b
if blackboard and _internal_blackboard:
remove_child(_internal_blackboard)
_internal_blackboard.free()
_internal_blackboard = null
elif not blackboard and not _internal_blackboard:
_internal_blackboard = Blackboard.new()
add_child(_internal_blackboard, false, Node.INTERNAL_MODE_BACK)
get:
return blackboard if blackboard else _internal_blackboard
## When enabled, this tree is tracked individually
## as a custom monitor.
@export var custom_monitor = false:
set(b):
custom_monitor = b
if custom_monitor and _process_time_metric_name != '':
Performance.add_custom_monitor(_process_time_metric_name, _get_process_time_metric_value)
BeehaveGlobalMetrics.register_tree(self)
else:
if _process_time_metric_name != '':
# Remove tree metric from the engine
Performance.remove_custom_monitor(_process_time_metric_name)
BeehaveGlobalMetrics.unregister_tree(self)
BeehaveDebuggerMessages.unregister_tree(get_instance_id())
var actor : Node
var status : int = -1
var _internal_blackboard: Blackboard
var _process_time_metric_name : String
var _process_time_metric_value : float = 0.0
var _can_send_message: bool = false
func _ready() -> void:
if Engine.is_editor_hint():
return
if self.get_child_count() > 0 and not self.get_child(0) is BeehaveNode:
push_warning("Beehave error: Root %s should have only one child of type BeehaveNode (NodePath: %s)" % [self.name, self.get_path()])
disable()
return
if not blackboard:
_internal_blackboard = Blackboard.new()
add_child(_internal_blackboard, false, Node.INTERNAL_MODE_BACK)
actor = get_parent()
if actor_node_path:
actor = get_node(actor_node_path)
# Get the name of the parent node name for metric
var parent_name = actor.name
_process_time_metric_name = "beehave [microseconds]/process_time_%s-%s" % [parent_name, get_instance_id()]
# Register custom metric to the engine
if custom_monitor:
Performance.add_custom_monitor(_process_time_metric_name, _get_process_time_metric_value)
BeehaveGlobalMetrics.register_tree(self)
set_physics_process(enabled)
BeehaveGlobalDebugger.register_tree(self)
BeehaveDebuggerMessages.register_tree(_get_debugger_data(self))
func _physics_process(delta: float) -> void:
if Engine.is_editor_hint():
return
# Start timing for metric
var start_time = Time.get_ticks_usec()
blackboard.set_value("can_send_message", _can_send_message)
if _can_send_message:
BeehaveDebuggerMessages.process_begin(get_instance_id())
if self.get_child_count() == 1:
tick()
if _can_send_message:
BeehaveDebuggerMessages.process_end(get_instance_id())
# Check the cost for this frame and save it for metric report
_process_time_metric_value = Time.get_ticks_usec() - start_time
func tick() -> int:
var child := self.get_child(0)
if status != RUNNING:
child.before_run(actor, blackboard)
status = child.tick(actor, blackboard)
if _can_send_message:
BeehaveDebuggerMessages.process_tick(child.get_instance_id(), status)
BeehaveDebuggerMessages.process_tick(get_instance_id(), status)
# Clear running action if nothing is running
if status != RUNNING:
blackboard.set_value("running_action", null, str(actor.get_instance_id()))
child.after_run(actor, blackboard)
return status
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
if get_children().any(func(x): return not (x is BeehaveNode)):
warnings.append("All children of this node should inherit from BeehaveNode class.")
if get_child_count() != 1:
warnings.append("BeehaveTree should have exactly one child node.")
return warnings
## Returns the currently running action
func get_running_action() -> ActionLeaf:
return blackboard.get_value("running_action", null, str(actor.get_instance_id()))
## Returns the last condition that was executed
func get_last_condition() -> ConditionLeaf:
return blackboard.get_value("last_condition", null, str(actor.get_instance_id()))
## Returns the status of the last executed condition
func get_last_condition_status() -> String:
if blackboard.has_value("last_condition_status", str(actor.get_instance_id())):
var status = blackboard.get_value("last_condition_status", null, str(actor.get_instance_id()))
if status == SUCCESS:
return "SUCCESS"
elif status == FAILURE:
return "FAILURE"
else:
return "RUNNING"
return ""
## interrupts this tree if anything was running
func interrupt() -> void:
if self.get_child_count() != 0:
var first_child = self.get_child(0)
if "interrupt" in first_child:
first_child.interrupt(actor, blackboard)
## Enables this tree.
func enable() -> void:
self.enabled = true
## Disables this tree.
func disable() -> void:
self.enabled = false
func _exit_tree() -> void:
if custom_monitor:
if _process_time_metric_name != '':
# Remove tree metric from the engine
Performance.remove_custom_monitor(_process_time_metric_name)
BeehaveGlobalMetrics.unregister_tree(self)
BeehaveDebuggerMessages.unregister_tree(get_instance_id())
# Called by the engine to profile this tree
func _get_process_time_metric_value() -> int:
return _process_time_metric_value
func _get_debugger_data(node: Node) -> Dictionary:
if not node is BeehaveTree and not node is BeehaveNode:
return {}
var data := { path = node.get_path(), name = node.name, type = node.get_class_name(), id = str(node.get_instance_id()) }
if node.get_child_count() > 0:
data.children = []
for child in node.get_children():
var child_data := _get_debugger_data(child)
if not child_data.is_empty():
data.children.push_back(child_data)
return data
func get_class_name() -> Array[StringName]:
return [&"BeehaveTree"]

View file

@ -0,0 +1,40 @@
## A Composite node controls the flow of execution of its children in a specific manner.
@tool
@icon("../../icons/category_composite.svg")
class_name Composite extends BeehaveNode
var running_child: BeehaveNode = null
func _ready():
if Engine.is_editor_hint():
return
if self.get_child_count() < 1:
push_warning("BehaviorTree Error: Composite %s should have at least one child (NodePath: %s)" % [self.name, self.get_path()])
func _get_configuration_warnings() -> PackedStringArray:
var warnings: PackedStringArray = super._get_configuration_warnings()
if get_children().filter(func(x): return x is BeehaveNode).size() < 2:
warnings.append("Any composite node should have at least two children. Otherwise it is not useful.")
return warnings
func interrupt(actor: Node, blackboard: Blackboard) -> void:
if running_child != null:
running_child.interrupt(actor, blackboard)
running_child = null
func after_run(actor: Node, blackboard: Blackboard) -> void:
running_child = null
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"Composite")
return classes

View file

@ -0,0 +1,57 @@
## Selector nodes will attempt to execute each of its children until one of
## them return `SUCCESS`. If all children return `FAILURE`, this node will also
## return `FAILURE`.
## If a child returns `RUNNING` it will tick again.
@tool
@icon("../../icons/selector.svg")
class_name SelectorComposite extends Composite
var last_execution_index: int = 0
func tick(actor: Node, blackboard: Blackboard) -> int:
for c in get_children():
if c.get_index() < last_execution_index:
continue
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
match response:
SUCCESS:
c.after_run(actor, blackboard)
return SUCCESS
FAILURE:
last_execution_index += 1
c.after_run(actor, blackboard)
RUNNING:
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
return FAILURE
func after_run(actor: Node, blackboard: Blackboard) -> void:
last_execution_index = 0
super(actor, blackboard)
func interrupt(actor: Node, blackboard: Blackboard) -> void:
after_run(actor, blackboard)
super(actor, blackboard)
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"SelectorComposite")
return classes

View file

@ -0,0 +1,88 @@
## This node will attempt to execute all of its children just like a
## [code]SelectorStar[/code] would, with the exception that the children
## will be executed in a random order.
@tool
@icon("../../icons/selector_random.svg")
class_name SelectorRandomComposite extends Composite
## Sets a predicable seed
@export var random_seed:int = 0:
set(rs):
random_seed = rs
if random_seed != 0:
seed(random_seed)
else:
randomize()
## A shuffled list of the children that will be executed in reverse order.
var _children_bag: Array[Node] = []
var c: Node
func _ready() -> void:
if random_seed == 0:
randomize()
func tick(actor: Node, blackboard: Blackboard) -> int:
if _children_bag.is_empty():
_reset()
# We need to traverse the array in reverse since we will be manipulating it.
for i in _get_reversed_indexes():
c = _children_bag[i]
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
match response:
SUCCESS:
_children_bag.erase(c)
c.after_run(actor, blackboard)
return SUCCESS
FAILURE:
_children_bag.erase(c)
c.after_run(actor, blackboard)
RUNNING:
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
return FAILURE
func after_run(actor: Node, blackboard: Blackboard) -> void:
_reset()
super(actor, blackboard)
func interrupt(actor: Node, blackboard: Blackboard) -> void:
after_run(actor, blackboard)
super(actor, blackboard)
func _get_reversed_indexes() -> Array[int]:
var reversed: Array[int]
reversed.assign(range(_children_bag.size()))
reversed.reverse()
return reversed
## Generates a new shuffled list of the children.
func _reset() -> void:
_children_bag = get_children().duplicate()
_children_bag.shuffle()
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"SelectorRandomComposite")
return classes

View file

@ -0,0 +1,45 @@
## Selector Reactive nodes will attempt to execute each of its children until one of
## them return `SUCCESS`. If all children return `FAILURE`, this node will also
## return `FAILURE`.
## If a child returns `RUNNING` it will restart.
@tool
@icon("../../icons/selector_reactive.svg")
class_name SelectorReactiveComposite extends Composite
func tick(actor: Node, blackboard: Blackboard) -> int:
for c in get_children():
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
match response:
SUCCESS:
# Interrupt any child that was RUNNING before.
if c != running_child:
interrupt(actor, blackboard)
c.after_run(actor, blackboard)
return SUCCESS
FAILURE:
c.after_run(actor, blackboard)
RUNNING:
if c != running_child:
interrupt(actor, blackboard)
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
return FAILURE
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"SelectorReactiveComposite")
return classes

View file

@ -0,0 +1,64 @@
## Sequence nodes will attempt to execute all of its children and report
## `SUCCESS` in case all of the children report a `SUCCESS` status code.
## If at least one child reports a `FAILURE` status code, this node will also
## return `FAILURE` and restart.
## In case a child returns `RUNNING` this node will tick again.
@tool
@icon("../../icons/sequence.svg")
class_name SequenceComposite extends Composite
var successful_index: int = 0
func tick(actor: Node, blackboard: Blackboard) -> int:
for c in get_children():
if c.get_index() < successful_index:
continue
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
match response:
SUCCESS:
successful_index += 1
c.after_run(actor, blackboard)
FAILURE:
# Interrupt any child that was RUNNING before.
interrupt(actor, blackboard)
c.after_run(actor, blackboard)
return FAILURE
RUNNING:
if c != running_child:
if running_child != null:
running_child.interrupt(actor, blackboard)
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
_reset()
return SUCCESS
func interrupt(actor: Node, blackboard: Blackboard) -> void:
_reset()
super(actor, blackboard)
func _reset() -> void:
successful_index = 0
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"SequenceComposite")
return classes

View file

@ -0,0 +1,96 @@
## This node will attempt to execute all of its children just like a
## [code]SequenceStar[/code] would, with the exception that the children
## will be executed in a random order.
@tool
@icon("../../icons/sequence_random.svg")
class_name SequenceRandomComposite extends Composite
## Whether the sequence should start where it left off after a previous failure.
@export var resume_on_failure: bool = false
## Whether the sequence should start where it left off after a previous interruption.
@export var resume_on_interrupt: bool = false
## Sets a predicable seed
@export var random_seed: int = 0:
set(rs):
random_seed = rs
if random_seed != 0:
seed(random_seed)
else:
randomize()
## A shuffled list of the children that will be executed in reverse order.
var _children_bag: Array[Node] = []
var c: Node
func _ready() -> void:
if random_seed == 0:
randomize()
func tick(actor: Node, blackboard: Blackboard) -> int:
if _children_bag.is_empty():
_reset()
# We need to traverse the array in reverse since we will be manipulating it.
for i in _get_reversed_indexes():
c = _children_bag[i]
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
match response:
SUCCESS:
_children_bag.erase(c)
c.after_run(actor, blackboard)
FAILURE:
_children_bag.erase(c)
c.after_run(actor, blackboard)
return FAILURE
RUNNING:
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
return SUCCESS
func after_run(actor: Node, blackboard: Blackboard) -> void:
if not resume_on_failure:
_reset()
super(actor, blackboard)
func interrupt(actor: Node, blackboard: Blackboard) -> void:
if not resume_on_interrupt:
_reset()
super(actor, blackboard)
func _get_reversed_indexes() -> Array[int]:
var reversed: Array[int]
reversed.assign(range(_children_bag.size()))
reversed.reverse()
return reversed
## Generates a new shuffled list of the children.
func _reset() -> void:
_children_bag = get_children().duplicate()
_children_bag.shuffle()
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"SequenceRandomComposite")
return classes

View file

@ -0,0 +1,62 @@
## Reactive Sequence nodes will attempt to execute all of its children and report
## `SUCCESS` in case all of the children report a `SUCCESS` status code.
## If at least one child reports a `FAILURE` status code, this node will also
## return `FAILURE` and restart.
## In case a child returns `RUNNING` this node will restart.
@tool
@icon("../../icons/sequence_reactive.svg")
class_name SequenceReactiveComposite extends Composite
var successful_index: int = 0
func tick(actor: Node, blackboard: Blackboard) -> int:
for c in get_children():
if c.get_index() < successful_index:
continue
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
match response:
SUCCESS:
successful_index += 1
c.after_run(actor, blackboard)
FAILURE:
# Interrupt any child that was RUNNING before.
interrupt(actor, blackboard)
c.after_run(actor, blackboard)
return FAILURE
RUNNING:
_reset()
if running_child != c:
interrupt(actor, blackboard)
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
_reset()
return SUCCESS
func interrupt(actor: Node, blackboard: Blackboard) -> void:
_reset()
super(actor, blackboard)
func _reset() -> void:
successful_index = 0
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"SequenceReactiveComposite")
return classes

View file

@ -0,0 +1,58 @@
## Sequence Star nodes will attempt to execute all of its children and report
## `SUCCESS` in case all of the children report a `SUCCESS` status code.
## If at least one child reports a `FAILURE` status code, this node will also
## return `FAILURE` and tick again.
## In case a child returns `RUNNING` this node will restart.
@tool
@icon("../../icons/sequence_reactive.svg")
class_name SequenceStarComposite extends Composite
var successful_index: int = 0
func tick(actor: Node, blackboard: Blackboard) -> int:
for c in get_children():
if c.get_index() < successful_index:
continue
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
match response:
SUCCESS:
successful_index += 1
c.after_run(actor, blackboard)
FAILURE:
c.after_run(actor, blackboard)
return FAILURE
RUNNING:
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
_reset()
return SUCCESS
func interrupt(actor: Node, blackboard: Blackboard) -> void:
_reset()
super(actor, blackboard)
func _reset() -> void:
successful_index = 0
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"SequenceStarComposite")
return classes

View file

@ -0,0 +1,41 @@
## Decorator nodes are used to transform the result received by its child.
## Must only have one child.
@tool
@icon("../../icons/category_decorator.svg")
class_name Decorator extends BeehaveNode
var running_child: BeehaveNode = null
func _ready():
if Engine.is_editor_hint():
return
if self.get_child_count() != 1:
push_warning("Beehave Error: Decorator %s should have only one child (NodePath: %s)" % [self.name, self.get_path()])
func _get_configuration_warnings() -> PackedStringArray:
var warnings: PackedStringArray = super._get_configuration_warnings()
if get_child_count() != 1:
warnings.append("Decorator should have exactly one child node.")
return warnings
func interrupt(actor: Node, blackboard: Blackboard) -> void:
if running_child != null:
running_child.interrupt(actor, blackboard)
running_child = null
func after_run(actor: Node, blackboard: Blackboard) -> void:
running_child = null
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"Decorator")
return classes

View file

@ -0,0 +1,34 @@
## A Failer node will always return a `FAILURE` status code.
@tool
@icon("../../icons/failer.svg")
class_name AlwaysFailDecorator extends Decorator
func tick(actor: Node, blackboard: Blackboard) -> int:
var c = get_child(0)
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
if response == RUNNING:
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
else:
c.after_run(actor, blackboard)
return FAILURE
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"AlwaysFailDecorator")
return classes

View file

@ -0,0 +1,42 @@
## An inverter will return `FAILURE` in case it's child returns a `SUCCESS` status
## code or `SUCCESS` in case its child returns a `FAILURE` status code.
@tool
@icon("../../icons/inverter.svg")
class_name InverterDecorator extends Decorator
func tick(actor: Node, blackboard: Blackboard) -> int:
var c = get_child(0)
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
match response:
SUCCESS:
c.after_run(actor, blackboard)
return FAILURE
FAILURE:
c.after_run(actor, blackboard)
return SUCCESS
RUNNING:
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
_:
push_error("This should be unreachable")
return -1
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"InverterDecorator")
return classes

View file

@ -0,0 +1,41 @@
## The limiter will execute its child `x` amount of times. When the number of
## maximum ticks is reached, it will return a `FAILURE` status code.
@tool
@icon("../../icons/limiter.svg")
class_name LimiterDecorator extends Decorator
@onready var cache_key = 'limiter_%s' % self.get_instance_id()
@export var max_count : float = 0
func tick(actor: Node, blackboard: Blackboard) -> int:
var child = self.get_child(0)
var current_count = blackboard.get_value(cache_key, 0, str(actor.get_instance_id()))
if current_count == 0:
child.before_run(actor, blackboard)
if current_count < max_count:
blackboard.set_value(cache_key, current_count + 1, str(actor.get_instance_id()))
var response = child.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(child.get_instance_id(), response)
if child is ConditionLeaf:
blackboard.set_value("last_condition", child, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
if child is ActionLeaf and response == RUNNING:
running_child = child
blackboard.set_value("running_action", child, str(actor.get_instance_id()))
return response
else:
child.after_run(actor, blackboard)
return FAILURE
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"LimiterDecorator")
return classes

View file

@ -0,0 +1,34 @@
## A succeeder node will always return a `SUCCESS` status code.
@tool
@icon("../../icons/succeeder.svg")
class_name AlwaysSucceedDecorator extends Decorator
func tick(actor: Node, blackboard: Blackboard) -> int:
var c = get_child(0)
if c != running_child:
c.before_run(actor, blackboard)
var response = c.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response)
if c is ConditionLeaf:
blackboard.set_value("last_condition", c, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
if response == RUNNING:
running_child = c
if c is ActionLeaf:
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
return RUNNING
else:
c.after_run(actor, blackboard)
return SUCCESS
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"AlwaysSucceedDecorator")
return classes

View file

@ -0,0 +1,46 @@
## The Time Limit Decorator will give its child a set amount of time to finish
## before interrupting it and return a `FAILURE` status code. The timer is reset
## every time before the node runs.
@tool
@icon("../../icons/limiter.svg")
class_name TimeLimiterDecorator extends Decorator
@export var wait_time: = 0.0
var time_left: = 0.0
@onready var child: BeehaveNode = get_child(0)
func tick(actor: Node, blackboard: Blackboard) -> int:
if time_left < wait_time:
time_left += get_physics_process_delta_time()
var response = child.tick(actor, blackboard)
if can_send_message(blackboard):
BeehaveDebuggerMessages.process_tick(child.get_instance_id(), response)
if child is ConditionLeaf:
blackboard.set_value("last_condition", child, str(actor.get_instance_id()))
blackboard.set_value("last_condition_status", response, str(actor.get_instance_id()))
if response == RUNNING:
running_child = child
if child is ActionLeaf:
blackboard.set_value("running_action", child, str(actor.get_instance_id()))
return response
else:
child.after_run(actor, blackboard)
interrupt(actor, blackboard)
return FAILURE
func before_run(actor: Node, blackboard: Blackboard) -> void:
time_left = 0.0
child.before_run(actor, blackboard)
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"TimeLimiterDecorator")
return classes

View file

@ -0,0 +1,13 @@
## Actions are leaf nodes that define a task to be performed by an actor.
## Their execution can be long running, potentially being called across multiple
## frame executions. In this case, the node should return `RUNNING` until the
## action is completed.
@tool
@icon("../../icons/action.svg")
class_name ActionLeaf extends Leaf
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"ActionLeaf")
return classes

View file

@ -0,0 +1,61 @@
## Compares two values using the specified comparison operator.
## Returns [code]FAILURE[/code] if any of the expression fails or the
## comparison operation returns [code]false[/code], otherwise it returns [code]SUCCESS[/code].
@tool
class_name BlackboardCompareCondition extends ConditionLeaf
enum Operators {
EQUAL,
NOT_EQUAL,
GREATER,
LESS,
GREATER_EQUAL,
LESS_EQUAL,
}
## Expression represetning left operand.
## This value can be any valid GDScript expression.
## In order to use the existing blackboard keys for comparison,
## use get_value("key_name") e.g. get_value("direction").length()
@export_placeholder(EXPRESSION_PLACEHOLDER) var left_operand: String = ""
## Comparison operator.
@export_enum("==", "!=", ">", "<", ">=", "<=") var operator: int = 0
## Expression represetning right operand.
## This value can be any valid GDScript expression.
## In order to use the existing blackboard keys for comparison,
## use get_value("key_name") e.g. get_value("direction").length()
@export_placeholder(EXPRESSION_PLACEHOLDER) var right_operand: String = ""
@onready var _left_expression: Expression = _parse_expression(left_operand)
@onready var _right_expression: Expression = _parse_expression(right_operand)
func tick(actor: Node, blackboard: Blackboard) -> int:
var left: Variant = _left_expression.execute([], blackboard)
if _left_expression.has_execute_failed():
return FAILURE
var right: Variant = _right_expression.execute([], blackboard)
if _right_expression.has_execute_failed():
return FAILURE
var result: bool = false
match operator:
Operators.EQUAL: result = left == right
Operators.NOT_EQUAL: result = left != right
Operators.GREATER: result = left > right
Operators.LESS: result = left < right
Operators.GREATER_EQUAL: result = left >= right
Operators.LESS_EQUAL: result = left <= right
return SUCCESS if result else FAILURE
func _get_expression_sources() -> Array[String]:
return [left_operand, right_operand]

View file

@ -0,0 +1,25 @@
## Erases the specified key from the blackboard.
## Returns [code]FAILURE[/code] if expression execution fails, otherwise [code]SUCCESS[/code].
@tool
class_name BlackboardEraseAction extends ActionLeaf
## Expression representing a blackboard key.
@export_placeholder(EXPRESSION_PLACEHOLDER) var key: String = ""
@onready var _key_expression: Expression = _parse_expression(key)
func tick(actor: Node, blackboard: Blackboard) -> int:
var key_value: Variant = _key_expression.execute([], blackboard)
if _key_expression.has_execute_failed():
return FAILURE
blackboard.erase_value(key_value)
return SUCCESS
func _get_expression_sources() -> Array[String]:
return [key]

View file

@ -0,0 +1,23 @@
## Returns [code]FAILURE[/code] if expression execution fails or the specified key doesn't exist.
## Returns [code]SUCCESS[/code] if blackboard has the specified key.
@tool
class_name BlackboardHasCondition extends ConditionLeaf
## Expression representing a blackboard key.
@export_placeholder(EXPRESSION_PLACEHOLDER) var key: String = ""
@onready var _key_expression: Expression = _parse_expression(key)
func tick(actor: Node, blackboard: Blackboard) -> int:
var key_value: Variant = _key_expression.execute([], blackboard)
if _key_expression.has_execute_failed():
return FAILURE
return SUCCESS if blackboard.has_value(key_value) else FAILURE
func _get_expression_sources() -> Array[String]:
return [key]

View file

@ -0,0 +1,34 @@
## Sets the specified key to the specified value.
## Returns [code]FAILURE[/code] if expression execution fails, otherwise [code]SUCCESS[/code].
@tool
class_name BlackboardSetAction extends ActionLeaf
## Expression representing a blackboard key.
@export_placeholder(EXPRESSION_PLACEHOLDER) var key: String = ""
## Expression representing a blackboard value to assign to the specified key.
@export_placeholder(EXPRESSION_PLACEHOLDER) var value: String = ""
@onready var _key_expression: Expression = _parse_expression(key)
@onready var _value_expression: Expression = _parse_expression(value)
func tick(actor: Node, blackboard: Blackboard) -> int:
var key_value: Variant = _key_expression.execute([], blackboard)
if _key_expression.has_execute_failed():
return FAILURE
var value_value: Variant = _value_expression.execute([], blackboard)
if _value_expression.has_execute_failed():
return FAILURE
blackboard.set_value(key_value, value_value)
return SUCCESS
func _get_expression_sources() -> Array[String]:
return [key, value]

View file

@ -0,0 +1,11 @@
## Conditions are leaf nodes that either return SUCCESS or FAILURE depending on
## a single simple condition. They should never return `RUNNING`.
@tool
@icon("../../icons/condition.svg")
class_name ConditionLeaf extends Leaf
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"ConditionLeaf")
return classes

View file

@ -0,0 +1,46 @@
## Base class for all leaf nodes of the tree.
@tool
@icon("../../icons/category_leaf.svg")
class_name Leaf extends BeehaveNode
const EXPRESSION_PLACEHOLDER: String = "Insert an expression..."
func _get_configuration_warnings() -> PackedStringArray:
var warnings: PackedStringArray = []
var children: Array[Node] = get_children()
if children.any(func(x): return x is BeehaveNode):
warnings.append("Leaf nodes should not have any child nodes. They won't be ticked.")
for source in _get_expression_sources():
var error_text: String = _parse_expression(source).get_error_text()
if not error_text.is_empty():
warnings.append("Expression `%s` is invalid! Error text: `%s`" % [source, error_text])
return warnings
func _parse_expression(source: String) -> Expression:
var result: Expression = Expression.new()
var error: int = result.parse(source)
if not Engine.is_editor_hint() and error != OK:
push_error(
"[Leaf] Couldn't parse expression with source: `%s` Error text: `%s`" %\
[source, result.get_error_text()]
)
return result
func _get_expression_sources() -> Array[String]: # virtual
return []
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"Leaf")
return classes

View file

@ -0,0 +1,7 @@
[plugin]
name="Beehave"
description="🐝 Behavior Tree addon for Godot Engine"
author="bitbrain"
version="2.7.4"
script="plugin.gd"

24
addons/beehave/plugin.gd Normal file
View file

@ -0,0 +1,24 @@
@tool
extends EditorPlugin
const BeehaveEditorDebugger := preload("debug/debugger.gd")
var editor_debugger: BeehaveEditorDebugger
var frames: RefCounted
func _init():
name = "BeehavePlugin"
add_autoload_singleton("BeehaveGlobalMetrics", "res://addons/beehave/metrics/beehave_global_metrics.gd")
add_autoload_singleton("BeehaveGlobalDebugger", "res://addons/beehave/debug/global_debugger.gd")
print("Beehave initialized!")
func _enter_tree() -> void:
editor_debugger = BeehaveEditorDebugger.new()
frames = preload("debug/frames.gd").new()
add_debugger_plugin(editor_debugger)
func _exit_tree() -> void:
remove_debugger_plugin(editor_debugger)
editor_debugger.free()
frames.free()

View file

@ -0,0 +1,22 @@
@tool
class_name BeehaveUtils
static func get_plugin() -> EditorPlugin:
var tree: SceneTree = Engine.get_main_loop()
return tree.get_root().get_child(0).get_node_or_null("BeehavePlugin")
static func get_editor_scale() -> float:
var plugin := get_plugin()
if plugin:
return plugin.get_editor_interface().get_editor_scale()
return 1.0
static func get_frames() -> RefCounted:
var plugin := get_plugin()
if plugin:
return plugin.frames
push_error("Can't find Beehave Plugin")
return null

View file

@ -15,12 +15,21 @@ run/main_scene="res://scenes/main.tscn"
config/features=PackedStringArray("4.0", "Forward Plus") config/features=PackedStringArray("4.0", "Forward Plus")
config/icon="res://icon.svg" config/icon="res://icon.svg"
[autoload]
BeehaveGlobalMetrics="*res://addons/beehave/metrics/beehave_global_metrics.gd"
BeehaveGlobalDebugger="*res://addons/beehave/debug/global_debugger.gd"
[display] [display]
window/size/viewport_width=1280 window/size/viewport_width=1280
window/size/viewport_height=720 window/size/viewport_height=720
window/stretch/scale=1.8 window/stretch/scale=1.8
[editor_plugins]
enabled=PackedStringArray("res://addons/beehave/plugin.cfg")
[input] [input]
move_right={ move_right={

View file

@ -1,7 +1,8 @@
[gd_scene load_steps=6 format=3 uid="uid://bktg1ypaav3q3"] [gd_scene load_steps=7 format=3 uid="uid://bktg1ypaav3q3"]
[ext_resource type="Texture2D" uid="uid://bbwsdd0jddmck" path="res://art/Pink_Monster_Walk_6.png" id="1_e5603"] [ext_resource type="Texture2D" uid="uid://bbwsdd0jddmck" path="res://art/Pink_Monster_Walk_6.png" id="1_e5603"]
[ext_resource type="Script" path="res://scripts/enemy.gd" id="1_l5lyv"] [ext_resource type="Script" path="res://scripts/enemy.gd" id="1_l5lyv"]
[ext_resource type="PackedScene" uid="uid://b51tdt5kunai" path="res://scenes/enemy_behavior_tree.tscn" id="3_jk76t"]
[sub_resource type="Animation" id="Animation_etqki"] [sub_resource type="Animation" id="Animation_etqki"]
resource_name = "walk" resource_name = "walk"
@ -45,3 +46,5 @@ libraries = {
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(-0.5, -5) position = Vector2(-0.5, -5)
shape = SubResource("RectangleShape2D_rlijp") shape = SubResource("RectangleShape2D_rlijp")
[node name="EnemyBehaviorTree" parent="." instance=ExtResource("3_jk76t")]

View file

@ -0,0 +1,22 @@
[gd_scene load_steps=6 format=3 uid="uid://b51tdt5kunai"]
[ext_resource type="Script" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_b2pc4"]
[ext_resource type="Script" path="res://addons/beehave/nodes/composites/sequence.gd" id="2_80fm4"]
[ext_resource type="Script" path="res://scripts/is_idle_condition.gd" id="3_5jur1"]
[ext_resource type="Script" path="res://scripts/move_to_target_action.gd" id="4_1on4v"]
[ext_resource type="Script" path="res://scripts/get_random_top_cell.gd" id="4_ouqf7"]
[node name="EnemyBehaviorTree" type="Node"]
script = ExtResource("1_b2pc4")
[node name="ReturnBallSequence" type="Node" parent="."]
script = ExtResource("2_80fm4")
[node name="IsIdle" type="Node" parent="ReturnBallSequence"]
script = ExtResource("3_5jur1")
[node name="GetRandomTopCell" type="Node" parent="ReturnBallSequence"]
script = ExtResource("4_ouqf7")
[node name="MoveToTargetAction" type="Node" parent="ReturnBallSequence"]
script = ExtResource("4_1on4v")

View file

@ -4,33 +4,9 @@ extends CharacterBody2D
@onready var animation_player = $AnimationPlayer @onready var animation_player = $AnimationPlayer
@export var speed = 80 @export var speed = 80
var y_spawn_offset = -8 var y_spawn_offset = -8
var is_moving = false
var destination: Vector2 = Vector2.ZERO var destination: Vector2 = Vector2.ZERO
func _ready(): func _ready():
var spawn_cell: Vector2i = tile_map.get_top_spawn_cell() var spawn_cell: Vector2i = tile_map.get_top_spawn_cell()
position = tile_map.map_to_local(spawn_cell) position = tile_map.map_to_local(spawn_cell)
position.y += y_spawn_offset position.y += y_spawn_offset
func _process(_delta):
if is_moving:
animation_player.play("walk")
else:
animation_player.stop()
func _physics_process(delta):
move_to_rand_cell(delta)
func move_to_rand_cell(delta):
if !is_moving:
var rand_cell: Vector2i = tile_map.get_random_top_cell()
tile_map.set_cell(0, Vector2i(rand_cell.x, rand_cell.y), 1, Vector2i(0, 0), 0) # debug purpose
destination = tile_map.map_to_local(rand_cell)
destination.y += y_spawn_offset
is_moving = true
position = position.move_toward(destination, delta * speed)
if position == destination:
is_moving = false

View file

@ -0,0 +1,11 @@
class_name GetRandomTopCell
extends ActionLeaf
func tick(actor, _blackboard):
var rand_cell: Vector2i = actor.tile_map.get_random_top_cell()
actor.tile_map.set_cell(0, Vector2i(rand_cell.x, rand_cell.y), 1, Vector2i(0, 0), 0) # debug purpose
actor.destination = actor.tile_map.map_to_local(rand_cell)
actor.destination.y += actor.y_spawn_offset
return SUCCESS

View file

@ -0,0 +1,5 @@
class_name IsIdleCondition
extends ConditionLeaf
func tick(actor, _blackboard):
return SUCCESS

View file

@ -0,0 +1,16 @@
class_name MoveToTargetAction
extends ActionLeaf
func before_run(actor, blackboard):
actor.animation_player.play("walk")
func tick(actor, _blackboard):
var delta = get_physics_process_delta_time()
actor.position = actor.position.move_toward(actor.destination, delta * actor.speed)
if actor.position == actor.destination:
return SUCCESS
return RUNNING
func after_run(actor, blackboard):
actor.animation_player.stop()