Add independent pixelation controls

This commit is contained in:
Alexander Sellite 2026-07-27 14:39:37 -04:00
parent 6fadca19b4
commit c7504d2585
21 changed files with 735 additions and 122 deletions

View file

@ -24,6 +24,12 @@ const FishingShopType = preload("res://ui/fishing_shop.gd")
const FishingShopInteractionType = preload( const FishingShopInteractionType = preload(
"res://world/fishing_shop_interaction.gd" "res://world/fishing_shop_interaction.gd"
) )
const UIPixelationPresenterType = preload(
"res://ui/ui_pixelation_presenter.gd"
)
const PixelationResetOverlayType = preload(
"res://ui/pixelation_reset_overlay.gd"
)
const TITLE_MUSIC_SILENCE_DB: float = -80.0 const TITLE_MUSIC_SILENCE_DB: float = -80.0
@ -43,6 +49,10 @@ const TITLE_MUSIC_SILENCE_DB: float = -80.0
@onready var _save_manager: PlayerSaveManagerType = %PlayerSaveManager @onready var _save_manager: PlayerSaveManagerType = %PlayerSaveManager
@onready var _settings_manager: PlayerSettingsManagerType = %PlayerSettingsManager @onready var _settings_manager: PlayerSettingsManagerType = %PlayerSettingsManager
@onready var _title_music: AudioStreamPlayer = %TitleMusic @onready var _title_music: AudioStreamPlayer = %TitleMusic
@onready var _ui_pixelation: UIPixelationPresenterType = %UIPresentation
@onready var _pixelation_reset: PixelationResetOverlayType = (
%PixelationResetOverlay
)
var _gameplay_started: bool = false var _gameplay_started: bool = false
var _shop_interaction: FishingShopInteractionType var _shop_interaction: FishingShopInteractionType
@ -119,6 +129,22 @@ func _ready() -> void:
_apply_runtime_settings _apply_runtime_settings
): ):
_settings_manager.settings_changed.connect(_apply_runtime_settings) _settings_manager.settings_changed.connect(_apply_runtime_settings)
_ui_pixelation.effective_pixel_size_changed.connect(
_on_effective_ui_pixel_size_changed
)
_game_ui.pixelation_settings_visibility_changed.connect(
_pixelation_reset.set_settings_open
)
_game_ui.crisp_reset_focus_requested.connect(
_pixelation_reset.focus_reset_button
)
_game_ui.interactive_pointer_ui_changed.connect(
_ui_pixelation.set_interactive_ui_open
)
_pixelation_reset.return_to_settings_requested.connect(
_game_ui.focus_open_settings_back_button
)
_pixelation_reset.reset_requested.connect(_reset_pixelation)
_settings_manager.load_settings() _settings_manager.load_settings()
_apply_runtime_settings(_settings_manager.current_settings) _apply_runtime_settings(_settings_manager.current_settings)
_set_gameplay_active(false) _set_gameplay_active(false)
@ -215,6 +241,18 @@ func _process(_delta: float) -> void:
func _apply_runtime_settings(settings: PlayerSettingsType) -> void: func _apply_runtime_settings(settings: PlayerSettingsType) -> void:
if settings == null: if settings == null:
return return
var root_viewport: Viewport = get_viewport()
root_viewport.scaling_3d_mode = Viewport.SCALING_3D_MODE_NEAREST
root_viewport.scaling_3d_scale = PlayerSettingsType.get_world_render_scale(
settings.world_pixel_size
)
root_viewport.msaa_3d = Viewport.MSAA_DISABLED
root_viewport.screen_space_aa = Viewport.SCREEN_SPACE_AA_DISABLED
root_viewport.use_taa = false
_ui_pixelation.set_pixel_size(settings.ui_pixel_size)
_game_ui.get_title_screen().set_world_pixelation(
settings.world_pixel_size
)
_player.apply_camera_settings( _player.apply_camera_settings(
settings.mouse_camera_sensitivity, settings.mouse_camera_sensitivity,
settings.controller_camera_sensitivity, settings.controller_camera_sensitivity,
@ -226,8 +264,24 @@ func _apply_runtime_settings(settings: PlayerSettingsType) -> void:
) )
func _on_effective_ui_pixel_size_changed(
_requested_pixel_size: int,
effective_pixel_size: int,
) -> void:
_game_ui.set_effective_ui_pixel_size(effective_pixel_size)
func _reset_pixelation() -> void:
if _settings_manager.apply_pixelation(
PlayerSettingsType.DEFAULT_WORLD_PIXEL_SIZE,
PlayerSettingsType.DEFAULT_UI_PIXEL_SIZE
):
_game_ui.refresh_open_settings_panel()
func _set_gameplay_active(active: bool) -> void: func _set_gameplay_active(active: bool) -> void:
_gameplay_started = active _gameplay_started = active
_ui_pixelation.set_gameplay_active(active)
if not active: if not active:
_player.item_effects.reset_all() _player.item_effects.reset_all()
_player.set_movement_enabled(active) _player.set_movement_enabled(active)

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=14 format=3] [gd_scene load_steps=16 format=3]
[ext_resource type="PackedScene" path="res://world/test_world.tscn" id="1_world"] [ext_resource type="PackedScene" path="res://world/test_world.tscn" id="1_world"]
[ext_resource type="PackedScene" path="res://player/player.tscn" id="2_player"] [ext_resource type="PackedScene" path="res://player/player.tscn" id="2_player"]
@ -13,6 +13,8 @@
[ext_resource type="Resource" path="res://items/catalog/item_catalog.tres" id="11_items"] [ext_resource type="Resource" path="res://items/catalog/item_catalog.tres" id="11_items"]
[ext_resource type="Resource" path="res://economy/buyers/main_fishing_shop.tres" id="12_main_shop"] [ext_resource type="Resource" path="res://economy/buyers/main_fishing_shop.tres" id="12_main_shop"]
[ext_resource type="AudioStream" path="res://audio/music/title/as_in_four_wolves.ogg" id="13_title_music"] [ext_resource type="AudioStream" path="res://audio/music/title/as_in_four_wolves.ogg" id="13_title_music"]
[ext_resource type="Script" path="res://ui/ui_pixelation_presenter.gd" id="14_pixelation"]
[ext_resource type="PackedScene" path="res://ui/pixelation_reset_overlay.tscn" id="15_reset"]
[node name="Main" type="Node3D"] [node name="Main" type="Node3D"]
script = ExtResource("3_main") script = ExtResource("3_main")
@ -51,5 +53,23 @@ stream = ExtResource("13_title_music")
volume_db = -80.0 volume_db = -80.0
bus = &"Music" bus = &"Music"
[node name="GameUI" parent="." instance=ExtResource("5_ui")] [node name="UIPresentation" type="SubViewportContainer" parent="."]
unique_name_in_owner = true
texture_filter = 1
offset_right = 1152.0
offset_bottom = 648.0
mouse_filter = 0
stretch = true
script = ExtResource("14_pixelation")
[node name="UIViewport" type="SubViewport" parent="UIPresentation"]
transparent_bg = true
handle_input_locally = false
size = Vector2i(1152, 648)
render_target_update_mode = 4
[node name="GameUI" parent="UIPresentation/UIViewport" instance=ExtResource("5_ui")]
unique_name_in_owner = true
[node name="PixelationResetOverlay" parent="." instance=ExtResource("15_reset")]
unique_name_in_owner = true unique_name_in_owner = true

View file

@ -18,7 +18,7 @@ config/icon="res://icon.svg"
[display] [display]
window/stretch/mode="canvas_items" window/stretch/mode="disabled"
window/stretch/aspect="expand" window/stretch/aspect="expand"
[gui] [gui]

View file

@ -7,12 +7,22 @@ const MIN_MOUSE_SENSITIVITY: float = 0.001
const MAX_MOUSE_SENSITIVITY: float = 0.012 const MAX_MOUSE_SENSITIVITY: float = 0.012
const MIN_CONTROLLER_SENSITIVITY: float = 0.5 const MIN_CONTROLLER_SENSITIVITY: float = 0.5
const MAX_CONTROLLER_SENSITIVITY: float = 5.0 const MAX_CONTROLLER_SENSITIVITY: float = 5.0
const MIN_WORLD_PIXEL_SIZE: int = 1
const MAX_WORLD_PIXEL_SIZE: int = 5
const DEFAULT_WORLD_PIXEL_SIZE: int = 3
const MIN_UI_PIXEL_SIZE: int = 1
const MAX_UI_PIXEL_SIZE: int = 5
const DEFAULT_UI_PIXEL_SIZE: int = 3
const WORLD_RENDER_SCALES: Array[float] = [1.0, 0.9, 0.8, 0.65, 0.45]
const UI_RENDER_SCALES: Array[float] = [1.0, 0.975, 0.95, 0.925, 0.9]
@export var auto_click_enabled: bool = false @export var auto_click_enabled: bool = false
@export_range(0.10, 0.50, 0.01) var auto_click_interval: float = 0.20 @export_range(0.10, 0.50, 0.01) var auto_click_interval: float = 0.20
@export_range(0.001, 0.012, 0.0005) var mouse_camera_sensitivity: float = 0.005 @export_range(0.001, 0.012, 0.0005) var mouse_camera_sensitivity: float = 0.005
@export_range(0.5, 5.0, 0.1) var controller_camera_sensitivity: float = 2.5 @export_range(0.5, 5.0, 0.1) var controller_camera_sensitivity: float = 2.5
@export var invert_camera_y: bool = false @export var invert_camera_y: bool = false
@export_range(1, 5, 1) var world_pixel_size: int = DEFAULT_WORLD_PIXEL_SIZE
@export_range(1, 5, 1) var ui_pixel_size: int = DEFAULT_UI_PIXEL_SIZE
func is_valid() -> bool: func is_valid() -> bool:
@ -26,6 +36,10 @@ func is_valid() -> bool:
and is_finite(controller_camera_sensitivity) and is_finite(controller_camera_sensitivity)
and controller_camera_sensitivity >= MIN_CONTROLLER_SENSITIVITY and controller_camera_sensitivity >= MIN_CONTROLLER_SENSITIVITY
and controller_camera_sensitivity <= MAX_CONTROLLER_SENSITIVITY and controller_camera_sensitivity <= MAX_CONTROLLER_SENSITIVITY
and world_pixel_size >= MIN_WORLD_PIXEL_SIZE
and world_pixel_size <= MAX_WORLD_PIXEL_SIZE
and ui_pixel_size >= MIN_UI_PIXEL_SIZE
and ui_pixel_size <= MAX_UI_PIXEL_SIZE
) )
@ -36,4 +50,24 @@ func copy() -> PlayerSettings:
result.mouse_camera_sensitivity = mouse_camera_sensitivity result.mouse_camera_sensitivity = mouse_camera_sensitivity
result.controller_camera_sensitivity = controller_camera_sensitivity result.controller_camera_sensitivity = controller_camera_sensitivity
result.invert_camera_y = invert_camera_y result.invert_camera_y = invert_camera_y
result.world_pixel_size = world_pixel_size
result.ui_pixel_size = ui_pixel_size
return result return result
static func get_world_render_scale(pixel_size: int) -> float:
var index: int = clampi(
pixel_size,
MIN_WORLD_PIXEL_SIZE,
MAX_WORLD_PIXEL_SIZE
) - 1
return WORLD_RENDER_SCALES[index]
static func get_ui_render_scale(pixel_size: int) -> float:
var index: int = clampi(
pixel_size,
MIN_UI_PIXEL_SIZE,
MAX_UI_PIXEL_SIZE
) - 1
return UI_RENDER_SCALES[index]

