extends Node2D ## The card class ## ## Represents an instance of a card to be displayed on the tabletop. ## Contains helper text for the text, the cards ID, and the image path. # Card information. var card_id: String var card_name: String var card_type: String var oracle_text: String # Card properties. var tapped: bool # Card input state. var is_focused: bool # Is the card a focus? var is_dragging: bool # Is the card currently being dragged? var mouse_offset: Vector2 func _physics_process(delta: float) -> void: if is_focused: # TODO: Export handling keypresses to its own area. if Input.is_action_just_pressed("MAIN"): tapped = not tapped $TweenController.tap(tapped, delta) if is_dragging: $TweenController.move_to(get_global_mouse_position() - mouse_offset, delta) func _on_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void: if event is not InputEventMouseButton: return match event.button_index: # MOUSE BUTTONS MOUSE_BUTTON_LEFT: if event.pressed: Input.set_default_cursor_shape(Input.CURSOR_DRAG) mouse_offset = get_global_mouse_position() - global_position is_dragging = true else: Input.set_default_cursor_shape(Input.CURSOR_POINTING_HAND) is_dragging = false MOUSE_BUTTON_RIGHT: # TODO: Tooltip menu for right-button clicking on cards. pass func _on_mouse_entered() -> void: # Do not care about mouse entering if we're dragging the card. if is_dragging: return Input.set_default_cursor_shape(Input.CURSOR_POINTING_HAND) $TweenController.scale(1.05) is_focused = true func _on_mouse_exited() -> void: # Do not care about mouse exiting if we're dragging the card. if is_dragging: return Input.set_default_cursor_shape(Input.CURSOR_ARROW) $TweenController.scale(1.0) is_focused = false func _card_error(error_type: String) -> String: return "ERROR::CARD::%s::%s::%s::\n" % [card_id, card_name, error_type] func init(id: String) -> void: card_id = id func _ready() -> void: var load_status = _load_card() if load_status != OK: # TODO: No need to push another error as the failure state of loading does that already, # if the card is not cached, perhaps a placeholder blank card can be used instead? # Setting that up can be put here later... push_error("Failed to load card.") func _load_card() -> Error: if _load_data() != OK: return FAILED if _load_image() != OK: return FAILED return OK func _load_data() -> Error: var cached_json = FileAccess.get_file_as_string("user://card_cache/" + card_id + "/card.json") if cached_json.is_empty(): push_error("%s\nCard json data was not found in cache" % _card_error("CACHE")) return FAILED var card_json = JSON.parse_string(cached_json) if card_json == null: push_error("%s\nCard json data is could not be parsed as valid json" % _card_error("DATA")) return FAILED card_name = card_json["name"] card_type = card_json["type_line"] oracle_text = card_json["oracle_text"] return OK func _load_image() -> Error: # NOTE: Assuming we're going with using the .png cards on board. var cached_img = FileAccess.get_file_as_bytes("user://card_cache/" + card_id + "/card.png") if cached_img.is_empty(): push_error("%sCard on-board image was not found in cache" % _card_error("CACHE")) return FAILED var image = Image.new() var image_status: Error = image.load_png_from_buffer(cached_img) if image_status != OK: push_error("%sCard on-board image failed to load correctly" % _card_error("IMAGE")) return FAILED var size = $Area2D/CollisionShape2D.shape.size image.resize(int(size.x), int(size.y), Image.INTERPOLATE_LANCZOS) var image_texture = ImageTexture.new() image_texture.set_image(image) $Sprite2D.texture = image_texture return OK