@tool extends PanelContainer class_name StateDropArea signal node_dropped(node: Node) @export var icon_path: NodePath = NodePath("TextureRect") const COLOR_IDLE: Color = Color(1, 1, 1, 1.0) const COLOR_CAN_DROP: Color = Color(0.4, 0.7, 1.0, 1.0) const COLOR_CANNOT_DROP: Color = Color(1.0, 0.35, 0.35, 1.0) const COLOR_CHECKED: Color = Color.GREEN var _icon: TextureRect var _state := 0 # 0 idle, 1 can, 2 cannot var _current_drag_data: Variant = null signal node_path_dropped(node_path: NodePath) # ===================================================== # Life cycle # ===================================================== func _ready() -> void: _icon = get_node_or_null(icon_path) as TextureRect mouse_filter = Control.MOUSE_FILTER_PASS _ignore_mouse_recursive(self) if _icon: _icon.modulate = COLOR_IDLE if custom_minimum_size == Vector2.ZERO: custom_minimum_size = Vector2(32, 32) #mouse_entered.connect(_on_mouse_entered) mouse_exited.connect(_on_mouse_exited) # ===================================================== # Drag & Drop # ===================================================== func _can_drop_data(_pos: Vector2, data) -> bool: _current_drag_data = data var r = StateResolveUtils.is_valid_state_drag(data) _set_state(1 if r else 2) return r func _drop_data(_pos: Vector2, data) -> void: var path := StateResolveUtils.get_state_path_from_drag(data) if path.is_empty(): return node_path_dropped.emit(path) func _notification(what: int) -> void: if what == NOTIFICATION_DRAG_END: _current_drag_data = null _set_state(0) # ===================================================== # Mouse events # ===================================================== func _on_mouse_exited() -> void: _set_state(0) func _ignore_mouse_recursive(n: Node) -> void: for c in n.get_children(): if c is Control: (c as Control).mouse_filter = Control.MOUSE_FILTER_IGNORE _ignore_mouse_recursive(c) func _set_state(s: int) -> void: if s == _state: return _state = s if _icon == null: return match _state: 0: _icon.modulate = COLOR_IDLE 1: _icon.modulate = COLOR_CAN_DROP 2: _icon.modulate = COLOR_CANNOT_DROP 3: _icon.modulate = COLOR_CHECKED