initial project

This commit is contained in:
Vivianne 2023-10-06 01:54:01 -07:00
commit d5591022f6
98 changed files with 4466 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# Godot 4+ specific ignores
.godot/

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bah77esichnyx"
path="res://.godot/imported/horizontal_layout.svg-d2a7af351e44f9bf61d0c938b6f47fac.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://da3b236rjbqns"
path="res://.godot/imported/port_bottom.svg-e5c5c61b642a79ab9c2b66ff56603d34.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bnufc8p6spdtn"
path="res://.godot/imported/port_left.svg-69cd927c4db555f1edbb8d1f553ea2fd.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bbmd6vk23ympm"
path="res://.godot/imported/port_right.svg-f760bd8be2dd613d0d3848c998c92a2a.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bw8wmxdfom8eh"
path="res://.godot/imported/port_top.svg-d1b336cdc6a0dd570305782a1e56f61d.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bpyxu6i1dx5qh"
path="res://.godot/imported/vertical_layout.svg-1a08fee4b09812a05bcf3defb8afcc4c.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://btrq8e0kyxthg"
path="res://.godot/imported/action.svg-e8a91246d0ba9ba3cf84290d65648f06.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dw7rom0hiff6c"
path="res://.godot/imported/blackboard.svg-18d4dfd4f6de558de250b67251ff1e69.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://qpdd6ue7x82h"
path="res://.godot/imported/category_bt.svg-8537bebd1c5f62dca3d7ee7f17efeed4.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://863s568sneja"
path="res://.godot/imported/category_composite.svg-43f66e63a7ccfa5ac8ec6da0583b3246.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c2ie8m4ddawlb"
path="res://.godot/imported/category_decorator.svg-79d598d6456f32724156248e09d6eaf3.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://eq0sp4g3s75r"
path="res://.godot/imported/category_leaf.svg-c740ecab6cfae632574ca5e39e46fd2e.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ck4toqx0nggiu"
path="res://.godot/imported/condition.svg-57892684b10a64086f68c09c388b17e5.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://2fj7htaqvcud"
path="res://.godot/imported/failer.svg-9a62b840e1eacc0437e7a67b14a302e4.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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.0 KiB

