diff --git a/Systems/Game/CameraController.gd b/Systems/Game/CameraController.gd new file mode 100644 index 0000000..1299ead --- /dev/null +++ b/Systems/Game/CameraController.gd @@ -0,0 +1,84 @@ +class_name CameraController +extends Node2D + +signal zoom_changed(zoom_level) + +# Camera movement properties +@export var min_zoom: float = 0.5 +@export var max_zoom: float = 2.0 +@export var zoom_step: float = 0.1 +@export var pan_speed: float = 1.0 + +var board_container: Node +var initial_board_position: Vector2 +var initial_board_size: Vector2 + +var current_zoom: float = 1.0 +var dragging: bool = false +var drag_start_position: Vector2 + +func _init(target_board: Node) -> void: + board_container = target_board + +func _ready() -> void: + initial_board_position = board_container.position + if board_container.has_method("get_combined_minimum_size"): + initial_board_size = board_container.get_combined_minimum_size() + else: + initial_board_size = board_container.size + + current_zoom = 1.0 + board_container.scale = Vector2(current_zoom, current_zoom) + + adjust_pivot() + +func adjust_pivot() -> void: + var center = initial_board_size / 2 + board_container.pivot_offset = center + +func _input(event: InputEvent) -> void: + if event is InputEventMouseButton: + if event.button_index == MOUSE_BUTTON_WHEEL_UP: + zoom_in(event.position) + elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: + zoom_out(event.position) + elif event.button_index == MOUSE_BUTTON_MIDDLE: + if event.pressed: + start_drag(event.position) + else: + end_drag() + + if event is InputEventMouseMotion and dragging: + update_drag(event.position) + +func zoom_in(mouse_pos: Vector2) -> void: + if current_zoom < max_zoom: + apply_zoom(current_zoom + zoom_step) + +func zoom_out(mouse_pos: Vector2) -> void: + if current_zoom > min_zoom: + apply_zoom(current_zoom - zoom_step) + +func apply_zoom(new_zoom: float) -> void: + current_zoom = new_zoom + board_container.scale = Vector2(current_zoom, current_zoom) + + emit_signal("zoom_changed", current_zoom) + +func start_drag(position: Vector2) -> void: + dragging = true + drag_start_position = position + +func end_drag() -> void: + dragging = false + +func update_drag(position: Vector2) -> void: + if dragging: + var delta = position - drag_start_position + board_container.position += delta * pan_speed + drag_start_position = position + +func reset_view() -> void: + current_zoom = 1.0 + board_container.scale = Vector2(current_zoom, current_zoom) + board_container.position = initial_board_position \ No newline at end of file diff --git a/Systems/Game/ChessGame.gd b/Systems/Game/ChessGame.gd index a1a702f..49b5f89 100644 --- a/Systems/Game/ChessGame.gd +++ b/Systems/Game/ChessGame.gd @@ -34,6 +34,7 @@ var stockfishPath = "res://Assets/ChessEngines/stockfish/stockfish.exe" @onready var p2String: RichTextLabel = $Player2Points @onready var deckManager: DeckManager @onready var tileManager: TileManager +@onready var cameraController: CameraController @onready var cardDisplay: CardDisplay @onready var cardPreview: CardPreview @@ -89,32 +90,56 @@ func initializeTiles() -> void: func get_base_style(is_white: bool) -> StyleBoxFlat: return lightStyle if is_white else darkStyle + func _unhandled_input(event: InputEvent) -> void: stateMachine.unhandledInput(event) + if event is InputEventKey: + if event.pressed: + if event.keycode == KEY_EQUAL or event.keycode == KEY_PLUS: # Zoom in with + key + cameraController.zoom_in(get_viewport().get_mouse_position()) + elif event.keycode == KEY_MINUS: # Zoom out with - key + cameraController.zoom_out(get_viewport().get_mouse_position()) + elif event.keycode == KEY_R: # Reset view with R key + cameraController.reset_view() + func _process(delta: float) -> void: stateMachine.process(delta) func initializeGame() -> void: setupStyles() - setupUI() initializeDeckSystem() initializeCardPreview() initializeBoard() + setupCameraController() + setupUI() func initializeCardPreview() -> void: cardPreview = CardPreview.new() add_child(cardPreview) + +func setupCameraController() -> void: + cameraController = CameraController.new(boardContainer) + cameraController.name = "CameraController" + add_child(cameraController) + + cameraController.zoom_changed.connect(_on_zoom_changed) + + +func _on_zoom_changed(zoom_level: float) -> void: + # manuall adjustements try to avoid + pass + + func getSpecialTilesFen() -> String: if tileManager.active_tiles.is_empty(): return "" var special_fen = " moves" - var portal_pairs = {} # Dictionary to track portal pairs by pair_id + var portal_pairs = {} - # First pass: Collect portal pairs for pos in tileManager.active_tiles: var tile = tileManager.active_tiles[pos] if tile is PortalTile: @@ -249,8 +274,39 @@ func setupUI() -> void: p1String.text = "0" p2String.text = "0" updateTurnIndicator() + + # Create control buttons + var zoom_in_button = Button.new() + zoom_in_button.text = "+" + zoom_in_button.size = Vector2(30, 30) + zoom_in_button.pressed.connect(func(): cameraController.zoom_in(zoom_in_button.global_position)) + + var zoom_out_button = Button.new() + zoom_out_button.text = "-" + zoom_out_button.size = Vector2(30, 30) + zoom_out_button.pressed.connect(func(): cameraController.zoom_out(zoom_out_button.global_position)) + + var reset_button = Button.new() + reset_button.text = "Reset View" + reset_button.size = Vector2(100, 30) + reset_button.pressed.connect(func(): cameraController.reset_view()) + + var control_container = VBoxContainer.new() + control_container.name = "ZoomControls" + + control_container.position = Vector2(windowXSize - 350, windowYSize - 120) + + var h_container = HBoxContainer.new() + h_container.add_child(zoom_out_button) + h_container.add_child(zoom_in_button) + + control_container.add_child(h_container) + control_container.add_child(reset_button) + + # Add the container to the scene + add_child(control_container) - + func initializeDeckSystem() -> void: deckManager = DeckManager.new() cardDisplay = CardDisplay.new() diff --git a/addons/Chess/Scripts/Pawn.gd b/addons/Chess/Scripts/Pawn.gd index 6972674..fef61b4 100644 --- a/addons/Chess/Scripts/Pawn.gd +++ b/addons/Chess/Scripts/Pawn.gd @@ -46,10 +46,10 @@ func _init(chess: ChessGame) -> void: func update_appearance() -> void: # print("update_appearance") - if !is_instance_valid(get_tree()) || !get_tree().get_root().has_node("Board"): + var chess_game = game + if !is_instance_valid(get_tree()) || !chess_game: return - var chess_game = get_tree().get_root().get_node("Board") if !chess_game.deckManager: return diff --git a/board.tscn b/board.tscn index 30ec2ba..9dc6a39 100644 --- a/board.tscn +++ b/board.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=17 format=3 uid="uid://d0qyk6v20uief"] +[gd_scene load_steps=18 format=3 uid="uid://d0qyk6v20uief"] [ext_resource type="Script" path="res://Systems/Game/ChessGame.gd" id="1_fkb2r"] [ext_resource type="Script" path="res://Systems/StateMachine/GameStates/WhiteTurn.gd" id="3_276ip"] @@ -16,6 +16,7 @@ [ext_resource type="Script" path="res://Systems/StateMachine/GameStates/EvaluatePosition.gd" id="14_icem8"] [ext_resource type="Script" path="res://Systems/StateMachine/GameStates/CleanupPhase.gd" id="15_m58r8"] [ext_resource type="Script" path="res://Systems/StateMachine/GameStates/RoundEnd.gd" id="16_8h5do"] +[ext_resource type="Script" path="res://Systems/Game/CameraController.gd" id="17_1epdx"] [node name="Board" type="Control"] layout_mode = 3 @@ -151,3 +152,6 @@ game = NodePath("../..") [node name="RoundEnd" type="Node" parent="StateMachine" node_paths=PackedStringArray("game")] script = ExtResource("16_8h5do") game = NodePath("../..") + +[node name="CameraController" type="Node2D" parent="."] +script = ExtResource("17_1epdx")