Add gdlint and gdformat scripts
This commit is contained in:
@@ -10,14 +10,19 @@ const GAMEPLAY_SCENES = {
|
||||
@onready var score_display: Label = $UI/ScoreDisplay
|
||||
|
||||
var current_gameplay_mode: String
|
||||
var global_score: int = 0 : set = set_global_score
|
||||
var global_score: int = 0:
|
||||
set = set_global_score
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not back_button.pressed.is_connected(_on_back_button_pressed):
|
||||
back_button.pressed.connect(_on_back_button_pressed)
|
||||
|
||||
# GameManager will set the gameplay mode, don't set default here
|
||||
DebugManager.log_debug("Game _ready() completed, waiting for GameManager to set gameplay mode", "Game")
|
||||
DebugManager.log_debug(
|
||||
"Game _ready() completed, waiting for GameManager to set gameplay mode", "Game"
|
||||
)
|
||||
|
||||
|
||||
func set_gameplay_mode(mode: String) -> void:
|
||||
DebugManager.log_info("set_gameplay_mode called with mode: %s" % mode, "Game")
|
||||
@@ -25,6 +30,7 @@ func set_gameplay_mode(mode: String) -> void:
|
||||
await load_gameplay(mode)
|
||||
DebugManager.log_info("set_gameplay_mode completed for mode: %s" % mode, "Game")
|
||||
|
||||
|
||||
func load_gameplay(mode: String) -> void:
|
||||
DebugManager.log_debug("Loading gameplay mode: %s" % mode, "Game")
|
||||
|
||||
@@ -38,7 +44,10 @@ func load_gameplay(mode: String) -> void:
|
||||
|
||||
# Wait for children to be properly removed from scene tree
|
||||
await get_tree().process_frame
|
||||
DebugManager.log_debug("Children removal complete, container count: %d" % gameplay_container.get_child_count(), "Game")
|
||||
DebugManager.log_debug(
|
||||
"Children removal complete, container count: %d" % gameplay_container.get_child_count(),
|
||||
"Game"
|
||||
)
|
||||
|
||||
# Load new gameplay
|
||||
if GAMEPLAY_SCENES.has(mode):
|
||||
@@ -47,7 +56,13 @@ func load_gameplay(mode: String) -> void:
|
||||
var gameplay_instance = gameplay_scene.instantiate()
|
||||
DebugManager.log_debug("Instantiated gameplay: %s" % gameplay_instance.name, "Game")
|
||||
gameplay_container.add_child(gameplay_instance)
|
||||
DebugManager.log_debug("Added gameplay to container, child count now: %d" % gameplay_container.get_child_count(), "Game")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Added gameplay to container, child count now: %d"
|
||||
% gameplay_container.get_child_count()
|
||||
),
|
||||
"Game"
|
||||
)
|
||||
|
||||
# Connect gameplay signals to shared systems
|
||||
if gameplay_instance.has_signal("score_changed"):
|
||||
@@ -56,23 +71,28 @@ func load_gameplay(mode: String) -> void:
|
||||
else:
|
||||
DebugManager.log_error("Gameplay mode '%s' not found in GAMEPLAY_SCENES" % mode, "Game")
|
||||
|
||||
|
||||
func set_global_score(value: int) -> void:
|
||||
global_score = value
|
||||
if score_display:
|
||||
score_display.text = "Score: " + str(global_score)
|
||||
|
||||
|
||||
func _on_score_changed(points: int) -> void:
|
||||
self.global_score += points
|
||||
SaveManager.update_current_score(self.global_score)
|
||||
|
||||
|
||||
func get_global_score() -> int:
|
||||
return global_score
|
||||
|
||||
|
||||
func _get_current_gameplay_instance() -> Node:
|
||||
if gameplay_container.get_child_count() > 0:
|
||||
return gameplay_container.get_child(0)
|
||||
return null
|
||||
|
||||
|
||||
func _on_back_button_pressed() -> void:
|
||||
DebugManager.log_debug("Back button pressed in game scene", "Game")
|
||||
AudioManager.play_ui_click()
|
||||
@@ -91,6 +111,7 @@ func _on_back_button_pressed() -> void:
|
||||
SaveManager.finish_game(global_score)
|
||||
GameManager.exit_to_main_menu()
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("ui_back"):
|
||||
# Handle gamepad/keyboard back action - same as back button
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
extends DebugMenuBase
|
||||
|
||||
|
||||
func _ready():
|
||||
# Set specific configuration for Match3DebugMenu
|
||||
log_category = "Match3"
|
||||
@@ -15,6 +16,7 @@ func _ready():
|
||||
if current_debug_state:
|
||||
_on_debug_toggled(true)
|
||||
|
||||
|
||||
func _find_target_scene():
|
||||
# Debug menu is now: Match3 -> UILayer -> Match3DebugMenu
|
||||
# So we need to go up two levels: get_parent() = UILayer, get_parent().get_parent() = Match3
|
||||
@@ -25,7 +27,15 @@ func _find_target_scene():
|
||||
var script_path = potential_match3.get_script().resource_path
|
||||
if script_path == target_script_path:
|
||||
match3_scene = potential_match3
|
||||
DebugManager.log_debug("Found match3 scene: " + match3_scene.name + " at path: " + str(match3_scene.get_path()), log_category)
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Found match3 scene: "
|
||||
+ match3_scene.name
|
||||
+ " at path: "
|
||||
+ str(match3_scene.get_path())
|
||||
),
|
||||
log_category
|
||||
)
|
||||
_update_ui_from_scene()
|
||||
_stop_search_timer()
|
||||
return
|
||||
|
||||
@@ -2,6 +2,7 @@ extends Node2D
|
||||
|
||||
signal score_changed(points: int)
|
||||
|
||||
|
||||
func _ready():
|
||||
DebugManager.log_info("Clickomania gameplay loaded", "Clickomania")
|
||||
# Example: Add some score after a few seconds to test the system
|
||||
|
||||
@@ -3,12 +3,7 @@ extends Node2D
|
||||
signal score_changed(points: int)
|
||||
signal grid_state_loaded(grid_size: Vector2i, tile_types: int)
|
||||
|
||||
enum GameState {
|
||||
WAITING, # Waiting for player input
|
||||
SELECTING, # First tile selected
|
||||
SWAPPING, # Animating tile swap
|
||||
PROCESSING # Processing matches and cascades
|
||||
}
|
||||
enum GameState { WAITING, SELECTING, SWAPPING, PROCESSING } # Waiting for player input # First tile selected # Animating tile swap # Processing matches and cascades
|
||||
|
||||
var GRID_SIZE := Vector2i(8, 8)
|
||||
var TILE_TYPES := 5
|
||||
@@ -32,22 +27,26 @@ const CASCADE_WAIT_TIME := 0.1
|
||||
const SWAP_ANIMATION_TIME := 0.3
|
||||
const TILE_DROP_WAIT_TIME := 0.2
|
||||
|
||||
var grid := []
|
||||
var grid: Array[Array] = []
|
||||
var tile_size: float = 48.0
|
||||
var grid_offset: Vector2
|
||||
var grid_offset: Vector2 = Vector2.ZERO
|
||||
var current_state: GameState = GameState.WAITING
|
||||
var selected_tile: Node2D = null
|
||||
var cursor_position: Vector2i = Vector2i(0, 0)
|
||||
var keyboard_navigation_enabled: bool = false
|
||||
var grid_initialized: bool = false
|
||||
var instance_id: String
|
||||
var instance_id: String = ""
|
||||
|
||||
func _ready():
|
||||
|
||||
func _ready() -> void:
|
||||
# Generate instance ID
|
||||
instance_id = "Match3_%d" % get_instance_id()
|
||||
|
||||
if grid_initialized:
|
||||
DebugManager.log_warn("[%s] Match3 _ready() called multiple times, skipping initialization" % instance_id, "Match3")
|
||||
DebugManager.log_warn(
|
||||
"[%s] Match3 _ready() called multiple times, skipping initialization" % instance_id,
|
||||
"Match3"
|
||||
)
|
||||
return
|
||||
|
||||
DebugManager.log_debug("[%s] Match3 _ready() started" % instance_id, "Match3")
|
||||
@@ -72,6 +71,7 @@ func _ready():
|
||||
# Debug: Check scene tree structure
|
||||
call_deferred("_debug_scene_structure")
|
||||
|
||||
|
||||
func _calculate_grid_layout():
|
||||
var viewport_size = get_viewport().get_visible_rect().size
|
||||
var available_width = viewport_size.x * SCREEN_WIDTH_USAGE
|
||||
@@ -85,13 +85,13 @@ func _calculate_grid_layout():
|
||||
# Align grid to left side with margins
|
||||
var total_grid_height = tile_size * GRID_SIZE.y
|
||||
grid_offset = Vector2(
|
||||
GRID_LEFT_MARGIN,
|
||||
(viewport_size.y - total_grid_height) / 2 + GRID_TOP_MARGIN
|
||||
GRID_LEFT_MARGIN, (viewport_size.y - total_grid_height) / 2 + GRID_TOP_MARGIN
|
||||
)
|
||||
|
||||
|
||||
func _initialize_grid():
|
||||
# Create gem pool for current tile types
|
||||
var gem_indices = []
|
||||
var gem_indices: Array[int] = []
|
||||
for i in range(TILE_TYPES):
|
||||
gem_indices.append(i)
|
||||
|
||||
@@ -113,9 +113,16 @@ func _initialize_grid():
|
||||
|
||||
# Connect tile signals
|
||||
tile.tile_selected.connect(_on_tile_selected)
|
||||
DebugManager.log_debug("Created tile at grid(%d,%d) world_pos(%s) with type %d" % [x, y, tile_position, new_type], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Created tile at grid(%d,%d) world_pos(%s) with type %d"
|
||||
% [x, y, tile_position, new_type]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
grid[y].append(tile)
|
||||
|
||||
|
||||
func _has_match_at(pos: Vector2i) -> bool:
|
||||
# Bounds and null checks
|
||||
if not _is_valid_grid_position(pos):
|
||||
@@ -131,7 +138,9 @@ func _has_match_at(pos: Vector2i) -> bool:
|
||||
|
||||
# Check if tile has required properties
|
||||
if not "tile_type" in tile:
|
||||
DebugManager.log_warn("Tile at (%d,%d) missing tile_type property" % [pos.x, pos.y], "Match3")
|
||||
DebugManager.log_warn(
|
||||
"Tile at (%d,%d) missing tile_type property" % [pos.x, pos.y], "Match3"
|
||||
)
|
||||
return false
|
||||
|
||||
var matches_horizontal = _get_match_line(pos, Vector2i(1, 0))
|
||||
@@ -141,6 +150,7 @@ func _has_match_at(pos: Vector2i) -> bool:
|
||||
var matches_vertical = _get_match_line(pos, Vector2i(0, 1))
|
||||
return matches_vertical.size() >= 3
|
||||
|
||||
|
||||
# Check for any matches on the board
|
||||
func _check_for_matches() -> bool:
|
||||
for y in range(GRID_SIZE.y):
|
||||
@@ -149,14 +159,19 @@ func _check_for_matches() -> bool:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _get_match_line(start: Vector2i, dir: Vector2i) -> Array:
|
||||
# Validate input parameters
|
||||
if not _is_valid_grid_position(start):
|
||||
DebugManager.log_error("Invalid start position for match line: (%d,%d)" % [start.x, start.y], "Match3")
|
||||
DebugManager.log_error(
|
||||
"Invalid start position for match line: (%d,%d)" % [start.x, start.y], "Match3"
|
||||
)
|
||||
return []
|
||||
|
||||
if abs(dir.x) + abs(dir.y) != 1 or (dir.x != 0 and dir.y != 0):
|
||||
DebugManager.log_error("Invalid direction vector for match line: (%d,%d)" % [dir.x, dir.y], "Match3")
|
||||
DebugManager.log_error(
|
||||
"Invalid direction vector for match line: (%d,%d)" % [dir.x, dir.y], "Match3"
|
||||
)
|
||||
return []
|
||||
|
||||
# Check grid bounds and tile validity
|
||||
@@ -194,6 +209,7 @@ func _get_match_line(start: Vector2i, dir: Vector2i) -> Array:
|
||||
|
||||
return line
|
||||
|
||||
|
||||
func _clear_matches():
|
||||
# Check grid integrity
|
||||
if not _validate_grid_integrity():
|
||||
@@ -278,10 +294,17 @@ func _clear_matches():
|
||||
|
||||
var tile_pos = tile.grid_position
|
||||
# Validate grid position before clearing reference
|
||||
if _is_valid_grid_position(tile_pos) and tile_pos.y < grid.size() and tile_pos.x < grid[tile_pos.y].size():
|
||||
if (
|
||||
_is_valid_grid_position(tile_pos)
|
||||
and tile_pos.y < grid.size()
|
||||
and tile_pos.x < grid[tile_pos.y].size()
|
||||
):
|
||||
grid[tile_pos.y][tile_pos.x] = null
|
||||
else:
|
||||
DebugManager.log_warn("Invalid grid position during tile removal: (%d,%d)" % [tile_pos.x, tile_pos.y], "Match3")
|
||||
DebugManager.log_warn(
|
||||
"Invalid grid position during tile removal: (%d,%d)" % [tile_pos.x, tile_pos.y],
|
||||
"Match3"
|
||||
)
|
||||
|
||||
tile.queue_free()
|
||||
|
||||
@@ -291,6 +314,7 @@ func _clear_matches():
|
||||
await get_tree().create_timer(TILE_DROP_WAIT_TIME).timeout
|
||||
_fill_empty_cells()
|
||||
|
||||
|
||||
func _drop_tiles():
|
||||
var moved = true
|
||||
while moved:
|
||||
@@ -309,6 +333,7 @@ func _drop_tiles():
|
||||
tile.position = grid_offset + Vector2(x, y + 1) * tile_size
|
||||
moved = true
|
||||
|
||||
|
||||
func _fill_empty_cells():
|
||||
# Safety check for grid integrity
|
||||
if not _validate_grid_integrity():
|
||||
@@ -316,7 +341,7 @@ func _fill_empty_cells():
|
||||
return
|
||||
|
||||
# Create gem pool for current tile types
|
||||
var gem_indices = []
|
||||
var gem_indices: Array[int] = []
|
||||
for i in range(TILE_TYPES):
|
||||
gem_indices.append(i)
|
||||
|
||||
@@ -334,7 +359,9 @@ func _fill_empty_cells():
|
||||
if not grid[y][x]:
|
||||
var tile = TILE_SCENE.instantiate()
|
||||
if not tile:
|
||||
DebugManager.log_error("Failed to instantiate tile at (%d,%d)" % [x, y], "Match3")
|
||||
DebugManager.log_error(
|
||||
"Failed to instantiate tile at (%d,%d)" % [x, y], "Match3"
|
||||
)
|
||||
continue
|
||||
|
||||
tile.grid_position = Vector2i(x, y)
|
||||
@@ -375,19 +402,35 @@ func _fill_empty_cells():
|
||||
iteration += 1
|
||||
|
||||
if iteration >= MAX_CASCADE_ITERATIONS:
|
||||
DebugManager.log_warn("Maximum cascade iterations reached (%d), stopping to prevent infinite loop" % MAX_CASCADE_ITERATIONS, "Match3")
|
||||
DebugManager.log_warn(
|
||||
(
|
||||
"Maximum cascade iterations reached (%d), stopping to prevent infinite loop"
|
||||
% MAX_CASCADE_ITERATIONS
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
# Save grid state after cascades complete
|
||||
save_current_state()
|
||||
|
||||
|
||||
func regenerate_grid():
|
||||
# Validate grid size before regeneration
|
||||
if GRID_SIZE.x < MIN_GRID_SIZE or GRID_SIZE.y < MIN_GRID_SIZE or GRID_SIZE.x > MAX_GRID_SIZE or GRID_SIZE.y > MAX_GRID_SIZE:
|
||||
DebugManager.log_error("Invalid grid size for regeneration: %dx%d" % [GRID_SIZE.x, GRID_SIZE.y], "Match3")
|
||||
if (
|
||||
GRID_SIZE.x < MIN_GRID_SIZE
|
||||
or GRID_SIZE.y < MIN_GRID_SIZE
|
||||
or GRID_SIZE.x > MAX_GRID_SIZE
|
||||
or GRID_SIZE.y > MAX_GRID_SIZE
|
||||
):
|
||||
DebugManager.log_error(
|
||||
"Invalid grid size for regeneration: %dx%d" % [GRID_SIZE.x, GRID_SIZE.y], "Match3"
|
||||
)
|
||||
return
|
||||
|
||||
if TILE_TYPES < 3 or TILE_TYPES > MAX_TILE_TYPES:
|
||||
DebugManager.log_error("Invalid tile types count for regeneration: %d" % TILE_TYPES, "Match3")
|
||||
DebugManager.log_error(
|
||||
"Invalid tile types count for regeneration: %d" % TILE_TYPES, "Match3"
|
||||
)
|
||||
return
|
||||
|
||||
# Use time-based seed to ensure different patterns each time
|
||||
@@ -440,6 +483,7 @@ func regenerate_grid():
|
||||
# Regenerate the grid with safety checks
|
||||
_initialize_grid()
|
||||
|
||||
|
||||
func set_tile_types(new_count: int):
|
||||
# Input validation
|
||||
if new_count < 3:
|
||||
@@ -447,7 +491,9 @@ func set_tile_types(new_count: int):
|
||||
return
|
||||
|
||||
if new_count > MAX_TILE_TYPES:
|
||||
DebugManager.log_error("Tile types count too high: %d (maximum %d)" % [new_count, MAX_TILE_TYPES], "Match3")
|
||||
DebugManager.log_error(
|
||||
"Tile types count too high: %d (maximum %d)" % [new_count, MAX_TILE_TYPES], "Match3"
|
||||
)
|
||||
return
|
||||
|
||||
if new_count == TILE_TYPES:
|
||||
@@ -460,14 +506,27 @@ func set_tile_types(new_count: int):
|
||||
# Regenerate grid with new tile types (gem pool is updated in regenerate_grid)
|
||||
await regenerate_grid()
|
||||
|
||||
|
||||
func set_grid_size(new_size: Vector2i):
|
||||
# Comprehensive input validation
|
||||
if new_size.x < MIN_GRID_SIZE or new_size.y < MIN_GRID_SIZE:
|
||||
DebugManager.log_error("Grid size too small: %dx%d (minimum %dx%d)" % [new_size.x, new_size.y, MIN_GRID_SIZE, MIN_GRID_SIZE], "Match3")
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"Grid size too small: %dx%d (minimum %dx%d)"
|
||||
% [new_size.x, new_size.y, MIN_GRID_SIZE, MIN_GRID_SIZE]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
return
|
||||
|
||||
if new_size.x > MAX_GRID_SIZE or new_size.y > MAX_GRID_SIZE:
|
||||
DebugManager.log_error("Grid size too large: %dx%d (maximum %dx%d)" % [new_size.x, new_size.y, MAX_GRID_SIZE, MAX_GRID_SIZE], "Match3")
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"Grid size too large: %dx%d (maximum %dx%d)"
|
||||
% [new_size.x, new_size.y, MAX_GRID_SIZE, MAX_GRID_SIZE]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
return
|
||||
|
||||
if new_size == GRID_SIZE:
|
||||
@@ -480,6 +539,7 @@ func set_grid_size(new_size: Vector2i):
|
||||
# Regenerate grid with new size
|
||||
await regenerate_grid()
|
||||
|
||||
|
||||
func reset_all_visual_states() -> void:
|
||||
# Debug function to reset all tile visual states
|
||||
DebugManager.log_debug("Resetting all tile visual states", "Match3")
|
||||
@@ -493,6 +553,7 @@ func reset_all_visual_states() -> void:
|
||||
current_state = GameState.WAITING
|
||||
keyboard_navigation_enabled = false
|
||||
|
||||
|
||||
func _debug_scene_structure() -> void:
|
||||
DebugManager.log_debug("=== Scene Structure Debug ===", "Match3")
|
||||
DebugManager.log_debug("Match3 node children count: %d" % get_child_count(), "Match3")
|
||||
@@ -510,22 +571,30 @@ func _debug_scene_structure() -> void:
|
||||
for x in range(GRID_SIZE.x):
|
||||
if y < grid.size() and x < grid[y].size() and grid[y][x]:
|
||||
tile_count += 1
|
||||
DebugManager.log_debug("Created %d tiles out of %d expected" % [tile_count, GRID_SIZE.x * GRID_SIZE.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"Created %d tiles out of %d expected" % [tile_count, GRID_SIZE.x * GRID_SIZE.y], "Match3"
|
||||
)
|
||||
|
||||
# Check first tile in detail
|
||||
if grid.size() > 0 and grid[0].size() > 0 and grid[0][0]:
|
||||
var first_tile = grid[0][0]
|
||||
DebugManager.log_debug("First tile global position: %s" % first_tile.global_position, "Match3")
|
||||
DebugManager.log_debug(
|
||||
"First tile global position: %s" % first_tile.global_position, "Match3"
|
||||
)
|
||||
DebugManager.log_debug("First tile local position: %s" % first_tile.position, "Match3")
|
||||
|
||||
# Check parent chain
|
||||
var current_node = self
|
||||
var depth = 0
|
||||
while current_node and depth < 10:
|
||||
DebugManager.log_debug("Parent level %d: %s (type: %s)" % [depth, current_node.name, current_node.get_class()], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"Parent level %d: %s (type: %s)" % [depth, current_node.name, current_node.get_class()],
|
||||
"Match3"
|
||||
)
|
||||
current_node = current_node.get_parent()
|
||||
depth += 1
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
# Debug key to reset all visual states
|
||||
if event.is_action_pressed("action_east") and DebugManager.is_debug_enabled():
|
||||
@@ -560,7 +629,9 @@ func _move_cursor(direction: Vector2i) -> void:
|
||||
return
|
||||
|
||||
if direction.x != 0 and direction.y != 0:
|
||||
DebugManager.log_error("Diagonal cursor movement not supported: " + str(direction), "Match3")
|
||||
DebugManager.log_error(
|
||||
"Diagonal cursor movement not supported: " + str(direction), "Match3"
|
||||
)
|
||||
return
|
||||
|
||||
# Validate grid integrity before cursor operations
|
||||
@@ -582,7 +653,10 @@ func _move_cursor(direction: Vector2i) -> void:
|
||||
if not old_tile.is_selected:
|
||||
old_tile.is_highlighted = false
|
||||
|
||||
DebugManager.log_debug("Cursor moved from (%d,%d) to (%d,%d)" % [old_pos.x, old_pos.y, new_pos.x, new_pos.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"Cursor moved from (%d,%d) to (%d,%d)" % [old_pos.x, old_pos.y, new_pos.x, new_pos.y],
|
||||
"Match3"
|
||||
)
|
||||
cursor_position = new_pos
|
||||
|
||||
# Safe access to new tile
|
||||
@@ -591,25 +665,48 @@ func _move_cursor(direction: Vector2i) -> void:
|
||||
if not new_tile.is_selected:
|
||||
new_tile.is_highlighted = true
|
||||
|
||||
|
||||
func _select_tile_at_cursor() -> void:
|
||||
# Validate cursor position and grid integrity
|
||||
if not _is_valid_grid_position(cursor_position):
|
||||
DebugManager.log_warn("Invalid cursor position for selection: (%d,%d)" % [cursor_position.x, cursor_position.y], "Match3")
|
||||
DebugManager.log_warn(
|
||||
(
|
||||
"Invalid cursor position for selection: (%d,%d)"
|
||||
% [cursor_position.x, cursor_position.y]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
return
|
||||
|
||||
var tile = _safe_grid_access(cursor_position)
|
||||
if tile:
|
||||
DebugManager.log_debug("Keyboard selection at cursor (%d,%d)" % [cursor_position.x, cursor_position.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"Keyboard selection at cursor (%d,%d)" % [cursor_position.x, cursor_position.y],
|
||||
"Match3"
|
||||
)
|
||||
_on_tile_selected(tile)
|
||||
else:
|
||||
DebugManager.log_warn("No valid tile at cursor position (%d,%d)" % [cursor_position.x, cursor_position.y], "Match3")
|
||||
DebugManager.log_warn(
|
||||
"No valid tile at cursor position (%d,%d)" % [cursor_position.x, cursor_position.y],
|
||||
"Match3"
|
||||
)
|
||||
|
||||
|
||||
func _on_tile_selected(tile: Node2D) -> void:
|
||||
if current_state == GameState.SWAPPING or current_state == GameState.PROCESSING:
|
||||
DebugManager.log_debug("Tile selection ignored - game busy (state: %s)" % [GameState.keys()[current_state]], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"Tile selection ignored - game busy (state: %s)" % [GameState.keys()[current_state]],
|
||||
"Match3"
|
||||
)
|
||||
return
|
||||
|
||||
DebugManager.log_debug("Tile selected at (%d,%d), gem type: %d" % [tile.grid_position.x, tile.grid_position.y, tile.tile_type], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Tile selected at (%d,%d), gem type: %d"
|
||||
% [tile.grid_position.x, tile.grid_position.y, tile.tile_type]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
if current_state == GameState.WAITING:
|
||||
# First tile selection
|
||||
@@ -621,7 +718,18 @@ func _on_tile_selected(tile: Node2D) -> void:
|
||||
_deselect_tile()
|
||||
else:
|
||||
# Attempt to swap with selected tile
|
||||
DebugManager.log_debug("Attempting swap between (%d,%d) and (%d,%d)" % [selected_tile.grid_position.x, selected_tile.grid_position.y, tile.grid_position.x, tile.grid_position.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Attempting swap between (%d,%d) and (%d,%d)"
|
||||
% [
|
||||
selected_tile.grid_position.x,
|
||||
selected_tile.grid_position.y,
|
||||
tile.grid_position.x,
|
||||
tile.grid_position.y
|
||||
]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
_attempt_swap(selected_tile, tile)
|
||||
|
||||
|
||||
@@ -629,13 +737,22 @@ func _select_tile(tile: Node2D) -> void:
|
||||
selected_tile = tile
|
||||
tile.is_selected = true
|
||||
current_state = GameState.SELECTING
|
||||
DebugManager.log_debug("Selected tile at (%d, %d)" % [tile.grid_position.x, tile.grid_position.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"Selected tile at (%d, %d)" % [tile.grid_position.x, tile.grid_position.y], "Match3"
|
||||
)
|
||||
|
||||
|
||||
func _deselect_tile() -> void:
|
||||
if selected_tile and is_instance_valid(selected_tile):
|
||||
# Safe access to tile properties
|
||||
if "grid_position" in selected_tile:
|
||||
DebugManager.log_debug("Deselecting tile at (%d,%d)" % [selected_tile.grid_position.x, selected_tile.grid_position.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Deselecting tile at (%d,%d)"
|
||||
% [selected_tile.grid_position.x, selected_tile.grid_position.y]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
else:
|
||||
DebugManager.log_debug("Deselecting tile (no grid position available)", "Match3")
|
||||
|
||||
@@ -653,7 +770,13 @@ func _deselect_tile() -> void:
|
||||
var cursor_tile = _safe_grid_access(cursor_position)
|
||||
if cursor_tile and "is_highlighted" in cursor_tile:
|
||||
cursor_tile.is_highlighted = true
|
||||
DebugManager.log_debug("Restored cursor highlighting at (%d,%d)" % [cursor_position.x, cursor_position.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Restored cursor highlighting at (%d,%d)"
|
||||
% [cursor_position.x, cursor_position.y]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
else:
|
||||
# For mouse navigation, just clear highlighting
|
||||
if "is_highlighted" in selected_tile:
|
||||
@@ -662,6 +785,7 @@ func _deselect_tile() -> void:
|
||||
selected_tile = null
|
||||
current_state = GameState.WAITING
|
||||
|
||||
|
||||
func _are_adjacent(tile1: Node2D, tile2: Node2D) -> bool:
|
||||
if not tile1 or not tile2:
|
||||
return false
|
||||
@@ -671,19 +795,44 @@ func _are_adjacent(tile1: Node2D, tile2: Node2D) -> bool:
|
||||
var diff = abs(pos1.x - pos2.x) + abs(pos1.y - pos2.y)
|
||||
return diff == 1
|
||||
|
||||
|
||||
func _attempt_swap(tile1: Node2D, tile2: Node2D) -> void:
|
||||
if not _are_adjacent(tile1, tile2):
|
||||
DebugManager.log_debug("Tiles are not adjacent, cannot swap", "Match3")
|
||||
return
|
||||
|
||||
DebugManager.log_debug("Starting swap animation: (%d,%d)[type:%d] <-> (%d,%d)[type:%d]" % [tile1.grid_position.x, tile1.grid_position.y, tile1.tile_type, tile2.grid_position.x, tile2.grid_position.y, tile2.tile_type], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Starting swap animation: (%d,%d)[type:%d] <-> (%d,%d)[type:%d]"
|
||||
% [
|
||||
tile1.grid_position.x,
|
||||
tile1.grid_position.y,
|
||||
tile1.tile_type,
|
||||
tile2.grid_position.x,
|
||||
tile2.grid_position.y,
|
||||
tile2.tile_type
|
||||
]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
current_state = GameState.SWAPPING
|
||||
await _swap_tiles(tile1, tile2)
|
||||
|
||||
# Check if swap creates matches
|
||||
if _has_match_at(tile1.grid_position) or _has_match_at(tile2.grid_position):
|
||||
DebugManager.log_info("Valid swap created matches at (%d,%d) or (%d,%d)" % [tile1.grid_position.x, tile1.grid_position.y, tile2.grid_position.x, tile2.grid_position.y], "Match3")
|
||||
DebugManager.log_info(
|
||||
(
|
||||
"Valid swap created matches at (%d,%d) or (%d,%d)"
|
||||
% [
|
||||
tile1.grid_position.x,
|
||||
tile1.grid_position.y,
|
||||
tile2.grid_position.x,
|
||||
tile2.grid_position.y
|
||||
]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
_deselect_tile()
|
||||
current_state = GameState.PROCESSING
|
||||
_clear_matches()
|
||||
@@ -697,6 +846,7 @@ func _attempt_swap(tile1: Node2D, tile2: Node2D) -> void:
|
||||
_deselect_tile()
|
||||
current_state = GameState.WAITING
|
||||
|
||||
|
||||
func _swap_tiles(tile1: Node2D, tile2: Node2D) -> void:
|
||||
if not tile1 or not tile2:
|
||||
DebugManager.log_error("Cannot swap tiles - one or both tiles are null", "Match3")
|
||||
@@ -706,7 +856,13 @@ func _swap_tiles(tile1: Node2D, tile2: Node2D) -> void:
|
||||
var pos1 = tile1.grid_position
|
||||
var pos2 = tile2.grid_position
|
||||
|
||||
DebugManager.log_debug("Swapping tile positions: (%d,%d) -> (%d,%d), (%d,%d) -> (%d,%d)" % [pos1.x, pos1.y, pos2.x, pos2.y, pos2.x, pos2.y, pos1.x, pos1.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Swapping tile positions: (%d,%d) -> (%d,%d), (%d,%d) -> (%d,%d)"
|
||||
% [pos1.x, pos1.y, pos2.x, pos2.y, pos2.x, pos2.y, pos1.x, pos1.y]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
tile1.grid_position = pos2
|
||||
tile2.grid_position = pos1
|
||||
@@ -729,9 +885,16 @@ func _swap_tiles(tile1: Node2D, tile2: Node2D) -> void:
|
||||
await tween.finished
|
||||
DebugManager.log_trace("Tile swap animation completed", "Match3")
|
||||
|
||||
|
||||
func serialize_grid_state() -> Array:
|
||||
# Convert the current grid to a serializable 2D array
|
||||
DebugManager.log_info("Starting serialization: grid.size()=%d, GRID_SIZE=(%d,%d)" % [grid.size(), GRID_SIZE.x, GRID_SIZE.y], "Match3")
|
||||
DebugManager.log_info(
|
||||
(
|
||||
"Starting serialization: grid.size()=%d, GRID_SIZE=(%d,%d)"
|
||||
% [grid.size(), GRID_SIZE.x, GRID_SIZE.y]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
if grid.size() == 0:
|
||||
DebugManager.log_error("Grid array is empty during serialization!", "Match3")
|
||||
@@ -749,18 +912,29 @@ func serialize_grid_state() -> Array:
|
||||
valid_tiles += 1
|
||||
# Only log first few for brevity
|
||||
if valid_tiles <= 5:
|
||||
DebugManager.log_debug("Serializing tile (%d,%d): type %d" % [x, y, grid[y][x].tile_type], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"Serializing tile (%d,%d): type %d" % [x, y, grid[y][x].tile_type], "Match3"
|
||||
)
|
||||
else:
|
||||
row.append(-1) # Invalid/empty tile
|
||||
null_tiles += 1
|
||||
# Only log first few nulls for brevity
|
||||
if null_tiles <= 5:
|
||||
DebugManager.log_debug("Serializing tile (%d,%d): NULL/empty (-1)" % [x, y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"Serializing tile (%d,%d): NULL/empty (-1)" % [x, y], "Match3"
|
||||
)
|
||||
serialized_grid.append(row)
|
||||
|
||||
DebugManager.log_info("Serialized grid state: %dx%d grid, %d valid tiles, %d null tiles" % [GRID_SIZE.x, GRID_SIZE.y, valid_tiles, null_tiles], "Match3")
|
||||
DebugManager.log_info(
|
||||
(
|
||||
"Serialized grid state: %dx%d grid, %d valid tiles, %d null tiles"
|
||||
% [GRID_SIZE.x, GRID_SIZE.y, valid_tiles, null_tiles]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
return serialized_grid
|
||||
|
||||
|
||||
func get_active_gem_types() -> Array:
|
||||
# Get active gem types from the first available tile
|
||||
if grid.size() > 0 and grid[0].size() > 0 and grid[0][0]:
|
||||
@@ -772,15 +946,23 @@ func get_active_gem_types() -> Array:
|
||||
default_types.append(i)
|
||||
return default_types
|
||||
|
||||
|
||||
func save_current_state():
|
||||
# Save complete game state
|
||||
var grid_layout = serialize_grid_state()
|
||||
var active_gems = get_active_gem_types()
|
||||
|
||||
DebugManager.log_info("Saving match3 state: size(%d,%d), %d tile types, %d active gems" % [GRID_SIZE.x, GRID_SIZE.y, TILE_TYPES, active_gems.size()], "Match3")
|
||||
DebugManager.log_info(
|
||||
(
|
||||
"Saving match3 state: size(%d,%d), %d tile types, %d active gems"
|
||||
% [GRID_SIZE.x, GRID_SIZE.y, TILE_TYPES, active_gems.size()]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
SaveManager.save_grid_state(GRID_SIZE, TILE_TYPES, active_gems, grid_layout)
|
||||
|
||||
|
||||
func load_saved_state() -> bool:
|
||||
# Check if there's a saved grid state
|
||||
if not SaveManager.has_saved_grid():
|
||||
@@ -792,10 +974,18 @@ func load_saved_state() -> bool:
|
||||
# Restore grid settings
|
||||
var saved_size = Vector2i(saved_state.grid_size.x, saved_state.grid_size.y)
|
||||
TILE_TYPES = saved_state.tile_types_count
|
||||
var saved_gems = saved_state.active_gem_types
|
||||
var saved_gems: Array[int] = []
|
||||
for gem in saved_state.active_gem_types:
|
||||
saved_gems.append(int(gem))
|
||||
var saved_layout = saved_state.grid_layout
|
||||
|
||||
DebugManager.log_info("[%s] Loading saved grid state: size(%d,%d), %d tile types, layout_size=%d" % [instance_id, saved_size.x, saved_size.y, TILE_TYPES, saved_layout.size()], "Match3")
|
||||
DebugManager.log_info(
|
||||
(
|
||||
"[%s] Loading saved grid state: size(%d,%d), %d tile types, layout_size=%d"
|
||||
% [instance_id, saved_size.x, saved_size.y, TILE_TYPES, saved_layout.size()]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
# Debug: Print first few rows of loaded layout
|
||||
for y in range(min(3, saved_layout.size())):
|
||||
@@ -806,11 +996,23 @@ func load_saved_state() -> bool:
|
||||
|
||||
# Validate saved data
|
||||
if saved_layout.size() != saved_size.y:
|
||||
DebugManager.log_error("Saved grid layout height mismatch: expected %d, got %d" % [saved_size.y, saved_layout.size()], "Match3")
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"Saved grid layout height mismatch: expected %d, got %d"
|
||||
% [saved_size.y, saved_layout.size()]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
return false
|
||||
|
||||
if saved_layout.size() > 0 and saved_layout[0].size() != saved_size.x:
|
||||
DebugManager.log_error("Saved grid layout width mismatch: expected %d, got %d" % [saved_size.x, saved_layout[0].size()], "Match3")
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"Saved grid layout width mismatch: expected %d, got %d"
|
||||
% [saved_size.x, saved_layout[0].size()]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
return false
|
||||
|
||||
# Apply the saved settings
|
||||
@@ -819,7 +1021,10 @@ func load_saved_state() -> bool:
|
||||
|
||||
# Recalculate layout if size changed
|
||||
if old_size != saved_size:
|
||||
DebugManager.log_info("Grid size changed from %s to %s, recalculating layout" % [old_size, saved_size], "Match3")
|
||||
DebugManager.log_info(
|
||||
"Grid size changed from %s to %s, recalculating layout" % [old_size, saved_size],
|
||||
"Match3"
|
||||
)
|
||||
_calculate_grid_layout()
|
||||
|
||||
await _restore_grid_from_layout(saved_layout, saved_gems)
|
||||
@@ -827,8 +1032,15 @@ func load_saved_state() -> bool:
|
||||
DebugManager.log_info("Successfully loaded saved grid state", "Match3")
|
||||
return true
|
||||
|
||||
func _restore_grid_from_layout(grid_layout: Array, active_gems: Array):
|
||||
DebugManager.log_info("[%s] Starting grid restoration: layout_size=%d, active_gems=%s" % [instance_id, grid_layout.size(), active_gems], "Match3")
|
||||
|
||||
func _restore_grid_from_layout(grid_layout: Array, active_gems: Array[int]) -> void:
|
||||
DebugManager.log_info(
|
||||
(
|
||||
"[%s] Starting grid restoration: layout_size=%d, active_gems=%s"
|
||||
% [instance_id, grid_layout.size(), active_gems]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
# Clear ALL existing tile children, not just ones in grid array
|
||||
# This ensures no duplicate layers are created
|
||||
@@ -839,7 +1051,9 @@ func _restore_grid_from_layout(grid_layout: Array, active_gems: Array):
|
||||
if script_path == "res://scenes/game/gameplays/tile.gd":
|
||||
all_tile_children.append(child)
|
||||
|
||||
DebugManager.log_debug("Found %d existing tile children to remove" % all_tile_children.size(), "Match3")
|
||||
DebugManager.log_debug(
|
||||
"Found %d existing tile children to remove" % all_tile_children.size(), "Match3"
|
||||
)
|
||||
|
||||
# Remove all found tile children
|
||||
for child in all_tile_children:
|
||||
@@ -872,26 +1086,44 @@ func _restore_grid_from_layout(grid_layout: Array, active_gems: Array):
|
||||
|
||||
# Set the saved tile type
|
||||
var saved_tile_type = grid_layout[y][x]
|
||||
DebugManager.log_debug("Setting tile (%d,%d): saved_type=%d, TILE_TYPES=%d" % [x, y, saved_tile_type, TILE_TYPES], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Setting tile (%d,%d): saved_type=%d, TILE_TYPES=%d"
|
||||
% [x, y, saved_tile_type, TILE_TYPES]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
if saved_tile_type >= 0 and saved_tile_type < TILE_TYPES:
|
||||
tile.tile_type = saved_tile_type
|
||||
DebugManager.log_debug("✓ Restored tile (%d,%d) with saved type %d" % [x, y, saved_tile_type], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"✓ Restored tile (%d,%d) with saved type %d" % [x, y, saved_tile_type], "Match3"
|
||||
)
|
||||
else:
|
||||
# Fallback for invalid tile types
|
||||
tile.tile_type = randi() % TILE_TYPES
|
||||
DebugManager.log_error("✗ Invalid saved tile type %d at (%d,%d), using random %d" % [saved_tile_type, x, y, tile.tile_type], "Match3")
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"✗ Invalid saved tile type %d at (%d,%d), using random %d"
|
||||
% [saved_tile_type, x, y, tile.tile_type]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
# Connect tile signals
|
||||
tile.tile_selected.connect(_on_tile_selected)
|
||||
grid[y].append(tile)
|
||||
|
||||
DebugManager.log_info("Completed grid restoration: %d tiles restored" % [GRID_SIZE.x * GRID_SIZE.y], "Match3")
|
||||
DebugManager.log_info(
|
||||
"Completed grid restoration: %d tiles restored" % [GRID_SIZE.x * GRID_SIZE.y], "Match3"
|
||||
)
|
||||
|
||||
|
||||
# Safety and validation helper functions
|
||||
func _is_valid_grid_position(pos: Vector2i) -> bool:
|
||||
return pos.x >= 0 and pos.y >= 0 and pos.x < GRID_SIZE.x and pos.y < GRID_SIZE.y
|
||||
|
||||
|
||||
func _validate_grid_integrity() -> bool:
|
||||
# Check if grid array structure is valid
|
||||
if not grid is Array:
|
||||
@@ -899,7 +1131,9 @@ func _validate_grid_integrity() -> bool:
|
||||
return false
|
||||
|
||||
if grid.size() != GRID_SIZE.y:
|
||||
DebugManager.log_error("Grid height mismatch: %d vs %d" % [grid.size(), GRID_SIZE.y], "Match3")
|
||||
DebugManager.log_error(
|
||||
"Grid height mismatch: %d vs %d" % [grid.size(), GRID_SIZE.y], "Match3"
|
||||
)
|
||||
return false
|
||||
|
||||
for y in range(grid.size()):
|
||||
@@ -908,11 +1142,14 @@ func _validate_grid_integrity() -> bool:
|
||||
return false
|
||||
|
||||
if grid[y].size() != GRID_SIZE.x:
|
||||
DebugManager.log_error("Grid row %d width mismatch: %d vs %d" % [y, grid[y].size(), GRID_SIZE.x], "Match3")
|
||||
DebugManager.log_error(
|
||||
"Grid row %d width mismatch: %d vs %d" % [y, grid[y].size(), GRID_SIZE.x], "Match3"
|
||||
)
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
|
||||
func _safe_grid_access(pos: Vector2i) -> Node2D:
|
||||
# Safe grid access with comprehensive bounds checking
|
||||
if not _is_valid_grid_position(pos):
|
||||
@@ -928,6 +1165,7 @@ func _safe_grid_access(pos: Vector2i) -> Node2D:
|
||||
|
||||
return tile
|
||||
|
||||
|
||||
func _safe_tile_access(tile: Node2D, property: String):
|
||||
# Safe property access on tiles
|
||||
if not tile or not is_instance_valid(tile):
|
||||
|
||||
@@ -2,10 +2,13 @@ extends Node2D
|
||||
|
||||
signal tile_selected(tile: Node2D)
|
||||
|
||||
@export var tile_type: int = 0 : set = _set_tile_type
|
||||
@export var tile_type: int = 0:
|
||||
set = _set_tile_type
|
||||
var grid_position: Vector2i
|
||||
var is_selected: bool = false : set = _set_selected
|
||||
var is_highlighted: bool = false : set = _set_highlighted
|
||||
var is_selected: bool = false:
|
||||
set = _set_selected
|
||||
var is_highlighted: bool = false:
|
||||
set = _set_highlighted
|
||||
var original_scale: Vector2 = Vector2.ONE # Store the original scale for the board
|
||||
|
||||
@onready var sprite: Sprite2D = $Sprite2D
|
||||
@@ -14,19 +17,20 @@ var original_scale: Vector2 = Vector2.ONE # Store the original scale for the bo
|
||||
const TILE_SIZE = 48 # Slightly smaller than 54 to leave some padding
|
||||
|
||||
# All available gem textures
|
||||
var all_gem_textures = [
|
||||
preload("res://assets/sprites/gems/bg_19.png"), # 0 - Blue gem
|
||||
preload("res://assets/sprites/gems/dg_19.png"), # 1 - Dark gem
|
||||
preload("res://assets/sprites/gems/gg_19.png"), # 2 - Green gem
|
||||
preload("res://assets/sprites/gems/mg_19.png"), # 3 - Magenta gem
|
||||
preload("res://assets/sprites/gems/rg_19.png"), # 4 - Red gem
|
||||
preload("res://assets/sprites/gems/yg_19.png"), # 5 - Yellow gem
|
||||
preload("res://assets/sprites/gems/pg_19.png"), # 6 - Purple gem
|
||||
preload("res://assets/sprites/gems/sg_19.png"), # 7 - Silver gem
|
||||
var all_gem_textures: Array[Texture2D] = [
|
||||
preload("res://assets/sprites/gems/bg_19.png"), # 0 - Blue gem
|
||||
preload("res://assets/sprites/gems/dg_19.png"), # 1 - Dark gem
|
||||
preload("res://assets/sprites/gems/gg_19.png"), # 2 - Green gem
|
||||
preload("res://assets/sprites/gems/mg_19.png"), # 3 - Magenta gem
|
||||
preload("res://assets/sprites/gems/rg_19.png"), # 4 - Red gem
|
||||
preload("res://assets/sprites/gems/yg_19.png"), # 5 - Yellow gem
|
||||
preload("res://assets/sprites/gems/pg_19.png"), # 6 - Purple gem
|
||||
preload("res://assets/sprites/gems/sg_19.png"), # 7 - Silver gem
|
||||
]
|
||||
|
||||
# Currently active gem types (indices into all_gem_textures)
|
||||
var active_gem_types = [] # Will be set from TileManager
|
||||
var active_gem_types: Array[int] = [] # Will be set from TileManager
|
||||
|
||||
|
||||
func _set_tile_type(value: int) -> void:
|
||||
tile_type = value
|
||||
@@ -38,7 +42,16 @@ func _set_tile_type(value: int) -> void:
|
||||
sprite.texture = all_gem_textures[texture_index]
|
||||
_scale_sprite_to_fit()
|
||||
else:
|
||||
DebugManager.log_error("Invalid tile type: " + str(value) + ". Available types: 0-" + str(active_gem_types.size() - 1), "Match3")
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"Invalid tile type: "
|
||||
+ str(value)
|
||||
+ ". Available types: 0-"
|
||||
+ str(active_gem_types.size() - 1)
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
|
||||
func _scale_sprite_to_fit() -> void:
|
||||
# Fixed: Add additional null checks
|
||||
@@ -48,9 +61,16 @@ func _scale_sprite_to_fit() -> void:
|
||||
var scale_factor = TILE_SIZE / max_dimension
|
||||
original_scale = Vector2(scale_factor, scale_factor)
|
||||
sprite.scale = original_scale
|
||||
DebugManager.log_debug("Set original scale to %s for tile (%d,%d)" % [original_scale, grid_position.x, grid_position.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Set original scale to %s for tile (%d,%d)"
|
||||
% [original_scale, grid_position.x, grid_position.y]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
func set_active_gem_types(gem_indices: Array) -> void:
|
||||
|
||||
func set_active_gem_types(gem_indices: Array[int]) -> void:
|
||||
if not gem_indices or gem_indices.is_empty():
|
||||
DebugManager.log_error("Empty gem indices array provided", "Tile")
|
||||
return
|
||||
@@ -60,7 +80,13 @@ func set_active_gem_types(gem_indices: Array) -> void:
|
||||
# Validate all gem indices are within bounds
|
||||
for gem_index in active_gem_types:
|
||||
if gem_index < 0 or gem_index >= all_gem_textures.size():
|
||||
DebugManager.log_error("Invalid gem index: %d (valid range: 0-%d)" % [gem_index, all_gem_textures.size() - 1], "Tile")
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"Invalid gem index: %d (valid range: 0-%d)"
|
||||
% [gem_index, all_gem_textures.size() - 1]
|
||||
),
|
||||
"Tile"
|
||||
)
|
||||
# Use default fallback
|
||||
active_gem_types = [0, 1, 2, 3, 4]
|
||||
break
|
||||
@@ -72,9 +98,11 @@ func set_active_gem_types(gem_indices: Array) -> void:
|
||||
|
||||
_set_tile_type(tile_type)
|
||||
|
||||
|
||||
func get_active_gem_count() -> int:
|
||||
return active_gem_types.size()
|
||||
|
||||
|
||||
func add_gem_type(gem_index: int) -> bool:
|
||||
if gem_index < 0 or gem_index >= all_gem_textures.size():
|
||||
DebugManager.log_error("Invalid gem index: %d" % gem_index, "Tile")
|
||||
@@ -86,6 +114,7 @@ func add_gem_type(gem_index: int) -> bool:
|
||||
|
||||
return false
|
||||
|
||||
|
||||
func remove_gem_type(gem_index: int) -> bool:
|
||||
var type_index = active_gem_types.find(gem_index)
|
||||
if type_index == -1:
|
||||
@@ -104,18 +133,33 @@ func remove_gem_type(gem_index: int) -> bool:
|
||||
|
||||
return true
|
||||
|
||||
|
||||
func _set_selected(value: bool) -> void:
|
||||
var old_value = is_selected
|
||||
is_selected = value
|
||||
DebugManager.log_debug("Tile (%d,%d) selection changed: %s -> %s" % [grid_position.x, grid_position.y, old_value, value], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Tile (%d,%d) selection changed: %s -> %s"
|
||||
% [grid_position.x, grid_position.y, old_value, value]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
_update_visual_feedback()
|
||||
|
||||
|
||||
func _set_highlighted(value: bool) -> void:
|
||||
var old_value = is_highlighted
|
||||
is_highlighted = value
|
||||
DebugManager.log_debug("Tile (%d,%d) highlight changed: %s -> %s" % [grid_position.x, grid_position.y, old_value, value], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Tile (%d,%d) highlight changed: %s -> %s"
|
||||
% [grid_position.x, grid_position.y, old_value, value]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
_update_visual_feedback()
|
||||
|
||||
|
||||
func _update_visual_feedback() -> void:
|
||||
if not sprite:
|
||||
return
|
||||
@@ -129,17 +173,35 @@ func _update_visual_feedback() -> void:
|
||||
# Selected: bright and 20% larger than original board size
|
||||
target_modulate = Color(1.2, 1.2, 1.2, 1.0)
|
||||
scale_multiplier = 1.2
|
||||
DebugManager.log_debug("SELECTING tile (%d,%d): target scale %.2fx, current scale %s" % [grid_position.x, grid_position.y, scale_multiplier, sprite.scale], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"SELECTING tile (%d,%d): target scale %.2fx, current scale %s"
|
||||
% [grid_position.x, grid_position.y, scale_multiplier, sprite.scale]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
elif is_highlighted:
|
||||
# Highlighted: subtle glow and 10% larger than original board size
|
||||
target_modulate = Color(1.1, 1.1, 1.1, 1.0)
|
||||
scale_multiplier = 1.1
|
||||
DebugManager.log_debug("HIGHLIGHTING tile (%d,%d): target scale %.2fx, current scale %s" % [grid_position.x, grid_position.y, scale_multiplier, sprite.scale], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"HIGHLIGHTING tile (%d,%d): target scale %.2fx, current scale %s"
|
||||
% [grid_position.x, grid_position.y, scale_multiplier, sprite.scale]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
else:
|
||||
# Normal state: white and original board size
|
||||
target_modulate = Color.WHITE
|
||||
scale_multiplier = 1.0
|
||||
DebugManager.log_debug("NORMALIZING tile (%d,%d): target scale %.2fx, current scale %s" % [grid_position.x, grid_position.y, scale_multiplier, sprite.scale], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"NORMALIZING tile (%d,%d): target scale %.2fx, current scale %s"
|
||||
% [grid_position.x, grid_position.y, scale_multiplier, sprite.scale]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
# Calculate target scale relative to original board scale
|
||||
target_scale = original_scale * scale_multiplier
|
||||
@@ -149,7 +211,13 @@ func _update_visual_feedback() -> void:
|
||||
|
||||
# Only animate scale if it's actually changing
|
||||
if sprite.scale != target_scale:
|
||||
DebugManager.log_debug("Animating scale from %s to %s for tile (%d,%d)" % [sprite.scale, target_scale, grid_position.x, grid_position.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Animating scale from %s to %s for tile (%d,%d)"
|
||||
% [sprite.scale, target_scale, grid_position.x, grid_position.y]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
var tween = create_tween()
|
||||
tween.tween_property(sprite, "scale", target_scale, 0.15)
|
||||
@@ -157,10 +225,20 @@ func _update_visual_feedback() -> void:
|
||||
# Add completion callback for debugging
|
||||
tween.tween_callback(_on_scale_animation_completed.bind(target_scale))
|
||||
else:
|
||||
DebugManager.log_debug("No scale change needed for tile (%d,%d)" % [grid_position.x, grid_position.y], "Match3")
|
||||
DebugManager.log_debug(
|
||||
"No scale change needed for tile (%d,%d)" % [grid_position.x, grid_position.y], "Match3"
|
||||
)
|
||||
|
||||
|
||||
func _on_scale_animation_completed(expected_scale: Vector2) -> void:
|
||||
DebugManager.log_debug("Scale animation completed for tile (%d,%d): expected %s, actual %s" % [grid_position.x, grid_position.y, expected_scale, sprite.scale], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Scale animation completed for tile (%d,%d): expected %s, actual %s"
|
||||
% [grid_position.x, grid_position.y, expected_scale, sprite.scale]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
|
||||
func force_reset_visual_state() -> void:
|
||||
# Force reset all visual states - debug function
|
||||
@@ -169,7 +247,27 @@ func force_reset_visual_state() -> void:
|
||||
if sprite:
|
||||
sprite.modulate = Color.WHITE
|
||||
sprite.scale = original_scale # Reset to original board scale, not 1.0
|
||||
DebugManager.log_debug("Forced visual reset on tile (%d,%d) to original scale %s" % [grid_position.x, grid_position.y, original_scale], "Match3")
|
||||
DebugManager.log_debug(
|
||||
(
|
||||
"Forced visual reset on tile (%d,%d) to original scale %s"
|
||||
% [grid_position.x, grid_position.y, original_scale]
|
||||
),
|
||||
"Match3"
|
||||
)
|
||||
|
||||
|
||||
# Handle input for tile selection
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||
# Check if the mouse click is within the tile's bounds
|
||||
var local_position = to_local(get_global_mouse_position())
|
||||
var sprite_rect = Rect2(-TILE_SIZE / 2.0, -TILE_SIZE / 2.0, TILE_SIZE, TILE_SIZE)
|
||||
|
||||
if sprite_rect.has_point(local_position):
|
||||
tile_selected.emit(self)
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
extends Control
|
||||
|
||||
@onready var splash_screen = $SplashScreen
|
||||
var current_menu = null
|
||||
@onready var splash_screen: Node = $SplashScreen
|
||||
var current_menu: Control = null
|
||||
|
||||
const MAIN_MENU_SCENE = preload("res://scenes/ui/MainMenu.tscn")
|
||||
const SETTINGS_MENU_SCENE = preload("res://scenes/ui/SettingsMenu.tscn")
|
||||
|
||||
func _ready():
|
||||
|
||||
func _ready() -> void:
|
||||
DebugManager.log_debug("Main scene ready", "Main")
|
||||
# Use alternative connection method with input handling
|
||||
_setup_splash_screen_connection()
|
||||
|
||||
func _setup_splash_screen_connection():
|
||||
|
||||
func _setup_splash_screen_connection() -> void:
|
||||
# Wait for all nodes to be ready
|
||||
await get_tree().process_frame
|
||||
await get_tree().process_frame
|
||||
@@ -41,45 +43,53 @@ func _setup_splash_screen_connection():
|
||||
DebugManager.log_error("Could not find SplashScreen node", "Main")
|
||||
_use_fallback_input_handling()
|
||||
|
||||
func _use_fallback_input_handling():
|
||||
|
||||
func _use_fallback_input_handling() -> void:
|
||||
# Fallback: handle input directly in the main scene
|
||||
set_process_unhandled_input(true)
|
||||
|
||||
func _unhandled_input(event):
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if splash_screen and splash_screen.is_inside_tree():
|
||||
# Forward input to splash screen or handle directly
|
||||
if event.is_action_pressed("action_south"):
|
||||
_on_any_key_pressed()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func _on_any_key_pressed():
|
||||
|
||||
func _on_any_key_pressed() -> void:
|
||||
DebugManager.log_debug("Transitioning to main menu", "Main")
|
||||
splash_screen.queue_free()
|
||||
show_main_menu()
|
||||
|
||||
func show_main_menu():
|
||||
|
||||
func show_main_menu() -> void:
|
||||
clear_current_menu()
|
||||
var main_menu = MAIN_MENU_SCENE.instantiate()
|
||||
main_menu.open_settings.connect(_on_open_settings)
|
||||
add_child(main_menu)
|
||||
current_menu = main_menu
|
||||
|
||||
func show_settings_menu():
|
||||
|
||||
func show_settings_menu() -> void:
|
||||
clear_current_menu()
|
||||
var settings_menu = SETTINGS_MENU_SCENE.instantiate()
|
||||
settings_menu.back_to_main_menu.connect(_on_back_to_main_menu)
|
||||
add_child(settings_menu)
|
||||
current_menu = settings_menu
|
||||
|
||||
func clear_current_menu():
|
||||
|
||||
func clear_current_menu() -> void:
|
||||
if current_menu:
|
||||
current_menu.queue_free()
|
||||
current_menu = null
|
||||
|
||||
func _on_open_settings():
|
||||
|
||||
func _on_open_settings() -> void:
|
||||
DebugManager.log_debug("Opening settings menu", "Main")
|
||||
show_settings_menu()
|
||||
|
||||
func _on_back_to_main_menu():
|
||||
|
||||
func _on_back_to_main_menu() -> void:
|
||||
DebugManager.log_debug("Back to main menu", "Main")
|
||||
show_main_menu()
|
||||
|
||||
@@ -2,15 +2,26 @@ extends Control
|
||||
|
||||
signal any_key_pressed
|
||||
|
||||
func _ready():
|
||||
|
||||
func _ready() -> void:
|
||||
DebugManager.log_debug("SplashScreen ready", "SplashScreen")
|
||||
update_text()
|
||||
|
||||
func _input(event):
|
||||
if event.is_action_pressed("action_south") or event is InputEventScreenTouch or (event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed):
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if (
|
||||
event.is_action_pressed("action_south")
|
||||
or event is InputEventScreenTouch
|
||||
or (
|
||||
event is InputEventMouseButton
|
||||
and event.button_index == MOUSE_BUTTON_LEFT
|
||||
and event.pressed
|
||||
)
|
||||
):
|
||||
DebugManager.log_debug("Action pressed: " + str(event), "SplashScreen")
|
||||
any_key_pressed.emit()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func update_text():
|
||||
|
||||
func update_text() -> void:
|
||||
$SplashContainer/ContinueLabel.text = tr("press_ok_continue")
|
||||
|
||||
@@ -2,6 +2,7 @@ extends Control
|
||||
|
||||
@onready var button: Button = $Button
|
||||
|
||||
|
||||
func _ready():
|
||||
button.pressed.connect(_on_button_pressed)
|
||||
DebugManager.debug_ui_toggled.connect(_on_debug_ui_toggled)
|
||||
@@ -10,8 +11,10 @@ func _ready():
|
||||
var current_state = DebugManager.is_debug_ui_visible()
|
||||
button.text = "Debug UI: " + ("ON" if current_state else "OFF")
|
||||
|
||||
|
||||
func _on_button_pressed():
|
||||
DebugManager.toggle_debug_ui()
|
||||
|
||||
|
||||
func _on_debug_ui_toggled(visible: bool):
|
||||
button.text = "Debug UI: " + ("ON" if visible else "OFF")
|
||||
button.text = "Debug UI: " + ("ON" if visible else "OFF")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
extends DebugMenuBase
|
||||
|
||||
|
||||
func _find_target_scene():
|
||||
# Fixed: Search more thoroughly for match3 scene
|
||||
if match3_scene:
|
||||
|
||||
@@ -4,10 +4,14 @@ extends Control
|
||||
@onready var regenerate_button: Button = $VBoxContainer/RegenerateButton
|
||||
@onready var gem_types_spinbox: SpinBox = $VBoxContainer/GemTypesContainer/GemTypesSpinBox
|
||||
@onready var gem_types_label: Label = $VBoxContainer/GemTypesContainer/GemTypesLabel
|
||||
@onready var grid_width_spinbox: SpinBox = $VBoxContainer/GridSizeContainer/GridWidthContainer/GridWidthSpinBox
|
||||
@onready var grid_height_spinbox: SpinBox = $VBoxContainer/GridSizeContainer/GridHeightContainer/GridHeightSpinBox
|
||||
@onready var grid_width_label: Label = $VBoxContainer/GridSizeContainer/GridWidthContainer/GridWidthLabel
|
||||
@onready var grid_height_label: Label = $VBoxContainer/GridSizeContainer/GridHeightContainer/GridHeightLabel
|
||||
@onready
|
||||
var grid_width_spinbox: SpinBox = $VBoxContainer/GridSizeContainer/GridWidthContainer/GridWidthSpinBox
|
||||
@onready
|
||||
var grid_height_spinbox: SpinBox = $VBoxContainer/GridSizeContainer/GridHeightContainer/GridHeightSpinBox
|
||||
@onready
|
||||
var grid_width_label: Label = $VBoxContainer/GridSizeContainer/GridWidthContainer/GridWidthLabel
|
||||
@onready
|
||||
var grid_height_label: Label = $VBoxContainer/GridSizeContainer/GridHeightContainer/GridHeightLabel
|
||||
|
||||
@export var target_script_path: String = "res://scenes/game/gameplays/match3_gameplay.gd"
|
||||
@export var log_category: String = "DebugMenu"
|
||||
@@ -23,16 +27,18 @@ var search_timer: Timer
|
||||
var last_scene_search_time: float = 0.0
|
||||
const SCENE_SEARCH_COOLDOWN := 0.5 # Prevent excessive scene searching
|
||||
|
||||
func _exit_tree():
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if search_timer:
|
||||
search_timer.queue_free()
|
||||
|
||||
func _ready():
|
||||
|
||||
func _ready() -> void:
|
||||
DebugManager.log_debug("DebugMenuBase _ready() called", log_category)
|
||||
DebugManager.debug_toggled.connect(_on_debug_toggled)
|
||||
|
||||
# Initialize with current debug state
|
||||
var current_debug_state = DebugManager.is_debug_enabled()
|
||||
var current_debug_state: bool = DebugManager.is_debug_enabled()
|
||||
visible = current_debug_state
|
||||
|
||||
# Connect signals
|
||||
@@ -50,7 +56,8 @@ func _ready():
|
||||
# Start searching for target scene
|
||||
_find_target_scene()
|
||||
|
||||
func _initialize_spinboxes():
|
||||
|
||||
func _initialize_spinboxes() -> void:
|
||||
# Initialize gem types spinbox with safety limits
|
||||
gem_types_spinbox.min_value = MIN_TILE_TYPES
|
||||
gem_types_spinbox.max_value = MAX_TILE_TYPES
|
||||
@@ -68,40 +75,47 @@ func _initialize_spinboxes():
|
||||
grid_height_spinbox.step = 1
|
||||
grid_height_spinbox.value = 8 # Default value
|
||||
|
||||
func _setup_scene_finding():
|
||||
|
||||
func _setup_scene_finding() -> void:
|
||||
# Create timer for periodic scene search with longer intervals to reduce CPU usage
|
||||
search_timer = Timer.new()
|
||||
search_timer.wait_time = 0.5 # Reduced frequency from 0.1 to 0.5 seconds
|
||||
search_timer.timeout.connect(_find_target_scene)
|
||||
add_child(search_timer)
|
||||
|
||||
|
||||
# Virtual method - override in derived classes for specific finding logic
|
||||
func _find_target_scene():
|
||||
func _find_target_scene() -> void:
|
||||
DebugManager.log_error("_find_target_scene() not implemented in derived class", log_category)
|
||||
|
||||
|
||||
func _find_node_by_script(node: Node, script_path: String) -> Node:
|
||||
# Helper function to find node by its script path
|
||||
if not node:
|
||||
return null
|
||||
|
||||
if node.get_script():
|
||||
var node_script = node.get_script()
|
||||
var node_script: Script = node.get_script()
|
||||
if node_script.resource_path == script_path:
|
||||
return node
|
||||
|
||||
for child in node.get_children():
|
||||
var result = _find_node_by_script(child, script_path)
|
||||
var result: Node = _find_node_by_script(child, script_path)
|
||||
if result:
|
||||
return result
|
||||
|
||||
return null
|
||||
|
||||
func _update_ui_from_scene():
|
||||
|
||||
func _update_ui_from_scene() -> void:
|
||||
if not match3_scene:
|
||||
return
|
||||
|
||||
# Connect to grid state loaded signal if not already connected
|
||||
if match3_scene.has_signal("grid_state_loaded") and not match3_scene.grid_state_loaded.is_connected(_on_grid_state_loaded):
|
||||
if (
|
||||
match3_scene.has_signal("grid_state_loaded")
|
||||
and not match3_scene.grid_state_loaded.is_connected(_on_grid_state_loaded)
|
||||
):
|
||||
match3_scene.grid_state_loaded.connect(_on_grid_state_loaded)
|
||||
DebugManager.log_debug("Connected to grid_state_loaded signal", log_category)
|
||||
|
||||
@@ -112,14 +126,18 @@ func _update_ui_from_scene():
|
||||
|
||||
# Update grid size display
|
||||
if "GRID_SIZE" in match3_scene:
|
||||
var grid_size = match3_scene.GRID_SIZE
|
||||
var grid_size: Vector2i = match3_scene.GRID_SIZE
|
||||
grid_width_spinbox.value = grid_size.x
|
||||
grid_height_spinbox.value = grid_size.y
|
||||
grid_width_label.text = "Width: " + str(grid_size.x)
|
||||
grid_height_label.text = "Height: " + str(grid_size.y)
|
||||
|
||||
func _on_grid_state_loaded(grid_size: Vector2i, tile_types: int):
|
||||
DebugManager.log_debug("Grid state loaded signal received: size=%s, types=%d" % [grid_size, tile_types], log_category)
|
||||
|
||||
func _on_grid_state_loaded(grid_size: Vector2i, tile_types: int) -> void:
|
||||
DebugManager.log_debug(
|
||||
"Grid state loaded signal received: size=%s, types=%d" % [grid_size, tile_types],
|
||||
log_category
|
||||
)
|
||||
|
||||
# Update the UI with the actual loaded values
|
||||
gem_types_spinbox.value = tile_types
|
||||
@@ -130,16 +148,19 @@ func _on_grid_state_loaded(grid_size: Vector2i, tile_types: int):
|
||||
grid_width_label.text = "Width: " + str(grid_size.x)
|
||||
grid_height_label.text = "Height: " + str(grid_size.y)
|
||||
|
||||
func _stop_search_timer():
|
||||
|
||||
func _stop_search_timer() -> void:
|
||||
if search_timer and search_timer.timeout.is_connected(_find_target_scene):
|
||||
search_timer.stop()
|
||||
|
||||
func _start_search_timer():
|
||||
|
||||
func _start_search_timer() -> void:
|
||||
if search_timer and not search_timer.timeout.is_connected(_find_target_scene):
|
||||
search_timer.timeout.connect(_find_target_scene)
|
||||
search_timer.start()
|
||||
|
||||
func _on_debug_toggled(enabled: bool):
|
||||
|
||||
func _on_debug_toggled(enabled: bool) -> void:
|
||||
DebugManager.log_debug("Debug toggled to " + str(enabled), log_category)
|
||||
visible = enabled
|
||||
if enabled:
|
||||
@@ -150,13 +171,17 @@ func _on_debug_toggled(enabled: bool):
|
||||
# Force refresh the values in case they changed while debug was hidden
|
||||
_refresh_current_values()
|
||||
|
||||
func _refresh_current_values():
|
||||
|
||||
func _refresh_current_values() -> void:
|
||||
# Refresh UI with current values from the scene
|
||||
if match3_scene:
|
||||
DebugManager.log_debug("Refreshing debug menu values from current scene state", log_category)
|
||||
DebugManager.log_debug(
|
||||
"Refreshing debug menu values from current scene state", log_category
|
||||
)
|
||||
_update_ui_from_scene()
|
||||
|
||||
func _on_regenerate_pressed():
|
||||
|
||||
func _on_regenerate_pressed() -> void:
|
||||
if not match3_scene:
|
||||
_find_target_scene()
|
||||
|
||||
@@ -170,9 +195,10 @@ func _on_regenerate_pressed():
|
||||
else:
|
||||
DebugManager.log_error("Target scene does not have regenerate_grid method", log_category)
|
||||
|
||||
func _on_gem_types_changed(value: float):
|
||||
|
||||
func _on_gem_types_changed(value: float) -> void:
|
||||
# Rate limiting for scene searches
|
||||
var current_time = Time.get_ticks_msec() / 1000.0
|
||||
var current_time: float = Time.get_ticks_msec() / 1000.0
|
||||
if current_time - last_scene_search_time < SCENE_SEARCH_COOLDOWN:
|
||||
return
|
||||
|
||||
@@ -184,10 +210,16 @@ func _on_gem_types_changed(value: float):
|
||||
DebugManager.log_error("Could not find target scene for gem types change", log_category)
|
||||
return
|
||||
|
||||
var new_value = int(value)
|
||||
var new_value: int = int(value)
|
||||
# Enhanced input validation with safety constants
|
||||
if new_value < MIN_TILE_TYPES or new_value > MAX_TILE_TYPES:
|
||||
DebugManager.log_error("Invalid gem types value: %d (range: %d-%d)" % [new_value, MIN_TILE_TYPES, MAX_TILE_TYPES], log_category)
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"Invalid gem types value: %d (range: %d-%d)"
|
||||
% [new_value, MIN_TILE_TYPES, MAX_TILE_TYPES]
|
||||
),
|
||||
log_category
|
||||
)
|
||||
# Reset to valid value
|
||||
gem_types_spinbox.value = clamp(new_value, MIN_TILE_TYPES, MAX_TILE_TYPES)
|
||||
return
|
||||
@@ -203,9 +235,10 @@ func _on_gem_types_changed(value: float):
|
||||
match3_scene.TILE_TYPES = new_value
|
||||
gem_types_label.text = "Gem Types: " + str(new_value)
|
||||
|
||||
func _on_grid_width_changed(value: float):
|
||||
|
||||
func _on_grid_width_changed(value: float) -> void:
|
||||
# Rate limiting for scene searches
|
||||
var current_time = Time.get_ticks_msec() / 1000.0
|
||||
var current_time: float = Time.get_ticks_msec() / 1000.0
|
||||
if current_time - last_scene_search_time < SCENE_SEARCH_COOLDOWN:
|
||||
return
|
||||
|
||||
@@ -217,10 +250,16 @@ func _on_grid_width_changed(value: float):
|
||||
DebugManager.log_error("Could not find target scene for grid width change", log_category)
|
||||
return
|
||||
|
||||
var new_width = int(value)
|
||||
var new_width: int = int(value)
|
||||
# Enhanced input validation with safety constants
|
||||
if new_width < MIN_GRID_SIZE or new_width > MAX_GRID_SIZE:
|
||||
DebugManager.log_error("Invalid grid width value: %d (range: %d-%d)" % [new_width, MIN_GRID_SIZE, MAX_GRID_SIZE], log_category)
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"Invalid grid width value: %d (range: %d-%d)"
|
||||
% [new_width, MIN_GRID_SIZE, MAX_GRID_SIZE]
|
||||
),
|
||||
log_category
|
||||
)
|
||||
# Reset to valid value
|
||||
grid_width_spinbox.value = clamp(new_width, MIN_GRID_SIZE, MAX_GRID_SIZE)
|
||||
return
|
||||
@@ -228,17 +267,20 @@ func _on_grid_width_changed(value: float):
|
||||
grid_width_label.text = "Width: " + str(new_width)
|
||||
|
||||
# Get current height
|
||||
var current_height = int(grid_height_spinbox.value)
|
||||
var current_height: int = int(grid_height_spinbox.value)
|
||||
|
||||
if match3_scene.has_method("set_grid_size"):
|
||||
DebugManager.log_debug("Setting grid size to " + str(new_width) + "x" + str(current_height), log_category)
|
||||
DebugManager.log_debug(
|
||||
"Setting grid size to " + str(new_width) + "x" + str(current_height), log_category
|
||||
)
|
||||
await match3_scene.set_grid_size(Vector2i(new_width, current_height))
|
||||
else:
|
||||
DebugManager.log_error("Target scene does not have set_grid_size method", log_category)
|
||||
|
||||
func _on_grid_height_changed(value: float):
|
||||
|
||||
func _on_grid_height_changed(value: float) -> void:
|
||||
# Rate limiting for scene searches
|
||||
var current_time = Time.get_ticks_msec() / 1000.0
|
||||
var current_time: float = Time.get_ticks_msec() / 1000.0
|
||||
if current_time - last_scene_search_time < SCENE_SEARCH_COOLDOWN:
|
||||
return
|
||||
|
||||
@@ -250,10 +292,16 @@ func _on_grid_height_changed(value: float):
|
||||
DebugManager.log_error("Could not find target scene for grid height change", log_category)
|
||||
return
|
||||
|
||||
var new_height = int(value)
|
||||
var new_height: int = int(value)
|
||||
# Enhanced input validation with safety constants
|
||||
if new_height < MIN_GRID_SIZE or new_height > MAX_GRID_SIZE:
|
||||
DebugManager.log_error("Invalid grid height value: %d (range: %d-%d)" % [new_height, MIN_GRID_SIZE, MAX_GRID_SIZE], log_category)
|
||||
DebugManager.log_error(
|
||||
(
|
||||
"Invalid grid height value: %d (range: %d-%d)"
|
||||
% [new_height, MIN_GRID_SIZE, MAX_GRID_SIZE]
|
||||
),
|
||||
log_category
|
||||
)
|
||||
# Reset to valid value
|
||||
grid_height_spinbox.value = clamp(new_height, MIN_GRID_SIZE, MAX_GRID_SIZE)
|
||||
return
|
||||
@@ -261,10 +309,12 @@ func _on_grid_height_changed(value: float):
|
||||
grid_height_label.text = "Height: " + str(new_height)
|
||||
|
||||
# Get current width
|
||||
var current_width = int(grid_width_spinbox.value)
|
||||
var current_width: int = int(grid_width_spinbox.value)
|
||||
|
||||
if match3_scene.has_method("set_grid_size"):
|
||||
DebugManager.log_debug("Setting grid size to " + str(current_width) + "x" + str(new_height), log_category)
|
||||
DebugManager.log_debug(
|
||||
"Setting grid size to " + str(current_width) + "x" + str(new_height), log_category
|
||||
)
|
||||
await match3_scene.set_grid_size(Vector2i(current_width, new_height))
|
||||
else:
|
||||
DebugManager.log_error("Target scene does not have set_grid_size method", log_category)
|
||||
DebugManager.log_error("Target scene does not have set_grid_size method", log_category)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
extends Button
|
||||
|
||||
|
||||
func _ready():
|
||||
pressed.connect(_on_pressed)
|
||||
DebugManager.debug_toggled.connect(_on_debug_toggled)
|
||||
@@ -8,8 +9,10 @@ func _ready():
|
||||
var current_state = DebugManager.is_debug_enabled()
|
||||
text = "Debug: " + ("ON" if current_state else "OFF")
|
||||
|
||||
|
||||
func _on_pressed():
|
||||
DebugManager.toggle_debug()
|
||||
|
||||
|
||||
func _on_debug_toggled(enabled: bool):
|
||||
text = "Debug: " + ("ON" if enabled else "OFF")
|
||||
|
||||
@@ -6,14 +6,16 @@ signal open_settings
|
||||
var current_menu_index: int = 0
|
||||
var original_button_scales: Array[Vector2] = []
|
||||
|
||||
func _ready():
|
||||
|
||||
func _ready() -> void:
|
||||
DebugManager.log_info("MainMenu ready", "MainMenu")
|
||||
_setup_menu_navigation()
|
||||
_update_new_game_button()
|
||||
|
||||
func _on_new_game_button_pressed():
|
||||
|
||||
func _on_new_game_button_pressed() -> void:
|
||||
AudioManager.play_ui_click()
|
||||
var button_text = $MenuContainer/NewGameButton.text
|
||||
var button_text: String = $MenuContainer/NewGameButton.text
|
||||
if button_text == "Continue":
|
||||
DebugManager.log_info("Continue pressed", "MainMenu")
|
||||
GameManager.continue_game()
|
||||
@@ -21,17 +23,20 @@ func _on_new_game_button_pressed():
|
||||
DebugManager.log_info("New Game pressed", "MainMenu")
|
||||
GameManager.start_new_game()
|
||||
|
||||
func _on_settings_button_pressed():
|
||||
|
||||
func _on_settings_button_pressed() -> void:
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Settings pressed", "MainMenu")
|
||||
open_settings.emit()
|
||||
|
||||
func _on_exit_button_pressed():
|
||||
|
||||
func _on_exit_button_pressed() -> void:
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Exit pressed", "MainMenu")
|
||||
get_tree().quit()
|
||||
|
||||
func _setup_menu_navigation():
|
||||
|
||||
func _setup_menu_navigation() -> void:
|
||||
menu_buttons.clear()
|
||||
original_button_scales.clear()
|
||||
|
||||
@@ -44,6 +49,7 @@ func _setup_menu_navigation():
|
||||
|
||||
_update_visual_selection()
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("move_up"):
|
||||
_navigate_menu(-1)
|
||||
@@ -60,7 +66,8 @@ func _input(event: InputEvent) -> void:
|
||||
DebugManager.log_info("Quit game shortcut pressed", "MainMenu")
|
||||
get_tree().quit()
|
||||
|
||||
func _navigate_menu(direction: int):
|
||||
|
||||
func _navigate_menu(direction: int) -> void:
|
||||
AudioManager.play_ui_click()
|
||||
current_menu_index = (current_menu_index + direction) % menu_buttons.size()
|
||||
if current_menu_index < 0:
|
||||
@@ -68,15 +75,17 @@ func _navigate_menu(direction: int):
|
||||
_update_visual_selection()
|
||||
DebugManager.log_info("Menu navigation: index " + str(current_menu_index), "MainMenu")
|
||||
|
||||
func _activate_current_button():
|
||||
|
||||
func _activate_current_button() -> void:
|
||||
if current_menu_index >= 0 and current_menu_index < menu_buttons.size():
|
||||
var button = menu_buttons[current_menu_index]
|
||||
var button: Button = menu_buttons[current_menu_index]
|
||||
DebugManager.log_info("Activating button via keyboard/gamepad: " + button.text, "MainMenu")
|
||||
button.pressed.emit()
|
||||
|
||||
func _update_visual_selection():
|
||||
|
||||
func _update_visual_selection() -> void:
|
||||
for i in range(menu_buttons.size()):
|
||||
var button = menu_buttons[i]
|
||||
var button: Button = menu_buttons[i]
|
||||
if i == current_menu_index:
|
||||
button.scale = original_button_scales[i] * 1.1
|
||||
button.modulate = Color(1.2, 1.2, 1.0)
|
||||
@@ -84,16 +93,23 @@ func _update_visual_selection():
|
||||
button.scale = original_button_scales[i]
|
||||
button.modulate = Color.WHITE
|
||||
|
||||
func _update_new_game_button():
|
||||
# Check if there's an existing save with progress
|
||||
var current_score = SaveManager.get_current_score()
|
||||
var games_played = SaveManager.get_games_played()
|
||||
var has_saved_grid = SaveManager.has_saved_grid()
|
||||
|
||||
var new_game_button = $MenuContainer/NewGameButton
|
||||
func _update_new_game_button() -> void:
|
||||
# Check if there's an existing save with progress
|
||||
var current_score: int = SaveManager.get_current_score()
|
||||
var games_played: int = SaveManager.get_games_played()
|
||||
var has_saved_grid: bool = SaveManager.has_saved_grid()
|
||||
|
||||
var new_game_button: Button = $MenuContainer/NewGameButton
|
||||
if current_score > 0 or games_played > 0 or has_saved_grid:
|
||||
new_game_button.text = "Continue"
|
||||
DebugManager.log_info("Updated button to Continue (score: %d, games: %d, grid: %s)" % [current_score, games_played, has_saved_grid], "MainMenu")
|
||||
DebugManager.log_info(
|
||||
(
|
||||
"Updated button to Continue (score: %d, games: %d, grid: %s)"
|
||||
% [current_score, games_played, has_saved_grid]
|
||||
),
|
||||
"MainMenu"
|
||||
)
|
||||
else:
|
||||
new_game_button.text = "New Game"
|
||||
DebugManager.log_info("Updated button to New Game", "MainMenu")
|
||||
|
||||
@@ -14,27 +14,27 @@ signal back_to_main_menu
|
||||
# Progress reset confirmation dialog
|
||||
var confirmation_dialog: AcceptDialog
|
||||
|
||||
|
||||
# Navigation system variables
|
||||
var navigable_controls: Array[Control] = []
|
||||
var current_control_index: int = 0
|
||||
var original_control_scales: Array[Vector2] = []
|
||||
var original_control_modulates: Array[Color] = []
|
||||
|
||||
func _ready():
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("localizable")
|
||||
DebugManager.log_info("SettingsMenu ready", "Settings")
|
||||
# Language selector is initialized automatically
|
||||
|
||||
var master_callback = _on_volume_slider_changed.bind("master_volume")
|
||||
var master_callback: Callable = _on_volume_slider_changed.bind("master_volume")
|
||||
if not master_slider.value_changed.is_connected(master_callback):
|
||||
master_slider.value_changed.connect(master_callback)
|
||||
|
||||
var music_callback = _on_volume_slider_changed.bind("music_volume")
|
||||
var music_callback: Callable = _on_volume_slider_changed.bind("music_volume")
|
||||
if not music_slider.value_changed.is_connected(music_callback):
|
||||
music_slider.value_changed.connect(music_callback)
|
||||
|
||||
var sfx_callback = _on_volume_slider_changed.bind("sfx_volume")
|
||||
var sfx_callback: Callable = _on_volume_slider_changed.bind("sfx_volume")
|
||||
if not sfx_slider.value_changed.is_connected(sfx_callback):
|
||||
sfx_slider.value_changed.connect(sfx_callback)
|
||||
|
||||
@@ -45,37 +45,41 @@ func _ready():
|
||||
_setup_navigation_system()
|
||||
_setup_confirmation_dialog()
|
||||
|
||||
func _update_controls_from_settings():
|
||||
|
||||
func _update_controls_from_settings() -> void:
|
||||
master_slider.value = settings_manager.get_setting("master_volume")
|
||||
music_slider.value = settings_manager.get_setting("music_volume")
|
||||
sfx_slider.value = settings_manager.get_setting("sfx_volume")
|
||||
|
||||
# Language display is handled by the ValueStepper component
|
||||
|
||||
func _on_volume_slider_changed(value, setting_key):
|
||||
|
||||
func _on_volume_slider_changed(value: float, setting_key: String) -> void:
|
||||
# Input validation for volume settings
|
||||
if not setting_key in ["master_volume", "music_volume", "sfx_volume"]:
|
||||
DebugManager.log_error("Invalid volume setting key: " + str(setting_key), "Settings")
|
||||
return
|
||||
|
||||
if not (value is float or value is int):
|
||||
if typeof(value) != TYPE_FLOAT and typeof(value) != TYPE_INT:
|
||||
DebugManager.log_error("Invalid volume value type: " + str(typeof(value)), "Settings")
|
||||
return
|
||||
|
||||
# Clamp value to valid range
|
||||
var clamped_value = clamp(float(value), 0.0, 1.0)
|
||||
var clamped_value: float = clamp(float(value), 0.0, 1.0)
|
||||
if clamped_value != value:
|
||||
DebugManager.log_warn("Volume value %f clamped to %f" % [value, clamped_value], "Settings")
|
||||
|
||||
if not settings_manager.set_setting(setting_key, clamped_value):
|
||||
DebugManager.log_error("Failed to set volume setting: " + setting_key, "Settings")
|
||||
|
||||
func _exit_settings():
|
||||
|
||||
func _exit_settings() -> void:
|
||||
DebugManager.log_info("Exiting settings", "Settings")
|
||||
settings_manager.save_settings()
|
||||
back_to_main_menu.emit()
|
||||
|
||||
func _input(event):
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("action_east") or event.is_action_pressed("pause_menu"):
|
||||
DebugManager.log_debug("Cancel/back action pressed in settings", "Settings")
|
||||
_exit_settings()
|
||||
@@ -103,14 +107,14 @@ func _input(event):
|
||||
_activate_current_control()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func _on_back_button_pressed():
|
||||
|
||||
func _on_back_button_pressed() -> void:
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Back button pressed", "Settings")
|
||||
_exit_settings()
|
||||
|
||||
|
||||
|
||||
func update_text():
|
||||
func update_text() -> void:
|
||||
$SettingsContainer/SettingsTitle.text = tr("settings_title")
|
||||
$SettingsContainer/MasterVolumeContainer/MasterVolume.text = tr("master_volume")
|
||||
$SettingsContainer/MusicVolumeContainer/MusicVolume.text = tr("music_volume")
|
||||
@@ -127,7 +131,8 @@ func _on_reset_setting_button_pressed() -> void:
|
||||
_update_controls_from_settings()
|
||||
localization_manager.change_language(settings_manager.get_setting("language"))
|
||||
|
||||
func _setup_navigation_system():
|
||||
|
||||
func _setup_navigation_system() -> void:
|
||||
navigable_controls.clear()
|
||||
original_control_scales.clear()
|
||||
original_control_modulates.clear()
|
||||
@@ -148,7 +153,8 @@ func _setup_navigation_system():
|
||||
|
||||
_update_visual_selection()
|
||||
|
||||
func _navigate_controls(direction: int):
|
||||
|
||||
func _navigate_controls(direction: int) -> void:
|
||||
AudioManager.play_ui_click()
|
||||
current_control_index = (current_control_index + direction) % navigable_controls.size()
|
||||
if current_control_index < 0:
|
||||
@@ -156,32 +162,36 @@ func _navigate_controls(direction: int):
|
||||
_update_visual_selection()
|
||||
DebugManager.log_info("Settings navigation: index " + str(current_control_index), "Settings")
|
||||
|
||||
func _adjust_current_control(direction: int):
|
||||
|
||||
func _adjust_current_control(direction: int) -> void:
|
||||
if current_control_index < 0 or current_control_index >= navigable_controls.size():
|
||||
return
|
||||
|
||||
var control = navigable_controls[current_control_index]
|
||||
var control: Control = navigable_controls[current_control_index]
|
||||
|
||||
# Handle sliders
|
||||
if control is HSlider:
|
||||
var slider = control as HSlider
|
||||
var step = slider.step if slider.step > 0 else 0.1
|
||||
var new_value = slider.value + (direction * step)
|
||||
var slider: HSlider = control as HSlider
|
||||
var step: float = slider.step if slider.step > 0 else 0.1
|
||||
var new_value: float = slider.value + (direction * step)
|
||||
new_value = clamp(new_value, slider.min_value, slider.max_value)
|
||||
slider.value = new_value
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Slider adjusted: %s = %f" % [_get_control_name(control), new_value], "Settings")
|
||||
DebugManager.log_info(
|
||||
"Slider adjusted: %s = %f" % [_get_control_name(control), new_value], "Settings"
|
||||
)
|
||||
|
||||
# Handle language stepper with left/right
|
||||
elif control == language_stepper:
|
||||
if language_stepper.handle_input_action("move_left" if direction == -1 else "move_right"):
|
||||
AudioManager.play_ui_click()
|
||||
|
||||
func _activate_current_control():
|
||||
|
||||
func _activate_current_control() -> void:
|
||||
if current_control_index < 0 or current_control_index >= navigable_controls.size():
|
||||
return
|
||||
|
||||
var control = navigable_controls[current_control_index]
|
||||
var control: Control = navigable_controls[current_control_index]
|
||||
|
||||
# Handle buttons
|
||||
if control is Button:
|
||||
@@ -193,7 +203,8 @@ func _activate_current_control():
|
||||
elif control == language_stepper:
|
||||
DebugManager.log_info("Language stepper selected - use left/right to change", "Settings")
|
||||
|
||||
func _update_visual_selection():
|
||||
|
||||
func _update_visual_selection() -> void:
|
||||
for i in range(navigable_controls.size()):
|
||||
var control = navigable_controls[i]
|
||||
if i == current_control_index:
|
||||
@@ -211,6 +222,7 @@ func _update_visual_selection():
|
||||
control.scale = original_control_scales[i]
|
||||
control.modulate = original_control_modulates[i]
|
||||
|
||||
|
||||
func _get_control_name(control: Control) -> String:
|
||||
if control == master_slider:
|
||||
return "master_volume"
|
||||
@@ -223,10 +235,15 @@ func _get_control_name(control: Control) -> String:
|
||||
else:
|
||||
return "button"
|
||||
|
||||
func _on_language_stepper_value_changed(new_value: String, new_index: int):
|
||||
DebugManager.log_info("Language changed via ValueStepper: " + new_value + " (index: " + str(new_index) + ")", "Settings")
|
||||
|
||||
func _setup_confirmation_dialog():
|
||||
func _on_language_stepper_value_changed(new_value: String, new_index: float) -> void:
|
||||
DebugManager.log_info(
|
||||
"Language changed via ValueStepper: " + new_value + " (index: " + str(int(new_index)) + ")",
|
||||
"Settings"
|
||||
)
|
||||
|
||||
|
||||
func _setup_confirmation_dialog() -> void:
|
||||
"""Create confirmation dialog for progress reset"""
|
||||
confirmation_dialog = AcceptDialog.new()
|
||||
confirmation_dialog.title = tr("confirm_reset_title")
|
||||
@@ -244,7 +261,8 @@ func _setup_confirmation_dialog():
|
||||
|
||||
add_child(confirmation_dialog)
|
||||
|
||||
func _on_reset_progress_button_pressed():
|
||||
|
||||
func _on_reset_progress_button_pressed() -> void:
|
||||
"""Handle reset progress button press with confirmation"""
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Reset progress button pressed", "Settings")
|
||||
@@ -257,7 +275,8 @@ func _on_reset_progress_button_pressed():
|
||||
# Show confirmation dialog
|
||||
confirmation_dialog.popup_centered()
|
||||
|
||||
func _on_reset_progress_confirmed():
|
||||
|
||||
func _on_reset_progress_confirmed() -> void:
|
||||
"""Actually reset the progress after confirmation"""
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Progress reset confirmed by user", "Settings")
|
||||
@@ -267,7 +286,7 @@ func _on_reset_progress_confirmed():
|
||||
DebugManager.log_info("All progress successfully reset", "Settings")
|
||||
|
||||
# Show success message
|
||||
var success_dialog = AcceptDialog.new()
|
||||
var success_dialog: AcceptDialog = AcceptDialog.new()
|
||||
success_dialog.title = tr("reset_success_title")
|
||||
success_dialog.dialog_text = tr("reset_success_message")
|
||||
success_dialog.ok_button_text = tr("ok")
|
||||
@@ -283,7 +302,7 @@ func _on_reset_progress_confirmed():
|
||||
DebugManager.log_error("Failed to reset progress", "Settings")
|
||||
|
||||
# Show error message
|
||||
var error_dialog = AcceptDialog.new()
|
||||
var error_dialog: AcceptDialog = AcceptDialog.new()
|
||||
error_dialog.title = tr("reset_error_title")
|
||||
error_dialog.dialog_text = tr("reset_error_message")
|
||||
error_dialog.ok_button_text = tr("ok")
|
||||
@@ -291,7 +310,8 @@ func _on_reset_progress_confirmed():
|
||||
error_dialog.popup_centered()
|
||||
error_dialog.confirmed.connect(func(): error_dialog.queue_free())
|
||||
|
||||
func _on_reset_progress_canceled():
|
||||
|
||||
func _on_reset_progress_canceled() -> void:
|
||||
"""Handle reset progress cancellation"""
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Progress reset canceled by user", "Settings")
|
||||
|
||||
@@ -29,7 +29,8 @@ var original_scale: Vector2
|
||||
var original_modulate: Color
|
||||
var is_highlighted: bool = false
|
||||
|
||||
func _ready():
|
||||
|
||||
func _ready() -> void:
|
||||
DebugManager.log_info("ValueStepper ready for: " + data_source, "ValueStepper")
|
||||
|
||||
# Store original visual properties
|
||||
@@ -47,8 +48,9 @@ func _ready():
|
||||
_load_data()
|
||||
_update_display()
|
||||
|
||||
|
||||
## Loads data based on the data_source type
|
||||
func _load_data():
|
||||
func _load_data() -> void:
|
||||
match data_source:
|
||||
"language":
|
||||
_load_language_data()
|
||||
@@ -59,8 +61,9 @@ func _load_data():
|
||||
_:
|
||||
DebugManager.log_warn("Unknown data_source: " + data_source, "ValueStepper")
|
||||
|
||||
func _load_language_data():
|
||||
var languages_data = SettingsManager.get_languages_data()
|
||||
|
||||
func _load_language_data() -> void:
|
||||
var languages_data: Dictionary = SettingsManager.get_languages_data()
|
||||
if languages_data.has("languages"):
|
||||
values.clear()
|
||||
display_names.clear()
|
||||
@@ -69,28 +72,31 @@ func _load_language_data():
|
||||
display_names.append(languages_data.languages[lang_code]["display_name"])
|
||||
|
||||
# Set current index based on current language
|
||||
var current_lang = SettingsManager.get_setting("language")
|
||||
var index = values.find(current_lang)
|
||||
var current_lang: String = SettingsManager.get_setting("language")
|
||||
var index: int = values.find(current_lang)
|
||||
current_index = max(0, index)
|
||||
|
||||
DebugManager.log_info("Loaded %d languages" % values.size(), "ValueStepper")
|
||||
|
||||
func _load_resolution_data():
|
||||
|
||||
func _load_resolution_data() -> void:
|
||||
# Example resolution data - customize as needed
|
||||
values = ["1920x1080", "1366x768", "1280x720", "1024x768"]
|
||||
display_names = ["1920×1080 (Full HD)", "1366×768", "1280×720 (HD)", "1024×768"]
|
||||
current_index = 0
|
||||
DebugManager.log_info("Loaded %d resolutions" % values.size(), "ValueStepper")
|
||||
|
||||
func _load_difficulty_data():
|
||||
|
||||
func _load_difficulty_data() -> void:
|
||||
# Example difficulty data - customize as needed
|
||||
values = ["easy", "normal", "hard", "nightmare"]
|
||||
display_names = ["Easy", "Normal", "Hard", "Nightmare"]
|
||||
current_index = 1 # Default to "normal"
|
||||
DebugManager.log_info("Loaded %d difficulty levels" % values.size(), "ValueStepper")
|
||||
|
||||
|
||||
## Updates the display text based on current selection
|
||||
func _update_display():
|
||||
func _update_display() -> void:
|
||||
if values.size() == 0 or current_index < 0 or current_index >= values.size():
|
||||
value_display.text = "N/A"
|
||||
return
|
||||
@@ -100,26 +106,30 @@ func _update_display():
|
||||
else:
|
||||
value_display.text = values[current_index]
|
||||
|
||||
|
||||
## Changes the current value by the specified direction (-1 for previous, +1 for next)
|
||||
func change_value(direction: int):
|
||||
func change_value(direction: int) -> void:
|
||||
if values.size() == 0:
|
||||
DebugManager.log_warn("No values available for: " + data_source, "ValueStepper")
|
||||
return
|
||||
|
||||
var new_index = (current_index + direction) % values.size()
|
||||
var new_index: int = (current_index + direction) % values.size()
|
||||
if new_index < 0:
|
||||
new_index = values.size() - 1
|
||||
|
||||
current_index = new_index
|
||||
var new_value = values[current_index]
|
||||
var new_value: String = values[current_index]
|
||||
|
||||
_update_display()
|
||||
_apply_value_change(new_value, current_index)
|
||||
value_changed.emit(new_value, current_index)
|
||||
DebugManager.log_info("Value changed to: " + new_value + " (index: " + str(current_index) + ")", "ValueStepper")
|
||||
DebugManager.log_info(
|
||||
"Value changed to: " + new_value + " (index: " + str(current_index) + ")", "ValueStepper"
|
||||
)
|
||||
|
||||
|
||||
## Override this method for custom value application logic
|
||||
func _apply_value_change(new_value: String, _index: int):
|
||||
func _apply_value_change(new_value: String, _index: int) -> void:
|
||||
match data_source:
|
||||
"language":
|
||||
SettingsManager.set_setting("language", new_value)
|
||||
@@ -132,29 +142,37 @@ func _apply_value_change(new_value: String, _index: int):
|
||||
# Apply difficulty change logic here
|
||||
DebugManager.log_info("Difficulty would change to: " + new_value, "ValueStepper")
|
||||
|
||||
|
||||
## Sets up custom values for the stepper
|
||||
func setup_custom_values(custom_values: Array[String], custom_display_names: Array[String] = []):
|
||||
func setup_custom_values(
|
||||
custom_values: Array[String], custom_display_names: Array[String] = []
|
||||
) -> void:
|
||||
values = custom_values.duplicate()
|
||||
display_names = custom_display_names.duplicate() if custom_display_names.size() > 0 else values.duplicate()
|
||||
display_names = (
|
||||
custom_display_names.duplicate() if custom_display_names.size() > 0 else values.duplicate()
|
||||
)
|
||||
current_index = 0
|
||||
_update_display()
|
||||
DebugManager.log_info("Setup custom values: " + str(values.size()) + " items", "ValueStepper")
|
||||
|
||||
|
||||
## Gets the current value
|
||||
func get_current_value() -> String:
|
||||
if values.size() > 0 and current_index >= 0 and current_index < values.size():
|
||||
return values[current_index]
|
||||
return ""
|
||||
|
||||
|
||||
## Sets the current value by string
|
||||
func set_current_value(value: String):
|
||||
var index = values.find(value)
|
||||
func set_current_value(value: String) -> void:
|
||||
var index: int = values.find(value)
|
||||
if index >= 0:
|
||||
current_index = index
|
||||
_update_display()
|
||||
|
||||
|
||||
## Visual highlighting for navigation systems
|
||||
func set_highlighted(highlighted: bool):
|
||||
func set_highlighted(highlighted: bool) -> void:
|
||||
is_highlighted = highlighted
|
||||
if highlighted:
|
||||
scale = original_scale * 1.05
|
||||
@@ -163,6 +181,7 @@ func set_highlighted(highlighted: bool):
|
||||
scale = original_scale
|
||||
modulate = original_modulate
|
||||
|
||||
|
||||
## Handle input actions for navigation integration
|
||||
func handle_input_action(action: String) -> bool:
|
||||
match action:
|
||||
@@ -175,16 +194,19 @@ func handle_input_action(action: String) -> bool:
|
||||
_:
|
||||
return false
|
||||
|
||||
func _on_left_button_pressed():
|
||||
|
||||
func _on_left_button_pressed() -> void:
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Left button clicked", "ValueStepper")
|
||||
change_value(-1)
|
||||
|
||||
func _on_right_button_pressed():
|
||||
|
||||
func _on_right_button_pressed() -> void:
|
||||
AudioManager.play_ui_click()
|
||||
DebugManager.log_info("Right button clicked", "ValueStepper")
|
||||
change_value(1)
|
||||
|
||||
|
||||
## For navigation system integration
|
||||
func get_control_name() -> String:
|
||||
return data_source + "_stepper"
|
||||
|
||||
Reference in New Issue
Block a user