Expand gameplay systems and interface controls
This commit is contained in:
parent
09b7a78533
commit
2710544070
46 changed files with 2072 additions and 153 deletions
|
|
@ -897,6 +897,8 @@ func _send() -> void:
|
|||
if body.strip_edges().is_empty():
|
||||
close_chat()
|
||||
return
|
||||
if _handle_editor_world_command(body):
|
||||
return
|
||||
_send_pending = true
|
||||
_pending_send_body = NetworkChatProtocol.sanitize_body(body)
|
||||
_entry.editable = false
|
||||
|
|
@ -912,6 +914,82 @@ func _send() -> void:
|
|||
_set_status("Sending…")
|
||||
|
||||
|
||||
func _handle_editor_world_command(body: String) -> bool:
|
||||
# These commands are deliberately limited to sessions launched by the
|
||||
# Godot editor. Exported builds do not have the editor feature tag, and a
|
||||
# joined editor client must not be able to mutate its host's world.
|
||||
if not OS.has_feature("editor"):
|
||||
return false
|
||||
var command_text: String = body.strip_edges()
|
||||
if not (
|
||||
command_text.begins_with("/time")
|
||||
or command_text.begins_with("/weather")
|
||||
):
|
||||
return false
|
||||
var parts: PackedStringArray = command_text.split(" ", false)
|
||||
var command: String = String(parts[0]).trim_prefix("/").to_lower()
|
||||
var result: String = ""
|
||||
if _session == null or not _session.is_host():
|
||||
result = "Editor world commands require the authoritative host."
|
||||
elif command == "time":
|
||||
result = _apply_editor_time_command(parts)
|
||||
elif command == "weather":
|
||||
result = _apply_editor_weather_command(parts)
|
||||
else:
|
||||
return false
|
||||
_entry.clear()
|
||||
_flush_draft()
|
||||
_set_status(result)
|
||||
close_chat(true)
|
||||
return true
|
||||
|
||||
|
||||
func _apply_editor_time_command(parts: PackedStringArray) -> String:
|
||||
if parts.size() != 2 or _world_time == null:
|
||||
return "Usage: /time [dawn, day, dusk, night]"
|
||||
var phase_name: String = String(parts[1]).to_lower()
|
||||
var target_hour: float = -1.0
|
||||
match phase_name:
|
||||
"dawn":
|
||||
target_hour = WorldTimeServiceType.DAWN_START_HOUR
|
||||
"day":
|
||||
target_hour = WorldTimeServiceType.DAWN_END_HOUR
|
||||
"dusk":
|
||||
target_hour = WorldTimeServiceType.DUSK_START_HOUR
|
||||
"night":
|
||||
target_hour = WorldTimeServiceType.DUSK_END_HOUR
|
||||
_:
|
||||
return "Usage: /time [dawn, day, dusk, night]"
|
||||
if not _world_time.set_authoritative_time(target_hour):
|
||||
return "Editor world time could not be changed."
|
||||
return "Editor time: %s (%s)." % [
|
||||
phase_name,
|
||||
_world_time.get_clock_text(),
|
||||
]
|
||||
|
||||
|
||||
func _apply_editor_weather_command(parts: PackedStringArray) -> String:
|
||||
if parts.size() != 2 or _world_weather == null:
|
||||
return "Usage: /weather [sunny, cloudy, rainy, foggy]"
|
||||
var weather_name: String = String(parts[1]).to_lower()
|
||||
var target_weather: WorldWeatherServiceType.Weather
|
||||
match weather_name:
|
||||
"clear", "sunny":
|
||||
weather_name = "sunny"
|
||||
target_weather = WorldWeatherServiceType.Weather.SUNNY
|
||||
"cloudy":
|
||||
target_weather = WorldWeatherServiceType.Weather.CLOUDY
|
||||
"rainy":
|
||||
target_weather = WorldWeatherServiceType.Weather.RAINY
|
||||
"foggy":
|
||||
target_weather = WorldWeatherServiceType.Weather.FOGGY
|
||||
_:
|
||||
return "Usage: /weather [sunny, cloudy, rainy, foggy]"
|
||||
if not _world_weather.set_authoritative_weather(target_weather):
|
||||
return "Editor world weather could not be changed."
|
||||
return "Editor weather: %s." % weather_name
|
||||
|
||||
|
||||
func _on_local_message_confirmed(message: Dictionary) -> void:
|
||||
if (
|
||||
not _send_pending
|
||||
|
|
|
|||
|
|
@ -168,6 +168,12 @@ func _on_pressed() -> void:
|
|||
|
||||
func _on_gui_input(event: InputEvent) -> void:
|
||||
var mouse_event := event as InputEventMouseButton
|
||||
if mouse_event != null and mouse_event.pressed:
|
||||
# Pointer clicks give Buttons keyboard focus after their GUI callback.
|
||||
# Release that pointer-created focus on the next frame so a tooltip does
|
||||
# not remain pinned after the pointer leaves. Controller navigation still
|
||||
# keeps focus normally because it does not arrive as a mouse event.
|
||||
call_deferred("_release_pointer_focus")
|
||||
if (
|
||||
mouse_event != null
|
||||
and mouse_event.button_index == MOUSE_BUTTON_RIGHT
|
||||
|
|
@ -179,6 +185,11 @@ func _on_gui_input(event: InputEvent) -> void:
|
|||
accept_event()
|
||||
|
||||
|
||||
func _release_pointer_focus() -> void:
|
||||
if has_focus():
|
||||
release_focus()
|
||||
|
||||
|
||||
func _set_context_hovered(active: bool) -> void:
|
||||
_context_hovered = active
|
||||
_update_context_presence()
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ var _controller_text_entry_is_open: Callable
|
|||
|
||||
|
||||
func _ready() -> void:
|
||||
_prioritize_surface_drawing_pointer_input()
|
||||
_bite_prompt_button.pressed.connect(_on_bite_prompt_pressed)
|
||||
_apply_active_bait_indicator_style()
|
||||
_refresh_active_bait_indicator()
|
||||
|
|
@ -487,6 +488,27 @@ func setup(
|
|||
)
|
||||
|
||||
|
||||
func _prioritize_surface_drawing_pointer_input() -> void:
|
||||
# Control input follows sibling order rather than CanvasItem.z_index. Chat is
|
||||
# a full-screen Control with interactive mobile children, so the toolbar must
|
||||
# follow it in the tree to own their overlap while the art kit is active.
|
||||
# Opening Chat deactivates surface drawing and hides the toolbar, returning
|
||||
# the same area to Chat without any special-case pointer forwarding.
|
||||
if (
|
||||
_surface_drawing_toolbar == null
|
||||
or _chat_ui == null
|
||||
or _surface_drawing_toolbar.get_parent() != _chat_ui.get_parent()
|
||||
):
|
||||
return
|
||||
var ui_root: Node = _surface_drawing_toolbar.get_parent()
|
||||
var toolbar_index: int = _surface_drawing_toolbar.get_index()
|
||||
var chat_index: int = _chat_ui.get_index()
|
||||
if toolbar_index > chat_index:
|
||||
return
|
||||
# Removing the earlier toolbar shifts Chat one position toward the start.
|
||||
ui_root.move_child(_surface_drawing_toolbar, chat_index)
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
# The on-screen keyboard owns controller input while it is open. Its
|
||||
# overlay is processed before the UI beneath it and consumes the event.
|
||||
|
|
@ -1264,6 +1286,7 @@ func _drawing_pointer_window_position() -> Vector2:
|
|||
|
||||
func setup_data_and_identity(
|
||||
data_root: PlayerDataRoot,
|
||||
progression_saves: PlayerSaveManager,
|
||||
identity_backups: IdentityBackupService,
|
||||
player_identity: PlayerIdentityStore,
|
||||
host_identity: HostIdentityStore,
|
||||
|
|
@ -1275,6 +1298,7 @@ func setup_data_and_identity(
|
|||
]:
|
||||
panel.setup_data_and_identity(
|
||||
data_root,
|
||||
progression_saves,
|
||||
identity_backups,
|
||||
player_identity,
|
||||
host_identity,
|
||||
|
|
@ -1603,9 +1627,14 @@ func _can_toggle_gameplay_hud() -> bool:
|
|||
|
||||
|
||||
func _refresh_gameplay_hud_visibility() -> void:
|
||||
var fishing_override_active: bool = (
|
||||
_gameplay_hud_hidden
|
||||
and _fishing_spot != null
|
||||
and _fishing_spot.is_fishing_sequence_active()
|
||||
)
|
||||
var show_world_hud: bool = (
|
||||
_gameplay_ui_enabled
|
||||
and not _gameplay_hud_hidden
|
||||
and (not _gameplay_hud_hidden or fishing_override_active)
|
||||
and not _system_menu_open
|
||||
and not _player_menu_open
|
||||
and not _shop_open
|
||||
|
|
@ -1660,6 +1689,7 @@ func set_storage_prompt_visible(
|
|||
_storage_prompt.visible = (
|
||||
requested_visible
|
||||
and _gameplay_ui_enabled
|
||||
and not _gameplay_hud_hidden
|
||||
and not _system_menu_open
|
||||
and not _player_menu_open
|
||||
and not _shop_open
|
||||
|
|
@ -1697,6 +1727,7 @@ func set_shop_prompt_visible(
|
|||
_shop_prompt.visible = (
|
||||
requested_visible
|
||||
and _gameplay_ui_enabled
|
||||
and not _gameplay_hud_hidden
|
||||
and not _system_menu_open
|
||||
and not _player_menu_open
|
||||
and not _shop_open
|
||||
|
|
@ -1923,6 +1954,7 @@ func _refresh_fishing_panel_visibility() -> void:
|
|||
_gameplay_ui_enabled
|
||||
and has_content
|
||||
)
|
||||
_refresh_gameplay_hud_visibility()
|
||||
|
||||
|
||||
func _on_bite_prompt_changed(prompt_visible: bool) -> void:
|
||||
|
|
|
|||
|
|
@ -430,7 +430,8 @@ func _show_native_keyboard_for(control: Control) -> void:
|
|||
|
||||
|
||||
func _hide_native_keyboard() -> void:
|
||||
DisplayServer.virtual_keyboard_hide()
|
||||
if DisplayServer.has_feature(DisplayServer.FEATURE_VIRTUAL_KEYBOARD):
|
||||
DisplayServer.virtual_keyboard_hide()
|
||||
|
||||
|
||||
static func _line_edit_keyboard_type(
|
||||
|
|
|
|||
|
|
@ -1693,6 +1693,7 @@ func close_menu(
|
|||
_release_controller_ownership(false, true)
|
||||
get_viewport().gui_cancel_drag()
|
||||
_close_sale_confirmation()
|
||||
_hide_inventory_context_tooltip()
|
||||
if reason in [
|
||||
CloseReason.BITE_STARTED,
|
||||
CloseReason.WATER_RECOVERY,
|
||||
|
|
@ -2497,6 +2498,8 @@ func _populate_tackle_column(
|
|||
owned.quantity,
|
||||
item.max_stack,
|
||||
&"QuantityBadge",
|
||||
UtilityPageStyle.SUPPLY_BADGE_EDGE_MARGIN,
|
||||
0.0,
|
||||
)
|
||||
button.pressed.connect(_select_tackle_item.bind(owned.item_id))
|
||||
button.gui_input.connect(
|
||||
|
|
@ -2540,6 +2543,8 @@ func _on_tackle_button_gui_input(
|
|||
button: Button,
|
||||
) -> void:
|
||||
var mouse_event := event as InputEventMouseButton
|
||||
if mouse_event != null and mouse_event.pressed:
|
||||
call_deferred("_release_pointer_focus", button)
|
||||
if (
|
||||
mouse_event == null
|
||||
or mouse_event.button_index != MOUSE_BUTTON_RIGHT
|
||||
|
|
@ -2555,6 +2560,11 @@ func _on_tackle_button_gui_input(
|
|||
button.accept_event()
|
||||
|
||||
|
||||
func _release_pointer_focus(control: Control) -> void:
|
||||
if control != null and is_instance_valid(control) and control.has_focus():
|
||||
control.release_focus()
|
||||
|
||||
|
||||
func _configure_tackle_item_focus() -> void:
|
||||
if not is_node_ready():
|
||||
return
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ var _environment_volume: float = 1.0
|
|||
var _network_profile: NetworkProfilePreferences
|
||||
var _network_session: NetworkSession
|
||||
var _data_root: PlayerDataRoot
|
||||
var _progression_saves: PlayerSaveManager
|
||||
var _identity_backups: IdentityBackupService
|
||||
var _player_identity: PlayerIdentityStore
|
||||
var _host_identity: HostIdentityStore
|
||||
|
|
@ -134,6 +135,8 @@ var _controller_mapping_panel: ControllerMappingPanelType
|
|||
var _keyboard_mouse_mapping_manager: KeyboardMouseMappingManagerType
|
||||
var _keyboard_mouse_mapping_panel: KeyboardMouseMappingPanelType
|
||||
var _data_folder_dialog: FileDialog
|
||||
var _progression_import_dialog: FileDialog
|
||||
var _progression_export_dialog: FileDialog
|
||||
var _backup_file_dialog: FileDialog
|
||||
var _export_file_dialog: FileDialog
|
||||
var _passphrase_dialog: ConfirmationDialog
|
||||
|
|
@ -143,6 +146,7 @@ var _pending_identity_operation := ""
|
|||
var _pending_identity_type := ""
|
||||
var _pending_identity_path := ""
|
||||
var _pending_import_data: Dictionary = {}
|
||||
var _pending_progression_path := ""
|
||||
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
|
|
@ -244,6 +248,8 @@ func _connect_controls() -> void:
|
|||
%KeyboardMapping.pressed.connect(_open_keyboard_mouse_mapping)
|
||||
%OpenDataFolder.pressed.connect(_open_data_folder)
|
||||
%ChangeDataFolder.pressed.connect(_choose_data_folder)
|
||||
%ExportProgression.pressed.connect(_choose_progression_export)
|
||||
%ImportProgression.pressed.connect(_choose_progression_import)
|
||||
%ExportPlayerIdentity.pressed.connect(
|
||||
_choose_identity_export.bind("player")
|
||||
)
|
||||
|
|
@ -337,6 +343,7 @@ func setup_keyboard_mouse_mapping(
|
|||
|
||||
func setup_data_and_identity(
|
||||
data_root: PlayerDataRoot,
|
||||
progression_saves: PlayerSaveManager,
|
||||
identity_backups: IdentityBackupService,
|
||||
player_identity: PlayerIdentityStore,
|
||||
host_identity: HostIdentityStore,
|
||||
|
|
@ -344,6 +351,7 @@ func setup_data_and_identity(
|
|||
interface_fonts: InterfaceFontController,
|
||||
) -> void:
|
||||
_data_root = data_root
|
||||
_progression_saves = progression_saves
|
||||
_identity_backups = identity_backups
|
||||
_player_identity = player_identity
|
||||
_host_identity = host_identity
|
||||
|
|
@ -611,6 +619,11 @@ func _refresh_data_page() -> void:
|
|||
_data_root.override_active
|
||||
or (_network_session != null and _network_session.is_session_active())
|
||||
)
|
||||
%ExportProgression.disabled = _progression_saves == null
|
||||
%ImportProgression.disabled = (
|
||||
_progression_saves == null
|
||||
or (_network_session != null and _network_session.is_session_active())
|
||||
)
|
||||
var fingerprint: String = (
|
||||
_player_identity.fingerprint if _player_identity != null else ""
|
||||
)
|
||||
|
|
@ -661,6 +674,118 @@ func _copy_player_fingerprint() -> void:
|
|||
_feedback.text = "full player fingerprint copied for server operator setup."
|
||||
|
||||
|
||||
func _choose_progression_export() -> void:
|
||||
if _progression_saves == null or _data_root == null:
|
||||
_feedback.text = "progression export is unavailable."
|
||||
return
|
||||
var timestamp: String = Time.get_datetime_string_from_system().replace(
|
||||
":", "-"
|
||||
)
|
||||
var suggested: String = _data_root.progression_backup_directory().path_join(
|
||||
"NETfishing-progression-%s%s"
|
||||
% [timestamp, PlayerSaveManager.ARCHIVE_EXTENSION]
|
||||
)
|
||||
if _progression_export_dialog == null:
|
||||
_progression_export_dialog = FileDialog.new()
|
||||
_progression_export_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE
|
||||
_progression_export_dialog.access = FileDialog.ACCESS_FILESYSTEM
|
||||
_progression_export_dialog.use_native_dialog = false
|
||||
_progression_export_dialog.filters = PackedStringArray([
|
||||
"*.nfsave ; NETfishing progression archive",
|
||||
])
|
||||
_progression_export_dialog.file_selected.connect(
|
||||
_progression_export_file_selected
|
||||
)
|
||||
_interface_fonts.apply_utility_theme(_progression_export_dialog)
|
||||
add_child(_progression_export_dialog)
|
||||
_progression_export_dialog.current_dir = suggested.get_base_dir()
|
||||
_progression_export_dialog.current_file = suggested.get_file()
|
||||
_interface_fonts.popup_file_dialog(_progression_export_dialog)
|
||||
|
||||
|
||||
func _progression_export_file_selected(path: String) -> void:
|
||||
var destination: String = (
|
||||
path
|
||||
if path.ends_with(PlayerSaveManager.ARCHIVE_EXTENSION)
|
||||
else path + PlayerSaveManager.ARCHIVE_EXTENSION
|
||||
)
|
||||
var result: Dictionary = _progression_saves.export_progression_archive(
|
||||
destination
|
||||
)
|
||||
_feedback.text = str(
|
||||
result.get("message", "progression export failed.")
|
||||
)
|
||||
|
||||
|
||||
func _choose_progression_import() -> void:
|
||||
if _progression_saves == null or _data_root == null:
|
||||
_feedback.text = "progression import is unavailable."
|
||||
return
|
||||
if _network_session != null and _network_session.is_session_active():
|
||||
_feedback.text = "return to title before importing progression."
|
||||
return
|
||||
if _progression_import_dialog == null:
|
||||
_progression_import_dialog = FileDialog.new()
|
||||
_progression_import_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
|
||||
_progression_import_dialog.access = FileDialog.ACCESS_FILESYSTEM
|
||||
_progression_import_dialog.use_native_dialog = false
|
||||
_progression_import_dialog.filters = PackedStringArray([
|
||||
"*.nfsave ; NETfishing progression archive",
|
||||
])
|
||||
_progression_import_dialog.file_selected.connect(
|
||||
_progression_import_file_selected
|
||||
)
|
||||
_interface_fonts.apply_utility_theme(_progression_import_dialog)
|
||||
add_child(_progression_import_dialog)
|
||||
_progression_import_dialog.current_dir = (
|
||||
_data_root.progression_backup_directory()
|
||||
)
|
||||
_interface_fonts.popup_file_dialog(_progression_import_dialog)
|
||||
|
||||
|
||||
func _progression_import_file_selected(path: String) -> void:
|
||||
var inspected: Dictionary = (
|
||||
_progression_saves.inspect_progression_archive(path)
|
||||
)
|
||||
if not bool(inspected.get("ok", false)):
|
||||
_feedback.text = str(
|
||||
inspected.get("message", "progression archive could not be opened.")
|
||||
)
|
||||
return
|
||||
_pending_progression_path = path
|
||||
var dialog := ConfirmationDialog.new()
|
||||
dialog.title = "replace saved progression?"
|
||||
dialog.ok_button_text = "import progression"
|
||||
dialog.dialog_text = (
|
||||
"this will replace the current progression after making a backup.\n\n"
|
||||
+ "fish: %d\ndiscovered: %d\nworld seed: %d\n\n"
|
||||
+ "identities, settings, friends, bans, and trusted servers are unchanged."
|
||||
) % [
|
||||
int(inspected.get("catch_count", 0)),
|
||||
int(inspected.get("discovered_species_count", 0)),
|
||||
int(inspected.get("world_seed", 0)),
|
||||
]
|
||||
dialog.confirmed.connect(_confirm_progression_import.bind(dialog))
|
||||
dialog.canceled.connect(dialog.queue_free)
|
||||
_interface_fonts.apply_utility_theme(dialog)
|
||||
add_child(dialog)
|
||||
dialog.popup_centered(Vector2i(640, 390))
|
||||
_configure_confirmation_dialog.call_deferred(
|
||||
dialog, dialog.get_cancel_button()
|
||||
)
|
||||
|
||||
|
||||
func _confirm_progression_import(dialog: ConfirmationDialog) -> void:
|
||||
var result: Dictionary = _progression_saves.import_progression_archive(
|
||||
_pending_progression_path
|
||||
)
|
||||
_feedback.text = str(
|
||||
result.get("message", "progression import failed.")
|
||||
)
|
||||
_pending_progression_path = ""
|
||||
dialog.queue_free()
|
||||
|
||||
|
||||
func _choose_data_folder() -> void:
|
||||
if _data_root == null or _data_root.override_active:
|
||||
_feedback.text = "the data folder is externally managed."
|
||||
|
|
|
|||
|
|
@ -567,7 +567,7 @@ size_flags_horizontal = 3
|
|||
focus_mode = 2
|
||||
focus_neighbor_right = NodePath("../ChangeDataFolder")
|
||||
focus_neighbor_top = NodePath("../../../../../../../../TabBar/DataTab")
|
||||
focus_neighbor_bottom = NodePath("../../CopyPlayerFingerprint")
|
||||
focus_neighbor_bottom = NodePath("../../ProgressionRow/ExportProgression")
|
||||
text = "open data folder"
|
||||
|
||||
[node name="ChangeDataFolder" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/DataPage/DataScroll/DataButtons/FolderRow"]
|
||||
|
|
@ -578,15 +578,41 @@ size_flags_horizontal = 3
|
|||
focus_mode = 2
|
||||
focus_neighbor_left = NodePath("../OpenDataFolder")
|
||||
focus_neighbor_top = NodePath("../../../../../../../../TabBar/DataTab")
|
||||
focus_neighbor_bottom = NodePath("../../CopyPlayerFingerprint")
|
||||
focus_neighbor_bottom = NodePath("../../ProgressionRow/ImportProgression")
|
||||
text = "change data folder"
|
||||
|
||||
[node name="ProgressionRow" type="HBoxContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/DataPage/DataScroll/DataButtons"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="ExportProgression" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/DataPage/DataScroll/DataButtons/ProgressionRow"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 44)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
focus_mode = 2
|
||||
focus_neighbor_right = NodePath("../ImportProgression")
|
||||
focus_neighbor_top = NodePath("../../FolderRow/OpenDataFolder")
|
||||
focus_neighbor_bottom = NodePath("../../CopyPlayerFingerprint")
|
||||
text = "export progression"
|
||||
|
||||
[node name="ImportProgression" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/DataPage/DataScroll/DataButtons/ProgressionRow"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 44)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
focus_mode = 2
|
||||
focus_neighbor_left = NodePath("../ExportProgression")
|
||||
focus_neighbor_top = NodePath("../../FolderRow/ChangeDataFolder")
|
||||
focus_neighbor_bottom = NodePath("../../CopyPlayerFingerprint")
|
||||
text = "import progression"
|
||||
|
||||
[node name="CopyPlayerFingerprint" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/DataPage/DataScroll/DataButtons"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 44)
|
||||
layout_mode = 2
|
||||
focus_mode = 2
|
||||
focus_neighbor_top = NodePath("../FolderRow/OpenDataFolder")
|
||||
focus_neighbor_top = NodePath("../ProgressionRow/ExportProgression")
|
||||
focus_neighbor_bottom = NodePath("../PlayerIdentityRow/ExportPlayerIdentity")
|
||||
text = "copy player fingerprint"
|
||||
|
||||
|
|
|
|||
|
|
@ -1295,7 +1295,7 @@ func _on_settings_applied() -> void:
|
|||
|
||||
|
||||
func _on_settings_closed() -> void:
|
||||
pass
|
||||
_refresh_save_inspection()
|
||||
|
||||
|
||||
func _on_settings_closing() -> void:
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ static func add_supply_quantity_badge(
|
|||
total: int,
|
||||
badge_name: StringName = &"SupplyQuantityBadge",
|
||||
top_margin: float = SUPPLY_BADGE_EDGE_MARGIN,
|
||||
x_offset: float = SUPPLY_BADGE_X_OFFSET,
|
||||
) -> Panel:
|
||||
var badge := Panel.new()
|
||||
badge.name = badge_name
|
||||
|
|
@ -68,7 +69,7 @@ static func add_supply_quantity_badge(
|
|||
quantity_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
badge.add_child(quantity_label)
|
||||
configure_supply_quantity_badge(
|
||||
badge, quantity_label, current, total, top_margin
|
||||
badge, quantity_label, current, total, top_margin, x_offset
|
||||
)
|
||||
return badge
|
||||
|
||||
|
|
@ -79,6 +80,7 @@ static func configure_supply_quantity_badge(
|
|||
current: int,
|
||||
total: int,
|
||||
top_margin: float = SUPPLY_BADGE_EDGE_MARGIN,
|
||||
x_offset: float = SUPPLY_BADGE_X_OFFSET,
|
||||
) -> void:
|
||||
var supply_text := supply_quantity_text(current, total)
|
||||
var text_width: float = TuffyFont.get_string_size(
|
||||
|
|
@ -92,10 +94,10 @@ static func configure_supply_quantity_badge(
|
|||
ceilf(text_width + SUPPLY_BADGE_HORIZONTAL_PADDING),
|
||||
)
|
||||
badge.offset_left = (
|
||||
-badge_width - SUPPLY_BADGE_EDGE_MARGIN + SUPPLY_BADGE_X_OFFSET
|
||||
-badge_width - SUPPLY_BADGE_EDGE_MARGIN + x_offset
|
||||
)
|
||||
badge.offset_top = top_margin
|
||||
badge.offset_right = -SUPPLY_BADGE_EDGE_MARGIN + SUPPLY_BADGE_X_OFFSET
|
||||
badge.offset_right = -SUPPLY_BADGE_EDGE_MARGIN + x_offset
|
||||
badge.offset_bottom = top_margin + SUPPLY_BADGE_HEIGHT
|
||||
badge.pivot_offset = Vector2(
|
||||
badge_width * 0.5,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue