87 lines
2.7 KiB
GDScript
87 lines
2.7 KiB
GDScript
@tool
|
|
extends Node
|
|
class_name CsgShortcutManager
|
|
|
|
# Provides global key handling for quick CSG creation & operation switching (Layers 1 & 2)
|
|
# Delegates actual creation to the sidebar instance to reuse UndoRedo + material logic.
|
|
|
|
var sidebar: CSGSideToolkitBar
|
|
var config: CsgTkConfig
|
|
|
|
# Mapping shape keycode -> factory id (string used for log / optional future use)
|
|
var _shape_key_map: Dictionary = {
|
|
KEY_B: CSGBox3D,
|
|
KEY_S: CSGSphere3D,
|
|
KEY_C: CSGCylinder3D,
|
|
KEY_T: CSGTorus3D,
|
|
KEY_M: CSGMesh3D,
|
|
KEY_P: CSGPolygon3D,
|
|
}
|
|
|
|
# Layer 2 operation selection numbers
|
|
var _op_number_map: Dictionary = {
|
|
KEY_1: 0, # Union
|
|
KEY_2: 1, # Intersection
|
|
KEY_3: 2, # Subtraction
|
|
}
|
|
|
|
# Optional cycle order
|
|
var _op_cycle: Array = [0,1,2]
|
|
var _cycle_index := 0
|
|
|
|
func _enter_tree():
|
|
set_process_unhandled_key_input(true)
|
|
|
|
func _unhandled_key_input(event: InputEvent):
|
|
if not event is InputEventKey: return
|
|
var ev := event as InputEventKey
|
|
if not ev.pressed or ev.echo: return
|
|
if config == null:
|
|
config = get_tree().root.get_node_or_null(CsgToolkit.AUTOLOAD_NAME) as CsgTkConfig
|
|
if sidebar == null:
|
|
# Try to find existing sidebar if not explicitly set
|
|
var candidates = get_tree().get_nodes_in_group("CSGSideToolkit")
|
|
if candidates.size() > 0:
|
|
sidebar = candidates[0]
|
|
# Prevent interfering with text input fields
|
|
var focus_owner = get_viewport().gui_get_focus_owner()
|
|
if focus_owner and (focus_owner is LineEdit or focus_owner is TextEdit):
|
|
return
|
|
|
|
# Operation & shape shortcuts only trigger when primary action key is held (secondary key reserved for behavior inversion in creation)
|
|
if Input.is_key_pressed(config.action_key):
|
|
if ev.physical_keycode in _op_number_map:
|
|
var op_val = _op_number_map[ev.physical_keycode]
|
|
sidebar.set_operation(op_val)
|
|
_print_feedback("Op -> %s" % _op_label(op_val))
|
|
return
|
|
# Cycle operation with backtick (`) or TAB
|
|
if ev.physical_keycode in [KEY_APOSTROPHE, KEY_QUOTELEFT, KEY_TAB]:
|
|
_cycle_index = (_cycle_index + 1) % _op_cycle.size()
|
|
var cyc_op = _op_cycle[_cycle_index]
|
|
sidebar.set_operation(cyc_op)
|
|
_print_feedback("Op Cycle -> %s" % _op_label(cyc_op))
|
|
return
|
|
# Direct shape create (Layer 1)
|
|
if ev.physical_keycode in _shape_key_map:
|
|
_create_shape(_shape_key_map[ev.physical_keycode])
|
|
return
|
|
|
|
func _create_shape(type_ref: Variant):
|
|
if sidebar == null:
|
|
_print_feedback("No sidebar found for creation")
|
|
return
|
|
# Delegates to sidebar logic (handles operation, insertion mode, UndoRedo, materials)
|
|
sidebar.create_csg(type_ref)
|
|
_print_feedback("Create %s (%s)" % [type_ref, _op_label(sidebar.operation)])
|
|
|
|
func _op_label(op: int) -> String:
|
|
match op:
|
|
0: return "Union"
|
|
1: return "Intersect"
|
|
2: return "Subtract"
|
|
_: return str(op)
|
|
|
|
func _print_feedback(msg: String):
|
|
print("CSG Toolkit: %s" % msg)
|