View File

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cffmoc3og8hux"
path="res://.godot/imported/inverter.svg-1f1b976d95de42c4ad99a92fa9a6c5d0.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c7akxvsg0f2by"
path="res://.godot/imported/limiter.svg-b4c7646605c46f53c5e403fe21d8f584.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b2c5d20doh4sp"
path="res://.godot/imported/selector.svg-78bccfc448bd1676b5a29bfde4b08e5b.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bmnkcmk7bkdjd"
path="res://.godot/imported/selector_random.svg-d52fea1352c24483ecd9dc8609cf00f3.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://crkbov0h8sb8l"
path="res://.godot/imported/selector_reactive.svg-dd3b8fb8cd2ffe331605aaad1e021cc0.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c5gw354thiofm"
path="res://.godot/imported/sequence.svg-76e5600611900cc81e9ec286977b8c6a.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bat8ptdw5qt1d"
path="res://.godot/imported/sequence_random.svg-58cee9098c622ef87db941279206422a.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://rmiu1slwfkh7"
path="res://.godot/imported/sequence_reactive.svg-7d384ca290f7934adb9e17d9e7116b6c.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dl6wo332kglbe"
path="res://.godot/imported/succeeder.svg-e5cf6f6e04b9b862b82fd2cb479272aa.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://deryyg2hbmaaw"
path="res://.godot/imported/tree.svg-c0b20ed88b2fe300c0296f7236049076.ctex"
metadata={
"has_editor_variant": true,
"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=true
editor/convert_colors_with_editor_theme=true

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,152 @@
@tool
class_name RandomizedComposite extends Composite
const WEIGHTS_PREFIX = "Weights/"
## Sets a predicable seed
@export var random_seed: int = 0:
set(rs):
random_seed = rs
if random_seed != 0:
seed(random_seed)
else:
randomize()
## Wether to use weights for every child or not.
@export var use_weights: bool:
set(value):
use_weights = value
if use_weights:
_update_weights(get_children())
_connect_children_changing_signals()
notify_property_list_changed()
var _weights: Dictionary
func _ready():
_connect_children_changing_signals()
func _connect_children_changing_signals():
if not child_entered_tree.is_connected(_on_child_entered_tree):
child_entered_tree.connect(_on_child_entered_tree)
if not child_exiting_tree.is_connected(_on_child_exiting_tree):
child_exiting_tree.connect(_on_child_exiting_tree)
func get_shuffled_children() -> Array[Node]:
var children_bag: Array[Node] = get_children().duplicate()
if use_weights:
var weights: Array[int]
weights.assign(children_bag.map(func (child): return _weights[child.name]))
children_bag.assign(_weighted_shuffle(children_bag, weights))
else:
children_bag.shuffle()
return children_bag
## Returns a shuffled version of a given array using the supplied array of weights.
## Think of weights as the chance of a given item being the first in the array.
func _weighted_shuffle(items: Array, weights: Array[int]) -> Array:
if len(items) != len(weights):
push_error("items and weights size mismatch: expected %d weights, got %d instead." % [len(items), len(weights)])
return items
# This method is based on the weighted random sampling algorithm
# by Efraimidis, Spirakis; 2005. This runs in O(n log(n)).
# For each index, it will calculate random_value^(1/weight).
var chance_calc = func(i): return [i, randf() ** (1.0 / weights[i])]
var random_distribuition = range(len(items)).map(chance_calc)
# Now we just have to order by the calculated value, descending.
random_distribuition.sort_custom(func(a, b): return a[1] > b[1])
return random_distribuition.map(func(dist): return items[dist[0]])
func _get_property_list():
var properties = []
if use_weights:
for key in _weights.keys():
properties.append({
"name": WEIGHTS_PREFIX + key,
"type": TYPE_INT,
"usage": PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR,
"hint": PROPERTY_HINT_RANGE,
"hint_string": "1,100"
})
return properties
func _set(property: StringName, value: Variant) -> bool:
if property.begins_with(WEIGHTS_PREFIX):
var weight_name = property.trim_prefix(WEIGHTS_PREFIX)
_weights[weight_name] = value
return true
return false
func _get(property: StringName):
if property.begins_with(WEIGHTS_PREFIX):
var weight_name = property.trim_prefix(WEIGHTS_PREFIX)
return _weights[weight_name]
return null
func _update_weights(children: Array[Node]) -> void:
var new_weights = {}
for c in children:
if _weights.has(c.name):
new_weights[c.name] = _weights[c.name]
else:
new_weights[c.name] = 1
_weights = new_weights
notify_property_list_changed()
func _on_child_entered_tree(node: Node):
_update_weights(get_children())
var renamed_callable = _on_child_renamed.bind(node.name, node)
if not node.renamed.is_connected(renamed_callable):
node.renamed.connect(renamed_callable)
func _on_child_exiting_tree(node: Node):
var renamed_callable = _on_child_renamed.bind(node.name, node)
if node.renamed.is_connected(renamed_callable):
node.renamed.disconnect(renamed_callable)
var children = get_children()
children.erase(node)
_update_weights(children)
func _on_child_renamed(old_name: String, renamed_child: Node):
if old_name == renamed_child.name:
return # No need to update the weights.
# Disconnect signal with old name...
renamed_child.renamed\
.disconnect(_on_child_renamed.bind(old_name, renamed_child))
# ...and connect with the new name.
renamed_child.renamed\
.connect(_on_child_renamed.bind(renamed_child.name, renamed_child))
var original_weight = _weights[old_name]
_weights.erase(old_name)
_weights[renamed_child.name] = original_weight
notify_property_list_changed()
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"RandomizedComposite")
return classes

View File

