Code stuff

This commit is contained in:
Melody Becker 2025-01-26 20:23:56 +01:00
parent cf22890c16
commit e58093b5a5
Signed by: mstar
SSH key fingerprint: SHA256:vkXfS9FG2pVNVfvDrzd1VW9n8VJzqqdKQGljxxX8uK8
153 changed files with 11196 additions and 4 deletions

View file

@ -0,0 +1,159 @@
@tool
extends Control
signal item_selected(index)
signal item_focused(index)
signal item_cancelled()
const button_margin = 6
@export var items := [] : set = set_items
@export var selected_index = -1 : set = set_selected_index
@export var radius = 100.0 : set = set_radius
var buttons = []
var pie_menus = []
var focused_index = -1
var theme_source_node = self : set = set_theme_source_node
var grow_with_max_button_width = false
func _ready():
set_items(items)
set_selected_index(selected_index)
set_radius(radius)
hide()
connect("visibility_changed", _on_visiblity_changed)
func _input(event):
if visible:
if event is InputEventKey:
if event.pressed:
match event.keycode:
KEY_ESCAPE:
cancel()
if event is InputEventMouseMotion:
focus_item()
get_viewport().set_input_as_handled()
if event is InputEventMouseButton:
if event.pressed:
match event.button_index:
MOUSE_BUTTON_LEFT:
select_item(focused_index)
get_viewport().set_input_as_handled()
MOUSE_BUTTON_RIGHT:
cancel()
get_viewport().set_input_as_handled()
func _on_visiblity_changed():
if not visible:
if selected_index != focused_index: # Cancellation
focused_index = selected_index
func cancel():
hide()
get_viewport().set_input_as_handled()
emit_signal("item_cancelled")
func select_item(index):
set_button_style(selected_index, "normal", "normal")
selected_index = index
focused_index = selected_index
hide()
emit_signal("item_selected", selected_index)
func focus_item():
queue_redraw()
var pos = get_global_mouse_position()
var count = max(buttons.size(), 1)
var angle_offset = 2 * PI / count
var angle = pos.angle_to_point(global_position) + PI / 2 # -90 deg initial offset
if angle < 0:
angle += 2 * PI
var index = (angle / angle_offset)
var decimal = index - floor(index)
index = floor(index)
if decimal >= 0.5:
index += 1
if index > buttons.size()-1:
index = 0
set_button_style(focused_index, "normal", "normal")
focused_index = index
set_button_style(focused_index, "normal", "hover")
set_button_style(selected_index, "normal", "focus")
emit_signal("item_focused", focused_index)
func popup(pos):
global_position = pos
show()
func populate_menu():
clear_menu()
buttons = []
for i in items.size():
var item = items[i]
var is_array = item is Array
var name = item if not is_array else item[0]
var value = null if not is_array else item[1]
var button = Button.new()
button.grow_horizontal = Control.GROW_DIRECTION_BOTH
button.text = name
if value != null:
button.set_meta("value", value)
buttons.append(button)
set_button_style(i, "hover", "hover")
set_button_style(i, "pressed", "pressed")
set_button_style(i, "focus", "focus")
set_button_style(i, "disabled", "disabled")
set_button_style(i, "normal", "normal")
add_child(button)
align()
set_button_style(selected_index, "normal", "focus")
func align():
var final_radius = radius
if grow_with_max_button_width:
var max_button_width = 0.0
for button in buttons:
max_button_width = max(max_button_width, button.size.x)
final_radius = max(radius, max_button_width)
var count = max(buttons.size(), 1)
var angle_offset = 2 * PI / count
var angle = PI / 2 # 90 deg initial offset
for button in buttons:
button.position = Vector2(final_radius, 0.0).rotated(angle) - (button.size / 2.0)
angle += angle_offset
func clear_menu():
for button in buttons:
button.queue_free()
func set_button_style(index, name, source):
if index < 0 or index > buttons.size() - 1:
return
buttons[index].set("theme_override_styles/%s" % name, get_theme_stylebox(source, "Button"))
func set_items(v):
items = v
if is_inside_tree():
populate_menu()
func set_selected_index(v):
set_button_style(selected_index, "normal", "normal")
selected_index = v
set_button_style(selected_index, "normal", "focus")
func set_radius(v):
radius = v
align()
func set_theme_source_node(v):
theme_source_node = v
for pie_menu in pie_menus:
if pie_menu:
pie_menu.theme_source_node = theme_source_node