View file

@ -39,6 +39,9 @@ func load_settings() -> bool:
return _use_defaults_after_corruption("Player settings structure is invalid.") return _use_defaults_after_corruption("Player settings structure is invalid.")
var accessibility: Dictionary = data["accessibility"] var accessibility: Dictionary = data["accessibility"]
var camera: Dictionary = data["camera"] var camera: Dictionary = data["camera"]
var presentation: Dictionary = {}
if typeof(data.get("presentation")) == TYPE_DICTIONARY:
presentation = data["presentation"]
if ( if (
typeof(accessibility.get("auto_click_enabled")) != TYPE_BOOL typeof(accessibility.get("auto_click_enabled")) != TYPE_BOOL
or typeof(camera.get("invert_vertical")) != TYPE_BOOL or typeof(camera.get("invert_vertical")) != TYPE_BOOL
@ -59,6 +62,24 @@ func load_settings() -> bool:
-1.0 -1.0
) )
loaded.invert_camera_y = camera["invert_vertical"] loaded.invert_camera_y = camera["invert_vertical"]
loaded.world_pixel_size = _read_clamped_integer(
presentation.get(
"world_pixel_size",
PlayerSettings.DEFAULT_WORLD_PIXEL_SIZE
),
PlayerSettings.MIN_WORLD_PIXEL_SIZE,
PlayerSettings.MAX_WORLD_PIXEL_SIZE,
PlayerSettings.DEFAULT_WORLD_PIXEL_SIZE
)
loaded.ui_pixel_size = _read_clamped_integer(
presentation.get(
"ui_pixel_size",
PlayerSettings.DEFAULT_UI_PIXEL_SIZE
),
PlayerSettings.MIN_UI_PIXEL_SIZE,
PlayerSettings.MAX_UI_PIXEL_SIZE,
PlayerSettings.DEFAULT_UI_PIXEL_SIZE
)
if not loaded.is_valid(): if not loaded.is_valid():
return _use_defaults_after_corruption("Player settings values are invalid.") return _use_defaults_after_corruption("Player settings values are invalid.")
current_settings = loaded current_settings = loaded
@ -80,6 +101,21 @@ func apply_settings(settings: PlayerSettings) -> bool:
return true return true
func apply_pixelation(world_pixel_size: int, ui_pixel_size: int) -> bool:
var edited: PlayerSettings = current_settings.copy()
edited.world_pixel_size = clampi(
world_pixel_size,
PlayerSettings.MIN_WORLD_PIXEL_SIZE,
PlayerSettings.MAX_WORLD_PIXEL_SIZE
)
edited.ui_pixel_size = clampi(
ui_pixel_size,
PlayerSettings.MIN_UI_PIXEL_SIZE,
PlayerSettings.MAX_UI_PIXEL_SIZE
)
return apply_settings(edited)
func save_now() -> bool: func save_now() -> bool:
if current_settings == null or not current_settings.is_valid(): if current_settings == null or not current_settings.is_valid():
return false return false
@ -94,6 +130,10 @@ func save_now() -> bool:
"controller_sensitivity": current_settings.controller_camera_sensitivity, "controller_sensitivity": current_settings.controller_camera_sensitivity,
"invert_vertical": current_settings.invert_camera_y, "invert_vertical": current_settings.invert_camera_y,
}, },
"presentation": {
"world_pixel_size": current_settings.world_pixel_size,
"ui_pixel_size": current_settings.ui_pixel_size,
},
} }
var file := FileAccess.open(TEMP_PATH, FileAccess.WRITE) var file := FileAccess.open(TEMP_PATH, FileAccess.WRITE)
if file == null: if file == null:
@ -160,6 +200,16 @@ func _read_float(value: Variant, fallback: float) -> float:
return result if is_finite(result) else fallback return result if is_finite(result) else fallback
func _read_clamped_integer(
value: Variant,
minimum: int,
maximum: int,
fallback: int,
) -> int:
var result: int = _read_integer(value, fallback)
return clampi(result, minimum, maximum)
func _rename_file(from_path: String, to_path: String) -> bool: func _rename_file(from_path: String, to_path: String) -> bool:
return DirAccess.rename_absolute( return DirAccess.rename_absolute(
ProjectSettings.globalize_path(from_path), ProjectSettings.globalize_path(from_path),

View file

@ -38,10 +38,10 @@ anchor_left = 0.5
anchor_top = 0.5 anchor_top = 0.5
anchor_right = 0.5 anchor_right = 0.5
anchor_bottom = 0.5 anchor_bottom = 0.5
offset_left = -480.0 offset_left = -560.0
offset_top = -310.0 offset_top = -320.0
offset_right = 480.0 offset_right = 560.0
offset_bottom = 310.0 offset_bottom = 320.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
@ -64,7 +64,7 @@ theme_override_constants/separation = 8
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
text = "fishing shop" text = "fishing shop"
theme_override_font_sizes/font_size = 24 theme_override_font_sizes/font_size = 36
theme_override_colors/font_color = Color(0.208, 0.725, 0.78, 1) theme_override_colors/font_color = Color(0.208, 0.725, 0.78, 1)
[node name="CoinIcon" type="TextureRect" parent="ShopPanel/Margin/Layout/Header"] [node name="CoinIcon" type="TextureRect" parent="ShopPanel/Margin/Layout/Header"]
@ -84,7 +84,7 @@ text = "wallet: $0"
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
text = "close" text = "close"
custom_minimum_size = Vector2(72, 30) custom_minimum_size = Vector2(110, 58)
[node name="Feedback" type="Label" parent="ShopPanel/Margin/Layout"] [node name="Feedback" type="Label" parent="ShopPanel/Margin/Layout"]
unique_name_in_owner = true unique_name_in_owner = true
@ -108,7 +108,7 @@ theme_override_constants/separation = 6
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
text = "sell individual cooler fish • full base value" text = "sell individual cooler fish • full base value"
theme_override_font_sizes/font_size = 17 theme_override_font_sizes/font_size = 26
[node name="SalesBody" type="HSplitContainer" parent="ShopPanel/Margin/Layout/Body/FishSales"] [node name="SalesBody" type="HSplitContainer" parent="ShopPanel/Margin/Layout/Body/FishSales"]
layout_mode = 2 layout_mode = 2
@ -173,7 +173,7 @@ unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
text = "select a fish" text = "select a fish"
horizontal_alignment = 1 horizontal_alignment = 1
theme_override_font_sizes/font_size = 19 theme_override_font_sizes/font_size = 29
[node name="FishDetails" type="Label" parent="ShopPanel/Margin/Layout/Body/FishSales/SalesBody/FishDetail/DetailMargin/DetailStack"] [node name="FishDetails" type="Label" parent="ShopPanel/Margin/Layout/Body/FishSales/SalesBody/FishDetail/DetailMargin/DetailStack"]
unique_name_in_owner = true unique_name_in_owner = true
@ -204,7 +204,7 @@ theme_override_constants/separation = 8
[node name="UpgradeTitle" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades"] [node name="UpgradeTitle" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades"]
layout_mode = 2 layout_mode = 2
text = "fishing upgrades" text = "fishing upgrades"
theme_override_font_sizes/font_size = 17 theme_override_font_sizes/font_size = 26
[node name="Supplies" type="VBoxContainer" parent="ShopPanel/Margin/Layout/Body"] [node name="Supplies" type="VBoxContainer" parent="ShopPanel/Margin/Layout/Body"]
custom_minimum_size = Vector2(210, 0) custom_minimum_size = Vector2(210, 0)
@ -214,7 +214,7 @@ theme_override_constants/separation = 6
[node name="Title" type="Label" parent="ShopPanel/Margin/Layout/Body/Supplies"] [node name="Title" type="Label" parent="ShopPanel/Margin/Layout/Body/Supplies"]
layout_mode = 2 layout_mode = 2
text = "supplies" text = "supplies"
theme_override_font_sizes/font_size = 17 theme_override_font_sizes/font_size = 26
[node name="Scroll" type="ScrollContainer" parent="ShopPanel/Margin/Layout/Body/Supplies"] [node name="Scroll" type="ScrollContainer" parent="ShopPanel/Margin/Layout/Body/Supplies"]
layout_mode = 2 layout_mode = 2
@ -256,7 +256,7 @@ size_flags_horizontal = 3
[node name="Name" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/ReelCard/Margin/Row/Data"] [node name="Name" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/ReelCard/Margin/Row/Data"]
layout_mode = 2 layout_mode = 2
text = "reel speed" text = "reel speed"
theme_override_font_sizes/font_size = 17 theme_override_font_sizes/font_size = 26
[node name="ReelLevel" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/ReelCard/Margin/Row/Data"] [node name="ReelLevel" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/ReelCard/Margin/Row/Data"]
unique_name_in_owner = true unique_name_in_owner = true
@ -307,7 +307,7 @@ size_flags_horizontal = 3
[node name="Name" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/BarrierCard/Margin/Row/Data"] [node name="Name" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/BarrierCard/Margin/Row/Data"]
layout_mode = 2 layout_mode = 2
text = "barrier power" text = "barrier power"
theme_override_font_sizes/font_size = 17 theme_override_font_sizes/font_size = 26
[node name="BarrierLevel" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/BarrierCard/Margin/Row/Data"] [node name="BarrierLevel" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/BarrierCard/Margin/Row/Data"]
unique_name_in_owner = true unique_name_in_owner = true
@ -358,7 +358,7 @@ size_flags_horizontal = 3
[node name="Name" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/CoolerCard/Margin/Row/Data"] [node name="Name" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/CoolerCard/Margin/Row/Data"]
layout_mode = 2 layout_mode = 2
text = "cooler capacity" text = "cooler capacity"
theme_override_font_sizes/font_size = 17 theme_override_font_sizes/font_size = 26
[node name="CoolerLevel" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/CoolerCard/Margin/Row/Data"] [node name="CoolerLevel" type="Label" parent="ShopPanel/Margin/Layout/Body/Upgrades/CoolerCard/Margin/Row/Data"]
unique_name_in_owner = true unique_name_in_owner = true
@ -390,10 +390,10 @@ anchor_left = 0.5
anchor_top = 0.5 anchor_top = 0.5
anchor_right = 0.5 anchor_right = 0.5
anchor_bottom = 0.5 anchor_bottom = 0.5
offset_left = -220.0 offset_left = -320.0
offset_top = -90.0 offset_top = -150.0
offset_right = 220.0 offset_right = 320.0
offset_bottom = 90.0 offset_bottom = 150.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2

View file

@ -146,7 +146,7 @@ corner_radius_bottom_left = 6
[resource] [resource]
default_font = ExtResource("1_font") default_font = ExtResource("1_font")
default_font_size = 15 default_font_size = 23
Label/colors/font_color = Color(0.956, 0.972, 0.976, 1) Label/colors/font_color = Color(0.956, 0.972, 0.976, 1)
Label/colors/font_shadow_color = Color(0, 0, 0, 0) Label/colors/font_shadow_color = Color(0, 0, 0, 0)
PanelContainer/styles/panel = SubResource("Panel") PanelContainer/styles/panel = SubResource("Panel")

View file

@ -17,6 +17,7 @@ const HotbarUIType = preload("res://ui/hotbar.gd")
const TitleScreenType = preload("res://ui/title_screen.gd") const TitleScreenType = preload("res://ui/title_screen.gd")
const PauseMenuType = preload("res://ui/pause_menu.gd") const PauseMenuType = preload("res://ui/pause_menu.gd")
const FishingShopType = preload("res://ui/fishing_shop.gd") const FishingShopType = preload("res://ui/fishing_shop.gd")
const SettingsPanelType = preload("res://ui/settings_panel.gd")
const PlayerFishingUpgradesType = preload( const PlayerFishingUpgradesType = preload(
"res://progression/player_fishing_upgrades.gd" "res://progression/player_fishing_upgrades.gd"
) )
@ -30,6 +31,10 @@ const PlayerCoolerCapacityType = preload(
"res://progression/player_cooler_capacity.gd" "res://progression/player_cooler_capacity.gd"
) )
signal pixelation_settings_visibility_changed(is_visible: bool)
signal crisp_reset_focus_requested
signal interactive_pointer_ui_changed(is_open: bool)
@onready var _status_label: Label = %StatusLabel @onready var _status_label: Label = %StatusLabel
@onready var _catch_track: Control = %CatchTrack @onready var _catch_track: Control = %CatchTrack
@onready var _green_catch_progress: ProgressBar = %GreenCatchProgress @onready var _green_catch_progress: ProgressBar = %GreenCatchProgress
@ -47,6 +52,12 @@ const PlayerCoolerCapacityType = preload(
@onready var _fishing_shop: FishingShopType = %FishingShop @onready var _fishing_shop: FishingShopType = %FishingShop
@onready var _shop_prompt: PanelContainer = %ShopPrompt @onready var _shop_prompt: PanelContainer = %ShopPrompt
@onready var _effect_status: Label = %EffectStatus @onready var _effect_status: Label = %EffectStatus
@onready var _title_settings_panel: SettingsPanelType = (
$UIRoot/TitleScreen/SettingsPanel
)
@onready var _pause_settings_panel: SettingsPanelType = (
$UIRoot/PauseMenu/SettingsCenter/SettingsPanel
)
var _showcase_active: bool = false var _showcase_active: bool = false
var _player_menu_open: bool = false var _player_menu_open: bool = false
@ -57,6 +68,21 @@ var _shop_open: bool = false
var _item_effects: PlayerItemEffectsType var _item_effects: PlayerItemEffectsType
func _ready() -> void:
_title_settings_panel.panel_visibility_changed.connect(
_on_settings_visibility_changed
)
_pause_settings_panel.panel_visibility_changed.connect(
_on_settings_visibility_changed
)
_title_settings_panel.crisp_reset_focus_requested.connect(
crisp_reset_focus_requested.emit
)
_pause_settings_panel.crisp_reset_focus_requested.connect(
crisp_reset_focus_requested.emit
)
func setup( func setup(
player: PlayerType, player: PlayerType,
inventory: FishInventoryType, inventory: FishInventoryType,
@ -195,6 +221,7 @@ func set_system_menu_open(is_open: bool) -> void:
_hotbar_ui.set_drag_enabled(_player_menu_open and not is_open) _hotbar_ui.set_drag_enabled(_player_menu_open and not is_open)
if is_open: if is_open:
_shop_prompt.hide() _shop_prompt.hide()
_emit_interactive_pointer_ui_changed()
func get_fishing_shop() -> FishingShopType: func get_fishing_shop() -> FishingShopType:
@ -219,6 +246,29 @@ func get_title_screen() -> TitleScreenType:
return _title_screen return _title_screen
func set_effective_ui_pixel_size(pixel_size: int) -> void:
_title_settings_panel.set_effective_ui_pixel_size(pixel_size)
_pause_settings_panel.set_effective_ui_pixel_size(pixel_size)
func focus_open_settings_back_button() -> void:
if _title_settings_panel.visible:
_title_settings_panel.focus_back_button()
elif _pause_settings_panel.visible:
_pause_settings_panel.focus_back_button()
func refresh_open_settings_panel() -> void:
_title_settings_panel.refresh_open_panel()
_pause_settings_panel.refresh_open_panel()
func _on_settings_visibility_changed(_is_visible: bool) -> void:
pixelation_settings_visibility_changed.emit(
_title_settings_panel.visible or _pause_settings_panel.visible
)
func _on_fishing_status_changed(status: String) -> void: func _on_fishing_status_changed(status: String) -> void:
if _showcase_active: if _showcase_active:
return return
@ -391,6 +441,7 @@ func _on_player_menu_visibility_changed(is_open: bool) -> void:
) )
_hotbar_ui.set_drag_enabled(is_open) _hotbar_ui.set_drag_enabled(is_open)
_refresh_fishing_panel_visibility() _refresh_fishing_panel_visibility()
_emit_interactive_pointer_ui_changed()
if is_open: if is_open:
_shop_prompt.hide() _shop_prompt.hide()
@ -408,3 +459,10 @@ func _on_shop_visibility_changed(is_open: bool) -> void:
) )
if is_open: if is_open:
_shop_prompt.hide() _shop_prompt.hide()
_emit_interactive_pointer_ui_changed()
func _emit_interactive_pointer_ui_changed() -> void:
interactive_pointer_ui_changed.emit(
_system_menu_open or _player_menu_open or _shop_open
)

View file

@ -36,7 +36,11 @@ bg_color = Color(0, 0, 0, 0)
[node name="GameUI" type="CanvasLayer"] [node name="GameUI" type="CanvasLayer"]
script = ExtResource("1_ui") script = ExtResource("1_ui")
[node name="FishingPanel" type="PanelContainer" parent="."] [node name="UIRoot" type="Control" parent="."]
unique_name_in_owner = true
mouse_filter = 2
[node name="FishingPanel" type="PanelContainer" parent="UIRoot"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
z_index = 60 z_index = 60
@ -54,33 +58,33 @@ grow_vertical = 0
mouse_filter = 2 mouse_filter = 2
theme = ExtResource("3_theme") theme = ExtResource("3_theme")
[node name="MarginContainer" type="MarginContainer" parent="FishingPanel"] [node name="MarginContainer" type="MarginContainer" parent="UIRoot/FishingPanel"]
theme_override_constants/margin_left = 14 theme_override_constants/margin_left = 14
theme_override_constants/margin_top = 8 theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 14 theme_override_constants/margin_right = 14
theme_override_constants/margin_bottom = 8 theme_override_constants/margin_bottom = 8
[node name="VBoxContainer" type="VBoxContainer" parent="FishingPanel/MarginContainer"] [node name="VBoxContainer" type="VBoxContainer" parent="UIRoot/FishingPanel/MarginContainer"]
theme_override_constants/separation = 4 theme_override_constants/separation = 4
[node name="StatusLabel" type="Label" parent="FishingPanel/MarginContainer/VBoxContainer"] [node name="StatusLabel" type="Label" parent="UIRoot/FishingPanel/MarginContainer/VBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
text = "" text = ""
horizontal_alignment = 1 horizontal_alignment = 1
theme_override_font_sizes/font_size = 16 theme_override_font_sizes/font_size = 16
[node name="ShowcaseDetails" type="Label" parent="FishingPanel/MarginContainer/VBoxContainer"] [node name="ShowcaseDetails" type="Label" parent="UIRoot/FishingPanel/MarginContainer/VBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
horizontal_alignment = 1 horizontal_alignment = 1
[node name="CatchTrack" type="Control" parent="FishingPanel/MarginContainer/VBoxContainer"] [node name="CatchTrack" type="Control" parent="UIRoot/FishingPanel/MarginContainer/VBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
custom_minimum_size = Vector2(0, 20) custom_minimum_size = Vector2(0, 20)
[node name="GreenCatchProgress" type="ProgressBar" parent="FishingPanel/MarginContainer/VBoxContainer/CatchTrack"] [node name="GreenCatchProgress" type="ProgressBar" parent="UIRoot/FishingPanel/MarginContainer/VBoxContainer/CatchTrack"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 1 layout_mode = 1
anchors_preset = 15 anchors_preset = 15
@ -94,7 +98,7 @@ theme_override_styles/fill = SubResource("StyleBox_catch_fill")
value = 0.0 value = 0.0
show_percentage = false show_percentage = false
[node name="RedChaseProgress" type="ProgressBar" parent="FishingPanel/MarginContainer/VBoxContainer/CatchTrack"] [node name="RedChaseProgress" type="ProgressBar" parent="UIRoot/FishingPanel/MarginContainer/VBoxContainer/CatchTrack"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 1 layout_mode = 1
anchors_preset = 15 anchors_preset = 15
@ -108,7 +112,7 @@ theme_override_styles/fill = SubResource("StyleBox_chase_fill")
value = 0.0 value = 0.0
show_percentage = false show_percentage = false
[node name="BarrierMarkers" type="Control" parent="FishingPanel/MarginContainer/VBoxContainer/CatchTrack"] [node name="BarrierMarkers" type="Control" parent="UIRoot/FishingPanel/MarginContainer/VBoxContainer/CatchTrack"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 1 layout_mode = 1
anchors_preset = 15 anchors_preset = 15
@ -118,23 +122,23 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
mouse_filter = 2 mouse_filter = 2
[node name="BarrierSummary" type="Label" parent="FishingPanel/MarginContainer/VBoxContainer"] [node name="BarrierSummary" type="Label" parent="UIRoot/FishingPanel/MarginContainer/VBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
horizontal_alignment = 1 horizontal_alignment = 1
[node name="BarrierHealth" type="Label" parent="FishingPanel/MarginContainer/VBoxContainer"] [node name="BarrierHealth" type="Label" parent="UIRoot/FishingPanel/MarginContainer/VBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
horizontal_alignment = 1 horizontal_alignment = 1
[node name="PlayerMenu" parent="." instance=ExtResource("2_menu")] [node name="PlayerMenu" parent="UIRoot" instance=ExtResource("2_menu")]
unique_name_in_owner = true unique_name_in_owner = true
[node name="Hotbar" parent="." instance=ExtResource("7_hotbar")] [node name="Hotbar" parent="UIRoot" instance=ExtResource("7_hotbar")]
unique_name_in_owner = true unique_name_in_owner = true
[node name="ShopPrompt" type="PanelContainer" parent="."] [node name="ShopPrompt" type="PanelContainer" parent="UIRoot"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
z_index = 55 z_index = 55
@ -152,22 +156,22 @@ grow_vertical = 0
mouse_filter = 2 mouse_filter = 2
theme = ExtResource("3_theme") theme = ExtResource("3_theme")
[node name="Margin" type="MarginContainer" parent="ShopPrompt"] [node name="Margin" type="MarginContainer" parent="UIRoot/ShopPrompt"]
layout_mode = 2 layout_mode = 2
theme_override_constants/margin_left = 12 theme_override_constants/margin_left = 12
theme_override_constants/margin_top = 7 theme_override_constants/margin_top = 7
theme_override_constants/margin_right = 12 theme_override_constants/margin_right = 12
theme_override_constants/margin_bottom = 7 theme_override_constants/margin_bottom = 7
[node name="Label" type="Label" parent="ShopPrompt/Margin"] [node name="Label" type="Label" parent="UIRoot/ShopPrompt/Margin"]
layout_mode = 2 layout_mode = 2
text = "press e to open fishing shop" text = "press e to open fishing shop"
horizontal_alignment = 1 horizontal_alignment = 1
[node name="FishingShop" parent="." instance=ExtResource("8_shop")] [node name="FishingShop" parent="UIRoot" instance=ExtResource("8_shop")]
unique_name_in_owner = true unique_name_in_owner = true
[node name="EffectStatus" type="Label" parent="."] [node name="EffectStatus" type="Label" parent="UIRoot"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
z_index = 54 z_index = 54
@ -181,7 +185,7 @@ theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.9)
theme_override_constants/shadow_offset_x = 2 theme_override_constants/shadow_offset_x = 2
theme_override_constants/shadow_offset_y = 2 theme_override_constants/shadow_offset_y = 2
[node name="ScreenFade" type="ColorRect" parent="."] [node name="ScreenFade" type="ColorRect" parent="UIRoot"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
z_index = 100 z_index = 100
@ -194,8 +198,8 @@ mouse_filter = 0
color = Color(0, 0, 0, 1) color = Color(0, 0, 0, 1)
script = ExtResource("4_fade") script = ExtResource("4_fade")
[node name="TitleScreen" parent="." instance=ExtResource("5_title")] [node name="TitleScreen" parent="UIRoot" instance=ExtResource("5_title")]
unique_name_in_owner = true unique_name_in_owner = true
[node name="PauseMenu" parent="." instance=ExtResource("6_pause")] [node name="PauseMenu" parent="UIRoot" instance=ExtResource("6_pause")]
unique_name_in_owner = true unique_name_in_owner = true

View file

@ -38,7 +38,7 @@ grow_vertical = 2
[node name="RootPanel" type="PanelContainer" parent="RootCenter"] [node name="RootPanel" type="PanelContainer" parent="RootCenter"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(420, 0) custom_minimum_size = Vector2(560, 0)
layout_mode = 2 layout_mode = 2
[node name="Margin" type="MarginContainer" parent="RootCenter/RootPanel"] [node name="Margin" type="MarginContainer" parent="RootCenter/RootPanel"]
@ -54,50 +54,50 @@ theme_override_constants/separation = 11
[node name="Title" type="Label" parent="RootCenter/RootPanel/Margin/Content"] [node name="Title" type="Label" parent="RootCenter/RootPanel/Margin/Content"]
layout_mode = 2 layout_mode = 2
theme_override_font_sizes/font_size = 30 theme_override_font_sizes/font_size = 45
text = "game menu" text = "game menu"
horizontal_alignment = 1 horizontal_alignment = 1
[node name="ResumeButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"] [node name="ResumeButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(0, 43) custom_minimum_size = Vector2(0, 64)
layout_mode = 2 layout_mode = 2
text = "return to game" text = "return to game"
[node name="SaveButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"] [node name="SaveButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(0, 43) custom_minimum_size = Vector2(0, 64)
layout_mode = 2 layout_mode = 2
text = "save now" text = "save now"
[node name="SettingsButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"] [node name="SettingsButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(0, 43) custom_minimum_size = Vector2(0, 64)
layout_mode = 2 layout_mode = 2
text = "settings" text = "settings"
[node name="ReturnToTitleButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"] [node name="ReturnToTitleButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(0, 43) custom_minimum_size = Vector2(0, 64)
layout_mode = 2 layout_mode = 2
text = "return to title" text = "return to title"
[node name="ResetProgressButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"] [node name="ResetProgressButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(0, 43) custom_minimum_size = Vector2(0, 64)
layout_mode = 2 layout_mode = 2
theme_type_variation = &"DangerButton" theme_type_variation = &"DangerButton"
text = "reset progress" text = "reset progress"
[node name="QuitButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"] [node name="QuitButton" type="Button" parent="RootCenter/RootPanel/Margin/Content"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(0, 43) custom_minimum_size = Vector2(0, 64)
layout_mode = 2 layout_mode = 2
text = "quit" text = "quit"
[node name="FeedbackLabel" type="Label" parent="RootCenter/RootPanel/Margin/Content"] [node name="FeedbackLabel" type="Label" parent="RootCenter/RootPanel/Margin/Content"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(0, 34) custom_minimum_size = Vector2(0, 54)
layout_mode = 2 layout_mode = 2
horizontal_alignment = 1 horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
@ -128,7 +128,7 @@ mouse_filter = 2
[node name="ConfirmationPanel" type="PanelContainer" parent="ConfirmationCenter"] [node name="ConfirmationPanel" type="PanelContainer" parent="ConfirmationCenter"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false visible = false
custom_minimum_size = Vector2(520, 0) custom_minimum_size = Vector2(700, 0)
layout_mode = 2 layout_mode = 2
[node name="Margin" type="MarginContainer" parent="ConfirmationCenter/ConfirmationPanel"] [node name="Margin" type="MarginContainer" parent="ConfirmationCenter/ConfirmationPanel"]
@ -146,7 +146,7 @@ theme_override_constants/separation = 15
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
theme_override_colors/font_color = Color(0.937, 0.357, 0.384, 1) theme_override_colors/font_color = Color(0.937, 0.357, 0.384, 1)
theme_override_font_sizes/font_size = 24 theme_override_font_sizes/font_size = 36
text = "confirm" text = "confirm"
horizontal_alignment = 1 horizontal_alignment = 1
@ -164,12 +164,12 @@ alignment = 1
[node name="ConfirmButton" type="Button" parent="ConfirmationCenter/ConfirmationPanel/Margin/Content/Buttons"] [node name="ConfirmButton" type="Button" parent="ConfirmationCenter/ConfirmationPanel/Margin/Content/Buttons"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(190, 43) custom_minimum_size = Vector2(240, 64)
layout_mode = 2 layout_mode = 2
text = "confirm" text = "confirm"
[node name="CancelConfirmButton" type="Button" parent="ConfirmationCenter/ConfirmationPanel/Margin/Content/Buttons"] [node name="CancelConfirmButton" type="Button" parent="ConfirmationCenter/ConfirmationPanel/Margin/Content/Buttons"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(130, 43) custom_minimum_size = Vector2(180, 64)
layout_mode = 2 layout_mode = 2
text = "cancel" text = "cancel"

View file

@ -0,0 +1,32 @@
class_name PixelationResetOverlay
extends CanvasLayer
signal reset_requested
signal return_to_settings_requested
@onready var _reset_button: Button = %ResetPixelationButton
func _ready() -> void:
_reset_button.pressed.connect(reset_requested.emit)
_reset_button.gui_input.connect(_on_reset_button_gui_input)
func set_settings_open(is_open: bool) -> void:
visible = is_open
if not is_open and _reset_button.has_focus():
_reset_button.release_focus()
func focus_reset_button() -> void:
if visible:
_reset_button.grab_focus()
func _on_reset_button_gui_input(event: InputEvent) -> void:
if (
event.is_action_pressed("ui_up")
or event.is_action_pressed("ui_focus_prev")
):
return_to_settings_requested.emit()
get_viewport().set_input_as_handled()

View file

@ -0,0 +1 @@
uid://bg7x4pmgy6mhn

View file

@ -0,0 +1,30 @@
[gd_scene load_steps=3 format=3]
[ext_resource type="Script" path="res://ui/pixelation_reset_overlay.gd" id="1_script"]
[ext_resource type="Theme" path="res://ui/game_theme.tres" id="2_theme"]
[node name="PixelationResetOverlay" type="CanvasLayer"]
layer = 300
visible = false
script = ExtResource("1_script")
[node name="ResetAnchor" type="MarginContainer" parent="."]
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -324.0
offset_top = -86.0
offset_right = -16.0
offset_bottom = -16.0
grow_horizontal = 0
grow_vertical = 0
mouse_filter = 2
theme = ExtResource("2_theme")
[node name="ResetPixelationButton" type="Button" parent="ResetAnchor"]
unique_name_in_owner = true
custom_minimum_size = Vector2(308, 70)
layout_mode = 2
text = "reset pixelation"

View file

@ -587,7 +587,7 @@ func _create_inventory_card(fish_catch: FishCatchType) -> Button:
"font_color", "font_color",
UIPalette.SECONDARY UIPalette.SECONDARY
) )
favorite_marker.add_theme_font_size_override("font_size", 18) favorite_marker.add_theme_font_size_override("font_size", 27)
favorite_marker.set_anchors_preset(Control.PRESET_TOP_RIGHT) favorite_marker.set_anchors_preset(Control.PRESET_TOP_RIGHT)
favorite_marker.offset_left = -28.0 favorite_marker.offset_left = -28.0
favorite_marker.offset_top = 5.0 favorite_marker.offset_top = 5.0
@ -603,7 +603,7 @@ func _create_inventory_card(fish_catch: FishCatchType) -> Button:
"font_color", "font_color",
UIPalette.SUCCESS UIPalette.SUCCESS
) )
selected_marker.add_theme_font_size_override("font_size", 18) selected_marker.add_theme_font_size_override("font_size", 27)
selected_marker.set_anchors_preset(Control.PRESET_TOP_LEFT) selected_marker.set_anchors_preset(Control.PRESET_TOP_LEFT)
selected_marker.offset_left = 8.0 selected_marker.offset_left = 8.0
selected_marker.offset_top = 5.0 selected_marker.offset_top = 5.0

View file

@ -29,10 +29,10 @@ color = Color(0.015, 0.02, 0.03, 0.72)
[node name="MenuPanel" type="PanelContainer" parent="."] [node name="MenuPanel" type="PanelContainer" parent="."]
layout_mode = 1 layout_mode = 1
anchor_left = 0.07 anchor_left = 0.02
anchor_top = 0.055 anchor_top = 0.025
anchor_right = 0.93 anchor_right = 0.98
anchor_bottom = 0.72 anchor_bottom = 0.96
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
@ -55,7 +55,7 @@ theme_override_constants/separation = 8
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.208, 0.725, 0.78, 1) theme_override_colors/font_color = Color(0.208, 0.725, 0.78, 1)
theme_override_font_sizes/font_size = 22 theme_override_font_sizes/font_size = 33
text = "player menu" text = "player menu"
[node name="WalletBalance" type="Label" parent="MenuPanel/Margin/Layout/Header"] [node name="WalletBalance" type="Label" parent="MenuPanel/Margin/Layout/Header"]
@ -69,27 +69,27 @@ unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
toggle_mode = true toggle_mode = true
text = "cooler" text = "cooler"
custom_minimum_size = Vector2(88, 30) custom_minimum_size = Vector2(130, 58)
[node name="BagTab" type="Button" parent="MenuPanel/Margin/Layout/Header"] [node name="BagTab" type="Button" parent="MenuPanel/Margin/Layout/Header"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
toggle_mode = true toggle_mode = true
text = "bag" text = "bag"
custom_minimum_size = Vector2(76, 30) custom_minimum_size = Vector2(110, 58)
[node name="LogbookTab" type="Button" parent="MenuPanel/Margin/Layout/Header"] [node name="LogbookTab" type="Button" parent="MenuPanel/Margin/Layout/Header"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
toggle_mode = true toggle_mode = true
text = "logbook" text = "logbook"
custom_minimum_size = Vector2(88, 30) custom_minimum_size = Vector2(140, 58)
[node name="CloseButton" type="Button" parent="MenuPanel/Margin/Layout/Header"] [node name="CloseButton" type="Button" parent="MenuPanel/Margin/Layout/Header"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
text = "close" text = "close"
custom_minimum_size = Vector2(68, 30) custom_minimum_size = Vector2(110, 58)
[node name="Separator" type="HSeparator" parent="MenuPanel/Margin/Layout"] [node name="Separator" type="HSeparator" parent="MenuPanel/Margin/Layout"]
layout_mode = 2 layout_mode = 2
@ -100,7 +100,7 @@ layout_mode = 2
text = "" text = ""
horizontal_alignment = 1 horizontal_alignment = 1
theme_override_colors/font_color = Color(1, 0.82, 0.4, 1) theme_override_colors/font_color = Color(1, 0.82, 0.4, 1)
theme_override_font_sizes/font_size = 14 theme_override_font_sizes/font_size = 21
[node name="Content" type="Control" parent="MenuPanel/Margin/Layout"] [node name="Content" type="Control" parent="MenuPanel/Margin/Layout"]
custom_minimum_size = Vector2(0, 260) custom_minimum_size = Vector2(0, 260)
@ -128,12 +128,12 @@ text = "sort:"
[node name="SortOption" type="OptionButton" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] [node name="SortOption" type="OptionButton" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
custom_minimum_size = Vector2(130, 30) custom_minimum_size = Vector2(190, 58)
[node name="SortDirection" type="Button" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] [node name="SortDirection" type="Button" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
custom_minimum_size = Vector2(112, 30) custom_minimum_size = Vector2(190, 58)
text = "newest first" text = "newest first"
[node name="SortSpacer" type="Control" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] [node name="SortSpacer" type="Control" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"]
@ -219,7 +219,7 @@ texture_filter = 1
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
theme_override_colors/font_color = Color(0.208, 0.725, 0.78, 1) theme_override_colors/font_color = Color(0.208, 0.725, 0.78, 1)
theme_override_font_sizes/font_size = 19 theme_override_font_sizes/font_size = 29
horizontal_alignment = 1 horizontal_alignment = 1
[node name="DetailData" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] [node name="DetailData" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"]
@ -339,7 +339,7 @@ texture_filter = 1
[node name="BagDetailName" type="Label" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"] [node name="BagDetailName" type="Label" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
theme_override_font_sizes/font_size = 19 theme_override_font_sizes/font_size = 29
horizontal_alignment = 1 horizontal_alignment = 1
[node name="BagDetailData" type="Label" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"] [node name="BagDetailData" type="Label" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"]
@ -389,10 +389,10 @@ anchor_left = 0.5
anchor_top = 0.5 anchor_top = 0.5
anchor_right = 0.5 anchor_right = 0.5
anchor_bottom = 0.5 anchor_bottom = 0.5
offset_left = -230.0 offset_left = -320.0
offset_top = -105.0 offset_top = -160.0
offset_right = 230.0 offset_right = 320.0
offset_bottom = 105.0 offset_bottom = 160.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
@ -422,10 +422,10 @@ unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
text = "confirm" text = "confirm"
theme_type_variation = &"DangerButton" theme_type_variation = &"DangerButton"
custom_minimum_size = Vector2(120, 38) custom_minimum_size = Vector2(170, 64)
[node name="CancelSaleButton" type="Button" parent="MenuPanel/Margin/Layout/Content/SaleConfirmation/ConfirmationMargin/ConfirmationLayout/ConfirmationButtons"] [node name="CancelSaleButton" type="Button" parent="MenuPanel/Margin/Layout/Content/SaleConfirmation/ConfirmationMargin/ConfirmationLayout/ConfirmationButtons"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
text = "cancel" text = "cancel"
custom_minimum_size = Vector2(120, 38) custom_minimum_size = Vector2(170, 64)

View file

@ -1,12 +1,16 @@
class_name SettingsPanel class_name SettingsPanel
extends PanelContainer extends PanelContainer
const MAX_PANEL_SIZE: Vector2 = Vector2(720.0, 600.0)
const PANEL_EDGE_MARGIN: float = 16.0
const SettingsManagerType = preload( const SettingsManagerType = preload(
"res://settings/player_settings_manager.gd" "res://settings/player_settings_manager.gd"
) )
signal applied signal applied
signal closed signal closed
signal crisp_reset_focus_requested
signal panel_visibility_changed(is_visible: bool)
@onready var _auto_click_toggle: CheckButton = %AutoClickToggle @onready var _auto_click_toggle: CheckButton = %AutoClickToggle
@onready var _auto_click_interval: HSlider = %AutoClickInterval @onready var _auto_click_interval: HSlider = %AutoClickInterval
@ -16,9 +20,15 @@ signal closed
@onready var _controller_sensitivity: HSlider = %ControllerSensitivity @onready var _controller_sensitivity: HSlider = %ControllerSensitivity
@onready var _controller_sensitivity_value: Label = %ControllerSensitivityValue @onready var _controller_sensitivity_value: Label = %ControllerSensitivityValue
@onready var _invert_y_toggle: CheckButton = %InvertYToggle @onready var _invert_y_toggle: CheckButton = %InvertYToggle
@onready var _world_pixel_size: HSlider = %WorldPixelSize
@onready var _world_pixel_size_value: Label = %WorldPixelSizeValue
@onready var _ui_pixel_size: HSlider = %UIPixelSize
@onready var _ui_pixel_size_value: Label = %UIPixelSizeValue
@onready var _feedback: Label = %SettingsFeedback @onready var _feedback: Label = %SettingsFeedback
var _settings_manager: SettingsManagerType var _settings_manager: SettingsManagerType
var _loading_controls: bool = false
var _effective_ui_pixel_size: int = PlayerSettings.DEFAULT_UI_PIXEL_SIZE
func _ready() -> void: func _ready() -> void:
@ -27,6 +37,14 @@ func _ready() -> void:
_auto_click_interval.value_changed.connect(_refresh_value_labels) _auto_click_interval.value_changed.connect(_refresh_value_labels)
_mouse_sensitivity.value_changed.connect(_refresh_value_labels) _mouse_sensitivity.value_changed.connect(_refresh_value_labels)
_controller_sensitivity.value_changed.connect(_refresh_value_labels) _controller_sensitivity.value_changed.connect(_refresh_value_labels)
_world_pixel_size.value_changed.connect(_on_pixel_size_changed)
_ui_pixel_size.value_changed.connect(_on_pixel_size_changed)
%CancelSettingsButton.gui_input.connect(_on_back_button_gui_input)
get_viewport().size_changed.connect(_refresh_panel_size)
var parent_control := get_parent() as Control
if parent_control != null:
parent_control.resized.connect(_refresh_panel_size)
call_deferred("_refresh_panel_size")
func open_panel(settings_manager: SettingsManagerType) -> void: func open_panel(settings_manager: SettingsManagerType) -> void:
@ -34,6 +52,7 @@ func open_panel(settings_manager: SettingsManagerType) -> void:
_load_controls() _load_controls()
_feedback.text = "" _feedback.text = ""
show() show()
panel_visibility_changed.emit(true)
_auto_click_toggle.grab_focus() _auto_click_toggle.grab_focus()
@ -41,6 +60,7 @@ func close_panel() -> void:
if not visible: if not visible:
return return
hide() hide()
panel_visibility_changed.emit(false)
_load_controls() _load_controls()
closed.emit() closed.emit()
@ -55,8 +75,11 @@ func _apply_settings() -> void:
edited.mouse_camera_sensitivity = float(_mouse_sensitivity.value) edited.mouse_camera_sensitivity = float(_mouse_sensitivity.value)
edited.controller_camera_sensitivity = float(_controller_sensitivity.value) edited.controller_camera_sensitivity = float(_controller_sensitivity.value)
edited.invert_camera_y = _invert_y_toggle.button_pressed edited.invert_camera_y = _invert_y_toggle.button_pressed
edited.world_pixel_size = roundi(_world_pixel_size.value)
edited.ui_pixel_size = roundi(_ui_pixel_size.value)
if _settings_manager.apply_settings(edited): if _settings_manager.apply_settings(edited):
hide() hide()
panel_visibility_changed.emit(false)
applied.emit() applied.emit()
else: else:
_feedback.text = "failed to save settings." _feedback.text = "failed to save settings."
@ -65,12 +88,16 @@ func _apply_settings() -> void:
func _load_controls() -> void: func _load_controls() -> void:
if _settings_manager == null or not is_node_ready(): if _settings_manager == null or not is_node_ready():
return return
_loading_controls = true
var settings: PlayerSettings = _settings_manager.current_settings var settings: PlayerSettings = _settings_manager.current_settings
_auto_click_toggle.button_pressed = settings.auto_click_enabled _auto_click_toggle.button_pressed = settings.auto_click_enabled
_auto_click_interval.value = settings.auto_click_interval _auto_click_interval.value = settings.auto_click_interval
_mouse_sensitivity.value = settings.mouse_camera_sensitivity _mouse_sensitivity.value = settings.mouse_camera_sensitivity
_controller_sensitivity.value = settings.controller_camera_sensitivity _controller_sensitivity.value = settings.controller_camera_sensitivity
_invert_y_toggle.button_pressed = settings.invert_camera_y _invert_y_toggle.button_pressed = settings.invert_camera_y
_world_pixel_size.value = settings.world_pixel_size
_ui_pixel_size.value = settings.ui_pixel_size
_loading_controls = false
_refresh_value_labels(0.0) _refresh_value_labels(0.0)
@ -78,3 +105,83 @@ func _refresh_value_labels(_unused: float) -> void:
_auto_click_interval_value.text = "%.2f s" % _auto_click_interval.value _auto_click_interval_value.text = "%.2f s" % _auto_click_interval.value
_mouse_sensitivity_value.text = "%.4f" % _mouse_sensitivity.value _mouse_sensitivity_value.text = "%.4f" % _mouse_sensitivity.value
_controller_sensitivity_value.text = "%.1f" % _controller_sensitivity.value _controller_sensitivity_value.text = "%.1f" % _controller_sensitivity.value
_world_pixel_size_value.text = _pixel_size_label(
roundi(_world_pixel_size.value),
true
)
_ui_pixel_size_value.text = _pixel_size_label(
roundi(_ui_pixel_size.value),
false
)
func _on_pixel_size_changed(_unused: float) -> void:
_refresh_value_labels(0.0)
if _loading_controls or _settings_manager == null:
return
if not _settings_manager.apply_pixelation(
roundi(_world_pixel_size.value),
roundi(_ui_pixel_size.value)
):
_feedback.text = "failed to save pixelation settings."
func _pixel_size_label(pixel_size: int, _is_world: bool) -> String:
var names: PackedStringArray = [
"legible",
"cute",
"retro",
"hardcore",
"wtf",
]
var index: int = clampi(pixel_size - 1, 0, names.size() - 1)
return names[index]
func set_effective_ui_pixel_size(pixel_size: int) -> void:
_effective_ui_pixel_size = clampi(
pixel_size,
PlayerSettings.MIN_UI_PIXEL_SIZE,
PlayerSettings.MAX_UI_PIXEL_SIZE
)
if is_node_ready():
_refresh_value_labels(0.0)
func focus_back_button() -> void:
%CancelSettingsButton.grab_focus()
func refresh_open_panel() -> void:
if visible:
_load_controls()
func _on_back_button_gui_input(event: InputEvent) -> void:
if (
event.is_action_pressed("ui_down")
or event.is_action_pressed("ui_focus_next")
):
crisp_reset_focus_requested.emit()
accept_event()
func _refresh_panel_size() -> void:
if not is_node_ready():
return
var parent_control := get_parent() as Control
if parent_control == null:
return
var available_size: Vector2 = parent_control.size - Vector2.ONE * (
PANEL_EDGE_MARGIN * 2.0
)
var target_size := Vector2(
minf(MAX_PANEL_SIZE.x, maxf(320.0, available_size.x)),
minf(MAX_PANEL_SIZE.y, maxf(240.0, available_size.y))
)
custom_minimum_size = target_size
if parent_control is CenterContainer:
return
set_anchors_preset(Control.PRESET_CENTER)
position = (parent_control.size - target_size) * 0.5
size = target_size

View file

@ -5,7 +5,7 @@
[node name="SettingsPanel" type="PanelContainer"] [node name="SettingsPanel" type="PanelContainer"]
visible = false visible = false
custom_minimum_size = Vector2(600, 490) custom_minimum_size = Vector2(720, 600)
theme = ExtResource("2_theme") theme = ExtResource("2_theme")
script = ExtResource("1_script") script = ExtResource("1_script")
@ -16,35 +16,42 @@ theme_override_constants/margin_top = 24
theme_override_constants/margin_right = 28 theme_override_constants/margin_right = 28
theme_override_constants/margin_bottom = 24 theme_override_constants/margin_bottom = 24
[node name="Content" type="VBoxContainer" parent="Margin"] [node name="Scroll" type="ScrollContainer" parent="Margin"]
layout_mode = 2 layout_mode = 2
horizontal_scroll_mode = 0
[node name="Content" type="VBoxContainer" parent="Margin/Scroll"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 12 theme_override_constants/separation = 12
[node name="Heading" type="Label" parent="Margin/Content"] [node name="Heading" type="Label" parent="Margin/Scroll/Content"]
layout_mode = 2 layout_mode = 2
theme_override_font_sizes/font_size = 26 theme_override_font_sizes/font_size = 39
text = "settings" text = "settings"
horizontal_alignment = 1 horizontal_alignment = 1
[node name="AutoClickToggle" type="CheckButton" parent="Margin/Content"] [node name="AutoClickToggle" type="CheckButton" parent="Margin/Scroll/Content"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
text = "accessibility auto-click" text = "accessibility auto-click"
[node name="AutoClickHelp" type="Label" parent="Margin/Content"] [node name="AutoClickHelp" type="Label" parent="Margin/Scroll/Content"]
layout_mode = 2 layout_mode = 2
text = "lower intervals click barriers faster while held." text = "lower intervals click barriers faster while held."
autowrap_mode = 2
[node name="AutoClickRow" type="HBoxContainer" parent="Margin/Content"] [node name="AutoClickRow" type="HBoxContainer" parent="Margin/Scroll/Content"]
layout_mode = 2 layout_mode = 2
theme_override_constants/separation = 12 theme_override_constants/separation = 12
[node name="Label" type="Label" parent="Margin/Content/AutoClickRow"] [node name="Label" type="Label" parent="Margin/Scroll/Content/AutoClickRow"]
custom_minimum_size = Vector2(190, 0) custom_minimum_size = Vector2(260, 0)
layout_mode = 2 layout_mode = 2
text = "auto-click interval" text = "auto-click interval"
autowrap_mode = 2
[node name="AutoClickInterval" type="HSlider" parent="Margin/Content/AutoClickRow"] [node name="AutoClickInterval" type="HSlider" parent="Margin/Scroll/Content/AutoClickRow"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
@ -53,22 +60,23 @@ max_value = 0.5
step = 0.01 step = 0.01
value = 0.2 value = 0.2
[node name="AutoClickIntervalValue" type="Label" parent="Margin/Content/AutoClickRow"] [node name="AutoClickIntervalValue" type="Label" parent="Margin/Scroll/Content/AutoClickRow"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(62, 0) custom_minimum_size = Vector2(100, 0)
layout_mode = 2 layout_mode = 2
text = "0.20 s" text = "0.20 s"
[node name="MouseRow" type="HBoxContainer" parent="Margin/Content"] [node name="MouseRow" type="HBoxContainer" parent="Margin/Scroll/Content"]
layout_mode = 2 layout_mode = 2
theme_override_constants/separation = 12 theme_override_constants/separation = 12
[node name="Label" type="Label" parent="Margin/Content/MouseRow"] [node name="Label" type="Label" parent="Margin/Scroll/Content/MouseRow"]
custom_minimum_size = Vector2(190, 0) custom_minimum_size = Vector2(260, 0)
layout_mode = 2 layout_mode = 2
text = "mouse camera sensitivity" text = "mouse camera sensitivity"
autowrap_mode = 2
[node name="MouseSensitivity" type="HSlider" parent="Margin/Content/MouseRow"] [node name="MouseSensitivity" type="HSlider" parent="Margin/Scroll/Content/MouseRow"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
@ -77,22 +85,23 @@ max_value = 0.012
step = 0.0005 step = 0.0005
value = 0.005 value = 0.005
[node name="MouseSensitivityValue" type="Label" parent="Margin/Content/MouseRow"] [node name="MouseSensitivityValue" type="Label" parent="Margin/Scroll/Content/MouseRow"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(62, 0) custom_minimum_size = Vector2(100, 0)
layout_mode = 2 layout_mode = 2
text = "0.0050" text = "0.0050"
[node name="ControllerRow" type="HBoxContainer" parent="Margin/Content"] [node name="ControllerRow" type="HBoxContainer" parent="Margin/Scroll/Content"]
layout_mode = 2 layout_mode = 2
theme_override_constants/separation = 12 theme_override_constants/separation = 12
[node name="Label" type="Label" parent="Margin/Content/ControllerRow"] [node name="Label" type="Label" parent="Margin/Scroll/Content/ControllerRow"]
custom_minimum_size = Vector2(190, 0) custom_minimum_size = Vector2(260, 0)
layout_mode = 2 layout_mode = 2
text = "controller camera sensitivity" text = "controller camera sensitivity"
autowrap_mode = 2
[node name="ControllerSensitivity" type="HSlider" parent="Margin/Content/ControllerRow"] [node name="ControllerSensitivity" type="HSlider" parent="Margin/Scroll/Content/ControllerRow"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
@ -101,36 +110,86 @@ max_value = 5.0
step = 0.1 step = 0.1
value = 2.5 value = 2.5
[node name="ControllerSensitivityValue" type="Label" parent="Margin/Content/ControllerRow"] [node name="ControllerSensitivityValue" type="Label" parent="Margin/Scroll/Content/ControllerRow"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(62, 0) custom_minimum_size = Vector2(100, 0)
layout_mode = 2 layout_mode = 2
text = "2.5" text = "2.5"
[node name="InvertYToggle" type="CheckButton" parent="Margin/Content"] [node name="InvertYToggle" type="CheckButton" parent="Margin/Scroll/Content"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
text = "invert vertical camera" text = "invert vertical camera"
[node name="SettingsFeedback" type="Label" parent="Margin/Content"] [node name="WorldPixelRow" type="HBoxContainer" parent="Margin/Scroll/Content"]
layout_mode = 2
theme_override_constants/separation = 12
[node name="Label" type="Label" parent="Margin/Scroll/Content/WorldPixelRow"]
custom_minimum_size = Vector2(260, 0)
layout_mode = 2
text = "world pixelation"
autowrap_mode = 2
[node name="WorldPixelSize" type="HSlider" parent="Margin/Scroll/Content/WorldPixelRow"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(0, 28) layout_mode = 2
size_flags_horizontal = 3
min_value = 1.0
max_value = 5.0
step = 1.0
value = 3.0
[node name="WorldPixelSizeValue" type="Label" parent="Margin/Scroll/Content/WorldPixelRow"]
unique_name_in_owner = true
custom_minimum_size = Vector2(170, 0)
layout_mode = 2
text = "retro"
[node name="UIPixelRow" type="HBoxContainer" parent="Margin/Scroll/Content"]
layout_mode = 2
theme_override_constants/separation = 12
[node name="Label" type="Label" parent="Margin/Scroll/Content/UIPixelRow"]
custom_minimum_size = Vector2(260, 0)
layout_mode = 2
text = "ui pixelation"
autowrap_mode = 2
[node name="UIPixelSize" type="HSlider" parent="Margin/Scroll/Content/UIPixelRow"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
min_value = 1.0
max_value = 5.0
step = 1.0
value = 3.0
[node name="UIPixelSizeValue" type="Label" parent="Margin/Scroll/Content/UIPixelRow"]
unique_name_in_owner = true
custom_minimum_size = Vector2(170, 0)
layout_mode = 2
text = "retro"
[node name="SettingsFeedback" type="Label" parent="Margin/Scroll/Content"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 44)
layout_mode = 2 layout_mode = 2
horizontal_alignment = 1 horizontal_alignment = 1
[node name="Buttons" type="HBoxContainer" parent="Margin/Content"] [node name="Buttons" type="HBoxContainer" parent="Margin/Scroll/Content"]
layout_mode = 2 layout_mode = 2
theme_override_constants/separation = 12 theme_override_constants/separation = 12
alignment = 2 alignment = 2
[node name="ApplySettingsButton" type="Button" parent="Margin/Content/Buttons"] [node name="ApplySettingsButton" type="Button" parent="Margin/Scroll/Content/Buttons"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(120, 42) custom_minimum_size = Vector2(150, 64)
layout_mode = 2 layout_mode = 2
text = "apply" text = "apply"
[node name="CancelSettingsButton" type="Button" parent="Margin/Content/Buttons"] [node name="CancelSettingsButton" type="Button" parent="Margin/Scroll/Content/Buttons"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(120, 42) custom_minimum_size = Vector2(150, 64)
layout_mode = 2 layout_mode = 2
text = "back" text = "back"

View file

@ -73,6 +73,7 @@ enum ConfirmationAction {
@onready var _confirmation_text: Label = %ConfirmationText @onready var _confirmation_text: Label = %ConfirmationText
@onready var _confirm_button: Button = %ConfirmButton @onready var _confirm_button: Button = %ConfirmButton
@onready var _settings_panel: SettingsPanelType = %SettingsPanel @onready var _settings_panel: SettingsPanelType = %SettingsPanel
@onready var _background: ColorRect = %Background
@onready var _decorative_fish_layer: Control = %DecorativeFishLayer @onready var _decorative_fish_layer: Control = %DecorativeFishLayer
@onready var _decorative_fish_timer: Timer = %DecorativeFishTimer @onready var _decorative_fish_timer: Timer = %DecorativeFishTimer
@onready var _decorative_bubble_layer: Control = %DecorativeBubbleLayer @onready var _decorative_bubble_layer: Control = %DecorativeBubbleLayer
@ -102,6 +103,7 @@ var _awaiting_start_input: bool = false
var _start_prompt_elapsed: float = 0.0 var _start_prompt_elapsed: float = 0.0
var _navigation_focus_active: bool = false var _navigation_focus_active: bool = false
var _modal_restore_navigation_focus: bool = false var _modal_restore_navigation_focus: bool = false
var _world_pixel_size: int = PlayerSettings.DEFAULT_WORLD_PIXEL_SIZE
func _ready() -> void: func _ready() -> void:
@ -201,6 +203,54 @@ func _update_title_layout() -> void:
minf(BUTTON_COLUMN_WIDTH, available_width), minf(BUTTON_COLUMN_WIDTH, available_width),
0.0 0.0
) )
_update_world_preview_resolution()
func set_world_pixelation(pixel_size: int) -> void:
_world_pixel_size = clampi(
pixel_size,
PlayerSettings.MIN_WORLD_PIXEL_SIZE,
PlayerSettings.MAX_WORLD_PIXEL_SIZE
)
if is_node_ready():
_update_world_preview_resolution()
func _update_world_preview_resolution() -> void:
var render_scale: float = PlayerSettings.get_world_render_scale(
_world_pixel_size
)
var shader_material := _background.material as ShaderMaterial
if shader_material != null:
shader_material.set_shader_parameter(
"virtual_pixel_density",
Vector2(
maxf(1.0, size.x * render_scale),
maxf(1.0, size.y * render_scale)
)
)
var logo_material := _title_logo.material as ShaderMaterial
if logo_material != null:
var effect_scale: float = 1.0 / render_scale
logo_material.set_shader_parameter(
"horizontal_displacement_pixels",
minf(2.0, 1.5 * effect_scale)
)
logo_material.set_shader_parameter(
"bob_amount_pixels",
minf(4.0, 3.0 * effect_scale)
)
func _snap_world_preview(value: Vector2) -> Vector2:
var render_scale: float = PlayerSettings.get_world_render_scale(
_world_pixel_size
)
var step: float = 1.0 / render_scale
return Vector2(
roundf(value.x / step) * step,
roundf(value.y / step) * step
)
func _process(delta: float) -> void: func _process(delta: float) -> void:
@ -742,6 +792,7 @@ func _update_decorative_fish(
8.0, 8.0,
maxf(8.0, _decorative_fish_layer.size.y - fish_control.size.y - 8.0) maxf(8.0, _decorative_fish_layer.size.y - fish_control.size.y - 8.0)
) )
fish_control.position = _snap_world_preview(fish_control.position)
func _on_decorative_fish_finished( func _on_decorative_fish_finished(
@ -944,13 +995,13 @@ func _update_decorative_bubble(
var wobble: float = sin( var wobble: float = sin(
wobble_phase + progress * TAU * wobble_cycles wobble_phase + progress * TAU * wobble_cycles
) * wobble_amplitude ) * wobble_amplitude
bubble.position = Vector2( bubble.position = _snap_world_preview(Vector2(
base_x base_x
+ horizontal_drift * progress + horizontal_drift * progress
+ wobble + wobble
- bubble.size.x * 0.5, - bubble.size.x * 0.5,
lerpf(start_y, end_y, progress) lerpf(start_y, end_y, progress)
) ))
func _on_decorative_bubble_finished( func _on_decorative_bubble_finished(

View file

@ -27,6 +27,7 @@ theme = ExtResource("2_theme")
script = ExtResource("1_script") script = ExtResource("1_script")
[node name="Background" type="ColorRect" parent="."] [node name="Background" type="ColorRect" parent="."]
unique_name_in_owner = true
material = SubResource("ShaderMaterial_title_water") material = SubResource("ShaderMaterial_title_water")
layout_mode = 1 layout_mode = 1
anchors_preset = 15 anchors_preset = 15
@ -92,7 +93,7 @@ mouse_filter = 2
theme_override_colors/font_color = Color(1, 1, 1, 1) theme_override_colors/font_color = Color(1, 1, 1, 1)
theme_override_colors/font_outline_color = Color(0.02, 0.075, 0.11, 0.9) theme_override_colors/font_outline_color = Color(0.02, 0.075, 0.11, 0.9)
theme_override_constants/outline_size = 3 theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 26 theme_override_font_sizes/font_size = 39
text = "press any key to start" text = "press any key to start"
horizontal_alignment = 1 horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
@ -194,10 +195,10 @@ anchor_left = 0.5
anchor_top = 0.5 anchor_top = 0.5
anchor_right = 0.5 anchor_right = 0.5
anchor_bottom = 0.5 anchor_bottom = 0.5
offset_left = -230.0 offset_left = -320.0
offset_top = -95.0 offset_top = -150.0
offset_right = 230.0 offset_right = 320.0
offset_bottom = 95.0 offset_bottom = 150.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
@ -226,13 +227,13 @@ alignment = 1
[node name="ConfirmButton" type="Button" parent="ConfirmationPanel/Margin/Content/Buttons"] [node name="ConfirmButton" type="Button" parent="ConfirmationPanel/Margin/Content/Buttons"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(150, 42) custom_minimum_size = Vector2(190, 64)
layout_mode = 2 layout_mode = 2
text = "confirm" text = "confirm"
[node name="CancelConfirmButton" type="Button" parent="ConfirmationPanel/Margin/Content/Buttons"] [node name="CancelConfirmButton" type="Button" parent="ConfirmationPanel/Margin/Content/Buttons"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(120, 42) custom_minimum_size = Vector2(160, 64)
layout_mode = 2 layout_mode = 2
text = "cancel" text = "cancel"
@ -245,9 +246,9 @@ anchor_left = 0.5
anchor_top = 0.5 anchor_top = 0.5
anchor_right = 0.5 anchor_right = 0.5
anchor_bottom = 0.5 anchor_bottom = 0.5
offset_left = -300.0 offset_left = -360.0
offset_top = -245.0 offset_top = -300.0
offset_right = 300.0 offset_right = 360.0
offset_bottom = 245.0 offset_bottom = 300.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2

View file

@ -0,0 +1,111 @@
class_name UIPixelationPresenter
extends SubViewportContainer
const MIN_UI_VIEWPORT_SIZE: Vector2i = Vector2i(320, 180)
signal effective_pixel_size_changed(
requested_pixel_size: int,
effective_pixel_size: int,
)
@onready var _ui_viewport: SubViewport = $UIViewport
@onready var _ui_root: Control = $UIViewport/GameUI/UIRoot
var _requested_pixel_size: int = PlayerSettings.DEFAULT_UI_PIXEL_SIZE
var _effective_pixel_size: int = PlayerSettings.DEFAULT_UI_PIXEL_SIZE
var _gameplay_active: bool = false
var _interactive_ui_open: bool = false
func _ready() -> void:
var root_viewport: Viewport = get_viewport()
root_viewport.size_changed.connect(_resize_presentation)
_resize_presentation()
func set_pixel_size(pixel_size: int) -> void:
_requested_pixel_size = clampi(
pixel_size,
PlayerSettings.MIN_UI_PIXEL_SIZE,
PlayerSettings.MAX_UI_PIXEL_SIZE
)
_resize_presentation()
func get_requested_pixel_size() -> int:
return _requested_pixel_size
func get_effective_pixel_size() -> int:
return _effective_pixel_size
func get_ui_viewport_size() -> Vector2i:
return _ui_viewport.size
func set_gameplay_active(active: bool) -> void:
_gameplay_active = active
_refresh_mouse_filter()
func set_interactive_ui_open(is_open: bool) -> void:
_interactive_ui_open = is_open
_refresh_mouse_filter()
func _refresh_mouse_filter() -> void:
mouse_filter = (
Control.MOUSE_FILTER_STOP
if not _gameplay_active or _interactive_ui_open
else Control.MOUSE_FILTER_IGNORE
)
func _resize_presentation() -> void:
if not is_node_ready():
return
var root_size: Vector2i = get_window().size
if root_size.x <= 0 or root_size.y <= 0:
return
var previous_effective_size: int = _effective_pixel_size
_effective_pixel_size = _resolve_effective_pixel_size(root_size)
var render_scale: float = PlayerSettings.get_ui_render_scale(
_effective_pixel_size
)
var viewport_size := Vector2i(
ceili(float(root_size.x) * render_scale),
ceili(float(root_size.y) * render_scale)
)
var presentation_size: Vector2 = Vector2(viewport_size) / render_scale
set_anchors_preset(Control.PRESET_TOP_LEFT)
position = (Vector2(root_size) - presentation_size) * 0.5
size = Vector2(viewport_size)
scale = Vector2.ONE / render_scale
stretch_shrink = 1
_ui_root.position = Vector2.ZERO
_ui_root.scale = Vector2.ONE * render_scale
_ui_root.size = Vector2(root_size)
if (
previous_effective_size != _effective_pixel_size
or _requested_pixel_size != _effective_pixel_size
):
effective_pixel_size_changed.emit(
_requested_pixel_size,
_effective_pixel_size
)
func _resolve_effective_pixel_size(root_size: Vector2i) -> int:
for candidate: int in range(_requested_pixel_size, 0, -1):
var render_scale: float = PlayerSettings.get_ui_render_scale(candidate)
var candidate_size := Vector2i(
ceili(float(root_size.x) * render_scale),
ceili(float(root_size.y) * render_scale)
)
if (
candidate_size.x >= MIN_UI_VIEWPORT_SIZE.x
and candidate_size.y >= MIN_UI_VIEWPORT_SIZE.y
):
return candidate
return PlayerSettings.MIN_UI_PIXEL_SIZE

View file

@ -0,0 +1 @@
uid://bdtb05vkiicd