@ -0,0 +1,69 @@
## 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:
_cleanup_running_task(c, actor, blackboard)
c.after_run(actor, blackboard)
return SUCCESS
FAILURE:
_cleanup_running_task(c, actor, blackboard)
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:
last_execution_index = 0
super(actor, blackboard)
## Changes `running_action` and `running_child` after the node finishes executing.
func _cleanup_running_task(finished_action: Node, actor: Node, blackboard: Blackboard):
var blackboard_name = str(actor.get_instance_id())
if finished_action == running_child:
running_child = null
if finished_action == blackboard.get_value("running_action", null, blackboard_name):
blackboard.set_value("running_action", null, blackboard_name)
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"SelectorComposite")
return classes

View File

@ -0,0 +1,80 @@
## 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 RandomizedComposite
## A shuffled list of the children that will be executed in reverse order.
var _children_bag: Array[Node] = []
var c: Node
func _ready() -> void:
super()
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:
_reset()
super(actor, blackboard)
func _get_reversed_indexes() -> Array[int]:
var reversed: Array[int]
reversed.assign(range(_children_bag.size()))
reversed.reverse()
return reversed
func _reset() -> void:
var new_order = get_shuffled_children()
_children_bag = new_order.duplicate()
_children_bag.reverse() # It needs to run the children in reverse order.
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,76 @@
## 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:
_cleanup_running_task(c, actor, blackboard)
successful_index += 1
c.after_run(actor, blackboard)
FAILURE:
_cleanup_running_task(c, actor, blackboard)
# 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
## Changes `running_action` and `running_child` after the node finishes executing.
func _cleanup_running_task(finished_action: Node, actor: Node, blackboard: Blackboard):
var blackboard_name = str(actor.get_instance_id())
if finished_action == running_child:
running_child = null
if finished_action == blackboard.get_value("running_action", null, blackboard_name):
blackboard.set_value("running_action", null, blackboard_name)
func get_class_name() -> Array[StringName]:
var classes := super()
classes.push_back(&"SequenceComposite")
return classes

View File

@ -0,0 +1,92 @@
## 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 RandomizedComposite
# Emitted whenever the children are shuffled.
signal reset(new_order: Array[Node])
## 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
## A shuffled list of the children that will be executed in reverse order.
var _children_bag: Array[Node] = []
var c: Node
func _ready() -> void:
super()
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
func _reset() -> void:
var new_order = get_shuffled_children()
_children_bag = new_order.duplicate()
_children_bag.reverse() # It needs to run the children in reverse order.
reset.emit(new_order)
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.5"
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

BIN
bad-dude.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1008 B

