extends Control # TrapezoidSwatch.gd (manual-drag version) # The trapezoid node ITSELF follows the cursor while dragging (no ghost). # On release over the board, it tells DropCatcher to paint the hit segment, # then asks the tray to consume the round's modifiers. @export var paint_texture: Texture2D: set(value): paint_texture = value queue_redraw() @export_range(0.0, 1.0) var top_width_ratio := 0.55 # Set by the tray when it spawns this piece. var drop_catcher: Control # the DropCatcher node (does the 3D raycast+paint) var tray: Node # the ModifierTray (so we can consume on use) # The full modifier this piece carries (texture + title + scoring rule). var modifier: Resource var _dragging := false var _home_position := Vector2.ZERO # where it sits in the tray var _drag_offset := Vector2.ZERO # cursor-to-corner offset so it doesn't snap func _ready() -> void: mouse_filter = Control.MOUSE_FILTER_STOP if custom_minimum_size == Vector2.ZERO: custom_minimum_size = Vector2(90, 110) size = custom_minimum_size func _draw() -> void: var w := size.x var h := size.y var inset := w * (1.0 - top_width_ratio) * 0.5 var points := PackedVector2Array([ Vector2(inset, 0), Vector2(w - inset, 0), Vector2(w, h), Vector2(0, h), ]) if paint_texture != null: var uvs := PackedVector2Array([ Vector2(inset / w, 0), Vector2((w - inset) / w, 0), Vector2(1, 1), Vector2(0, 1), ]) draw_polygon(points, PackedColorArray([Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE]), uvs, paint_texture) else: draw_colored_polygon(points, Color(0.8, 0.8, 0.8)) var outline := points outline.append(points[0]) draw_polyline(outline, Color(0, 0, 0, 0.6), 2.0) func _gui_input(event: InputEvent) -> void: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: if event.pressed: _start_drag() else: _end_drag() func _start_drag() -> void: _dragging = true _home_position = global_position _drag_offset = global_position - get_global_mouse_position() # top_level lets us move by global_position freely, ignoring the container # layout, WITHOUT reparenting (reparenting mid-drag breaks the release event). top_level = true z_index = 100 # float above everything during drag modulate.a = 0.85 func _end_drag() -> void: if not _dragging: return _dragging = false modulate.a = 1.0 z_index = 0 # Ask the DropCatcher to try painting wherever we released. var painted := false print("PIECE released. drop_catcher=", drop_catcher, " modifier=", modifier) if drop_catcher == null: push_error("Piece has no drop_catcher reference! (tray export not set?)") elif not drop_catcher.has_method("apply_modifier_at_screen_pos"): push_error("drop_catcher has no apply_modifier_at_screen_pos method.") else: painted = drop_catcher.apply_modifier_at_screen_pos(get_global_mouse_position(), modifier) if painted: # Used successfully: consume this round's modifier choices. if tray and tray.has_method("consume"): tray.consume() else: queue_free() else: # Missed the board: snap back home. top_level = false global_position = _home_position func _process(_delta: float) -> void: if _dragging: global_position = get_global_mouse_position() + _drag_offset