View file

@ -0,0 +1,11 @@
[gd_scene load_steps=2 format=3 uid="uid://bxummco35581e"]
[ext_resource type="Script" path="res://addons/gd-blender-3d-shortcuts/scenes/pie_menu/PieMenu.gd" id="1"]
[node name="PieMenu" type="Control"]
visible = false
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource("1")

View file

@ -0,0 +1,113 @@
@tool
extends Control
const PieMenuScn = preload("PieMenu.tscn")
signal item_focused(menu, index)
signal item_selected(menu, index)
signal item_cancelled(menu)
var root
var page_index = [0]
var theme_source_node = self : set = set_theme_source_node
func _ready():
hide()
func _on_item_cancelled(pie_menu):
back()
emit_signal("item_cancelled", pie_menu)
func _on_item_focused(index, pie_menu):
var current_menu = get_current_menu()
if current_menu == pie_menu:
emit_signal("item_focused", current_menu, index)
func _on_item_selected(index):
var last_menu = get_current_menu()
page_index.append(index)
var current_menu = get_current_menu()
if current_menu:
current_menu.selected_index = -1
if current_menu.pie_menus.size() > 0: # Has next page
current_menu.popup(global_position)
else:
# Final selection, revert page index
if page_index.size() > 1:
page_index.pop_back()
last_menu = get_current_menu()
page_index = [0]
hide()
emit_signal("item_selected", last_menu, index)
func popup(pos):
global_position = pos
var pie_menu = get_current_menu()
pie_menu.popup(global_position)
show()
func populate_menu(items, pie_menu):
add_child(pie_menu)
if not root:
root = pie_menu
root.connect("item_focused", _on_item_focused.bind(pie_menu))
root.connect("item_selected", _on_item_selected)
root.connect("item_cancelled", _on_item_cancelled.bind(pie_menu))
pie_menu.items = items
for i in items.size():
var item = items[i]
var is_array = item is Array
# var name = item if not is_array else item[0]
var value = null if not is_array else item[1]
if value is Array:
var new_pie_menu = PieMenuScn.instantiate()
new_pie_menu.connect("item_focused", _on_item_focused.bind(new_pie_menu))
new_pie_menu.connect("item_selected", _on_item_selected)
new_pie_menu.connect("item_cancelled", _on_item_cancelled.bind(new_pie_menu))
populate_menu(value, new_pie_menu)
pie_menu.pie_menus.append(new_pie_menu)
else:
pie_menu.pie_menus.append(null)
return pie_menu
func clear_menu():
if root:
root.queue_free()
func back():
var last_menu = get_current_menu()
last_menu.hide()
page_index.pop_back()
if page_index.size() == 0:
page_index = [0]
hide()
return
else:
var current_menu = get_current_menu()
if current_menu:
current_menu.popup(global_position)
func get_menu(indexes=[0]):
var pie_menu = root
for i in indexes.size():
if i == 0:
continue # root
var page = indexes[i]
pie_menu = pie_menu.pie_menus[page]
return pie_menu
func get_current_menu():
return get_menu(page_index)
func set_theme_source_node(v):
theme_source_node = v
if not root:
return
for pie_menu in root.pie_menus:
if pie_menu:
pie_menu.theme_source_node = theme_source_node

View file

@ -0,0 +1,13 @@
[gd_scene load_steps=2 format=3 uid="uid://c4cfbaj52t05b"]
[ext_resource type="Script" path="res://addons/gd-blender-3d-shortcuts/scenes/pie_menu/PieMenuGroup.gd" id="1"]
[node name="PieMenuGroup" type="Control"]
visible = false
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1")