34
bad-dude.png.import Normal file
View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://belbhsx23yyd"
path="res://.godot/imported/bad-dude.png-388369b3f83dfa89ce800f1660bac9bb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://bad-dude.png"
dest_files=["res://.godot/imported/bad-dude.png-388369b3f83dfa89ce800f1660bac9bb.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

124
bad_dude.tscn Normal file
View File

@ -0,0 +1,124 @@
[gd_scene load_steps=11 format=3 uid="uid://byuqbh3u5cxqo"]
[ext_resource type="Script" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_von5m"]
[ext_resource type="Script" path="res://addons/beehave/nodes/composites/selector.gd" id="2_tmsoc"]
[ext_resource type="Script" path="res://addons/beehave/nodes/composites/sequence.gd" id="3_wl46j"]
[ext_resource type="Script" path="res://addons/beehave/nodes/leaves/blackboard_has.gd" id="4_m2b65"]
[ext_resource type="Script" path="res://leaves/actions/dude_say.gd" id="5_jwdvu"]
[ext_resource type="Script" path="res://leaves/conditions/eye_condition.gd" id="6_5751j"]
[ext_resource type="Script" path="res://addons/beehave/nodes/leaves/blackboard_set.gd" id="6_pjfxk"]
[ext_resource type="Texture2D" uid="uid://belbhsx23yyd" path="res://bad-dude.png" id="8_67is2"]
[sub_resource type="GDScript" id="GDScript_jijww"]
script/source = "class_name MeanDude
extends Node
@export var blackboard: Blackboard
var visible: Array[Node] = []
func _ready():
$BeehaveTree.blackboard = blackboard
func say_shit(shit):
print(self.name, \": \", shit)
func _on_eyes_body_entered(body):
# simplification of course
if body != get_parent():
visible.append(body)
func _on_eyes_body_exited(body):
if body != get_parent():
visible.erase(body)
"
[sub_resource type="CircleShape2D" id="CircleShape2D_tt36q"]
radius = 31.3847
[node name="BadDude" type="RigidBody2D"]
script = SubResource("GDScript_jijww")
[node name="BeehaveTree" type="Node" parent="."]
script = ExtResource("1_von5m")
actor_node_path = NodePath("..")
[node name="Root" type="Node" parent="BeehaveTree"]
script = ExtResource("2_tmsoc")
[node name="Emergency" type="Node" parent="BeehaveTree/Root"]
script = ExtResource("3_wl46j")
[node name="IsEmergency" type="Node" parent="BeehaveTree/Root/Emergency"]
script = ExtResource("4_m2b65")
key = "\"Emergency\""
[node name="DudePanicing" type="Node" parent="BeehaveTree/Root/Emergency"]
script = ExtResource("5_jwdvu")
shit_to_say = "Firing! Taking heavy fire!"
[node name="HeroSpotted" type="Node" parent="BeehaveTree/Root"]
script = ExtResource("3_wl46j")
[node name="SeeHero" type="Node" parent="BeehaveTree/Root/HeroSpotted"]
script = ExtResource("6_5751j")
looking_for = "Hero"
[node name="Investigation" type="Node" parent="BeehaveTree/Root/HeroSpotted"]
script = ExtResource("3_wl46j")
[node name="WhatWasThat" type="Node" parent="BeehaveTree/Root/HeroSpotted/Investigation"]
script = ExtResource("5_jwdvu")
shit_to_say = "Huh? What was that?"
[node name="Looking" type="Node" parent="BeehaveTree/Root/HeroSpotted/Investigation"]
script = ExtResource("2_tmsoc")
[node name="Found" type="Node" parent="BeehaveTree/Root/HeroSpotted/Investigation/Looking"]
script = ExtResource("3_wl46j")
[node name="SeeHero" type="Node" parent="BeehaveTree/Root/HeroSpotted/Investigation/Looking/Found"]
script = ExtResource("6_5751j")
looking_for = "Hero"
[node name="ReportContact" type="Node" parent="BeehaveTree/Root/HeroSpotted/Investigation/Looking/Found"]
script = ExtResource("5_jwdvu")
shit_to_say = "CONTACT! LOTS OF CONTACT!!"
[node name="PullAlarm" type="Node" parent="BeehaveTree/Root/HeroSpotted/Investigation/Looking/Found"]
script = ExtResource("6_pjfxk")
key = "\"Emergency\""
value = "true"
[node name="MustBeWind" type="Node" parent="BeehaveTree/Root/HeroSpotted/Investigation/Looking"]
script = ExtResource("5_jwdvu")
shit_to_say = "Must have been the wind..."
[node name="ImBored" type="Node" parent="BeehaveTree/Root"]
script = ExtResource("5_jwdvu")
shit_to_say = "What a boring night this is..."
[node name="Sprite" type="Sprite2D" parent="."]
texture_filter = 1
scale = Vector2(2.09614, 2.09614)
texture = ExtResource("8_67is2")
[node name="Body" type="CollisionShape2D" parent="."]
shape = SubResource("CircleShape2D_tt36q")
[node name="Eyes" type="Area2D" parent="."]
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Eyes"]
position = Vector2(0, 1.14396)
scale = Vector2(2.79924, 2.13395)
polygon = PackedVector2Array(12, -12, 96, -59, 96, 60, 12, 11)
[node name="Polygon2D" type="Polygon2D" parent="."]
color = Color(0.929412, 1, 0.458824, 0.239216)
polygon = PackedVector2Array(32, -25, 33, 24, 269, 129, 269, -126)
[connection signal="body_entered" from="Eyes" to="." method="_on_eyes_body_entered"]
[connection signal="body_exited" from="Eyes" to="." method="_on_eyes_body_exited"]

13
hero.gd Normal file
View File

@ -0,0 +1,13 @@
extends RigidBody2D
@export var speed = 200.0
func _physics_process(delta):
if Input.is_action_pressed("up"):
apply_force(Vector2.UP * speed * delta)
if Input.is_action_pressed("down"):
apply_force(Vector2.DOWN * speed * delta)
if Input.is_action_pressed("left"):
apply_force(Vector2.LEFT * speed * delta)
if Input.is_action_pressed("right"):
apply_force(Vector2.RIGHT * speed * delta)

BIN
hero.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

34
hero.png.import Normal file
View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://diju4t0etxyar"
path="res://.godot/imported/hero.png-87aa9197b739ca3ad1031ac3d1b82853.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://hero.png"
dest_files=["res://.godot/imported/hero.png-87aa9197b739ca3ad1031ac3d1b82853.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

View File

@ -0,0 +1,16 @@
class_name DudeSay extends ActionLeaf
@export_multiline var shit_to_say: String
var _timer: SceneTreeTimer
func tick(actor: Node, _blackboard: Blackboard) -> int:
if not _timer:
_timer = get_tree().create_timer(1)
actor.say_shit(shit_to_say)
return RUNNING
elif _timer.time_left > 0:
return RUNNING
else:
_timer = null
return SUCCESS

View File

@ -0,0 +1,6 @@
class_name EyeCondition extends ConditionLeaf
@export var looking_for: String
func tick(actor: Node, blackboard: Blackboard) -> int:
return SUCCESS if actor.visible.any(func(n): return n.name == looking_for) else FAILURE

37
main.tscn Normal file
View File

@ -0,0 +1,37 @@
[gd_scene load_steps=6 format=3 uid="uid://buervcbmbh1dg"]
[ext_resource type="PackedScene" uid="uid://byuqbh3u5cxqo" path="res://bad_dude.tscn" id="2_bghxq"]
[ext_resource type="Script" path="res://hero.gd" id="3_fmhqm"]
[ext_resource type="Texture2D" uid="uid://diju4t0etxyar" path="res://hero.png" id="4_svfrs"]
[ext_resource type="Script" path="res://addons/beehave/blackboard.gd" id="5_6difr"]
[sub_resource type="CircleShape2D" id="CircleShape2D_eiiek"]
radius = 28.7924
[node name="Node2D" type="Node2D"]
[node name="Blackboard" type="Node" parent="."]
script = ExtResource("5_6difr")
[node name="BadDude" parent="." node_paths=PackedStringArray("blackboard") instance=ExtResource("2_bghxq")]
position = Vector2(77, 140)
blackboard = NodePath("../Blackboard")
[node name="BadDude2" parent="." node_paths=PackedStringArray("blackboard") instance=ExtResource("2_bghxq")]
position = Vector2(788, 69)
rotation = 1.56094
blackboard = NodePath("../Blackboard")
[node name="Hero" type="RigidBody2D" parent="."]
position = Vector2(545, 223)
mass = 0.1
script = ExtResource("3_fmhqm")
speed = 2000.0
[node name="Body" type="CollisionShape2D" parent="Hero"]
shape = SubResource("CircleShape2D_eiiek")
[node name="Icon" type="Sprite2D" parent="Hero"]
texture_filter = 1
scale = Vector2(1.21875, 1.21875)
texture = ExtResource("4_svfrs")

52
project.godot Normal file
View File

@ -0,0 +1,52 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="godoit"
run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.1", "Forward Plus")
config/icon="res://icon.svg"
[autoload]
BeehaveGlobalMetrics="*res://addons/beehave/metrics/beehave_global_metrics.gd"
BeehaveGlobalDebugger="*res://addons/beehave/debug/global_debugger.gd"
[editor_plugins]
enabled=PackedStringArray("res://addons/beehave/plugin.cfg")
[input]
up={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
down={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
left={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
right={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
[physics]
2d/default_gravity_vector=Vector2(0, 0)