# Add or modify this in your CardVisual.gd script extends Control class_name NodePopup signal pressed(id) # Node references @onready var card_container = $CardContainer @onready var name_label = $CardContainer/VBoxContainer/NameLabel @onready var desc_label = $CardContainer/VBoxContainer/DescriptionLabel @onready var enter_btn = $CardContainer/VBoxContainer/HBoxContainer/EnterButton @onready var close_btn = $CardContainer/VBoxContainer/HBoxContainer/CloseButton var node_id = null; var animation_tween func _ready(): mouse_filter = Control.MOUSE_FILTER_STOP gui_input.connect(_on_gui_input) if card_container: card_container.mouse_filter = Control.MOUSE_FILTER_PASS for child in get_children(): if child is Control: child.mouse_filter = Control.MOUSE_FILTER_PASS if enter_btn: enter_btn.connect("pressed", Callable(self, "_on_enter_button_pressed")) if close_btn: close_btn.connect("pressed", Callable(self, "_on_close_button_pressed")) card_container.visible = false # Setup initial scale for animation card_container.scale = Vector2(0.8, 0.8) set_process_input(true) func set_card(id:int, name: String, desc: String): if id == null: card_container.visible = false return node_id = id card_container.visible = true name_label.text = name desc_label.text = desc # Animate popup appearance if animation_tween: animation_tween.kill() animation_tween = create_tween() animation_tween.tween_property(card_container, "scale", Vector2(1.0, 1.0), 0.2).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK) # Make sure popup is fully visible on screen call_deferred("ensure_on_screen") func ensure_on_screen(): await get_tree().process_frame # Get viewport size var viewport_size = get_viewport_rect().size # Get popup global position and size var popup_rect = Rect2(global_position, card_container.size) # Adjust if off-screen if popup_rect.position.x < 0: global_position.x = 10 elif popup_rect.position.x + popup_rect.size.x > viewport_size.x: global_position.x = viewport_size.x - popup_rect.size.x - 10 if popup_rect.position.y < 0: global_position.y = 10 elif popup_rect.position.y + popup_rect.size.y > viewport_size.y: global_position.y = viewport_size.y - popup_rect.size.y - 10 func _on_gui_input(event): if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_LEFT and event.pressed: var tween = create_tween() tween.tween_property(card_container, "scale", Vector2(1.05, 1.05), 0.1) tween.tween_property(card_container, "scale", Vector2(1.0, 1.0), 0.1) # Handle dragging the popup var dragging = false var drag_start_pos = Vector2() func _input(event): if not visible or not card_container.visible: return if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_LEFT: if event.pressed: # Check if mouse is over the card container var local_mouse_pos = get_local_mouse_position() if card_container.get_rect().has_point(local_mouse_pos): dragging = true drag_start_pos = local_mouse_pos - card_container.position else: dragging = false elif event is InputEventMouseMotion and dragging: card_container.position = get_local_mouse_position() - drag_start_pos func _on_enter_button_pressed(): # Add a confirmation animation before closing var tween = create_tween() tween.tween_property(card_container, "scale", Vector2(1.1, 1.1), 0.1) tween.tween_property(card_container, "scale", Vector2(0.8, 0.8), 0.2) tween.tween_callback(func(): _confirm_selection()) func _disable_enter(): enter_btn.disabled = true; func _enable_enter(): enter_btn.disabled = false; func _confirm_selection(): emit_signal("pressed", node_id) card_container.visible = false visible = false func _on_close_button_pressed(): # Add a closing animation var tween = create_tween() tween.tween_property(card_container, "scale", Vector2(0.8, 0.8), 0.2) tween.tween_callback(func(): _cancel_selection()) func _cancel_selection(): emit_signal("pressed", null) card_container.visible = false visible = false