From 5af84eaf47d1b52792ea4e9781a6153731d5c37d Mon Sep 17 00:00:00 2001 From: Voyager Date: Tue, 28 Jul 2026 23:43:03 -0400 Subject: [PATCH] Checkpoint Player Menu visual revisions --- .../bubble_hotbar/bubble_hotbar_slot.gd | 45 +- .../bubble_hotbar/bubble_hotbar_slot.tscn | 2 +- ui/components/bubble_menu/bag_item_sprite.gd | 131 ++ .../bubble_menu/bag_item_sprite.gd.uid | 1 + .../bubble_menu/bag_item_sprite.tscn | 83 + .../bubble_menu/bubble_inventory_cell.gd | 125 -- .../bubble_menu/bubble_inventory_cell.gd.uid | 1 - .../bubble_menu/bubble_inventory_cell.tscn | 78 - .../bubble_menu/bubble_status_bubble.tscn | 6 +- .../bubble_menu/cooler_fish_sprite.gd | 140 ++ .../bubble_menu/cooler_fish_sprite.gd.uid | 1 + .../bubble_menu/cooler_fish_sprite.tscn | 75 + .../bubble_menu/cooler_water.gdshader | 40 + .../bubble_menu/cooler_water.gdshader.uid | 1 + ui/components/bubble_menu/logbook_entry.gd | 103 + .../bubble_menu/logbook_entry.gd.uid | 1 + ui/components/bubble_menu/logbook_entry.tscn | 66 + .../bubble_menu/notepad_ink_action.gd | 82 + .../bubble_menu/notepad_ink_action.gd.uid | 1 + .../bubble_menu/notepad_ink_action.tscn | 23 + .../bubble_menu/notepad_ink_choice.gd | 114 ++ .../bubble_menu/notepad_ink_choice.gd.uid | 1 + .../bubble_menu/notepad_ink_choice.tscn | 24 + .../bubble_menu/notepad_ink_outline.gd | 64 + .../bubble_menu/notepad_ink_outline.gd.uid | 1 + ui/hotbar.gd | 4 +- ui/hotbar.tscn | 40 +- ui/player_menu.gd | 1797 ++++++++++++++--- ui/player_menu.tscn | 814 ++++++-- 29 files changed, 3236 insertions(+), 628 deletions(-) create mode 100644 ui/components/bubble_menu/bag_item_sprite.gd create mode 100644 ui/components/bubble_menu/bag_item_sprite.gd.uid create mode 100644 ui/components/bubble_menu/bag_item_sprite.tscn delete mode 100644 ui/components/bubble_menu/bubble_inventory_cell.gd delete mode 100644 ui/components/bubble_menu/bubble_inventory_cell.gd.uid delete mode 100644 ui/components/bubble_menu/bubble_inventory_cell.tscn create mode 100644 ui/components/bubble_menu/cooler_fish_sprite.gd create mode 100644 ui/components/bubble_menu/cooler_fish_sprite.gd.uid create mode 100644 ui/components/bubble_menu/cooler_fish_sprite.tscn create mode 100644 ui/components/bubble_menu/cooler_water.gdshader create mode 100644 ui/components/bubble_menu/cooler_water.gdshader.uid create mode 100644 ui/components/bubble_menu/logbook_entry.gd create mode 100644 ui/components/bubble_menu/logbook_entry.gd.uid create mode 100644 ui/components/bubble_menu/logbook_entry.tscn create mode 100644 ui/components/bubble_menu/notepad_ink_action.gd create mode 100644 ui/components/bubble_menu/notepad_ink_action.gd.uid create mode 100644 ui/components/bubble_menu/notepad_ink_action.tscn create mode 100644 ui/components/bubble_menu/notepad_ink_choice.gd create mode 100644 ui/components/bubble_menu/notepad_ink_choice.gd.uid create mode 100644 ui/components/bubble_menu/notepad_ink_choice.tscn create mode 100644 ui/components/bubble_menu/notepad_ink_outline.gd create mode 100644 ui/components/bubble_menu/notepad_ink_outline.gd.uid diff --git a/ui/components/bubble_hotbar/bubble_hotbar_slot.gd b/ui/components/bubble_hotbar/bubble_hotbar_slot.gd index 09d2346..8ce3428 100644 --- a/ui/components/bubble_hotbar/bubble_hotbar_slot.gd +++ b/ui/components/bubble_hotbar/bubble_hotbar_slot.gd @@ -26,8 +26,8 @@ const DEFORMATION_Y_AMPLITUDE: float = 0.007 @export_range(0, PlayerHotbarType.SLOT_COUNT - 1, 1) var slot_index: int = 0 @export_group("Authored Layout") -@export var desktop_size: Vector2 = Vector2(80.0, 78.0) -@export var compact_size: Vector2 = Vector2(56.0, 54.0) +@export var desktop_size: Vector2 = Vector2(78.0, 78.0) +@export var compact_size: Vector2 = Vector2(54.0, 54.0) @export var desktop_anchor: Vector2 = Vector2.ZERO @export var compact_anchor: Vector2 = Vector2.ZERO @export_group("Motion") @@ -204,29 +204,31 @@ func _apply_style() -> void: return var normal_fill: Color = profile.normal_fill normal_fill.a = 1.0 - var normal_border: Color = profile.normal_border - var normal_border_width: int = profile.normal_border_width + var selected_fill: Color = normal_fill if _selected: - normal_border = profile.pressed_border - normal_border_width = profile.emphasized_border_width + selected_fill = normal_fill.lightened(0.12) add_theme_stylebox_override( "normal", - _make_style(normal_fill, normal_border, normal_border_width) + _make_style( + selected_fill, + 5 if _selected else 2, + 0.38 if _selected else 0.20, + ) ) add_theme_stylebox_override( "hover", _make_style( - normal_fill, - profile.hover_border, - profile.emphasized_border_width + selected_fill.lightened(0.055), + 5 if _selected else 3, + 0.40 if _selected else 0.29, ) ) add_theme_stylebox_override( "pressed", _make_style( - normal_fill, - profile.pressed_border, - profile.emphasized_border_width + selected_fill.lightened(0.085), + 6, + 0.44, ) ) add_theme_stylebox_override( @@ -237,8 +239,8 @@ func _apply_style() -> void: "disabled", _make_style( normal_fill, - profile.disabled_border, - profile.normal_border_width + 1, + 0.12, ) ) add_theme_color_override("font_color", profile.text_color) @@ -249,21 +251,20 @@ func _apply_style() -> void: func _make_style( fill_color: Color, - border_color: Color, - border_width: int, + shadow_size: int, + shadow_alpha: float, ) -> StyleBoxFlat: var style := StyleBoxFlat.new() style.bg_color = fill_color - style.border_color = border_color - style.border_width_left = border_width - style.border_width_top = border_width - style.border_width_right = border_width - style.border_width_bottom = border_width + style.set_border_width_all(0) var radius: int = ceili(maxf(_presented_size.x, _presented_size.y) * 0.5) style.corner_radius_top_left = radius style.corner_radius_top_right = radius style.corner_radius_bottom_right = radius style.corner_radius_bottom_left = radius + style.shadow_color = Color(0.015, 0.06, 0.09, shadow_alpha) + style.shadow_size = shadow_size + style.shadow_offset = Vector2(0.0, 2.0) return style diff --git a/ui/components/bubble_hotbar/bubble_hotbar_slot.tscn b/ui/components/bubble_hotbar/bubble_hotbar_slot.tscn index 280f03d..893ce3b 100644 --- a/ui/components/bubble_hotbar/bubble_hotbar_slot.tscn +++ b/ui/components/bubble_hotbar/bubble_hotbar_slot.tscn @@ -5,7 +5,7 @@ [ext_resource type="Theme" path="res://ui/game_theme.tres" id="3_theme"] [node name="BubbleHotbarSlot" type="Button"] -custom_minimum_size = Vector2(80, 78) +custom_minimum_size = Vector2(78, 78) focus_mode = 0 mouse_default_cursor_shape = 2 theme = ExtResource("3_theme") diff --git a/ui/components/bubble_menu/bag_item_sprite.gd b/ui/components/bubble_menu/bag_item_sprite.gd new file mode 100644 index 0000000..86e5066 --- /dev/null +++ b/ui/components/bubble_menu/bag_item_sprite.gd @@ -0,0 +1,131 @@ +class_name BagItemSprite +extends ItemDragSource + +signal drag_started +signal drag_finished + +@onready var _visual_root: Control = %VisualRoot +@onready var _item_texture: TextureRect = %ItemTexture +@onready var _quantity_badge: PanelContainer = %QuantityBadge +@onready var _quantity_label: Label = %QuantityLabel +@onready var _compatibility_marker: Label = %CompatibilityMarker + +var _motion_phase: float = 0.0 +var _depth_scale: float = 1.0 +var _selected: bool = false +var _hovered: bool = false +var _dragging: bool = false + + +func _ready() -> void: + mouse_entered.connect(_set_hovered.bind(true)) + mouse_exited.connect(_set_hovered.bind(false)) + focus_entered.connect(_refresh_style) + focus_exited.connect(_refresh_style) + resized.connect(_update_visual_pivot) + _update_visual_pivot() + _apply_quantity_style() + _refresh_style() + + +func configure_item( + new_item_id: StringName, + new_item_name: String, + new_icon: Texture2D, + quantity: int, + hotbar_compatible: bool, + phase: float, + depth_scale: float, +) -> void: + setup(new_item_id, new_item_name, new_icon) + _item_texture.texture = new_icon + _quantity_label.text = "×%d" % quantity + _quantity_badge.visible = quantity > 1 + _compatibility_marker.visible = not hotbar_compatible + _motion_phase = phase + _depth_scale = depth_scale + + +func set_selected(selected: bool) -> void: + _selected = selected + _refresh_style() + + +func advance_presentation(elapsed: float, motion_enabled: bool) -> void: + if not motion_enabled or _dragging: + return + var bob: float = sin(elapsed * TAU / 7.4 + _motion_phase) * 0.9 + var tilt: float = sin( + elapsed * TAU / 10.2 + _motion_phase * 1.29 + ) * 0.014 + _visual_root.position = Vector2(0.0, bob) + _visual_root.rotation = tilt + var emphasis: float = 1.04 if _hovered or has_focus() else 1.0 + _visual_root.scale = Vector2.ONE * _depth_scale * emphasis + + +func _get_drag_data(at_position: Vector2) -> Variant: + var payload: Variant = super(at_position) + if payload != null: + _dragging = true + drag_started.emit() + return payload + + +func _notification(what: int) -> void: + if what == NOTIFICATION_DRAG_END and _dragging: + _dragging = false + drag_finished.emit() + + +func _has_point(point: Vector2) -> bool: + var radius: Vector2 = size * Vector2(0.46, 0.42) + if radius.x <= 0.0 or radius.y <= 0.0: + return false + var normalized: Vector2 = (point - size * 0.5) / radius + return normalized.length_squared() <= 1.0 + + +func _set_hovered(hovered: bool) -> void: + _hovered = hovered + _refresh_style() + + +func _update_visual_pivot() -> void: + _visual_root.pivot_offset = size * 0.5 + + +func _refresh_style() -> void: + var style := StyleBoxFlat.new() + style.bg_color = Color(0.95, 0.9, 0.75, 0.12) if _selected else Color.TRANSPARENT + style.border_color = Color.TRANSPARENT + var width: int = 0 + if _selected: + style.border_color = Color(0.28, 0.19, 0.1, 1.0) + width = 4 + if has_focus(): + style.border_color = Color(0.035, 0.145, 0.22, 1.0) + width = 4 + elif _hovered: + style.border_color = Color(0.48, 0.35, 0.2, 0.9) + width = 2 + style.set_border_width_all(width) + style.set_corner_radius_all(64) + for state: StringName in [ + &"normal", + &"hover", + &"focus", + &"pressed", + ]: + add_theme_stylebox_override(state, style) + + +func _apply_quantity_style() -> void: + var style := StyleBoxFlat.new() + style.bg_color = Color(0.94, 0.86, 0.64, 1.0) + style.border_color = Color(0.31, 0.22, 0.12, 1.0) + style.set_border_width_all(2) + style.set_corner_radius_all(18) + style.content_margin_left = 5.0 + style.content_margin_right = 5.0 + _quantity_badge.add_theme_stylebox_override("panel", style) diff --git a/ui/components/bubble_menu/bag_item_sprite.gd.uid b/ui/components/bubble_menu/bag_item_sprite.gd.uid new file mode 100644 index 0000000..7ee12e5 --- /dev/null +++ b/ui/components/bubble_menu/bag_item_sprite.gd.uid @@ -0,0 +1 @@ +uid://dgbagitemsprite2026 diff --git a/ui/components/bubble_menu/bag_item_sprite.tscn b/ui/components/bubble_menu/bag_item_sprite.tscn new file mode 100644 index 0000000..e6f886c --- /dev/null +++ b/ui/components/bubble_menu/bag_item_sprite.tscn @@ -0,0 +1,83 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://ui/components/bubble_menu/bag_item_sprite.gd" id="1_script"] + +[node name="BagItemSprite" type="Button"] +custom_minimum_size = Vector2(118, 86) +focus_mode = 1 +mouse_default_cursor_shape = 2 +script = ExtResource("1_script") + +[node name="VisualRoot" type="Control" parent="."] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="ItemTexture" type="TextureRect" parent="VisualRoot"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 10.0 +offset_top = 8.0 +offset_right = -10.0 +offset_bottom = -8.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +texture_filter = 1 +expand_mode = 1 +stretch_mode = 5 + +[node name="QuantityBadge" type="PanelContainer" parent="VisualRoot"] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -42.0 +offset_top = -28.0 +offset_right = -2.0 +offset_bottom = -2.0 +grow_horizontal = 0 +grow_vertical = 0 +mouse_filter = 2 + +[node name="QuantityLabel" type="Label" parent="VisualRoot/QuantityBadge"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.17, 0.105, 0.05, 1) +theme_override_font_sizes/font_size = 15 +text = "×2" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="CompatibilityMarker" type="Label" parent="VisualRoot"] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -28.0 +offset_top = 0.0 +offset_right = -2.0 +offset_bottom = 24.0 +grow_horizontal = 0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.31, 0.22, 0.12, 1) +theme_override_colors/font_outline_color = Color(0.96, 0.93, 0.82, 1) +theme_override_constants/outline_size = 2 +theme_override_font_sizes/font_size = 17 +text = "×" +horizontal_alignment = 1 diff --git a/ui/components/bubble_menu/bubble_inventory_cell.gd b/ui/components/bubble_menu/bubble_inventory_cell.gd deleted file mode 100644 index 96e14aa..0000000 --- a/ui/components/bubble_menu/bubble_inventory_cell.gd +++ /dev/null @@ -1,125 +0,0 @@ -class_name BubbleInventoryCell -extends Button - -@export var profile: BubbleMenuProfile - -@onready var _icon: TextureRect = %Icon -@onready var _primary_label: Label = %PrimaryLabel -@onready var _secondary_label: Label = %SecondaryLabel -@onready var _favorite_marker: Label = %FavoriteMarker -@onready var _selected_marker: Label = %SelectedMarker - -var _selected: bool = false -var _focused_item: bool = false -var _compact: bool = false -var _icon_texture: Texture2D -var _primary_text: String = "" -var _secondary_text: String = "" -var _favorite: bool = false - - -func _ready() -> void: - focus_entered.connect(_refresh_style) - focus_exited.connect(_refresh_style) - _apply_compact_layout() - _apply_content() - _refresh_style() - - -func configure( - icon_texture: Texture2D, - primary_text: String, - secondary_text: String, -) -> void: - _icon_texture = icon_texture - _primary_text = primary_text - _secondary_text = secondary_text - if is_node_ready(): - _apply_content() - - -func set_item_state( - selected: bool, - focused_item: bool, - favorite: bool, -) -> void: - _selected = selected - _focused_item = focused_item - _favorite = favorite - if is_node_ready(): - _apply_content() - _refresh_style() - - -func set_compact(compact: bool) -> void: - _compact = compact - if not is_node_ready(): - custom_minimum_size = ( - Vector2(104.0, 98.0) - if compact - else Vector2(144.0, 136.0) - ) - return - _apply_compact_layout() - - -func _apply_compact_layout() -> void: - custom_minimum_size = ( - Vector2(104.0, 98.0) - if _compact - else Vector2(144.0, 136.0) - ) - _icon.custom_minimum_size = ( - Vector2(72.0, 44.0) - if _compact - else Vector2(104.0, 68.0) - ) - _primary_label.add_theme_font_size_override( - "font_size", - 15 if _compact else 18, - ) - _secondary_label.add_theme_font_size_override( - "font_size", - 13 if _compact else 15, - ) - - -func _apply_content() -> void: - _icon.texture = _icon_texture - _primary_label.text = _primary_text - _secondary_label.text = _secondary_text - _selected_marker.visible = _selected - _favorite_marker.visible = _favorite - - -func _has_point(point: Vector2) -> bool: - var radius: Vector2 = size * 0.5 - if radius.x <= 0.0 or radius.y <= 0.0: - return false - var normalized: Vector2 = (point - radius) / radius - return normalized.length_squared() <= 1.0 - - -func _refresh_style() -> void: - if profile == null: - return - var normal_style: StyleBoxFlat = profile.make_normal_style() - var border_width: int = ( - profile.emphasized_border_width - if _selected or _focused_item or has_focus() - else profile.normal_border_width - ) - normal_style.border_width_left = border_width - normal_style.border_width_top = border_width - normal_style.border_width_right = border_width - normal_style.border_width_bottom = border_width - if _selected: - normal_style.bg_color = profile.pressed_fill - if _focused_item: - normal_style.border_color = profile.text_color - add_theme_stylebox_override("normal", normal_style) - add_theme_stylebox_override("hover", profile.make_hover_style()) - add_theme_stylebox_override("focus", normal_style) - add_theme_stylebox_override("pressed", profile.make_pressed_style()) - add_theme_stylebox_override("disabled", profile.make_disabled_style()) - add_theme_color_override("font_color", profile.text_color) diff --git a/ui/components/bubble_menu/bubble_inventory_cell.gd.uid b/ui/components/bubble_menu/bubble_inventory_cell.gd.uid deleted file mode 100644 index 5455c81..0000000 --- a/ui/components/bubble_menu/bubble_inventory_cell.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bubbleinventorycell diff --git a/ui/components/bubble_menu/bubble_inventory_cell.tscn b/ui/components/bubble_menu/bubble_inventory_cell.tscn deleted file mode 100644 index d6774a3..0000000 --- a/ui/components/bubble_menu/bubble_inventory_cell.tscn +++ /dev/null @@ -1,78 +0,0 @@ -[gd_scene load_steps=3 format=3] - -[ext_resource type="Script" path="res://ui/components/bubble_menu/bubble_inventory_cell.gd" id="1_cell"] -[ext_resource type="Resource" path="res://ui/components/bubble_menu/bubble_menu_profile.tres" id="2_profile"] - -[node name="BubbleInventoryCell" type="Button"] -custom_minimum_size = Vector2(144, 136) -toggle_mode = true -script = ExtResource("1_cell") -profile = ExtResource("2_profile") - -[node name="Content" type="VBoxContainer" parent="."] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 17.0 -offset_top = 14.0 -offset_right = -17.0 -offset_bottom = -14.0 -grow_horizontal = 2 -grow_vertical = 2 -mouse_filter = 2 -theme_override_constants/separation = 2 - -[node name="Icon" type="TextureRect" parent="Content"] -unique_name_in_owner = true -custom_minimum_size = Vector2(104, 68) -layout_mode = 2 -size_flags_vertical = 3 -mouse_filter = 2 -texture_filter = 1 -expand_mode = 1 -stretch_mode = 5 - -[node name="PrimaryLabel" type="Label" parent="Content"] -unique_name_in_owner = true -layout_mode = 2 -mouse_filter = 2 -theme_override_font_sizes/font_size = 18 -horizontal_alignment = 1 -text_overrun_behavior = 3 - -[node name="SecondaryLabel" type="Label" parent="Content"] -unique_name_in_owner = true -layout_mode = 2 -mouse_filter = 2 -theme_override_colors/font_color = Color(0.16, 0.25, 0.29, 0.78) -theme_override_font_sizes/font_size = 15 -horizontal_alignment = 1 - -[node name="FavoriteMarker" type="Label" parent="."] -unique_name_in_owner = true -visible = false -layout_mode = 0 -offset_left = 102.0 -offset_top = 12.0 -offset_right = 132.0 -offset_bottom = 42.0 -mouse_filter = 2 -theme_override_colors/font_color = Color(1, 0.82, 0.4, 1) -theme_override_font_sizes/font_size = 23 -text = "★" -horizontal_alignment = 1 - -[node name="SelectedMarker" type="Label" parent="."] -unique_name_in_owner = true -visible = false -layout_mode = 0 -offset_left = 14.0 -offset_top = 10.0 -offset_right = 42.0 -offset_bottom = 38.0 -mouse_filter = 2 -theme_override_colors/font_color = Color(0.035, 0.145, 0.22, 1) -theme_override_font_sizes/font_size = 22 -text = "✓" -horizontal_alignment = 1 diff --git a/ui/components/bubble_menu/bubble_status_bubble.tscn b/ui/components/bubble_menu/bubble_status_bubble.tscn index 87858ec..eb5bd9b 100644 --- a/ui/components/bubble_menu/bubble_status_bubble.tscn +++ b/ui/components/bubble_menu/bubble_status_bubble.tscn @@ -4,7 +4,7 @@ [ext_resource type="Resource" path="res://ui/components/bubble_menu/bubble_menu_profile.tres" id="2_profile"] [node name="BubbleStatusBubble" type="PanelContainer"] -custom_minimum_size = Vector2(128, 88) +custom_minimum_size = Vector2(112, 62) mouse_filter = 2 script = ExtResource("1_status") profile = ExtResource("2_profile") @@ -19,7 +19,7 @@ alignment = 1 unique_name_in_owner = true layout_mode = 2 mouse_filter = 2 -theme_override_font_sizes/font_size = 15 +theme_override_font_sizes/font_size = 13 text = "status" horizontal_alignment = 1 @@ -27,6 +27,6 @@ horizontal_alignment = 1 unique_name_in_owner = true layout_mode = 2 mouse_filter = 2 -theme_override_font_sizes/font_size = 21 +theme_override_font_sizes/font_size = 18 text = "0" horizontal_alignment = 1 diff --git a/ui/components/bubble_menu/cooler_fish_sprite.gd b/ui/components/bubble_menu/cooler_fish_sprite.gd new file mode 100644 index 0000000..60c6578 --- /dev/null +++ b/ui/components/bubble_menu/cooler_fish_sprite.gd @@ -0,0 +1,140 @@ +class_name CoolerFishSprite +extends Button + +@onready var _visual_root: Control = %VisualRoot +@onready var _fish_shadow: TextureRect = %FishShadow +@onready var _fish_texture: TextureRect = %FishTexture +@onready var _favorite_marker: Label = %FavoriteMarker + +var catch_id: StringName +var _neutral_position := Vector2.ZERO +var _target_position := Vector2.ZERO +var _motion_phase: float = 0.0 +var _depth_scale: float = 1.0 +var _batch_selected: bool = false +var _focused_catch: bool = false +var _hovered: bool = false +var _rarity_color := Color.WHITE + + +func _ready() -> void: + resized.connect(_update_visual_pivot) + focus_entered.connect(_refresh_style) + focus_exited.connect(_refresh_style) + mouse_entered.connect(func() -> void: + _hovered = true + _refresh_style() + ) + mouse_exited.connect(func() -> void: + _hovered = false + _refresh_style() + ) + _update_visual_pivot() + _refresh_style() + + +func configure( + identity: StringName, + texture: Texture2D, + phase: float, + depth_scale: float, + rarity_color: Color, +) -> void: + catch_id = identity + _fish_texture.texture = texture + _fish_shadow.texture = texture + _motion_phase = phase + _depth_scale = depth_scale + _rarity_color = rarity_color + _refresh_style() + + +func set_target_position(target: Vector2, immediate: bool = false) -> void: + _target_position = target + if immediate: + _neutral_position = target + position = _neutral_position + + +func set_item_state( + batch_selected: bool, + focused_catch: bool, + favorite: bool, +) -> void: + _batch_selected = batch_selected + _focused_catch = focused_catch + _favorite_marker.visible = favorite + _refresh_style() + + +func advance_presentation(delta: float, elapsed: float) -> void: + var response: float = 1.0 - exp(-9.0 * delta) + _neutral_position = _neutral_position.lerp(_target_position, response) + position = _neutral_position + var bob: float = sin(elapsed * TAU / 7.2 + _motion_phase) * 1.1 + var tilt: float = sin(elapsed * TAU / 9.0 + _motion_phase * 1.31) * 0.018 + var interaction_lift: float = 0.0 + if _batch_selected: + interaction_lift += 3.0 + if _focused_catch or has_focus(): + interaction_lift += 1.5 + elif _hovered: + interaction_lift += 0.8 + _visual_root.position = Vector2(0.0, bob - interaction_lift) + _visual_root.rotation = tilt + var emphasis: float = 1.0 + if _batch_selected: + emphasis += 0.085 + if _focused_catch or has_focus(): + emphasis += 0.035 + elif _hovered: + emphasis += 0.045 + _visual_root.scale = Vector2.ONE * _depth_scale * emphasis + + +func _has_point(point: Vector2) -> bool: + var radius: float = minf(size.x, size.y) * 0.48 + if radius <= 0.0: + return false + return (point - size * 0.5).length_squared() <= radius * radius + + +func _update_visual_pivot() -> void: + _visual_root.pivot_offset = size * 0.5 + + +func _refresh_style() -> void: + var normal := _make_rarity_style(_rarity_color, 2, 0.25) + var hover := _make_rarity_style(_rarity_color.lightened(0.08), 4, 0.34) + var selected_fill: Color = ( + _rarity_color.lightened(0.12) + if _batch_selected + else _rarity_color + ) + var selected := _make_rarity_style( + selected_fill, + 6 if _batch_selected else 4, + 0.46 if _batch_selected else 0.34, + ) + add_theme_stylebox_override( + "normal", + selected if _batch_selected or _focused_catch else normal, + ) + add_theme_stylebox_override("hover", selected if _batch_selected else hover) + add_theme_stylebox_override("focus", selected) + add_theme_stylebox_override("pressed", selected) + + +func _make_rarity_style( + fill: Color, + shadow_size: int, + shadow_alpha: float, +) -> StyleBoxFlat: + var style := StyleBoxFlat.new() + style.bg_color = fill + style.set_border_width_all(0) + style.set_corner_radius_all(128) + style.shadow_color = Color(0.01, 0.045, 0.06, shadow_alpha) + style.shadow_size = shadow_size + style.shadow_offset = Vector2(0.0, 2.0) + return style diff --git a/ui/components/bubble_menu/cooler_fish_sprite.gd.uid b/ui/components/bubble_menu/cooler_fish_sprite.gd.uid new file mode 100644 index 0000000..82d429e --- /dev/null +++ b/ui/components/bubble_menu/cooler_fish_sprite.gd.uid @@ -0,0 +1 @@ +uid://dscoolerfishsprite diff --git a/ui/components/bubble_menu/cooler_fish_sprite.tscn b/ui/components/bubble_menu/cooler_fish_sprite.tscn new file mode 100644 index 0000000..74ad599 --- /dev/null +++ b/ui/components/bubble_menu/cooler_fish_sprite.tscn @@ -0,0 +1,75 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://ui/components/bubble_menu/cooler_fish_sprite.gd" id="1_script"] + +[node name="CoolerFishSprite" type="Button"] +custom_minimum_size = Vector2(72, 72) +focus_mode = 1 +mouse_default_cursor_shape = 2 +script = ExtResource("1_script") + +[node name="VisualRoot" type="Control" parent="."] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +pivot_offset = Vector2(36, 36) + +[node name="FishShadow" type="TextureRect" parent="VisualRoot"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 10.0 +offset_top = 11.0 +offset_right = -4.0 +offset_bottom = -3.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +modulate = Color(0.015, 0.055, 0.07, 0.32) +texture_filter = 1 +expand_mode = 1 +stretch_mode = 5 + +[node name="FishTexture" type="TextureRect" parent="VisualRoot"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 7.0 +offset_top = 7.0 +offset_right = -7.0 +offset_bottom = -7.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +texture_filter = 1 +expand_mode = 1 +stretch_mode = 5 + +[node name="FavoriteMarker" type="Label" parent="VisualRoot"] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -22.0 +offset_top = 0.0 +offset_right = 0.0 +offset_bottom = 22.0 +grow_horizontal = 0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.92, 0.68, 0.16, 1) +theme_override_colors/font_outline_color = Color(0.035, 0.145, 0.22, 1) +theme_override_constants/outline_size = 2 +theme_override_font_sizes/font_size = 16 +text = "★" +horizontal_alignment = 1 diff --git a/ui/components/bubble_menu/cooler_water.gdshader b/ui/components/bubble_menu/cooler_water.gdshader new file mode 100644 index 0000000..5418727 --- /dev/null +++ b/ui/components/bubble_menu/cooler_water.gdshader @@ -0,0 +1,40 @@ +shader_type canvas_item; +render_mode unshaded; + +uniform vec4 water_top : source_color = vec4(0.055, 0.38, 0.50, 1.0); +uniform vec4 water_bottom : source_color = vec4(0.018, 0.16, 0.25, 1.0); +uniform vec4 caustic_color : source_color = vec4(0.66, 0.91, 0.95, 1.0); +uniform float caustic_opacity : hint_range(0.0, 0.2) = 0.055; +uniform float caustic_speed : hint_range(0.0, 0.2) = 0.045; +uniform float bubble_opacity : hint_range(0.0, 0.25) = 0.11; + +float hash(float value) { + return fract(sin(value * 91.713) * 43758.5453); +} + +void fragment() { + vec2 uv = UV; + vec3 base = mix(water_top.rgb, water_bottom.rgb, smoothstep(0.0, 1.0, uv.y)); + float slow_time = TIME * caustic_speed; + float broad_wave = sin((uv.x * 8.0 + uv.y * 5.0 + slow_time) * 6.28318); + float crossing_wave = sin((uv.x * 5.5 - uv.y * 7.0 - slow_time * 0.73) * 6.28318); + float caustic = smoothstep(1.46, 1.88, broad_wave + crossing_wave); + base += caustic_color.rgb * caustic * caustic_opacity; + float sheen = (1.0 - smoothstep(0.0, 0.12, uv.y)) * 0.11; + base += caustic_color.rgb * sheen; + + float bubbles = 0.0; + for (int index = 0; index < 8; index++) { + float key = float(index) + 1.0; + float x = 0.08 + hash(key * 2.13) * 0.84; + float phase = hash(key * 4.71); + float y = 1.08 - mod(slow_time * (0.42 + hash(key) * 0.34) + phase, 1.18); + float radius = 0.005 + hash(key * 8.23) * 0.008; + vec2 delta = uv - vec2(x, y); + delta.x *= 0.62; + float distance_to_edge = abs(length(delta) - radius); + bubbles += 1.0 - smoothstep(0.0015, 0.004, distance_to_edge); + } + base += caustic_color.rgb * min(bubbles, 1.0) * bubble_opacity; + COLOR = vec4(base, 1.0); +} diff --git a/ui/components/bubble_menu/cooler_water.gdshader.uid b/ui/components/bubble_menu/cooler_water.gdshader.uid new file mode 100644 index 0000000..389d753 --- /dev/null +++ b/ui/components/bubble_menu/cooler_water.gdshader.uid @@ -0,0 +1 @@ +uid://dejhqrp2nij1 diff --git a/ui/components/bubble_menu/logbook_entry.gd b/ui/components/bubble_menu/logbook_entry.gd new file mode 100644 index 0000000..0c22a85 --- /dev/null +++ b/ui/components/bubble_menu/logbook_entry.gd @@ -0,0 +1,103 @@ +class_name LogbookEntry +extends PanelContainer + +var _discovered: bool = false + + +func _ready() -> void: + mouse_filter = Control.MOUSE_FILTER_IGNORE + _apply_paper_style(_discovered) + + +func configure( + artwork: Texture2D, + species_name: String, + rarity_name: String, + owned_count: int, + discovered: bool, +) -> void: + _discovered = discovered + var artwork_control := get_node( + ^"Margin/Content/Artwork" + ) as TextureRect + var name_control := get_node( + ^"Margin/Content/Text/NameLabel" + ) as Label + var rarity_control := get_node( + ^"Margin/Content/Text/RarityLabel" + ) as Label + var owned_control := get_node( + ^"Margin/Content/Text/OwnedLabel" + ) as Label + artwork_control.texture = artwork + artwork_control.modulate = ( + Color.WHITE + if discovered + else Color(0.20, 0.17, 0.13, 0.48) + ) + name_control.text = species_name if discovered else "???" + rarity_control.text = rarity_name if discovered else "undiscovered" + owned_control.text = ( + "owned: %d" % owned_count if discovered else "not recorded" + ) + owned_control.visible = true + _apply_paper_style(discovered) + + +func apply_compact_layout(compact: bool) -> void: + var artwork_control := get_node( + ^"Margin/Content/Artwork" + ) as TextureRect + var name_control := get_node( + ^"Margin/Content/Text/NameLabel" + ) as Label + var rarity_control := get_node( + ^"Margin/Content/Text/RarityLabel" + ) as Label + var owned_control := get_node( + ^"Margin/Content/Text/OwnedLabel" + ) as Label + custom_minimum_size = ( + Vector2(236.0, 108.0) if compact else Vector2(214.0, 150.0) + ) + artwork_control.custom_minimum_size = ( + Vector2(92.0, 54.0) if compact else Vector2(128.0, 76.0) + ) + name_control.add_theme_font_size_override( + "font_size", + 16 if compact else 18, + ) + rarity_control.add_theme_font_size_override( + "font_size", + 11 if compact else 13, + ) + owned_control.add_theme_font_size_override( + "font_size", + 11 if compact else 13, + ) + + +func _apply_paper_style(discovered: bool) -> void: + if not is_node_ready(): + return + var style := StyleBoxFlat.new() + style.bg_color = ( + Color(0.965, 0.925, 0.80, 0.78) + if discovered + else Color(0.89, 0.84, 0.72, 0.58) + ) + style.border_color = ( + Color(0.50, 0.39, 0.25, 0.62) + if discovered + else Color(0.39, 0.34, 0.27, 0.42) + ) + style.border_width_bottom = 2 + style.corner_radius_top_left = 18 + style.corner_radius_top_right = 12 + style.corner_radius_bottom_right = 16 + style.corner_radius_bottom_left = 10 + style.content_margin_left = 8.0 + style.content_margin_top = 6.0 + style.content_margin_right = 8.0 + style.content_margin_bottom = 6.0 + add_theme_stylebox_override("panel", style) diff --git a/ui/components/bubble_menu/logbook_entry.gd.uid b/ui/components/bubble_menu/logbook_entry.gd.uid new file mode 100644 index 0000000..30525da --- /dev/null +++ b/ui/components/bubble_menu/logbook_entry.gd.uid @@ -0,0 +1 @@ +uid://dclogbookentry2026 diff --git a/ui/components/bubble_menu/logbook_entry.tscn b/ui/components/bubble_menu/logbook_entry.tscn new file mode 100644 index 0000000..34778a3 --- /dev/null +++ b/ui/components/bubble_menu/logbook_entry.tscn @@ -0,0 +1,66 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://ui/components/bubble_menu/logbook_entry.gd" id="1_script"] + +[node name="LogbookEntry" type="PanelContainer"] +custom_minimum_size = Vector2(214, 150) +mouse_filter = 2 +script = ExtResource("1_script") + +[node name="Margin" type="MarginContainer" parent="."] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_top = 4 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_bottom = 4 + +[node name="Content" type="HBoxContainer" parent="Margin"] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/separation = 7 + +[node name="Artwork" type="TextureRect" parent="Margin/Content"] +unique_name_in_owner = true +custom_minimum_size = Vector2(128, 76) +layout_mode = 2 +size_flags_horizontal = 3 +mouse_filter = 2 +texture_filter = 1 +expand_mode = 1 +stretch_mode = 5 + +[node name="Text" type="VBoxContainer" parent="Margin/Content"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 4 +mouse_filter = 2 +theme_override_constants/separation = 2 + +[node name="NameLabel" type="Label" parent="Margin/Content/Text"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.20, 0.145, 0.085, 1) +theme_override_font_sizes/font_size = 18 +text = "species" +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="RarityLabel" type="Label" parent="Margin/Content/Text"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.34, 0.25, 0.15, 1) +theme_override_font_sizes/font_size = 13 +text = "common" +horizontal_alignment = 1 + +[node name="OwnedLabel" type="Label" parent="Margin/Content/Text"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.34, 0.25, 0.15, 1) +theme_override_font_sizes/font_size = 13 +text = "owned: 0" +horizontal_alignment = 1 diff --git a/ui/components/bubble_menu/notepad_ink_action.gd b/ui/components/bubble_menu/notepad_ink_action.gd new file mode 100644 index 0000000..0d8ba1c --- /dev/null +++ b/ui/components/bubble_menu/notepad_ink_action.gd @@ -0,0 +1,82 @@ +class_name NotepadInkAction +extends Button + +@export var ink_color := Color(0.19, 0.16, 0.12, 1.0) +@export var disabled_ink_color := Color(0.31, 0.28, 0.23, 0.46) +@export var persistent_mark: bool = false: + set(value): + persistent_mark = value + _refresh_ink() + +@onready var _ink_outline: NotepadInkOutline = %InkOutline + +var _hovered: bool = false +var _focused: bool = false +var _pressed: bool = false + + +func _ready() -> void: + mouse_entered.connect(_set_hovered.bind(true)) + mouse_exited.connect(_set_hovered.bind(false)) + focus_entered.connect(_set_focused.bind(true)) + focus_exited.connect(_set_focused.bind(false)) + button_down.connect(_set_pressed.bind(true)) + button_up.connect(_set_pressed.bind(false)) + _apply_paper_style() + _refresh_ink() + + +func refresh_ink_state() -> void: + _apply_text_color() + _refresh_ink() + + +func _set_hovered(value: bool) -> void: + _hovered = value + _refresh_ink() + + +func _set_focused(value: bool) -> void: + _focused = value + _refresh_ink() + + +func _set_pressed(value: bool) -> void: + _pressed = value + _refresh_ink() + + +func _refresh_ink() -> void: + if not is_node_ready(): + return + var strength: float = 0.0 + if not disabled: + if persistent_mark: + strength = 0.78 + if _hovered or _focused: + strength = maxf(strength, 0.92) + if _pressed: + strength = 1.0 + _ink_outline.set_mark_strength(strength) + + +func _apply_paper_style() -> void: + var empty := StyleBoxEmpty.new() + for state: StringName in [ + &"normal", + &"hover", + &"pressed", + &"focus", + &"disabled", + ]: + add_theme_stylebox_override(state, empty) + _apply_text_color() + + +func _apply_text_color() -> void: + var color: Color = disabled_ink_color if disabled else ink_color + add_theme_color_override("font_color", color) + add_theme_color_override("font_hover_color", color.darkened(0.08)) + add_theme_color_override("font_focus_color", color.darkened(0.08)) + add_theme_color_override("font_pressed_color", color.darkened(0.16)) + add_theme_color_override("font_disabled_color", disabled_ink_color) diff --git a/ui/components/bubble_menu/notepad_ink_action.gd.uid b/ui/components/bubble_menu/notepad_ink_action.gd.uid new file mode 100644 index 0000000..120d2f6 --- /dev/null +++ b/ui/components/bubble_menu/notepad_ink_action.gd.uid @@ -0,0 +1 @@ +uid://b42bnpyhxn35k diff --git a/ui/components/bubble_menu/notepad_ink_action.tscn b/ui/components/bubble_menu/notepad_ink_action.tscn new file mode 100644 index 0000000..4ed4b6e --- /dev/null +++ b/ui/components/bubble_menu/notepad_ink_action.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=3 format=3] + +[ext_resource type="Script" path="res://ui/components/bubble_menu/notepad_ink_action.gd" id="1_action"] +[ext_resource type="Script" path="res://ui/components/bubble_menu/notepad_ink_outline.gd" id="2_outline"] + +[node name="NotepadInkAction" type="Button"] +custom_minimum_size = Vector2(104, 46) +focus_mode = 1 +mouse_default_cursor_shape = 2 +flat = true +script = ExtResource("1_action") + +[node name="InkOutline" type="Control" parent="."] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +script = ExtResource("2_outline") diff --git a/ui/components/bubble_menu/notepad_ink_choice.gd b/ui/components/bubble_menu/notepad_ink_choice.gd new file mode 100644 index 0000000..c9be830 --- /dev/null +++ b/ui/components/bubble_menu/notepad_ink_choice.gd @@ -0,0 +1,114 @@ +class_name NotepadInkChoice +extends OptionButton + +@export var ink_color := Color(0.19, 0.16, 0.12, 1.0) + +@onready var _ink_outline: NotepadInkOutline = %InkOutline + +var _hovered: bool = false +var _focused: bool = false + + +func _ready() -> void: + mouse_entered.connect(_set_hovered.bind(true)) + mouse_exited.connect(_set_hovered.bind(false)) + focus_entered.connect(_set_focused.bind(true)) + focus_exited.connect(_set_focused.bind(false)) + _apply_paper_style() + _style_popup() + queue_redraw() + + +func refresh_ink_state() -> void: + _refresh_ink() + + +func _draw() -> void: + var chevron_x: float = size.x - 13.0 + var chevron_y: float = size.y * 0.5 - 1.0 + var chevron := PackedVector2Array([ + Vector2(chevron_x - 4.0, chevron_y - 2.0), + Vector2(chevron_x, chevron_y + 2.0), + Vector2(chevron_x + 4.0, chevron_y - 2.5), + ]) + draw_polyline(chevron, ink_color, 1.8, true) + var underline_y: float = size.y - 5.0 + var underline := PackedVector2Array([ + Vector2(7.0, underline_y), + Vector2(size.x * 0.34, underline_y + 0.7), + Vector2(size.x * 0.68, underline_y - 0.5), + Vector2(size.x - 8.0, underline_y + 0.2), + ]) + var underline_color: Color = ink_color + underline_color.a = 0.48 + draw_polyline(underline, underline_color, 1.1, true) + + +func _set_hovered(value: bool) -> void: + _hovered = value + _refresh_ink() + + +func _set_focused(value: bool) -> void: + _focused = value + _refresh_ink() + + +func _refresh_ink() -> void: + if is_node_ready(): + _ink_outline.set_mark_strength( + 0.88 if (_hovered or _focused) and not disabled else 0.0 + ) + + +func _apply_paper_style() -> void: + var empty := StyleBoxEmpty.new() + for state: StringName in [ + &"normal", + &"hover", + &"pressed", + &"focus", + &"disabled", + ]: + add_theme_stylebox_override(state, empty) + var empty_arrow := ImageTexture.new() + add_theme_icon_override("arrow", empty_arrow) + add_theme_color_override("font_color", ink_color) + add_theme_color_override("font_hover_color", ink_color.darkened(0.08)) + add_theme_color_override("font_focus_color", ink_color.darkened(0.08)) + add_theme_color_override("font_pressed_color", ink_color.darkened(0.14)) + add_theme_color_override("font_disabled_color", Color(ink_color, 0.42)) + + +func _style_popup() -> void: + var popup: PopupMenu = get_popup() + var paper := StyleBoxFlat.new() + paper.bg_color = Color(0.93, 0.885, 0.73, 1.0) + paper.border_color = Color(0.22, 0.19, 0.15, 1.0) + paper.set_border_width_all(2) + paper.set_corner_radius_all(5) + var hover_paper := paper.duplicate() as StyleBoxFlat + hover_paper.bg_color = Color(0.82, 0.775, 0.63, 1.0) + hover_paper.border_color = Color(0.30, 0.26, 0.20, 0.62) + hover_paper.set_border_width_all(1) + popup.add_theme_stylebox_override("panel", paper) + popup.add_theme_stylebox_override("hover", hover_paper) + popup.add_theme_stylebox_override("separator", StyleBoxEmpty.new()) + popup.add_theme_color_override("font_color", ink_color) + popup.add_theme_color_override("font_hover_color", ink_color.darkened(0.08)) + popup.add_theme_color_override( + "font_separator_color", + Color(ink_color, 0.56), + ) + var empty_mark := ImageTexture.new() + for icon_name: StringName in [ + &"checked", + &"unchecked", + &"radio_checked", + &"radio_unchecked", + &"checked_disabled", + &"unchecked_disabled", + &"radio_checked_disabled", + &"radio_unchecked_disabled", + ]: + popup.add_theme_icon_override(icon_name, empty_mark) diff --git a/ui/components/bubble_menu/notepad_ink_choice.gd.uid b/ui/components/bubble_menu/notepad_ink_choice.gd.uid new file mode 100644 index 0000000..67a40c0 --- /dev/null +++ b/ui/components/bubble_menu/notepad_ink_choice.gd.uid @@ -0,0 +1 @@ +uid://h754d8qatlse diff --git a/ui/components/bubble_menu/notepad_ink_choice.tscn b/ui/components/bubble_menu/notepad_ink_choice.tscn new file mode 100644 index 0000000..bc9828f --- /dev/null +++ b/ui/components/bubble_menu/notepad_ink_choice.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=3 format=3] + +[ext_resource type="Script" path="res://ui/components/bubble_menu/notepad_ink_choice.gd" id="1_choice"] +[ext_resource type="Script" path="res://ui/components/bubble_menu/notepad_ink_outline.gd" id="2_outline"] + +[node name="NotepadInkChoice" type="OptionButton"] +custom_minimum_size = Vector2(124, 38) +focus_mode = 1 +mouse_default_cursor_shape = 2 +clip_text = true +fit_to_longest_item = false +script = ExtResource("1_choice") + +[node name="InkOutline" type="Control" parent="."] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +script = ExtResource("2_outline") diff --git a/ui/components/bubble_menu/notepad_ink_outline.gd b/ui/components/bubble_menu/notepad_ink_outline.gd new file mode 100644 index 0000000..b7efd56 --- /dev/null +++ b/ui/components/bubble_menu/notepad_ink_outline.gd @@ -0,0 +1,64 @@ +class_name NotepadInkOutline +extends Control + +@export var ink_color := Color(0.20, 0.17, 0.13, 0.9) +@export_range(0.5, 6.0, 0.1) var stroke_width: float = 2.0 +@export_range(0.0, 16.0, 0.5) var padding: float = 3.0 +@export_range(0, 1000000, 1) var shape_seed: int = 17 + +var _mark_strength: float = 0.0 + + +func _ready() -> void: + mouse_filter = Control.MOUSE_FILTER_IGNORE + + +func set_mark_strength(strength: float) -> void: + _mark_strength = clampf(strength, 0.0, 1.0) + visible = _mark_strength > 0.001 + queue_redraw() + + +func _draw() -> void: + if _mark_strength <= 0.001: + return + var center: Vector2 = size * 0.5 + var radius := Vector2( + maxf(size.x * 0.5 - padding, 1.0), + maxf(size.y * 0.5 - padding, 1.0), + ) + var primary := _build_rough_loop(center, radius, 0) + var secondary := _build_rough_loop( + center + Vector2(0.7, -0.45), + radius - Vector2(1.2, 0.8), + 41, + ) + var primary_color: Color = ink_color + primary_color.a *= _mark_strength + var secondary_color: Color = ink_color + secondary_color.a *= _mark_strength * 0.36 + draw_polyline(primary, primary_color, stroke_width, true) + draw_polyline(secondary, secondary_color, maxf(stroke_width * 0.62, 0.8), true) + + +func _build_rough_loop( + center: Vector2, + radius: Vector2, + seed_offset: int, +) -> PackedVector2Array: + const POINT_COUNT: int = 26 + var points := PackedVector2Array() + for index: int in POINT_COUNT: + var angle: float = TAU * float(index) / float(POINT_COUNT) + var wobble: float = ( + sin(float(shape_seed + seed_offset) * 0.73 + float(index) * 2.17) + + sin(float(shape_seed + seed_offset) * 0.31 + float(index) * 4.03) + * 0.45 + ) + var radial_scale: float = 1.0 + wobble * 0.018 + points.append( + center + + Vector2(cos(angle), sin(angle)) * radius * radial_scale + ) + points.append(points[0]) + return points diff --git a/ui/components/bubble_menu/notepad_ink_outline.gd.uid b/ui/components/bubble_menu/notepad_ink_outline.gd.uid new file mode 100644 index 0000000..ac7d0ac --- /dev/null +++ b/ui/components/bubble_menu/notepad_ink_outline.gd.uid @@ -0,0 +1 @@ +uid://dwh3kpogaelxo diff --git a/ui/hotbar.gd b/ui/hotbar.gd index 427c46a..fb2b96c 100644 --- a/ui/hotbar.gd +++ b/ui/hotbar.gd @@ -162,9 +162,9 @@ func _apply_layout() -> void: available_size.y - reference_size.y * presentation_scale ) var field_size := ( - Vector2(600.0, 82.0) + Vector2(580.0, 82.0) if _compact_layout - else Vector2(820.0, 104.0) + else Vector2(790.0, 104.0) ) _bubble_field.size = field_size _bubble_field.position = Vector2( diff --git a/ui/hotbar.tscn b/ui/hotbar.tscn index eaf704c..6150b5d 100644 --- a/ui/hotbar.tscn +++ b/ui/hotbar.tscn @@ -37,73 +37,73 @@ mouse_filter = 2 [node name="BubbleField" type="Control" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot"] unique_name_in_owner = true layout_mode = 0 -offset_left = 230.0 +offset_left = 245.0 offset_top = 608.0 -offset_right = 1050.0 +offset_right = 1035.0 offset_bottom = 712.0 mouse_filter = 2 [node name="Slot1" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot/BubbleField" instance=ExtResource("3_slot")] layout_mode = 0 slot_index = 0 -desktop_anchor = Vector2(58, 49) -compact_anchor = Vector2(52, 42) +desktop_anchor = Vector2(55, 49) +compact_anchor = Vector2(50, 42) motion_phase = 0.15 [node name="Slot2" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot/BubbleField" instance=ExtResource("3_slot")] layout_mode = 0 slot_index = 1 -desktop_anchor = Vector2(146, 53) -compact_anchor = Vector2(114, 46) +desktop_anchor = Vector2(140, 53) +compact_anchor = Vector2(110, 46) motion_phase = 0.82 [node name="Slot3" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot/BubbleField" instance=ExtResource("3_slot")] layout_mode = 0 slot_index = 2 -desktop_anchor = Vector2(234, 57) -compact_anchor = Vector2(176, 50) +desktop_anchor = Vector2(225, 57) +compact_anchor = Vector2(170, 50) motion_phase = 1.49 [node name="Slot4" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot/BubbleField" instance=ExtResource("3_slot")] layout_mode = 0 slot_index = 3 -desktop_anchor = Vector2(322, 60) -compact_anchor = Vector2(238, 53) +desktop_anchor = Vector2(310, 60) +compact_anchor = Vector2(230, 53) motion_phase = 2.16 [node name="Slot5" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot/BubbleField" instance=ExtResource("3_slot")] layout_mode = 0 slot_index = 4 -desktop_anchor = Vector2(410, 62) -compact_anchor = Vector2(300, 55) +desktop_anchor = Vector2(395, 62) +compact_anchor = Vector2(290, 55) motion_phase = 2.83 [node name="Slot6" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot/BubbleField" instance=ExtResource("3_slot")] layout_mode = 0 slot_index = 5 -desktop_anchor = Vector2(498, 60) -compact_anchor = Vector2(362, 53) +desktop_anchor = Vector2(480, 60) +compact_anchor = Vector2(350, 53) motion_phase = 3.5 [node name="Slot7" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot/BubbleField" instance=ExtResource("3_slot")] layout_mode = 0 slot_index = 6 -desktop_anchor = Vector2(586, 57) -compact_anchor = Vector2(424, 50) +desktop_anchor = Vector2(565, 57) +compact_anchor = Vector2(410, 50) motion_phase = 4.17 [node name="Slot8" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot/BubbleField" instance=ExtResource("3_slot")] layout_mode = 0 slot_index = 7 -desktop_anchor = Vector2(674, 53) -compact_anchor = Vector2(486, 46) +desktop_anchor = Vector2(650, 53) +compact_anchor = Vector2(470, 46) motion_phase = 4.84 [node name="Slot9" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot/BubbleField" instance=ExtResource("3_slot")] layout_mode = 0 slot_index = 8 -desktop_anchor = Vector2(762, 49) -compact_anchor = Vector2(548, 42) +desktop_anchor = Vector2(735, 49) +compact_anchor = Vector2(530, 42) motion_phase = 5.51 [node name="SelectedItemLabel" type="Label" parent="ResponsiveHotbarStage/HotbarPresentationScaleRoot"] diff --git a/ui/player_menu.gd b/ui/player_menu.gd index 9ebc27c..5ad512a 100644 --- a/ui/player_menu.gd +++ b/ui/player_menu.gd @@ -18,7 +18,6 @@ const ItemDataType = preload("res://items/item_data.gd") const OwnedItemType = preload("res://items/owned_item.gd") const PlayerBagType = preload("res://inventory/player_bag.gd") const PlayerHotbarType = preload("res://inventory/player_hotbar.gd") -const ItemDragSourceType = preload("res://ui/item_drag_source.gd") const PlayerCoolerCapacityType = preload( "res://progression/player_cooler_capacity.gd" ) @@ -34,21 +33,48 @@ const BubbleClusterType = preload( const BubbleContentShellType = preload( "res://ui/components/bubble_menu/bubble_content_shell.gd" ) -const BubbleInventoryCellType = preload( - "res://ui/components/bubble_menu/bubble_inventory_cell.gd" -) -const BubbleInventoryCellScene = preload( - "res://ui/components/bubble_menu/bubble_inventory_cell.tscn" -) const BubbleStatusBubbleType = preload( "res://ui/components/bubble_menu/bubble_status_bubble.gd" ) +const NotepadInkActionType = preload( + "res://ui/components/bubble_menu/notepad_ink_action.gd" +) +const NotepadInkChoiceType = preload( + "res://ui/components/bubble_menu/notepad_ink_choice.gd" +) +const CoolerFishSpriteType = preload( + "res://ui/components/bubble_menu/cooler_fish_sprite.gd" +) +const CoolerFishSpriteScene = preload( + "res://ui/components/bubble_menu/cooler_fish_sprite.tscn" +) +const BagItemSpriteType = preload( + "res://ui/components/bubble_menu/bag_item_sprite.gd" +) +const BagItemSpriteScene = preload( + "res://ui/components/bubble_menu/bag_item_sprite.tscn" +) +const LogbookEntryType = preload( + "res://ui/components/bubble_menu/logbook_entry.gd" +) +const LogbookEntryScene = preload( + "res://ui/components/bubble_menu/logbook_entry.tscn" +) const MENU_ENTER_DURATION: float = 0.58 const MENU_EXIT_DURATION: float = 0.52 const PAGE_OUT_DURATION: float = 0.34 const PAGE_IN_DURATION: float = 0.42 +const LOGBOOK_PAGE_DURATION: float = 0.18 const TRANSITION_SAFE_MARGIN: float = 28.0 +const DESKTOP_REFERENCE_SIZE := Vector2(1280.0, 720.0) +const COMPACT_REFERENCE_SIZE := Vector2(640.0, 480.0) +const COMPACT_HEIGHT_THRESHOLD: float = 560.0 +const COOLER_RARITY_COMMON := Color("e8eef0") +const COOLER_RARITY_UNCOMMON := Color("64c87c") +const COOLER_RARITY_RARE := Color("6098dd") +const COOLER_RARITY_EPIC := Color("a979cf") +const COOLER_RARITY_LEGENDARY := Color("db78a7") signal menu_visibility_changed(is_open: bool) @@ -74,6 +100,55 @@ enum CloseReason { } @onready var _navigation_cluster: BubbleClusterType = %NavigationCluster +@onready var _presentation_scale_root: Control = %PlayerMenuPresentationScaleRoot +@onready var _cooler_page: Control = %CoolerPage +@onready var _cooler_outer_wall: PanelContainer = %CoolerOuterWall +@onready var _cooler_inner_liner: PanelContainer = %CoolerInnerLiner +@onready var _fish_field: Control = %FishField +@onready var _cooler_empty: Label = %CoolerEmpty +@onready var _cooler_sort_controls: HBoxContainer = %CoolerSortControls +@onready var _cooler_sort_option: NotepadInkChoiceType = %CoolerSortOption +@onready var _cooler_sort_direction: NotepadInkActionType = %CoolerSortDirection +@onready var _detail_constellation: Control = %DetailConstellation +@onready var _detail_bubble: Control = %DetailBubble +@onready var _notepad_binding: Label = %BindingDecoration +@onready var _notepad_title: Label = %NotepadTitle +@onready var _notepad_rule: ColorRect = %NotepadRule +@onready var _notepad_wallet: Label = %NotepadWallet +@onready var _notepad_capacity: Label = %NotepadCapacity +@onready var _cooler_detail_texture: TextureRect = %CoolerDetailTexture +@onready var _cooler_detail_name: Label = %CoolerDetailName +@onready var _cooler_detail_data: Label = %CoolerDetailData +@onready var _cooler_selection_summary: Label = %CoolerSelectionSummary +@onready var _favorite_bubble: NotepadInkActionType = %FavoriteBubble +@onready var _sell_bubble: NotepadInkActionType = %SellBubble +@onready var _bag_page: Control = %BagPage +@onready var _bag_outer_wall: PanelContainer = %BagOuterWall +@onready var _bag_inner_liner: PanelContainer = %BagInnerLiner +@onready var _bag_scroll: ScrollContainer = %BagScroll +@onready var _bag_host: Control = %BagHost +@onready var _bag_item_field: Control = %BagItemField +@onready var _bag_empty_state: Label = %BagEmptyState +@onready var _bag_instruction_bubble: PanelContainer = %BagInstructionBubble +@onready var _bag_detail_constellation: Control = %BagDetailConstellation +@onready var _bag_sprite_detail_bubble: Control = %BagDetailBubble +@onready var _bag_sprite_detail_texture: TextureRect = %BagSpriteDetailTexture +@onready var _bag_sprite_detail_name: Label = %BagSpriteDetailName +@onready var _bag_sprite_detail_data: Label = %BagSpriteDetailData +@onready var _logbook_page: Control = %LogbookPage +@onready var _book_backing: PanelContainer = %BookBacking +@onready var _book_spread: BoxContainer = %BookSpread +@onready var _left_page: PanelContainer = %LeftPage +@onready var _right_page: PanelContainer = %RightPage +@onready var _book_gutter: ColorRect = %BookGutter +@onready var _left_heading: Label = %LeftHeading +@onready var _right_heading: Label = %RightHeading +@onready var _left_entry_field: BoxContainer = %LeftEntryField +@onready var _right_entry_field: BoxContainer = %RightEntryField +@onready var _logbook_empty_state: Label = %LogbookEmptyState +@onready var _logbook_previous: BubbleButtonType = %LogbookPrevious +@onready var _logbook_next: BubbleButtonType = %LogbookNext +@onready var _logbook_page_status: BubbleStatusBubbleType = %LogbookPageStatus @onready var _inventory_tab: BubbleButtonType = %InventoryTab @onready var _bag_tab: BubbleButtonType = %BagTab @onready var _logbook_tab: BubbleButtonType = %LogbookTab @@ -81,7 +156,7 @@ enum CloseReason { @onready var _content_shell: BubbleContentShellType = %MenuPanel @onready var _content_stage: Control = %Content @onready var _cooler_scroll: ScrollContainer = %CoolerScroll -@onready var _cooler_host: VBoxContainer = %CoolerHost +@onready var _cooler_host: Control = %CoolerHost @onready var _wallet_balance: Label = %WalletBalance @onready var _header: Control = %Header @onready var _separator: Control = %Separator @@ -164,16 +239,27 @@ var _transitioning: bool = false var _page_transitioning: bool = false var _presentation_rest_position: Vector2 = Vector2.ZERO var _content_rest_position: Vector2 = Vector2.ZERO +var _cooler_rest_position: Vector2 = Vector2.ZERO +var _bag_rest_position: Vector2 = Vector2.ZERO +var _logbook_rest_position: Vector2 = Vector2.ZERO +var _page_outgoing_root: Control +var _page_incoming_root: Control +var _page_hosts_shared: bool = false +var _fish_nodes: Dictionary[StringName, CoolerFishSpriteType] = {} +var _sorted_catches: Array[FishCatchType] = [] +var _bag_item_nodes: Dictionary[StringName, BagItemSpriteType] = {} +var _sorted_bag_items: Array[OwnedItemType] = [] +var _bag_drag_active: bool = false +var _motion_elapsed: float = 0.0 +var _logbook_species: Array[FishDataType] = [] +var _logbook_current_page: int = 0 +var _logbook_page_count: int = 1 +var _logbook_page_transitioning: bool = false +var _logbook_page_generation: int = 0 +var _logbook_page_tween: Tween func _ready() -> void: - _inventory_section.reparent(_cooler_host) - _inventory_section.size_flags_horizontal = Control.SIZE_EXPAND_FILL - _inventory_section.size_flags_vertical = Control.SIZE_EXPAND_FILL - _inventory_section.move_child( - _sort_bar, - _inventory_section.get_child_count() - 1, - ) _inventory_tab.pressed.connect( _show_section.bind(Section.COOLER) ) @@ -182,16 +268,27 @@ func _ready() -> void: _show_section.bind(Section.LOGBOOK) ) _close_button.pressed.connect(close_menu) - _sort_option.item_selected.connect(_on_sort_selected) + _sort_option.item_selected.connect(_on_sort_selected.bind(_sort_option)) _sort_direction.pressed.connect(_on_sort_direction_pressed) + _cooler_sort_option.item_selected.connect( + _on_sort_selected.bind(_cooler_sort_option) + ) + _cooler_sort_direction.pressed.connect(_on_sort_direction_pressed) _favorite_button.pressed.connect(_on_favorite_pressed) _sell_button.pressed.connect(_on_sell_pressed) + _favorite_bubble.pressed.connect(_on_favorite_pressed) + _sell_bubble.pressed.connect(_on_sell_pressed) _confirm_sale_button.pressed.connect(_on_confirm_sale_pressed) _cancel_sale_button.pressed.connect(_close_sale_confirmation) + _configure_sale_confirmation_focus() _sort_option.add_item("catch order", SortMode.CATCH_ORDER) _sort_option.add_item("name", SortMode.NAME) _sort_option.add_item("rarity", SortMode.RARITY) _sort_option.select(SortMode.CATCH_ORDER) + _cooler_sort_option.add_item("catch order", SortMode.CATCH_ORDER) + _cooler_sort_option.add_item("name", SortMode.NAME) + _cooler_sort_option.add_item("rarity", SortMode.RARITY) + _cooler_sort_option.select(SortMode.CATCH_ORDER) _update_sort_direction_text() _navigation_cluster.configure([ _inventory_tab, @@ -200,7 +297,16 @@ func _ready() -> void: _close_button, ]) _configure_navigation_focus() + _apply_navigation_styles() _apply_cooler_control_styles() + _apply_cooler_wall_styles() + _apply_cooler_notepad_style() + _fish_field.gui_input.connect(_on_fish_field_gui_input) + _apply_bag_styles() + _bag_item_field.gui_input.connect(_on_bag_field_gui_input) + _apply_logbook_styles() + _logbook_previous.pressed.connect(_request_logbook_page.bind(-1)) + _logbook_next.pressed.connect(_request_logbook_page.bind(1)) resized.connect(_update_shell_layout) _show_section_immediate(_current_section) call_deferred("_update_shell_layout") @@ -407,17 +513,33 @@ func _show_section_immediate(section: Section) -> void: _current_section = section if not is_node_ready(): return - _inventory_section.visible = section == Section.COOLER - _cooler_scroll.visible = section == Section.COOLER - _bag_section.visible = section == Section.BAG + _configure_navigation_focus() + _cooler_page.visible = section == Section.COOLER + _bag_page.visible = section == Section.BAG + _logbook_page.visible = section == Section.LOGBOOK + _content_shell.visible = false + _inventory_section.visible = false + _bag_section.visible = false _logbook_section.visible = section == Section.LOGBOOK - _content_shell.set_background_visible(section != Section.COOLER) + _content_shell.set_background_visible(true) _header.visible = section != Section.COOLER _separator.visible = section != Section.COOLER + if section == Section.COOLER: + _refresh_inventory() + else: + _fish_selection.clear() + _close_detail_constellation() + if section != Section.BAG: + _close_bag_detail() + else: + _update_bag_detail() + if section != Section.LOGBOOK: + _cancel_logbook_page_transition(true) _inventory_tab.button_pressed = section == Section.COOLER _bag_tab.button_pressed = section == Section.BAG _logbook_tab.button_pressed = section == Section.LOGBOOK _update_navigation_selection() + _configure_active_page_focus() func _focus_current_section() -> void: @@ -431,7 +553,21 @@ func _focus_current_section() -> void: func _process(delta: float) -> void: if visible: + _motion_elapsed += delta _navigation_cluster.advance_motion(delta) + _apply_navigation_selection_presentation() + for fish_node: CoolerFishSpriteType in _fish_nodes.values(): + fish_node.advance_presentation(delta, _motion_elapsed) + var bag_motion_enabled: bool = ( + not _bag_drag_active and not get_viewport().gui_is_dragging() + ) + for item_node: BagItemSpriteType in _bag_item_nodes.values(): + item_node.advance_presentation( + _motion_elapsed, + bag_motion_enabled, + ) + if _current_section == Section.LOGBOOK: + _advance_logbook_page_controls(delta) func _configure_navigation_focus() -> void: @@ -455,6 +591,47 @@ func _configure_navigation_focus() -> void: bubble.focus_neighbor_bottom = bubble.focus_neighbor_right +func _configure_sale_confirmation_focus() -> void: + _confirm_sale_button.focus_neighbor_left = ( + _confirm_sale_button.get_path_to(_cancel_sale_button) + ) + _confirm_sale_button.focus_neighbor_right = ( + _confirm_sale_button.focus_neighbor_left + ) + _confirm_sale_button.focus_neighbor_top = ( + _confirm_sale_button.focus_neighbor_left + ) + _confirm_sale_button.focus_neighbor_bottom = ( + _confirm_sale_button.focus_neighbor_left + ) + _cancel_sale_button.focus_neighbor_left = ( + _cancel_sale_button.get_path_to(_confirm_sale_button) + ) + _cancel_sale_button.focus_neighbor_right = ( + _cancel_sale_button.focus_neighbor_left + ) + _cancel_sale_button.focus_neighbor_top = ( + _cancel_sale_button.focus_neighbor_left + ) + _cancel_sale_button.focus_neighbor_bottom = ( + _cancel_sale_button.focus_neighbor_left + ) + if not _sale_confirmation.visible: + for button: Button in [_confirm_sale_button, _cancel_sale_button]: + button.focus_mode = Control.FOCUS_NONE + button.mouse_filter = Control.MOUSE_FILTER_IGNORE + + +func _configure_active_page_focus() -> void: + match _current_section: + Section.COOLER: + _configure_cooler_fish_focus() + Section.BAG: + _configure_bag_item_focus() + Section.LOGBOOK: + _configure_logbook_focus() + + func _apply_cooler_control_styles() -> void: var profile: BubbleMenuProfile = _inventory_tab.profile if profile == null: @@ -484,6 +661,189 @@ func _apply_cooler_control_styles() -> void: "font_focus_color", profile.text_hover_color, ) +func _apply_cooler_wall_styles() -> void: + var outer := StyleBoxFlat.new() + outer.bg_color = Color(0.76, 0.9, 0.96, 1.0) + outer.border_color = Color(0.91, 0.98, 1.0, 1.0) + outer.set_border_width_all(7) + outer.set_corner_radius_all(58) + _cooler_outer_wall.add_theme_stylebox_override("panel", outer) + var inner := StyleBoxFlat.new() + inner.bg_color = Color(0.018, 0.16, 0.25, 1.0) + inner.border_color = Color(0.56, 0.78, 0.86, 1.0) + inner.set_border_width_all(5) + inner.set_corner_radius_all(45) + _cooler_inner_liner.add_theme_stylebox_override("panel", inner) + var scroll_bar := _cooler_scroll.get_v_scroll_bar() + var scroll_grabber := StyleBoxFlat.new() + scroll_grabber.bg_color = Color(0.56, 0.78, 0.86, 0.58) + scroll_grabber.set_corner_radius_all(6) + scroll_bar.add_theme_stylebox_override("grabber", scroll_grabber) + scroll_bar.add_theme_stylebox_override("grabber_highlight", scroll_grabber) + scroll_bar.add_theme_stylebox_override("grabber_pressed", scroll_grabber) + var scroll_track := StyleBoxFlat.new() + scroll_track.bg_color = Color(0.02, 0.1, 0.14, 0.28) + scroll_track.set_corner_radius_all(6) + scroll_bar.add_theme_stylebox_override("scroll", scroll_track) + + +func _apply_cooler_notepad_style() -> void: + var paper := StyleBoxFlat.new() + paper.bg_color = Color(0.93, 0.885, 0.73, 1.0) + paper.border_color = Color(0.22, 0.19, 0.15, 1.0) + paper.set_border_width_all(4) + paper.corner_radius_top_left = 9 + paper.corner_radius_top_right = 7 + paper.corner_radius_bottom_right = 11 + paper.corner_radius_bottom_left = 8 + paper.shadow_color = Color(0.10, 0.08, 0.06, 0.46) + paper.shadow_size = 4 + paper.shadow_offset = Vector2(3.0, 4.0) + _detail_bubble.add_theme_stylebox_override("panel", paper) + + +func _apply_navigation_styles() -> void: + var profile: BubbleMenuProfile = _inventory_tab.profile + if profile == null: + return + var normal := _make_navigation_style(profile.normal_fill, 2, 0.24) + var hover := _make_navigation_style( + profile.hover_fill.lightened(0.025), + 4, + 0.34, + ) + var pressed := _make_navigation_style( + profile.pressed_fill.lightened(0.055), + 5, + 0.40, + ) + var disabled := _make_navigation_style(profile.disabled_fill, 1, 0.14) + for bubble: BubbleButtonType in [ + _inventory_tab, + _bag_tab, + _logbook_tab, + _close_button, + ]: + bubble.add_theme_stylebox_override("normal", normal) + bubble.add_theme_stylebox_override("hover", hover) + bubble.add_theme_stylebox_override("focus", hover) + bubble.add_theme_stylebox_override("pressed", pressed) + bubble.add_theme_stylebox_override("disabled", disabled) + + +func _make_navigation_style( + fill: Color, + shadow_size: int, + shadow_alpha: float, +) -> StyleBoxFlat: + var style := StyleBoxFlat.new() + style.bg_color = fill + style.set_corner_radius_all(128) + style.set_border_width_all(0) + style.shadow_color = Color(0.015, 0.06, 0.09, shadow_alpha) + style.shadow_size = shadow_size + style.shadow_offset = Vector2(0.0, 2.0) + return style + + +func _apply_navigation_selection_presentation() -> void: + for bubble: BubbleButtonType in [ + _inventory_tab, + _bag_tab, + _logbook_tab, + ]: + if not bubble.button_pressed: + continue + bubble.position.y -= 2.0 + bubble.scale *= 1.025 + + +func _apply_bag_styles() -> void: + var outer := StyleBoxFlat.new() + outer.bg_color = Color(0.39, 0.31, 0.2, 1.0) + outer.border_color = Color(0.67, 0.54, 0.33, 1.0) + outer.set_border_width_all(7) + outer.corner_radius_top_left = 88 + outer.corner_radius_top_right = 64 + outer.corner_radius_bottom_right = 94 + outer.corner_radius_bottom_left = 70 + _bag_outer_wall.add_theme_stylebox_override("panel", outer) + var inner := StyleBoxFlat.new() + inner.bg_color = Color(0.92, 0.85, 0.68, 1.0) + inner.border_color = Color(0.75, 0.62, 0.38, 1.0) + inner.set_border_width_all(4) + inner.corner_radius_top_left = 68 + inner.corner_radius_top_right = 48 + inner.corner_radius_bottom_right = 72 + inner.corner_radius_bottom_left = 52 + _bag_inner_liner.add_theme_stylebox_override("panel", inner) + var bubble := StyleBoxFlat.new() + bubble.bg_color = Color(0.96, 0.91, 0.78, 0.98) + bubble.border_color = Color(0.55, 0.41, 0.23, 1.0) + bubble.set_border_width_all(3) + bubble.set_corner_radius_all(54) + bubble.content_margin_left = 12.0 + bubble.content_margin_top = 9.0 + bubble.content_margin_right = 12.0 + bubble.content_margin_bottom = 9.0 + _bag_instruction_bubble.add_theme_stylebox_override("panel", bubble) + _bag_sprite_detail_bubble.add_theme_stylebox_override( + "panel", + bubble.duplicate(), + ) + + +func _apply_logbook_styles() -> void: + var backing := StyleBoxFlat.new() + backing.bg_color = Color(0.54, 0.42, 0.27, 1.0) + backing.border_color = Color(0.72, 0.59, 0.39, 1.0) + backing.set_border_width_all(6) + backing.corner_radius_top_left = 42 + backing.corner_radius_top_right = 34 + backing.corner_radius_bottom_right = 46 + backing.corner_radius_bottom_left = 36 + _book_backing.add_theme_stylebox_override("panel", backing) + var left_paper := StyleBoxFlat.new() + left_paper.bg_color = Color(0.95, 0.91, 0.79, 1.0) + left_paper.border_color = Color(0.80, 0.70, 0.52, 1.0) + left_paper.set_border_width_all(3) + left_paper.corner_radius_top_left = 30 + left_paper.corner_radius_bottom_left = 38 + left_paper.corner_radius_top_right = 8 + left_paper.corner_radius_bottom_right = 6 + _left_page.add_theme_stylebox_override("panel", left_paper) + var right_paper := StyleBoxFlat.new() + right_paper.bg_color = Color(0.925, 0.875, 0.74, 1.0) + right_paper.border_color = Color(0.77, 0.66, 0.48, 1.0) + right_paper.set_border_width_all(3) + right_paper.corner_radius_top_left = 8 + right_paper.corner_radius_bottom_left = 6 + right_paper.corner_radius_top_right = 34 + right_paper.corner_radius_bottom_right = 40 + _right_page.add_theme_stylebox_override("panel", right_paper) + for label: Label in [_left_heading, _right_heading, _logbook_empty_state]: + label.add_theme_color_override( + "font_color", + Color(0.22, 0.16, 0.09, 1.0), + ) + var page_profile: BubbleMenuProfile = _logbook_previous.profile + if page_profile != null: + var disabled_style: StyleBoxFlat = page_profile.make_normal_style() + disabled_style.bg_color.a = 0.82 + disabled_style.border_color.a = 0.72 + for control: BubbleButtonType in [ + _logbook_previous, + _logbook_next, + ]: + control.add_theme_stylebox_override( + "disabled", + disabled_style.duplicate(), + ) + control.add_theme_color_override( + "font_disabled_color", + Color(0.035, 0.145, 0.22, 0.68), + ) + _logbook_page_status.set_content("pages", "1 / 1") func _update_navigation_selection() -> void: @@ -499,69 +859,256 @@ func _set_navigation_target(section: Section) -> void: func _update_shell_layout() -> void: if not is_node_ready(): return - var compact: bool = size.y < 560.0 or size.x < 760.0 + _cancel_logbook_page_transition(true) + var display_size := Vector2(maxf(size.x, 1.0), maxf(size.y, 1.0)) + var compact: bool = display_size.y < COMPACT_HEIGHT_THRESHOLD _compact_layout = compact - var side_margin: float = 10.0 if compact else 42.0 - var top_margin: float = 96.0 if compact else 104.0 - var bottom_margin: float = 96.0 if compact else 138.0 - _content_shell.position = Vector2(side_margin, top_margin) - _content_shell.size = Vector2( - maxf(1.0, size.x - side_margin * 2.0), - maxf(1.0, size.y - top_margin - bottom_margin) + var reference_size := ( + COMPACT_REFERENCE_SIZE if compact else DESKTOP_REFERENCE_SIZE ) + var presentation_scale: float = minf( + display_size.x / reference_size.x, + display_size.y / reference_size.y, + ) + presentation_scale = clampf(presentation_scale, 0.85, 3.0) + _presentation_scale_root.size = reference_size + _presentation_scale_root.scale = Vector2.ONE * presentation_scale + _presentation_scale_root.position = ( + display_size - reference_size * presentation_scale + ) * 0.5 + _content_shell.position = Vector2(14.0, 92.0) if compact else Vector2(42.0, 104.0) + _content_shell.size = Vector2(612.0, 286.0) if compact else Vector2(1196.0, 478.0) _presentation_rest_position = _content_shell.position - var navigation_size := Vector2( - minf(size.x - 20.0, 610.0 if compact else 760.0), - 52.0 if compact else 96.0 + var navigation_size := ( + Vector2(620.0, 75.0) if compact else Vector2(620.0, 100.0) ) _navigation_cluster.position = Vector2( - (size.x - navigation_size.x) * 0.5, - 4.0 if compact else 14.0 + (reference_size.x - navigation_size.x) * 0.5, + 4.0 if compact else 8.0 ) _navigation_cluster.size = navigation_size _navigation_cluster.apply_layout(navigation_size, compact) - _inventory_grid.columns = 2 if compact else 3 + _cooler_page.size = reference_size + _cooler_page.position = Vector2.ZERO + _cooler_rest_position = Vector2.ZERO + _layout_cooler_fish(false) + _cooler_outer_wall.position = ( + Vector2(14.0, 154.0) if compact else Vector2(54.0, 126.0) + ) + _cooler_outer_wall.size = ( + Vector2(300.0, 206.0) if compact else Vector2(866.0, 476.0) + ) + _detail_constellation.position = ( + Vector2(320.0, 154.0) if compact else Vector2(942.0, 126.0) + ) + _detail_constellation.size = ( + Vector2(306.0, 196.0) if compact else Vector2(288.0, 476.0) + ) + _notepad_binding.position = Vector2(44.0, 1.0) if compact else Vector2(28.0, 4.0) + _notepad_binding.size = Vector2(218.0, 20.0) if compact else Vector2(232.0, 27.0) + _notepad_binding.add_theme_font_size_override("font_size", 13 if compact else 20) + _notepad_title.position = Vector2(10.0, 16.0) if compact else Vector2(20.0, 31.0) + _notepad_title.size = Vector2(286.0, 18.0) if compact else Vector2(248.0, 28.0) + _notepad_title.add_theme_font_size_override("font_size", 12 if compact else 19) + _notepad_rule.position = Vector2(10.0, 46.0) if compact else Vector2(18.0, 87.0) + _notepad_rule.size = Vector2(286.0, 2.0) if compact else Vector2(252.0, 2.0) + _cooler_sort_controls.position = ( + Vector2(10.0, 48.0) if compact else Vector2(18.0, 98.0) + ) + _cooler_sort_controls.size = ( + Vector2(286.0, 31.0) if compact else Vector2(252.0, 38.0) + ) + _cooler_sort_controls.get_child(0).visible = false + _cooler_sort_option.custom_minimum_size = ( + Vector2(140.0, 31.0) if compact else Vector2(123.0, 38.0) + ) + _cooler_sort_direction.custom_minimum_size = ( + Vector2(140.0, 31.0) if compact else Vector2(123.0, 38.0) + ) + for sort_control: Control in [ + _cooler_sort_option, + _cooler_sort_direction, + ]: + sort_control.add_theme_font_size_override( + "font_size", + 9 if compact else 10, + ) + _notepad_wallet.position = Vector2(10.0, 31.0) if compact else Vector2(18.0, 61.0) + _notepad_wallet.size = Vector2(138.0, 17.0) if compact else Vector2(122.0, 23.0) + _notepad_capacity.position = Vector2(154.0, 31.0) if compact else Vector2(146.0, 61.0) + _notepad_capacity.size = Vector2(142.0, 17.0) if compact else Vector2(124.0, 23.0) + for status_label: Label in [_notepad_wallet, _notepad_capacity]: + status_label.add_theme_font_size_override("font_size", 10 if compact else 14) + _cooler_detail_texture.position = ( + Vector2(10.0, 84.0) if compact else Vector2(88.0, 143.0) + ) + _cooler_detail_texture.size = ( + Vector2(66.0, 52.0) if compact else Vector2(112.0, 92.0) + ) + _cooler_detail_name.position = ( + Vector2(82.0, 82.0) if compact else Vector2(18.0, 239.0) + ) + _cooler_detail_name.size = ( + Vector2(214.0, 24.0) if compact else Vector2(252.0, 30.0) + ) + _cooler_detail_name.add_theme_font_size_override( + "font_size", 14 if compact else 21, + ) + _cooler_detail_data.position = ( + Vector2(82.0, 105.0) if compact else Vector2(18.0, 269.0) + ) + _cooler_detail_data.size = ( + Vector2(214.0, 43.0) if compact else Vector2(252.0, 75.0) + ) + _cooler_detail_data.add_theme_font_size_override( + "font_size", 9 if compact else 16, + ) + _cooler_selection_summary.position = ( + Vector2(10.0, 151.0) if compact else Vector2(18.0, 346.0) + ) + _cooler_selection_summary.size = ( + Vector2(130.0, 35.0) if compact else Vector2(252.0, 36.0) + ) + _cooler_selection_summary.add_theme_font_size_override( + "font_size", 9 if compact else 13, + ) + _favorite_bubble.custom_minimum_size = ( + Vector2(72.0, 42.0) if compact else Vector2(108.0, 50.0) + ) + _sell_bubble.custom_minimum_size = ( + Vector2(74.0, 42.0) if compact else Vector2(118.0, 50.0) + ) + _favorite_bubble.position = ( + Vector2(144.0, 148.0) if compact else Vector2(26.0, 400.0) + ) + _favorite_bubble.size = ( + Vector2(72.0, 42.0) if compact else Vector2(108.0, 50.0) + ) + _sell_bubble.position = ( + Vector2(222.0, 148.0) if compact else Vector2(144.0, 400.0) + ) + _sell_bubble.size = ( + Vector2(74.0, 42.0) if compact else Vector2(118.0, 50.0) + ) + _favorite_bubble.add_theme_font_size_override( + "font_size", 10 if compact else 15, + ) + _sell_bubble.add_theme_font_size_override( + "font_size", 10 if compact else 15, + ) + _update_sort_direction_text() + _bag_page.size = reference_size + _bag_page.position = Vector2.ZERO + _bag_rest_position = Vector2.ZERO + _bag_outer_wall.position = ( + Vector2(14.0, 170.0) if compact else Vector2(72.0, 132.0) + ) + _bag_outer_wall.size = ( + Vector2(612.0, 200.0) if compact else Vector2(896.0, 442.0) + ) + _bag_host.custom_minimum_size = ( + Vector2(520.0, 140.0) if compact else Vector2(820.0, 350.0) + ) + _bag_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED + _bag_instruction_bubble.position = ( + Vector2(218.0, 145.0) if compact else Vector2(992.0, 140.0) + ) + _bag_instruction_bubble.size = ( + Vector2(204.0, 48.0) if compact else Vector2(240.0, 98.0) + ) + _bag_detail_constellation.position = ( + Vector2.ZERO if compact else Vector2(984.0, 266.0) + ) + _bag_detail_constellation.size = ( + Vector2(640.0, 390.0) if compact else Vector2(272.0, 304.0) + ) + _bag_sprite_detail_bubble.position = ( + Vector2(170.0, 164.0) if compact else Vector2.ZERO + ) + _bag_sprite_detail_bubble.size = ( + Vector2(300.0, 188.0) if compact else Vector2(272.0, 304.0) + ) + _bag_sprite_detail_texture.custom_minimum_size = ( + Vector2(72.0, 48.0) if compact else Vector2(100.0, 72.0) + ) + _bag_sprite_detail_name.add_theme_font_size_override( + "font_size", + 18 if compact else 22, + ) + _bag_sprite_detail_data.add_theme_font_size_override( + "font_size", + 12 if compact else 15, + ) + _logbook_page.size = reference_size + _logbook_page.position = Vector2.ZERO + _logbook_rest_position = Vector2.ZERO + _book_backing.position = ( + Vector2(14.0, 164.0) if compact else Vector2(58.0, 128.0) + ) + _book_backing.size = ( + Vector2(612.0, 210.0) if compact else Vector2(1164.0, 460.0) + ) + _right_page.visible = not compact + _book_gutter.visible = not compact + _left_entry_field.vertical = not compact + _right_entry_field.vertical = true + _left_heading.text = "field notes" if not compact else "field notes • page" + _left_heading.add_theme_font_size_override( + "font_size", + 17 if compact else 20, + ) + _right_heading.add_theme_font_size_override("font_size", 20) + _logbook_empty_state.position = ( + Vector2(120.0, 240.0) if compact else Vector2(402.0, 314.0) + ) + _logbook_empty_state.size = ( + Vector2(400.0, 52.0) if compact else Vector2(476.0, 52.0) + ) + _logbook_previous.apply_layout( + Vector2(58.0, 310.0) if compact else Vector2(116.0, 530.0), + Vector2(66.0, 62.0) if compact else Vector2(76.0, 72.0), + 0.18, + ) + _logbook_next.apply_layout( + Vector2(582.0, 310.0) if compact else Vector2(1164.0, 530.0), + Vector2(66.0, 62.0) if compact else Vector2(76.0, 72.0), + 0.18, + ) + _logbook_page_status.position = ( + Vector2(255.0, 286.0) if compact else Vector2(555.0, 524.0) + ) + _logbook_page_status.size = ( + Vector2(130.0, 46.0) if compact else Vector2(170.0, 56.0) + ) + _refresh_logbook_page(false) + _sale_confirmation.position = ( + Vector2(70.0, 128.0) if compact else Vector2(320.0, 200.0) + ) + _sale_confirmation.size = ( + Vector2(500.0, 250.0) if compact else Vector2(640.0, 320.0) + ) + _cooler_host.custom_minimum_size = Vector2( + 520.0 if compact else 810.0, + 500.0 if compact else 412.0, + ) _bag_grid.columns = 2 if compact else 3 _logbook_grid.columns = 3 if compact else 4 - _inventory_list.custom_minimum_size.x = 292.0 if compact else 350.0 - _inventory_list.size_flags_horizontal = Control.SIZE_EXPAND_FILL - _detail_panel.custom_minimum_size.x = 176.0 if compact else 210.0 _bag_list.custom_minimum_size.x = 300.0 if compact else 360.0 _bag_detail.custom_minimum_size.x = 176.0 if compact else 220.0 _content_stage.custom_minimum_size.y = 220.0 if compact else 260.0 - call_deferred("_sync_cooler_width") - _inventory_body.vertical = compact - _inventory_scroll.vertical_scroll_mode = ( - ScrollContainer.SCROLL_MODE_DISABLED - if compact - else ScrollContainer.SCROLL_MODE_AUTO - ) - _inventory_list.custom_minimum_size.y = 240.0 if compact else 0.0 - _detail_panel.custom_minimum_size = ( - Vector2(0.0, 310.0) - if compact - else Vector2(430.0, 0.0) - ) - _status_shoal.add_theme_constant_override( - "separation", - 4 if compact else 8, - ) - _inventory_body.queue_sort() _content_rest_position = _content_stage.position if not _transitioning: _content_shell.position = _presentation_rest_position + _cooler_page.position = _cooler_rest_position + _bag_page.position = _bag_rest_position + _logbook_page.position = _logbook_rest_position + _cooler_page.modulate.a = 1.0 + _bag_page.modulate.a = 1.0 + _logbook_page.modulate.a = 1.0 if not _page_transitioning: _content_stage.position = _content_rest_position - - -func _sync_cooler_width() -> void: - if not is_node_ready(): - return - _cooler_host.custom_minimum_size.x = minf( - _content_stage.size.x, - 1380.0, - ) - _cooler_host.size_flags_horizontal = Control.SIZE_SHRINK_CENTER + _layout_cooler_fish(false) + _layout_bag_items() func _begin_menu_entry() -> void: @@ -569,8 +1116,13 @@ func _begin_menu_entry() -> void: _set_shell_interactive(false) set_process(true) var generation: int = _transition_generation - var start_offset: float = size.y + TRANSITION_SAFE_MARGIN + var start_offset: float = ( + _presentation_scale_root.size.y + TRANSITION_SAFE_MARGIN + ) _content_shell.position = _presentation_rest_position + Vector2.DOWN * start_offset + _cooler_page.position = _cooler_rest_position + Vector2.DOWN * start_offset + _bag_page.position = _bag_rest_position + Vector2.DOWN * start_offset + _logbook_page.position = _logbook_rest_position + Vector2.DOWN * start_offset var navigation_rest: Vector2 = _navigation_cluster.position _navigation_cluster.position = navigation_rest + Vector2.DOWN * start_offset _presentation_tween = create_tween().set_parallel(true) @@ -580,6 +1132,24 @@ func _begin_menu_entry() -> void: _presentation_rest_position, MENU_ENTER_DURATION ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _presentation_tween.tween_property( + _cooler_page, + "position", + _cooler_rest_position, + MENU_ENTER_DURATION + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _presentation_tween.tween_property( + _bag_page, + "position", + _bag_rest_position, + MENU_ENTER_DURATION + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _presentation_tween.tween_property( + _logbook_page, + "position", + _logbook_rest_position, + MENU_ENTER_DURATION + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) _presentation_tween.tween_property( _navigation_cluster, "position", @@ -622,6 +1192,24 @@ func _begin_menu_exit(reason: CloseReason, restore_controls: bool) -> void: end_y, MENU_EXIT_DURATION ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _presentation_tween.tween_property( + _cooler_page, + "position:y", + -_cooler_page.size.y - TRANSITION_SAFE_MARGIN, + MENU_EXIT_DURATION + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _presentation_tween.tween_property( + _bag_page, + "position:y", + -_bag_page.size.y - TRANSITION_SAFE_MARGIN, + MENU_EXIT_DURATION + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _presentation_tween.tween_property( + _logbook_page, + "position:y", + -_logbook_page.size.y - TRANSITION_SAFE_MARGIN, + MENU_EXIT_DURATION + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) _presentation_tween.tween_property( _navigation_cluster, "position:y", @@ -657,8 +1245,11 @@ func _finish_close( ) -> void: _cancel_presentation_tween() _cancel_page_tween() + _cancel_logbook_page_transition(true) _transitioning = false _page_transitioning = false + _bag_drag_active = false + _reset_page_transition_visuals() visible = false set_process(false) get_viewport().gui_release_focus() @@ -674,39 +1265,68 @@ func _finish_close( menu_visibility_changed.emit(false) +func _get_section_root(section: Section) -> Control: + match section: + Section.COOLER: + return _cooler_page + Section.BAG: + return _bag_page + _: + return _logbook_page + + +func _get_section_rest_position(section: Section) -> Vector2: + match section: + Section.COOLER: + return _cooler_rest_position + Section.BAG: + return _bag_rest_position + _: + return _logbook_rest_position + + func _begin_page_transition(section: Section) -> void: + _cancel_logbook_page_transition(true) _page_transition_generation += 1 _cancel_page_tween() _page_transitioning = true _set_content_interactive(false) _set_navigation_target(section) var generation: int = _page_transition_generation + _page_outgoing_root = _get_section_root(_current_section) + _page_incoming_root = _get_section_root(section) + _page_hosts_shared = _page_outgoing_root == _page_incoming_root + var outgoing_rest: Vector2 = _get_section_rest_position(_current_section) + var incoming_rest: Vector2 = _get_section_rest_position(section) + if not _page_hosts_shared: + _page_incoming_root.position = incoming_rest + Vector2.DOWN * 18.0 + _page_incoming_root.modulate.a = 0.0 _page_tween = create_tween() _page_tween.tween_property( - _content_stage, + _page_outgoing_root, "modulate:a", 0.0, PAGE_OUT_DURATION ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) _page_tween.parallel().tween_property( - _content_stage, + _page_outgoing_root, "position:y", - _content_rest_position.y - 18.0, + outgoing_rest.y - 18.0, PAGE_OUT_DURATION ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) _page_tween.tween_callback( _swap_page.bind(section, generation) ) _page_tween.tween_property( - _content_stage, + _page_incoming_root, "modulate:a", 1.0, PAGE_IN_DURATION ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) _page_tween.parallel().tween_property( - _content_stage, + _page_incoming_root, "position", - _content_rest_position, + incoming_rest, PAGE_IN_DURATION ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) _page_tween.finished.connect( @@ -719,7 +1339,11 @@ func _swap_page(section: Section, generation: int) -> void: if generation != _page_transition_generation or not visible: return _show_section_immediate(section) - _content_stage.position = _content_rest_position + Vector2.DOWN * 18.0 + if _page_hosts_shared: + _page_incoming_root.position = ( + _presentation_rest_position + Vector2.DOWN * 18.0 + ) + _page_incoming_root.modulate.a = 0.0 func _finish_page_transition(generation: int) -> void: @@ -727,8 +1351,7 @@ func _finish_page_transition(generation: int) -> void: return _page_tween = null _page_transitioning = false - _content_stage.position = _content_rest_position - _content_stage.modulate.a = 1.0 + _reset_page_transition_visuals() _set_content_interactive(true) _focus_current_section() @@ -755,6 +1378,75 @@ func _set_content_interactive(interactive: bool) -> void: if interactive else Control.MOUSE_FILTER_IGNORE ) + _cooler_page.mouse_filter = ( + Control.MOUSE_FILTER_PASS + if interactive and _current_section == Section.COOLER + else Control.MOUSE_FILTER_IGNORE + ) + _bag_page.mouse_filter = ( + Control.MOUSE_FILTER_PASS + if interactive and _current_section == Section.BAG + else Control.MOUSE_FILTER_IGNORE + ) + _logbook_page.mouse_filter = ( + Control.MOUSE_FILTER_PASS + if interactive and _current_section == Section.LOGBOOK + else Control.MOUSE_FILTER_IGNORE + ) + var cooler_interactive: bool = ( + interactive and _current_section == Section.COOLER + ) + _cooler_sort_option.disabled = not cooler_interactive + _cooler_sort_direction.disabled = not cooler_interactive + _cooler_sort_option.refresh_ink_state() + _cooler_sort_direction.refresh_ink_state() + for fish_node: CoolerFishSpriteType in _fish_nodes.values(): + fish_node.focus_mode = ( + Control.FOCUS_ALL + if cooler_interactive + else Control.FOCUS_NONE + ) + fish_node.mouse_filter = ( + Control.MOUSE_FILTER_STOP + if cooler_interactive + else Control.MOUSE_FILTER_IGNORE + ) + var detail_interactive: bool = ( + cooler_interactive and _detail_constellation.visible + ) + for action: NotepadInkActionType in [_favorite_bubble, _sell_bubble]: + var action_interactive: bool = detail_interactive and not action.disabled + action.focus_mode = ( + Control.FOCUS_ALL + if action_interactive + else Control.FOCUS_NONE + ) + action.mouse_filter = ( + Control.MOUSE_FILTER_STOP + if action_interactive + else Control.MOUSE_FILTER_IGNORE + ) + action.refresh_ink_state() + var bag_interactive: bool = ( + interactive + and _current_section == Section.BAG + and not _bag_drag_active + ) + for item_node: BagItemSpriteType in _bag_item_nodes.values(): + item_node.focus_mode = ( + Control.FOCUS_ALL if bag_interactive else Control.FOCUS_NONE + ) + item_node.mouse_filter = ( + Control.MOUSE_FILTER_STOP + if bag_interactive + else Control.MOUSE_FILTER_IGNORE + ) + var logbook_interactive: bool = ( + interactive + and _current_section == Section.LOGBOOK + and not _logbook_page_transitioning + ) + _update_logbook_page_control_state(logbook_interactive) func _cancel_presentation_tween() -> void: @@ -767,10 +1459,22 @@ func _cancel_page_tween() -> void: if _page_tween != null: _page_tween.kill() _page_tween = null + _reset_page_transition_visuals() -func _on_sort_selected(index: int) -> void: - _sort_mode = _sort_option.get_item_id(index) +func _reset_page_transition_visuals() -> void: + for section: Section in [Section.COOLER, Section.BAG, Section.LOGBOOK]: + var page: Control = _get_section_root(section) + page.position = _get_section_rest_position(section) + page.modulate.a = 1.0 + _page_outgoing_root = null + _page_incoming_root = null + + +func _on_sort_selected(index: int, source: OptionButton) -> void: + _sort_mode = source.get_item_id(index) + _sort_option.select(_sort_mode) + _cooler_sort_option.select(_sort_mode) _refresh_inventory() @@ -781,13 +1485,26 @@ func _on_sort_direction_pressed() -> void: func _update_sort_direction_text() -> void: + var direction_text: String match _sort_mode: SortMode.CATCH_ORDER: - _sort_direction.text = "newest first" if _sort_descending else "oldest first" + if _compact_layout: + direction_text = "newest" if _sort_descending else "oldest" + else: + direction_text = ( + "newest first" if _sort_descending else "oldest first" + ) SortMode.NAME: - _sort_direction.text = "z–a" if _sort_descending else "a–z" + direction_text = "z–a" if _sort_descending else "a–z" SortMode.RARITY: - _sort_direction.text = "high to low" if _sort_descending else "low to high" + if _compact_layout: + direction_text = "high–low" if _sort_descending else "low–high" + else: + direction_text = ( + "high to low" if _sort_descending else "low to high" + ) + _sort_direction.text = direction_text + _cooler_sort_direction.text = direction_text func _refresh_all() -> void: @@ -804,39 +1521,158 @@ func _on_bag_changed() -> void: func _refresh_bag() -> void: if not is_node_ready(): return - _clear_container(_bag_grid) var owned_items: Array[OwnedItemType] = ( _bag.get_all_items() if _bag != null else [] ) owned_items.sort_custom(_sort_bag_items) + _sorted_bag_items = owned_items _bag_empty.visible = owned_items.is_empty() + _bag_empty_state.visible = owned_items.is_empty() if ( not _selected_bag_item_id.is_empty() and (_bag == null or not _bag.owns_item(_selected_bag_item_id)) ): _selected_bag_item_id = StringName() + _sync_bag_item_nodes(owned_items) + _update_bag_detail() + + +func _sync_bag_item_nodes(owned_items: Array[OwnedItemType]) -> void: + var retained: Dictionary[StringName, bool] = {} for owned: OwnedItemType in owned_items: var item: ItemDataType = _item_catalog.get_item_by_id(owned.item_id) if item == null: continue - var card := ItemDragSourceType.new() - card.custom_minimum_size = Vector2(140, 88) - card.expand_icon = true - card.icon = item.icon - card.text = "%s%s\n%s" % [ + retained[owned.item_id] = true + var item_node := _bag_item_nodes.get( + owned.item_id + ) as BagItemSpriteType + if item_node == null: + item_node = BagItemSpriteScene.instantiate() + _bag_item_field.add_child(item_node) + _bag_item_nodes[owned.item_id] = item_node + item_node.pressed.connect( + _select_bag_item.bind(owned.item_id) + ) + item_node.focus_entered.connect( + _select_bag_item.bind(owned.item_id) + ) + item_node.drag_started.connect(_on_bag_drag_started) + item_node.drag_finished.connect(_on_bag_drag_finished) + var identity_hash: int = absi(String(owned.item_id).hash()) + item_node.configure_item( + item.item_id, item.display_name, - " ×%d" % owned.quantity if owned.quantity > 1 else "", - item.get_category_name(), - ] - card.tooltip_text = ( + item.icon, + owned.quantity, + item.hotbar_allowed, + float(identity_hash % 628) / 100.0, + 0.97 + float(identity_hash % 7) * 0.01, + ) + item_node.tooltip_text = ( "drag to a hotbar slot." if item.hotbar_allowed else "this item cannot be assigned to the hotbar." ) - card.setup(item.item_id, item.display_name, item.icon) - card.pressed.connect(_select_bag_item.bind(item.item_id)) - _bag_grid.add_child(card) - _update_bag_detail() + item_node.disabled = false + item_node.set_selected(item.item_id == _selected_bag_item_id) + for item_id: StringName in _bag_item_nodes.keys(): + if retained.has(item_id): + continue + var removed := _bag_item_nodes[item_id] as BagItemSpriteType + _bag_item_nodes.erase(item_id) + _release_focus_from(removed, _bag_tab) + removed.queue_free() + _layout_bag_items() + _configure_bag_item_focus() + + +func _layout_bag_items() -> void: + if not is_node_ready() or _sorted_bag_items.is_empty(): + return + _bag_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED + var columns: int = 3 + var cell_size := ( + Vector2(166.0, 72.0) + if _compact_layout + else Vector2(246.0, 154.0) + ) + var item_size := ( + Vector2(86.0, 62.0) + if _compact_layout + else Vector2(138.0, 102.0) + ) + var origin := ( + Vector2(16.0, 4.0) + if _compact_layout + else Vector2(54.0, 44.0) + ) + _bag_item_field.custom_minimum_size = ( + Vector2(520.0, 140.0) + if _compact_layout + else Vector2(820.0, 350.0) + ) + for index: int in _sorted_bag_items.size(): + var owned: OwnedItemType = _sorted_bag_items[index] + var item_node := _bag_item_nodes.get( + owned.item_id + ) as BagItemSpriteType + if item_node == null: + continue + var identity_hash: int = absi(String(owned.item_id).hash()) + var column: int = index % columns + var row: int = floori(float(index) / float(columns)) + var stable_offset := Vector2( + float(identity_hash % 13) - 6.0, + float((identity_hash / 19) % 11) - 5.0, + ) + var lane_offset: float = 18.0 if row % 2 == 1 else 0.0 + item_node.custom_minimum_size = item_size + item_node.size = item_size + item_node.position = ( + origin + + Vector2( + float(column) * cell_size.x + lane_offset, + float(row) * cell_size.y, + ) + + stable_offset + ) + + +func _configure_bag_item_focus() -> void: + if _current_section != Section.BAG: + return + var controls: Array[BagItemSpriteType] = [] + for owned: OwnedItemType in _sorted_bag_items: + var item_node := _bag_item_nodes.get( + owned.item_id + ) as BagItemSpriteType + if item_node != null: + controls.append(item_node) + if controls.is_empty(): + _bag_tab.focus_neighbor_bottom = NodePath() + return + _bag_tab.focus_neighbor_bottom = _bag_tab.get_path_to(controls.front()) + for index: int in controls.size(): + var control: BagItemSpriteType = controls[index] + var column: int = index % 3 + var row: int = floori(float(index) / 3.0) + var left_index: int = row * 3 + maxi(column - 1, 0) + var right_index: int = mini(index + 1, controls.size() - 1) + control.focus_neighbor_left = control.get_path_to( + controls[left_index] + ) + control.focus_neighbor_right = control.get_path_to( + controls[right_index] + ) + control.focus_neighbor_top = ( + control.get_path_to(_bag_tab) + if index < 3 + else control.get_path_to(controls[index - 3]) + ) + control.focus_neighbor_bottom = control.get_path_to( + controls[mini(index + 3, controls.size() - 1)] + ) func _sort_bag_items(a: OwnedItemType, b: OwnedItemType) -> bool: @@ -852,7 +1688,12 @@ func _sort_bag_items(a: OwnedItemType, b: OwnedItemType) -> bool: func _select_bag_item(item_id: StringName) -> void: + if _bag_drag_active or get_viewport().gui_is_dragging(): + return _selected_bag_item_id = item_id + for candidate_id: StringName in _bag_item_nodes: + var item_node := _bag_item_nodes[candidate_id] as BagItemSpriteType + item_node.set_selected(candidate_id == item_id) _update_bag_detail() @@ -884,6 +1725,61 @@ func _update_bag_detail() -> void: if item != null else "select a bag item for details." ) + _bag_sprite_detail_texture.texture = item.icon if item != null else null + _bag_sprite_detail_name.text = item.display_name if item != null else "" + _bag_sprite_detail_data.text = ( + "%s • quantity: %d\n%s\n%s" + % [ + item.get_category_name(), + quantity, + item.description, + ( + "drag to any hotbar slot." + if item.hotbar_allowed + else "not compatible with the hotbar." + ), + ] + if item != null + else "" + ) + _bag_detail_constellation.visible = ( + item != null and _current_section == Section.BAG + ) + _bag_instruction_bubble.visible = ( + item == null and _current_section == Section.BAG + ) + + +func _close_bag_detail() -> void: + _bag_detail_constellation.visible = false + _bag_instruction_bubble.visible = _current_section == Section.BAG + + +func _on_bag_field_gui_input(event: InputEvent) -> void: + if ( + event is InputEventMouseButton + and event.button_index == MOUSE_BUTTON_LEFT + and event.pressed + and not get_viewport().gui_is_dragging() + ): + _selected_bag_item_id = StringName() + for item_node: BagItemSpriteType in _bag_item_nodes.values(): + item_node.set_selected(false) + _update_bag_detail() + + +func _on_bag_drag_started() -> void: + _bag_drag_active = true + _close_bag_detail() + _set_content_interactive(false) + + +func _on_bag_drag_finished() -> void: + _bag_drag_active = false + if visible and _current_section == Section.BAG: + _set_content_interactive( + not _transitioning and not _page_transitioning + ) func _on_inventory_changed() -> void: @@ -915,10 +1811,15 @@ func _refresh_economy_summary() -> void: ) _wallet_balance.text = "wallet: $%d" % balance _wallet_status.set_content("wallet", "$%d" % balance) + _notepad_wallet.text = "wallet $%d" % balance _capacity_status.set_content("cooler", "%d / %d" % [ _inventory.get_all_catches().size() if _inventory != null else 0, _cooler_capacity.get_capacity() if _cooler_capacity != null else 0, ]) + _notepad_capacity.text = "cooler %d / %d" % [ + _inventory.get_all_catches().size() if _inventory != null else 0, + _cooler_capacity.get_capacity() if _cooler_capacity != null else 0, + ] _held_value_status.set_content("held value", "$%d" % held_total) _held_value.text = "held fish base value: $%d" % held_total _cooler_count.text = "%d / %d" % [ @@ -934,48 +1835,207 @@ func _on_cooler_capacity_changed(_level: int, _capacity: int) -> void: func _refresh_inventory() -> void: if not is_node_ready(): return - _clear_container(_inventory_grid) var catches: Array[FishCatchType] = [] if _inventory != null: for fish_catch: FishCatchType in _inventory.get_all_catches(): if fish_catch != null and fish_catch.is_valid(): catches.append(fish_catch) catches.sort_custom(_compare_catches) + _sorted_catches = catches _inventory_empty.visible = catches.is_empty() + _cooler_empty.visible = catches.is_empty() var visible_ids: Array[StringName] = [] for fish_catch: FishCatchType in catches: visible_ids.append(fish_catch.catch_id) _fish_selection.set_visible_order(visible_ids) - var selected: FishCatchType - if _inventory != null: - selected = _inventory.get_catch(_fish_selection.get_focused_id()) - for fish_catch: FishCatchType in catches: - _inventory_grid.add_child(_create_inventory_card(fish_catch)) - _configure_inventory_card_focus() + _sync_cooler_fish_nodes(catches) + var selected: FishCatchType = ( + _inventory.get_catch(_fish_selection.get_focused_id()) + if _inventory != null + else null + ) _update_inventory_detail(selected) _update_sale_summary() _update_sort_direction_text() -func _configure_inventory_card_focus() -> void: - var cards: Array[Control] = [] - for child: Node in _inventory_grid.get_children(): - if child is Control: - cards.append(child as Control) - var columns: int = maxi(_inventory_grid.columns, 1) - for index: int in cards.size(): - var card: Control = cards[index] - var row: int = floori(float(index) / float(columns)) +func _sync_cooler_fish_nodes(catches: Array[FishCatchType]) -> void: + var retained: Dictionary[StringName, bool] = {} + for fish_catch: FishCatchType in catches: + retained[fish_catch.catch_id] = true + var fish_node := _fish_nodes.get( + fish_catch.catch_id + ) as CoolerFishSpriteType + var is_new: bool = fish_node == null + if is_new: + fish_node = CoolerFishSpriteScene.instantiate() + _fish_field.add_child(fish_node) + _fish_nodes[fish_catch.catch_id] = fish_node + fish_node.set_meta("new_cooler_fish", true) + fish_node.pressed.connect( + _on_catch_card_pressed.bind(fish_catch.catch_id) + ) + var identity_hash: int = absi(String(fish_catch.catch_id).hash()) + fish_node.configure( + fish_catch.catch_id, + fish_catch.fish.display_texture, + float(identity_hash % 628) / 100.0, + 0.96 + float(identity_hash % 9) * 0.01, + _get_cooler_rarity_color(fish_catch.fish.rarity), + ) + fish_node.set_item_state( + _fish_selection.is_selected(fish_catch.catch_id), + fish_catch.catch_id == _fish_selection.get_focused_id(), + fish_catch.is_favorited, + ) + for catch_id: StringName in _fish_nodes.keys(): + if retained.has(catch_id): + continue + var removed := _fish_nodes[catch_id] as CoolerFishSpriteType + _fish_nodes.erase(catch_id) + _release_focus_from(removed, _inventory_tab) + removed.queue_free() + _layout_cooler_fish(true) + _configure_cooler_fish_focus() + + +func _get_cooler_rarity_color(rarity: int) -> Color: + match rarity: + FishDataType.Rarity.UNCOMMON: + return COOLER_RARITY_UNCOMMON + FishDataType.Rarity.RARE: + return COOLER_RARITY_RARE + FishDataType.Rarity.EPIC: + return COOLER_RARITY_EPIC + FishDataType.Rarity.LEGENDARY: + return COOLER_RARITY_LEGENDARY + _: + return COOLER_RARITY_COMMON + + +func _layout_cooler_fish(animate: bool = true) -> void: + if not is_node_ready(): + return + var columns: int = 3 if _compact_layout else 9 + var cell_size := ( + Vector2(68.0, 58.0) if _compact_layout else Vector2(84.0, 80.0) + ) + var fish_size := ( + Vector2(52.0, 52.0) if _compact_layout else Vector2(72.0, 72.0) + ) + var visible_field_size := ( + Vector2(218.0, 124.0) + if _compact_layout + else Vector2(784.0, 394.0) + ) + var side_margin: float = 2.0 if _compact_layout else 8.0 + var top_margin: float = 4.0 if _compact_layout else 6.0 + var required_rows: int = ceili( + float(_sorted_catches.size()) / float(columns) + ) if not _sorted_catches.is_empty() else 0 + var required_height: float = ( + top_margin * 2.0 + float(required_rows) * cell_size.y + ) + var content_size := Vector2( + visible_field_size.x, + maxf(visible_field_size.y, required_height), + ) + _cooler_host.custom_minimum_size = content_size + _fish_field.custom_minimum_size = content_size + _cooler_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_AUTO + for index: int in _sorted_catches.size(): + var fish_catch: FishCatchType = _sorted_catches[index] + var fish_node := _fish_nodes.get( + fish_catch.catch_id + ) as CoolerFishSpriteType + if fish_node == null: + continue + var identity_hash: int = absi(String(fish_catch.catch_id).hash()) var column: int = index % columns - var left_index: int = row * columns + maxi(column - 1, 0) - var right_index: int = mini(index + 1, cards.size() - 1) - var top_index: int = maxi(index - columns, 0) - var bottom_index: int = mini(index + columns, cards.size() - 1) - card.focus_neighbor_left = card.get_path_to(cards[left_index]) - card.focus_neighbor_right = card.get_path_to(cards[right_index]) - card.focus_neighbor_top = card.get_path_to(cards[top_index]) - card.focus_neighbor_bottom = card.get_path_to(cards[bottom_index]) + var row: int = floori(float(index) / float(columns)) + var offset_span: int = 5 if _compact_layout else 7 + var offset_center: float = 2.0 if _compact_layout else 3.0 + var stable_offset := Vector2( + float(identity_hash % offset_span) - offset_center, + float((identity_hash / 17) % offset_span) - offset_center, + ) + var lane_offset: float = 5.0 if row % 2 == 1 else 0.0 + var target := Vector2( + side_margin + float(column) * cell_size.x + lane_offset, + top_margin + float(row) * cell_size.y, + ) + stable_offset + fish_node.custom_minimum_size = fish_size + fish_node.size = fish_size + var immediate: bool = ( + not animate or fish_node.has_meta("new_cooler_fish") + ) + fish_node.set_target_position(target, immediate) + if fish_node.has_meta("new_cooler_fish"): + fish_node.remove_meta("new_cooler_fish") + + +func _configure_cooler_fish_focus() -> void: + if _current_section != Section.COOLER: + return + var controls: Array[CoolerFishSpriteType] = [] + for fish_catch: FishCatchType in _sorted_catches: + var fish_node := _fish_nodes.get( + fish_catch.catch_id + ) as CoolerFishSpriteType + if fish_node != null: + controls.append(fish_node) + var columns: int = 3 if _compact_layout else 9 + if controls.is_empty(): + _inventory_tab.focus_neighbor_bottom = NodePath() + return + _inventory_tab.focus_neighbor_bottom = _inventory_tab.get_path_to( + controls.front() + ) + for index: int in controls.size(): + var control: CoolerFishSpriteType = controls[index] + control.focus_neighbor_left = control.get_path_to( + controls[maxi(index - 1, 0)] + ) + control.focus_neighbor_right = control.get_path_to( + controls[mini(index + 1, controls.size() - 1)] + ) + control.focus_neighbor_top = ( + control.get_path_to(_inventory_tab) + if index < columns + else control.get_path_to(controls[index - columns]) + ) + control.focus_neighbor_bottom = ( + control.get_path_to(_favorite_bubble) + if ( + not _favorite_bubble.disabled + and index + columns >= controls.size() + ) + else control.get_path_to( + controls[mini(index + columns, controls.size() - 1)] + ) + ) + var focused_node := _fish_nodes.get( + _fish_selection.get_focused_id() + ) as CoolerFishSpriteType + if focused_node == null: + focused_node = controls.front() + _favorite_bubble.focus_neighbor_left = ( + _favorite_bubble.get_path_to(focused_node) + ) + _favorite_bubble.focus_neighbor_right = ( + _favorite_bubble.get_path_to(_sell_bubble) + ) + _favorite_bubble.focus_neighbor_top = ( + _favorite_bubble.get_path_to(focused_node) + ) + _sell_bubble.focus_neighbor_left = ( + _sell_bubble.get_path_to(_favorite_bubble) + ) + _sell_bubble.focus_neighbor_right = ( + _sell_bubble.get_path_to(_close_button) + ) + _sell_bubble.focus_neighbor_top = _sell_bubble.get_path_to(focused_node) func _compare_catches(left: FishCatchType, right: FishCatchType) -> bool: @@ -994,95 +2054,6 @@ func _compare_catches(left: FishCatchType, right: FishCatchType) -> bool: return comparison > 0 if _sort_descending else comparison < 0 -func _create_inventory_card(fish_catch: FishCatchType) -> Button: - var card := BubbleInventoryCellScene.instantiate() as BubbleInventoryCellType - card.set_compact(_compact_layout) - var is_selected: bool = _fish_selection.is_selected(fish_catch.catch_id) - var is_focused: bool = ( - fish_catch.catch_id == _fish_selection.get_focused_id() - ) - card.configure( - fish_catch.fish.display_texture, - fish_catch.fish.display_name, - "%.2f lb" % fish_catch.weight_lb, - ) - card.set_item_state( - is_selected, - is_focused, - fish_catch.is_favorited, - ) - card.pressed.connect(_on_catch_card_pressed.bind(fish_catch.catch_id)) - return card - - -func _apply_inventory_card_styles( - card: Button, - rarity_color: Color, - is_selected: bool, - is_focused: bool, -) -> void: - card.add_theme_stylebox_override( - "normal", - _create_inventory_card_style( - rarity_color, - 0, - is_selected, - is_focused - ) - ) - card.add_theme_stylebox_override( - "hover", - _create_inventory_card_style( - rarity_color, - 1, - is_selected, - is_focused - ) - ) - card.add_theme_stylebox_override( - "focus", - _create_inventory_card_style( - rarity_color, - 1, - is_selected, - true - ) - ) - card.add_theme_stylebox_override( - "pressed", - _create_inventory_card_style(rarity_color, 2, true, is_focused) - ) - - -func _create_inventory_card_style( - rarity_color: Color, - state_index: int, - is_selected: bool, - is_focused: bool, -) -> StyleBoxFlat: - var style := StyleBoxFlat.new() - match state_index: - 1: - style.bg_color = UIPalette.ELEVATED_PANEL.lightened(0.1) - 2: - style.bg_color = UIPalette.PRIMARY.darkened(0.48) - _: - style.bg_color = ( - UIPalette.PRIMARY.darkened(0.55) - if is_selected - else UIPalette.ELEVATED_PANEL - ) - style.border_color = rarity_color - var border_width: int = 4 if state_index == 2 or is_focused else 2 - style.set_border_width_all(border_width) - style.set_corner_radius_all(8) - style.content_margin_left = 7.0 - style.content_margin_top = 7.0 - style.content_margin_right = 7.0 - style.content_margin_bottom = 7.0 - return style - - func _on_catch_card_pressed(catch_id: StringName) -> void: if _inventory == null: return @@ -1098,18 +2069,63 @@ func _on_catch_card_pressed(catch_id: StringName) -> void: _refresh_inventory() +func _on_fish_field_gui_input(event: InputEvent) -> void: + if ( + event is InputEventMouseButton + and event.button_index == MOUSE_BUTTON_LEFT + and event.pressed + and not get_viewport().gui_is_dragging() + ): + _fish_selection.clear() + _transaction_feedback.text = "" + _refresh_inventory() + + +func _close_detail_constellation() -> void: + _detail_constellation.visible = _current_section == Section.COOLER + _cooler_detail_texture.texture = null + _cooler_detail_texture.visible = false + _cooler_detail_name.text = "select a fish" + _cooler_detail_data.text = "" + _cooler_selection_summary.text = "no fish selected" + _favorite_bubble.disabled = true + _favorite_bubble.text = "favorite" + _favorite_bubble.persistent_mark = false + _sell_bubble.disabled = true + _sell_bubble.text = "sell fish" + _sell_bubble.persistent_mark = false + _favorite_bubble.focus_mode = Control.FOCUS_NONE + _sell_bubble.focus_mode = Control.FOCUS_NONE + _favorite_bubble.mouse_filter = Control.MOUSE_FILTER_IGNORE + _sell_bubble.mouse_filter = Control.MOUSE_FILTER_IGNORE + _favorite_bubble.refresh_ink_state() + _sell_bubble.refresh_ink_state() + _configure_cooler_fish_focus() + + func _update_inventory_detail(fish_catch: FishCatchType) -> void: if fish_catch == null: - _detail_texture.texture = null - _detail_texture.visible = false - _detail_name.text = "" - _detail_data.text = "" + _cooler_detail_texture.texture = null + _cooler_detail_texture.visible = false + _cooler_detail_name.text = "select a fish" + _cooler_detail_data.text = "" _favorite_button.disabled = true _favorite_button.text = "favorite" + _favorite_bubble.disabled = true + _favorite_bubble.text = "favorite" + _favorite_bubble.persistent_mark = false + _detail_constellation.visible = _current_section == Section.COOLER + _favorite_bubble.focus_mode = Control.FOCUS_NONE + _sell_bubble.focus_mode = Control.FOCUS_NONE + _favorite_bubble.mouse_filter = Control.MOUSE_FILTER_IGNORE + _sell_bubble.mouse_filter = Control.MOUSE_FILTER_IGNORE + _favorite_bubble.refresh_ink_state() + _sell_bubble.refresh_ink_state() + _configure_cooler_fish_focus() return - _detail_texture.texture = fish_catch.fish.display_texture - _detail_texture.visible = fish_catch.fish.display_texture != null - _detail_name.text = fish_catch.fish.display_name + _cooler_detail_texture.texture = fish_catch.fish.display_texture + _cooler_detail_texture.visible = fish_catch.fish.display_texture != null + _cooler_detail_name.text = fish_catch.fish.display_name var individual_preview: FishSaleResultType = ( _sale_service.preview_batch([fish_catch.catch_id], _default_buyer) if _sale_service != null @@ -1126,7 +2142,7 @@ func _update_inventory_detail(fish_catch: FishCatchType) -> void: _default_buyer.display_name, buyer_offer, ] - _detail_data.text = "%.2f lb\n%s\nbase value: $%d\n%s" % [ + _cooler_detail_data.text = "%.2f lb • %s\nbase value: $%d\n%s" % [ fish_catch.weight_lb, fish_catch.fish.get_rarity_name(), fish_catch.sale_value, @@ -1136,6 +2152,31 @@ func _update_inventory_detail(fish_catch: FishCatchType) -> void: _favorite_button.text = ( "unfavorite" if fish_catch.is_favorited else "favorite" ) + _favorite_bubble.disabled = false + _favorite_bubble.text = _favorite_button.text + _favorite_bubble.persistent_mark = fish_catch.is_favorited + _favorite_bubble.refresh_ink_state() + _detail_constellation.visible = _current_section == Section.COOLER + _cooler_sort_controls.visible = true + var detail_interactive: bool = ( + _detail_constellation.visible + and not _transitioning + and not _page_transitioning + ) + for action: NotepadInkActionType in [_favorite_bubble, _sell_bubble]: + var action_interactive: bool = detail_interactive and not action.disabled + action.focus_mode = ( + Control.FOCUS_ALL + if action_interactive + else Control.FOCUS_NONE + ) + action.mouse_filter = ( + Control.MOUSE_FILTER_STOP + if action_interactive + else Control.MOUSE_FILTER_IGNORE + ) + action.refresh_ink_state() + _configure_cooler_fish_focus() func _update_sale_summary() -> void: @@ -1146,12 +2187,18 @@ func _update_sale_summary() -> void: if selected_count == 1 else "sell %d fish" % selected_count ) + _sell_bubble.text = _sell_button.text if selected_count == 0: _selection_summary.text = "no fish selected" _selection_status.set_content("selected", "none") _offer_status.set_content("pelican offer", "—") _sell_button.text = "sell fish" _sell_button.disabled = true + _sell_bubble.disabled = true + _sell_bubble.text = "sell fish" + _sell_bubble.persistent_mark = false + _sell_bubble.refresh_ink_state() + _cooler_selection_summary.text = "no fish selected" _sale_unavailable.text = "" _sale_unavailable.visible = false return @@ -1166,6 +2213,7 @@ func _update_sale_summary() -> void: else "%d fish selected" % selected_count ) _selection_summary.text = count_text + _cooler_selection_summary.text = count_text _selection_status.set_content("selected", str(selected_count)) if ( preview != null @@ -1180,10 +2228,17 @@ func _update_sale_summary() -> void: _default_buyer.display_name, preview.payout, ] + _cooler_selection_summary.text += ( + "\ncombined offer: $%d" % preview.payout + ) _offer_status.set_content("pelican offer", "$%d" % preview.payout) else: + _cooler_selection_summary.text += "\noffer unavailable" _offer_status.set_content("pelican offer", "unavailable") _sell_button.disabled = preview == null or not preview.is_success() + _sell_bubble.disabled = _sell_button.disabled + _sell_bubble.persistent_mark = false + _sell_bubble.refresh_ink_state() if preview != null and preview.status == FishSaleResultType.Status.FAVORITED: _sale_unavailable.text = ( "favorited fish cannot be sold. " @@ -1257,8 +2312,12 @@ func _on_sell_pressed() -> void: ] ) _sale_confirmation.visible = true + _set_shell_interactive(false) + for button: Button in [_confirm_sale_button, _cancel_sale_button]: + button.focus_mode = Control.FOCUS_ALL + button.mouse_filter = Control.MOUSE_FILTER_STOP _confirm_sale_button.disabled = false - _confirm_sale_button.grab_focus() + _cancel_sale_button.grab_focus() func _on_confirm_sale_pressed() -> void: @@ -1294,6 +2353,7 @@ func _on_confirm_sale_pressed() -> void: func _close_sale_confirmation() -> void: + var was_visible: bool = _sale_confirmation.visible _confirmation_catch_ids.clear() _confirmation_buyer = null _confirmation_buyer_id = StringName() @@ -1301,6 +2361,17 @@ func _close_sale_confirmation() -> void: _sale_confirmation.visible = false _confirmation_message.text = "" _confirm_sale_button.disabled = false + for button: Button in [_confirm_sale_button, _cancel_sale_button]: + button.focus_mode = Control.FOCUS_NONE + button.mouse_filter = Control.MOUSE_FILTER_IGNORE + if ( + was_visible + and visible + and not _transitioning + and not _page_transitioning + ): + _set_shell_interactive(true) + _focus_current_section() func _revalidate_confirmation() -> void: @@ -1352,64 +2423,282 @@ func _get_buyer_display_group( func _refresh_logbook() -> void: if not is_node_ready(): return - _clear_container(_logbook_grid) var valid_species: Array[FishDataType] = [] if _catalog != null: for fish: FishDataType in _catalog.candidates: if fish != null and not fish.id.is_empty(): valid_species.append(fish) + _logbook_species = valid_species _logbook_empty.visible = valid_species.is_empty() _logbook_empty.text = ( "no fish catalog configured." if valid_species.is_empty() else "no species discovered yet." ) - if not valid_species.is_empty() and _collection_log != null: - var any_discovered: bool = false - for fish: FishDataType in valid_species: - if _collection_log.has_discovered(fish.id): - any_discovered = true - break - _logbook_empty.visible = not any_discovered - for fish: FishDataType in valid_species: - _logbook_grid.add_child(_create_logbook_card(fish)) + _logbook_empty_state.visible = valid_species.is_empty() + _logbook_empty_state.text = ( + "no fish catalog configured" + if valid_species.is_empty() + else "" + ) + _refresh_logbook_page(false) -func _create_logbook_card(fish: FishDataType) -> Control: +func _refresh_logbook_page(keep_transition_state: bool = true) -> void: + if not is_node_ready(): + return + var entries_per_spread: int = 2 if _compact_layout else 4 + _logbook_page_count = maxi( + 1, + ceili(float(_logbook_species.size()) / float(entries_per_spread)), + ) + _logbook_current_page = clampi( + _logbook_current_page, + 0, + _logbook_page_count - 1, + ) + _clear_logbook_entries() + var start_index: int = _logbook_current_page * entries_per_spread + var end_index: int = mini( + start_index + entries_per_spread, + _logbook_species.size(), + ) + var visible_species: Array[FishDataType] = [] + for index: int in range(start_index, end_index): + visible_species.append(_logbook_species[index]) + if _compact_layout: + for fish: FishDataType in visible_species: + _left_entry_field.add_child(_create_logbook_entry(fish)) + else: + var left_count: int = mini(2, visible_species.size()) + for index: int in visible_species.size(): + var destination: BoxContainer = ( + _left_entry_field + if index < left_count + else _right_entry_field + ) + destination.add_child(_create_logbook_entry( + visible_species[index] + )) + _logbook_page_status.set_content( + "pages", + "%d / %d" % [_logbook_current_page + 1, _logbook_page_count], + ) + _logbook_page_status.visible = _logbook_page_count > 1 + _update_logbook_page_control_state( + keep_transition_state + and visible + and _current_section == Section.LOGBOOK + and not _transitioning + and not _page_transitioning + and not _logbook_page_transitioning + ) + _configure_logbook_focus() + + +func _create_logbook_entry(fish: FishDataType) -> LogbookEntryType: var discovered: bool = ( _collection_log != null and _collection_log.has_discovered(fish.id) ) - var card := PanelContainer.new() - card.custom_minimum_size = Vector2(158.0, 154.0) - var content := VBoxContainer.new() - content.add_theme_constant_override("separation", 4) - card.add_child(content) - var texture_frame: TextureRect = _create_texture_frame( + var entry := LogbookEntryScene.instantiate() as LogbookEntryType + entry.set_meta("fish_id", fish.id) + entry.configure( fish.display_texture, - Vector2(142.0, 82.0) + fish.display_name, + fish.get_rarity_name(), + _inventory.get_count(fish.id) if _inventory != null else 0, + discovered, ) - if not discovered: - texture_frame.modulate = UIPalette.PANEL - content.add_child(texture_frame) - var name_label := Label.new() - name_label.text = fish.display_name if discovered else "???" - name_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - content.add_child(name_label) - var details := Label.new() - if discovered: - var owned_count: int = ( - _inventory.get_count(fish.id) if _inventory != null else 0 + entry.apply_compact_layout(_compact_layout) + return entry + + +func _clear_logbook_entries() -> void: + for field: BoxContainer in [_left_entry_field, _right_entry_field]: + for child: Node in field.get_children(): + _release_focus_from(child, _logbook_tab) + field.remove_child(child) + child.queue_free() + + +func _release_focus_from(node: Node, fallback: Control) -> void: + var focus_owner: Control = get_viewport().gui_get_focus_owner() + if ( + focus_owner == null + or ( + focus_owner != node + and not node.is_ancestor_of(focus_owner) + ) + ): + return + get_viewport().gui_release_focus() + if ( + visible + and not _transitioning + and not _page_transitioning + and fallback != null + and fallback.focus_mode != Control.FOCUS_NONE + ): + fallback.call_deferred("grab_focus") + + +func _request_logbook_page(direction: int) -> void: + if ( + _current_section != Section.LOGBOOK + or _logbook_page_transitioning + or _transitioning + or _page_transitioning + ): + return + var target_page: int = clampi( + _logbook_current_page + direction, + 0, + _logbook_page_count - 1, + ) + if target_page == _logbook_current_page: + return + _logbook_page_generation += 1 + _logbook_page_transitioning = true + _update_logbook_page_control_state(false) + var generation: int = _logbook_page_generation + var travel: float = -12.0 if direction > 0 else 12.0 + _logbook_page_tween = create_tween() + _logbook_page_tween.tween_property( + _book_spread, + "modulate:a", + 0.0, + LOGBOOK_PAGE_DURATION * 0.5, + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _logbook_page_tween.parallel().tween_property( + _book_spread, + "position:x", + travel, + LOGBOOK_PAGE_DURATION * 0.5, + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _logbook_page_tween.tween_callback( + _swap_logbook_page.bind(target_page, travel, generation) + ) + _logbook_page_tween.tween_property( + _book_spread, + "modulate:a", + 1.0, + LOGBOOK_PAGE_DURATION * 0.5, + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _logbook_page_tween.parallel().tween_property( + _book_spread, + "position:x", + 0.0, + LOGBOOK_PAGE_DURATION * 0.5, + ).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + _logbook_page_tween.finished.connect( + _finish_logbook_page_transition.bind(generation), + CONNECT_ONE_SHOT, + ) + + +func _swap_logbook_page( + target_page: int, + travel: float, + generation: int, +) -> void: + if ( + generation != _logbook_page_generation + or not visible + or _current_section != Section.LOGBOOK + ): + return + _logbook_current_page = target_page + _refresh_logbook_page(false) + _book_spread.position.x = -travel + _book_spread.modulate.a = 0.0 + + +func _finish_logbook_page_transition(generation: int) -> void: + if generation != _logbook_page_generation: + return + _logbook_page_tween = null + _logbook_page_transitioning = false + _book_spread.position.x = 0.0 + _book_spread.modulate.a = 1.0 + _update_logbook_page_control_state( + visible and _current_section == Section.LOGBOOK + ) + _configure_logbook_focus() + if _logbook_next.visible and not _logbook_next.disabled: + _logbook_next.grab_focus() + elif _logbook_previous.visible and not _logbook_previous.disabled: + _logbook_previous.grab_focus() + + +func _cancel_logbook_page_transition(reset_visuals: bool) -> void: + _logbook_page_generation += 1 + if _logbook_page_tween != null: + _logbook_page_tween.kill() + _logbook_page_tween = null + _logbook_page_transitioning = false + if reset_visuals and is_instance_valid(_book_spread): + _book_spread.position.x = 0.0 + _book_spread.modulate.a = 1.0 + + +func _update_logbook_page_control_state(interactive: bool) -> void: + var has_multiple_pages: bool = _logbook_page_count > 1 + _logbook_previous.visible = has_multiple_pages + _logbook_next.visible = has_multiple_pages + _logbook_previous.disabled = ( + not interactive or _logbook_current_page <= 0 + ) + _logbook_next.disabled = ( + not interactive + or _logbook_current_page >= _logbook_page_count - 1 + ) + for control: BubbleButtonType in [_logbook_previous, _logbook_next]: + control.focus_mode = ( + Control.FOCUS_ALL + if control.visible and not control.disabled + else Control.FOCUS_NONE + ) + control.mouse_filter = ( + Control.MOUSE_FILTER_STOP + if control.visible and not control.disabled + else Control.MOUSE_FILTER_IGNORE + ) + + +func _configure_logbook_focus() -> void: + if _current_section != Section.LOGBOOK: + return + _logbook_tab.focus_neighbor_bottom = _logbook_tab.focus_neighbor_right + if _logbook_page_count <= 1: + return + var first_control: BubbleButtonType = ( + _logbook_previous + if not _logbook_previous.disabled + else _logbook_next + ) + _logbook_tab.focus_neighbor_bottom = _logbook_tab.get_path_to( + first_control + ) + for control: BubbleButtonType in [_logbook_previous, _logbook_next]: + control.focus_neighbor_top = control.get_path_to(_logbook_tab) + control.focus_neighbor_bottom = control.focus_neighbor_top + control.focus_neighbor_left = control.get_path_to( + _logbook_previous + ) + control.focus_neighbor_right = control.get_path_to(_logbook_next) + + +func _advance_logbook_page_controls(delta: float) -> void: + for control: BubbleButtonType in [_logbook_previous, _logbook_next]: + if not control.visible: + continue + control.advance_emphasis(delta) + control.apply_presentation( + control.calculate_target(_motion_elapsed, 1.0, 1.0), + control.calculate_visual_scale(_motion_elapsed, 1.0), + minf(1.0, delta * 10.0), ) - details.text = "%s\nowned: %d" % [ - fish.get_rarity_name(), - owned_count, - ] - else: - details.text = "undiscovered" - details.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - content.add_child(details) - return card func _create_texture_frame( diff --git a/ui/player_menu.tscn b/ui/player_menu.tscn index 61a075e..e917825 100644 --- a/ui/player_menu.tscn +++ b/ui/player_menu.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=9 format=3] +[gd_scene load_steps=16 format=3] [ext_resource type="Script" path="res://ui/player_menu.gd" id="1_menu"] [ext_resource type="Theme" path="res://ui/game_theme.tres" id="2_theme"] @@ -8,9 +8,18 @@ [ext_resource type="Script" path="res://ui/components/bubble_menu/bubble_button.gd" id="6_bubble"] [ext_resource type="PackedScene" path="res://ui/components/bubble_menu/bubble_status_bubble.tscn" id="7_status"] [ext_resource type="Script" path="res://ui/components/bubble_menu/bubble_information_panel.gd" id="8_info"] +[ext_resource type="PackedScene" path="res://ui/components/bubble_menu/bubble_information_panel.tscn" id="9_info_scene"] +[ext_resource type="PackedScene" path="res://ui/components/bubble_menu/bubble_status_bubble.tscn" id="10_status_scene"] +[ext_resource type="Script" path="res://ui/components/bubble_menu/bubble_button.gd" id="11_bubble"] +[ext_resource type="PackedScene" path="res://ui/components/bubble_menu/notepad_ink_action.tscn" id="12_ink_action"] +[ext_resource type="PackedScene" path="res://ui/components/bubble_menu/notepad_ink_choice.tscn" id="13_ink_choice"] +[ext_resource type="Shader" path="res://ui/components/bubble_menu/cooler_water.gdshader" id="14_water"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_collection"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_cooler_water"] +shader = ExtResource("14_water") + [node name="PlayerMenu" type="Control"] visible = false z_index = 30 @@ -35,7 +44,594 @@ grow_vertical = 2 mouse_filter = 2 color = Color(0.015, 0.02, 0.03, 0.72) -[node name="MenuPanel" type="PanelContainer" parent="."] +[node name="ResponsivePlayerMenuStage" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="PlayerMenuPresentationScaleRoot" type="Control" parent="ResponsivePlayerMenuStage"] +unique_name_in_owner = true +layout_mode = 0 +offset_right = 1280.0 +offset_bottom = 720.0 +mouse_filter = 2 + +[node name="CoolerPage" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"] +unique_name_in_owner = true +layout_mode = 0 +offset_right = 1280.0 +offset_bottom = 720.0 +mouse_filter = 1 + +[node name="CoolerOuterWall" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 54.0 +offset_top = 126.0 +offset_right = 936.0 +offset_bottom = 602.0 + +[node name="CoolerWallMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/CoolerOuterWall"] +layout_mode = 2 +theme_override_constants/margin_left = 13 +theme_override_constants/margin_top = 13 +theme_override_constants/margin_right = 13 +theme_override_constants/margin_bottom = 13 + +[node name="CoolerInnerLiner" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/CoolerOuterWall/CoolerWallMargin"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="CoolerInnerMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/CoolerOuterWall/CoolerWallMargin/CoolerInnerLiner"] +layout_mode = 2 +theme_override_constants/margin_left = 16 +theme_override_constants/margin_top = 16 +theme_override_constants/margin_right = 16 +theme_override_constants/margin_bottom = 16 + +[node name="CoolerScroll" type="ScrollContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/CoolerOuterWall/CoolerWallMargin/CoolerInnerLiner/CoolerInnerMargin"] +unique_name_in_owner = true +layout_mode = 2 +horizontal_scroll_mode = 0 + +[node name="CoolerHost" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/CoolerOuterWall/CoolerWallMargin/CoolerInnerLiner/CoolerInnerMargin/CoolerScroll"] +unique_name_in_owner = true +custom_minimum_size = Vector2(784, 394) +layout_mode = 2 +mouse_filter = 1 + +[node name="WaterSurface" type="ColorRect" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/CoolerOuterWall/CoolerWallMargin/CoolerInnerLiner/CoolerInnerMargin/CoolerScroll/CoolerHost"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +material = SubResource("ShaderMaterial_cooler_water") +color = Color(1, 1, 1, 1) + +[node name="FishField" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/CoolerOuterWall/CoolerWallMargin/CoolerInnerLiner/CoolerInnerMargin/CoolerScroll/CoolerHost"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 1 + +[node name="CoolerEmpty" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/CoolerOuterWall/CoolerWallMargin/CoolerInnerLiner/CoolerInnerMargin/CoolerScroll/CoolerHost"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.91, 0.97, 0.98, 0.82) +theme_override_font_sizes/font_size = 24 +text = "the cooler is empty" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="DetailConstellation" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 942.0 +offset_top = 126.0 +offset_right = 1230.0 +offset_bottom = 602.0 +mouse_filter = 1 + +[node name="DetailBubble" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="BindingDecoration" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 28.0 +offset_top = 4.0 +offset_right = 260.0 +offset_bottom = 31.0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.31, 0.27, 0.2, 0.8) +theme_override_font_sizes/font_size = 20 +text = "● ● ● ●" +horizontal_alignment = 1 + +[node name="NotepadTitle" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 20.0 +offset_top = 31.0 +offset_right = 268.0 +offset_bottom = 59.0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.16, 0.16, 0.14, 1) +theme_override_font_sizes/font_size = 19 +text = "cooler notes" +horizontal_alignment = 1 + +[node name="NotepadWallet" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 18.0 +offset_top = 61.0 +offset_right = 140.0 +offset_bottom = 84.0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.16, 0.16, 0.14, 1) +theme_override_font_sizes/font_size = 14 +text = "wallet $0" + +[node name="NotepadCapacity" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 146.0 +offset_top = 61.0 +offset_right = 270.0 +offset_bottom = 84.0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.16, 0.16, 0.14, 1) +theme_override_font_sizes/font_size = 14 +text = "cooler 0 / 12" +horizontal_alignment = 2 + +[node name="NotepadRule" type="ColorRect" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 18.0 +offset_top = 87.0 +offset_right = 270.0 +offset_bottom = 89.0 +mouse_filter = 2 +color = Color(0.44, 0.36, 0.24, 0.34) + +[node name="CoolerSortControls" type="HBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 18.0 +offset_top = 98.0 +offset_right = 270.0 +offset_bottom = 136.0 +theme_override_constants/separation = 6 + +[node name="CoolerSortLabel" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation/CoolerSortControls"] +visible = false +layout_mode = 2 +theme_override_colors/font_color = Color(0.035, 0.145, 0.22, 1) +text = "sort" +vertical_alignment = 1 + +[node name="CoolerSortOption" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation/CoolerSortControls" instance=ExtResource("13_ink_choice")] +unique_name_in_owner = true +custom_minimum_size = Vector2(123, 38) +layout_mode = 2 +clip_text = true +fit_to_longest_item = false + +[node name="CoolerSortDirection" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation/CoolerSortControls" instance=ExtResource("12_ink_action")] +unique_name_in_owner = true +custom_minimum_size = Vector2(123, 38) +layout_mode = 2 +clip_text = true + +[node name="CoolerDetailTexture" type="TextureRect" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 88.0 +offset_top = 143.0 +offset_right = 200.0 +offset_bottom = 235.0 +mouse_filter = 2 +texture_filter = 1 +expand_mode = 1 +stretch_mode = 5 + +[node name="CoolerDetailName" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 18.0 +offset_top = 239.0 +offset_right = 270.0 +offset_bottom = 269.0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.16, 0.16, 0.14, 1) +theme_override_font_sizes/font_size = 21 +text = "select a fish" +horizontal_alignment = 1 +text_overrun_behavior = 3 + +[node name="CoolerDetailData" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 18.0 +offset_top = 269.0 +offset_right = 270.0 +offset_bottom = 344.0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.16, 0.16, 0.14, 1) +theme_override_font_sizes/font_size = 16 +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="CoolerSelectionSummary" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 18.0 +offset_top = 346.0 +offset_right = 270.0 +offset_bottom = 382.0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.2, 0.18, 0.15, 0.86) +theme_override_font_sizes/font_size = 13 +text = "no fish selected" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="FavoriteBubble" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation" instance=ExtResource("12_ink_action")] +unique_name_in_owner = true +custom_minimum_size = Vector2(98, 78) +layout_mode = 0 +offset_left = 36.0 +offset_top = 386.0 +offset_right = 134.0 +offset_bottom = 464.0 +text = "favorite" + +[node name="SellBubble" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/CoolerPage/DetailConstellation" instance=ExtResource("12_ink_action")] +unique_name_in_owner = true +custom_minimum_size = Vector2(108, 82) +layout_mode = 0 +offset_left = 148.0 +offset_top = 382.0 +offset_right = 256.0 +offset_bottom = 464.0 +text = "sell fish" + +[node name="BagPage" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"] +unique_name_in_owner = true +visible = false +layout_mode = 0 +offset_right = 1280.0 +offset_bottom = 720.0 +mouse_filter = 1 + +[node name="BagOuterWall" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 72.0 +offset_top = 132.0 +offset_right = 968.0 +offset_bottom = 574.0 + +[node name="BagOuterMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagOuterWall"] +layout_mode = 2 +theme_override_constants/margin_left = 14 +theme_override_constants/margin_top = 16 +theme_override_constants/margin_right = 14 +theme_override_constants/margin_bottom = 12 + +[node name="BagInnerLiner" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagOuterWall/BagOuterMargin"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="BagInnerMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagOuterWall/BagOuterMargin/BagInnerLiner"] +layout_mode = 2 +theme_override_constants/margin_left = 18 +theme_override_constants/margin_top = 18 +theme_override_constants/margin_right = 18 +theme_override_constants/margin_bottom = 18 + +[node name="BagScroll" type="ScrollContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagOuterWall/BagOuterMargin/BagInnerLiner/BagInnerMargin"] +unique_name_in_owner = true +layout_mode = 2 +horizontal_scroll_mode = 0 + +[node name="BagHost" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagOuterWall/BagOuterMargin/BagInnerLiner/BagInnerMargin/BagScroll"] +unique_name_in_owner = true +custom_minimum_size = Vector2(820, 350) +layout_mode = 2 +mouse_filter = 1 + +[node name="BagItemField" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagOuterWall/BagOuterMargin/BagInnerLiner/BagInnerMargin/BagScroll/BagHost"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 1 + +[node name="BagEmptyState" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagOuterWall/BagOuterMargin/BagInnerLiner/BagInnerMargin/BagScroll/BagHost"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.22, 0.15, 0.08, 0.8) +theme_override_font_sizes/font_size = 24 +text = "your bag is empty" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="BagInstructionBubble" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage" instance=ExtResource("9_info_scene")] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 992.0 +offset_top = 140.0 +offset_right = 1232.0 +offset_bottom = 238.0 +mouse_filter = 2 + +[node name="BagInstructionText" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagInstructionBubble"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.22, 0.15, 0.08, 1) +theme_override_font_sizes/font_size = 18 +text = "drag items\nto the hotbar" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="BagDetailConstellation" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage"] +unique_name_in_owner = true +visible = false +layout_mode = 0 +offset_left = 984.0 +offset_top = 266.0 +offset_right = 1256.0 +offset_bottom = 570.0 +mouse_filter = 2 + +[node name="BagDetailBubble" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagDetailConstellation" instance=ExtResource("9_info_scene")] +unique_name_in_owner = true +layout_mode = 0 +offset_right = 272.0 +offset_bottom = 304.0 + +[node name="BagDetailLayout" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagDetailConstellation/BagDetailBubble"] +layout_mode = 2 +theme_override_constants/separation = 4 + +[node name="BagSpriteDetailTexture" type="TextureRect" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagDetailConstellation/BagDetailBubble/BagDetailLayout"] +unique_name_in_owner = true +custom_minimum_size = Vector2(100, 72) +layout_mode = 2 +texture_filter = 1 +expand_mode = 1 +stretch_mode = 5 + +[node name="BagSpriteDetailName" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagDetailConstellation/BagDetailBubble/BagDetailLayout"] +unique_name_in_owner = true +layout_mode = 2 +theme_override_colors/font_color = Color(0.22, 0.15, 0.08, 1) +theme_override_font_sizes/font_size = 22 +horizontal_alignment = 1 + +[node name="BagSpriteDetailData" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagDetailConstellation/BagDetailBubble/BagDetailLayout"] +unique_name_in_owner = true +layout_mode = 2 +theme_override_colors/font_color = Color(0.22, 0.15, 0.08, 1) +theme_override_font_sizes/font_size = 15 +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="LogbookPage" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"] +unique_name_in_owner = true +visible = false +layout_mode = 0 +offset_right = 1280.0 +offset_bottom = 720.0 +mouse_filter = 1 + +[node name="BookBacking" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage"] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 58.0 +offset_top = 128.0 +offset_right = 1222.0 +offset_bottom = 588.0 +mouse_filter = 2 + +[node name="BookOuterMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking"] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/margin_left = 12 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 12 +theme_override_constants/margin_bottom = 12 + +[node name="BookSpread" type="HBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/separation = 0 + +[node name="LeftPage" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +mouse_filter = 2 + +[node name="LeftPageMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread/LeftPage"] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/margin_left = 22 +theme_override_constants/margin_top = 18 +theme_override_constants/margin_right = 24 +theme_override_constants/margin_bottom = 18 + +[node name="LeftPageLayout" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread/LeftPage/LeftPageMargin"] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/separation = 8 + +[node name="LeftHeading" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread/LeftPage/LeftPageMargin/LeftPageLayout"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.22, 0.16, 0.09, 1) +theme_override_font_sizes/font_size = 20 +text = "field notes" +horizontal_alignment = 1 + +[node name="LeftEntryField" type="BoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread/LeftPage/LeftPageMargin/LeftPageLayout"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +mouse_filter = 2 +theme_override_constants/separation = 10 +vertical = true + +[node name="BookGutter" type="ColorRect" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread"] +unique_name_in_owner = true +custom_minimum_size = Vector2(18, 0) +layout_mode = 2 +mouse_filter = 2 +color = Color(0.44, 0.34, 0.21, 0.52) + +[node name="RightPage" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +mouse_filter = 2 + +[node name="RightPageMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread/RightPage"] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/margin_left = 24 +theme_override_constants/margin_top = 18 +theme_override_constants/margin_right = 22 +theme_override_constants/margin_bottom = 18 + +[node name="RightPageLayout" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread/RightPage/RightPageMargin"] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/separation = 8 + +[node name="RightHeading" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread/RightPage/RightPageMargin/RightPageLayout"] +unique_name_in_owner = true +layout_mode = 2 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.22, 0.16, 0.09, 1) +theme_override_font_sizes/font_size = 20 +text = "catch record" +horizontal_alignment = 1 + +[node name="RightEntryField" type="BoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage/BookBacking/BookOuterMargin/BookSpread/RightPage/RightPageMargin/RightPageLayout"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +mouse_filter = 2 +theme_override_constants/separation = 10 +vertical = true + +[node name="LogbookEmptyState" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage"] +unique_name_in_owner = true +visible = false +layout_mode = 0 +offset_left = 402.0 +offset_top = 314.0 +offset_right = 878.0 +offset_bottom = 366.0 +mouse_filter = 2 +theme_override_colors/font_color = Color(0.28, 0.21, 0.13, 0.82) +theme_override_font_sizes/font_size = 20 +text = "no fish catalog configured" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="LogbookPrevious" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage"] +unique_name_in_owner = true +custom_minimum_size = Vector2(76, 72) +layout_mode = 0 +offset_left = 78.0 +offset_top = 494.0 +offset_right = 154.0 +offset_bottom = 566.0 +text = "previous" +script = ExtResource("11_bubble") +profile = ExtResource("4_profile") +neutral_size = Vector2(76, 72) +desktop_anchor = Vector2(116, 530) +compact_anchor = Vector2(58, 332) +compact_minimum_size = Vector2(66, 62) +minimum_font_size = 11 +maximum_font_size = 15 +horizontal_amplitude = 0.0 +vertical_amplitude = 0.5 +deformation_amplitude = 0.006 + +[node name="LogbookNext" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage"] +unique_name_in_owner = true +custom_minimum_size = Vector2(76, 72) +layout_mode = 0 +offset_left = 1126.0 +offset_top = 494.0 +offset_right = 1202.0 +offset_bottom = 566.0 +text = "next" +script = ExtResource("11_bubble") +profile = ExtResource("4_profile") +neutral_size = Vector2(76, 72) +desktop_anchor = Vector2(1164, 530) +compact_anchor = Vector2(582, 332) +compact_minimum_size = Vector2(66, 62) +minimum_font_size = 11 +maximum_font_size = 15 +horizontal_amplitude = 0.0 +vertical_amplitude = 0.5 +motion_phase = 2.2 +deformation_amplitude = 0.006 + +[node name="LogbookPageStatus" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage" instance=ExtResource("10_status_scene")] +unique_name_in_owner = true +layout_mode = 0 +offset_left = 555.0 +offset_top = 524.0 +offset_right = 725.0 +offset_bottom = 580.0 +mouse_filter = 2 + +[node name="MenuPanel" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"] unique_name_in_owner = true layout_mode = 0 offset_left = 42.0 @@ -47,34 +643,34 @@ profile = ExtResource("4_profile") content_margin = 22.0 corner_radius = 74 -[node name="Margin" type="MarginContainer" parent="MenuPanel"] +[node name="Margin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel"] layout_mode = 2 theme_override_constants/margin_left = 14 theme_override_constants/margin_top = 12 theme_override_constants/margin_right = 14 theme_override_constants/margin_bottom = 12 -[node name="Layout" type="VBoxContainer" parent="MenuPanel/Margin"] +[node name="Layout" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin"] layout_mode = 2 theme_override_constants/separation = 8 -[node name="Header" type="HBoxContainer" parent="MenuPanel/Margin/Layout"] +[node name="Header" type="HBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout"] unique_name_in_owner = true layout_mode = 2 theme_override_constants/separation = 8 -[node name="WalletBalance" type="Label" parent="MenuPanel/Margin/Layout/Header"] +[node name="WalletBalance" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Header"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 text = "wallet: $0" theme_override_colors/font_color = Color(1, 0.82, 0.4, 1) -[node name="Separator" type="HSeparator" parent="MenuPanel/Margin/Layout"] +[node name="Separator" type="HSeparator" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout"] unique_name_in_owner = true layout_mode = 2 -[node name="TransactionFeedback" type="Label" parent="MenuPanel/Margin/Layout"] +[node name="TransactionFeedback" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout"] unique_name_in_owner = true layout_mode = 2 text = "" @@ -82,28 +678,13 @@ horizontal_alignment = 1 theme_override_colors/font_color = Color(1, 0.82, 0.4, 1) theme_override_font_sizes/font_size = 21 -[node name="Content" type="Control" parent="MenuPanel/Margin/Layout"] +[node name="Content" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout"] unique_name_in_owner = true custom_minimum_size = Vector2(0, 260) layout_mode = 2 size_flags_vertical = 3 -[node name="CoolerScroll" type="ScrollContainer" parent="MenuPanel/Margin/Layout/Content"] -unique_name_in_owner = true -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -horizontal_scroll_mode = 0 - -[node name="CoolerHost" type="VBoxContainer" parent="MenuPanel/Margin/Layout/Content/CoolerScroll"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="InventorySection" type="VBoxContainer" parent="MenuPanel/Margin/Layout/Content"] +[node name="InventorySection" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content"] unique_name_in_owner = true layout_mode = 1 anchors_preset = 15 @@ -113,39 +694,39 @@ grow_horizontal = 2 grow_vertical = 2 theme_override_constants/separation = 7 -[node name="StatusShoal" type="HBoxContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection"] +[node name="StatusShoal" type="HBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection"] unique_name_in_owner = true layout_mode = 2 theme_override_constants/separation = 8 alignment = 1 -[node name="WalletStatus" parent="MenuPanel/Margin/Layout/Content/InventorySection/StatusShoal" instance=ExtResource("7_status")] +[node name="WalletStatus" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/StatusShoal" instance=ExtResource("7_status")] unique_name_in_owner = true layout_mode = 2 -[node name="CapacityStatus" parent="MenuPanel/Margin/Layout/Content/InventorySection/StatusShoal" instance=ExtResource("7_status")] +[node name="CapacityStatus" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/StatusShoal" instance=ExtResource("7_status")] unique_name_in_owner = true layout_mode = 2 -[node name="HeldValueStatus" parent="MenuPanel/Margin/Layout/Content/InventorySection/StatusShoal" instance=ExtResource("7_status")] +[node name="HeldValueStatus" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/StatusShoal" instance=ExtResource("7_status")] unique_name_in_owner = true layout_mode = 2 -[node name="SortBar" type="HBoxContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection"] +[node name="SortBar" type="HBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection"] unique_name_in_owner = true layout_mode = 2 theme_override_constants/separation = 6 -[node name="SortLabel" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] +[node name="SortLabel" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] layout_mode = 2 text = "sort:" -[node name="SortOption" type="OptionButton" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] +[node name="SortOption" type="OptionButton" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] unique_name_in_owner = true layout_mode = 2 custom_minimum_size = Vector2(136, 104) -[node name="SortDirection" type="Button" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] +[node name="SortDirection" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] unique_name_in_owner = true layout_mode = 2 custom_minimum_size = Vector2(136, 104) @@ -159,60 +740,60 @@ horizontal_amplitude = 0.0 vertical_amplitude = 0.0 deformation_amplitude = 0.0 -[node name="SortSpacer" type="Control" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] +[node name="SortSpacer" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] layout_mode = 2 size_flags_horizontal = 3 -[node name="CoolerCount" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] +[node name="CoolerCount" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] unique_name_in_owner = true visible = false layout_mode = 2 text = "0 / 12" theme_override_colors/font_color = Color(0.208, 0.725, 0.78, 1) -[node name="HeldValue" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] +[node name="HeldValue" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/SortBar"] unique_name_in_owner = true visible = false layout_mode = 2 text = "held fish base value: $0" theme_override_colors/font_color = Color(0.682, 0.733, 0.761, 1) -[node name="InventoryBody" type="BoxContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection"] +[node name="InventoryBody" type="BoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection"] unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 3 theme_override_constants/separation = 8 -[node name="InventoryList" type="PanelContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody"] +[node name="InventoryList" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody"] unique_name_in_owner = true custom_minimum_size = Vector2(350, 0) layout_mode = 2 theme_override_styles/panel = SubResource("StyleBoxEmpty_collection") -[node name="InventoryListMargin" type="MarginContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList"] +[node name="InventoryListMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList"] layout_mode = 2 theme_override_constants/margin_left = 8 theme_override_constants/margin_top = 8 theme_override_constants/margin_right = 8 theme_override_constants/margin_bottom = 8 -[node name="InventoryStack" type="VBoxContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList/InventoryListMargin"] +[node name="InventoryStack" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList/InventoryListMargin"] layout_mode = 2 theme_override_constants/separation = 6 -[node name="InventoryEmpty" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList/InventoryListMargin/InventoryStack"] +[node name="InventoryEmpty" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList/InventoryListMargin/InventoryStack"] unique_name_in_owner = true layout_mode = 2 text = "your cooler is empty." horizontal_alignment = 1 -[node name="InventoryScroll" type="ScrollContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList/InventoryListMargin/InventoryStack"] +[node name="InventoryScroll" type="ScrollContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList/InventoryListMargin/InventoryStack"] unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 3 horizontal_scroll_mode = 0 -[node name="InventoryGrid" type="GridContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList/InventoryListMargin/InventoryStack/InventoryScroll"] +[node name="InventoryGrid" type="GridContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/InventoryList/InventoryListMargin/InventoryStack/InventoryScroll"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -220,7 +801,7 @@ theme_override_constants/h_separation = 7 theme_override_constants/v_separation = 7 columns = 3 -[node name="DetailPanel" type="PanelContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody"] +[node name="DetailPanel" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody"] unique_name_in_owner = true custom_minimum_size = Vector2(210, 0) layout_mode = 2 @@ -229,18 +810,18 @@ profile = ExtResource("4_profile") content_margin = 12.0 corner_radius = 96 -[node name="DetailMargin" type="MarginContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel"] +[node name="DetailMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel"] layout_mode = 2 theme_override_constants/margin_left = 10 theme_override_constants/margin_top = 9 theme_override_constants/margin_right = 10 theme_override_constants/margin_bottom = 9 -[node name="DetailStack" type="VBoxContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin"] +[node name="DetailStack" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin"] layout_mode = 2 theme_override_constants/separation = 6 -[node name="DetailTexture" type="TextureRect" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] +[node name="DetailTexture" type="TextureRect" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] unique_name_in_owner = true custom_minimum_size = Vector2(178, 100) layout_mode = 2 @@ -248,7 +829,7 @@ expand_mode = 1 stretch_mode = 5 texture_filter = 1 -[node name="DetailName" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] +[node name="DetailName" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] unique_name_in_owner = true layout_mode = 2 theme_override_colors/font_color = Color(0.208, 0.725, 0.78, 1) @@ -256,14 +837,14 @@ theme_override_font_sizes/font_size = 29 horizontal_alignment = 1 theme_override_colors/font_color = Color(0.035, 0.145, 0.22, 1) -[node name="DetailData" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] +[node name="DetailData" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] unique_name_in_owner = true layout_mode = 2 autowrap_mode = 2 horizontal_alignment = 1 theme_override_colors/font_color = Color(0.035, 0.145, 0.22, 1) -[node name="SelectionSummary" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] +[node name="SelectionSummary" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] unique_name_in_owner = true visible = false layout_mode = 2 @@ -272,12 +853,12 @@ autowrap_mode = 2 horizontal_alignment = 1 theme_override_colors/font_color = Color(0.208, 0.725, 0.78, 1) -[node name="ActionRow" type="HBoxContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] +[node name="ActionRow" type="HBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] layout_mode = 2 theme_override_constants/separation = 8 alignment = 1 -[node name="FavoriteButton" type="Button" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack/ActionRow"] +[node name="FavoriteButton" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack/ActionRow"] unique_name_in_owner = true layout_mode = 2 disabled = true @@ -293,7 +874,7 @@ horizontal_amplitude = 0.0 vertical_amplitude = 0.0 deformation_amplitude = 0.0 -[node name="SellButton" type="Button" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack/ActionRow"] +[node name="SellButton" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack/ActionRow"] unique_name_in_owner = true layout_mode = 2 disabled = true @@ -309,22 +890,22 @@ horizontal_amplitude = 0.0 vertical_amplitude = 0.0 deformation_amplitude = 0.0 -[node name="ContextStatus" type="HBoxContainer" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] +[node name="ContextStatus" type="HBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] layout_mode = 2 theme_override_constants/separation = 6 alignment = 1 -[node name="SelectionStatus" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack/ContextStatus" instance=ExtResource("7_status")] +[node name="SelectionStatus" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack/ContextStatus" instance=ExtResource("7_status")] unique_name_in_owner = true custom_minimum_size = Vector2(108, 78) layout_mode = 2 -[node name="OfferStatus" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack/ContextStatus" instance=ExtResource("7_status")] +[node name="OfferStatus" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack/ContextStatus" instance=ExtResource("7_status")] unique_name_in_owner = true custom_minimum_size = Vector2(128, 78) layout_mode = 2 -[node name="SaleUnavailable" type="Label" parent="MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] +[node name="SaleUnavailable" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/InventorySection/InventoryBody/DetailPanel/DetailMargin/DetailStack"] unique_name_in_owner = true visible = false layout_mode = 2 @@ -332,7 +913,7 @@ autowrap_mode = 2 horizontal_alignment = 1 theme_override_colors/font_color = Color(1, 0.702, 0.278, 1) -[node name="BagSection" type="VBoxContainer" parent="MenuPanel/Margin/Layout/Content"] +[node name="BagSection" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content"] unique_name_in_owner = true visible = false layout_mode = 1 @@ -343,46 +924,46 @@ grow_horizontal = 2 grow_vertical = 2 theme_override_constants/separation = 7 -[node name="BagHint" type="Label" parent="MenuPanel/Margin/Layout/Content/BagSection"] +[node name="BagHint" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection"] layout_mode = 2 text = "drag hotbar-compatible items onto a slot below. right-click a slot to clear it." horizontal_alignment = 1 autowrap_mode = 2 -[node name="BagBody" type="HSplitContainer" parent="MenuPanel/Margin/Layout/Content/BagSection"] +[node name="BagBody" type="HSplitContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection"] layout_mode = 2 size_flags_vertical = 3 split_offset = 540 theme_override_constants/separation = 8 -[node name="BagList" type="PanelContainer" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody"] +[node name="BagList" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody"] unique_name_in_owner = true custom_minimum_size = Vector2(360, 0) layout_mode = 2 -[node name="Margin" type="MarginContainer" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList"] +[node name="Margin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList"] layout_mode = 2 theme_override_constants/margin_left = 8 theme_override_constants/margin_top = 8 theme_override_constants/margin_right = 8 theme_override_constants/margin_bottom = 8 -[node name="Stack" type="VBoxContainer" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList/Margin"] +[node name="Stack" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList/Margin"] layout_mode = 2 theme_override_constants/separation = 6 -[node name="BagEmpty" type="Label" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList/Margin/Stack"] +[node name="BagEmpty" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList/Margin/Stack"] unique_name_in_owner = true layout_mode = 2 text = "your bag is empty." horizontal_alignment = 1 -[node name="BagScroll" type="ScrollContainer" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList/Margin/Stack"] +[node name="BagScroll" type="ScrollContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList/Margin/Stack"] layout_mode = 2 size_flags_vertical = 3 horizontal_scroll_mode = 0 -[node name="BagGrid" type="GridContainer" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList/Margin/Stack/BagScroll"] +[node name="BagGrid" type="GridContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagList/Margin/Stack/BagScroll"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -390,23 +971,23 @@ theme_override_constants/h_separation = 7 theme_override_constants/v_separation = 7 columns = 3 -[node name="BagDetail" type="PanelContainer" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody"] +[node name="BagDetail" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody"] unique_name_in_owner = true custom_minimum_size = Vector2(220, 0) layout_mode = 2 -[node name="Margin" type="MarginContainer" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail"] +[node name="Margin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail"] layout_mode = 2 theme_override_constants/margin_left = 10 theme_override_constants/margin_top = 9 theme_override_constants/margin_right = 10 theme_override_constants/margin_bottom = 9 -[node name="Stack" type="VBoxContainer" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin"] +[node name="Stack" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin"] layout_mode = 2 theme_override_constants/separation = 6 -[node name="BagDetailTexture" type="TextureRect" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"] +[node name="BagDetailTexture" type="TextureRect" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"] unique_name_in_owner = true custom_minimum_size = Vector2(180, 96) layout_mode = 2 @@ -414,20 +995,20 @@ expand_mode = 1 stretch_mode = 5 texture_filter = 1 -[node name="BagDetailName" type="Label" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"] +[node name="BagDetailName" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"] unique_name_in_owner = true layout_mode = 2 theme_override_font_sizes/font_size = 29 horizontal_alignment = 1 -[node name="BagDetailData" type="Label" parent="MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"] +[node name="BagDetailData" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/BagSection/BagBody/BagDetail/Margin/Stack"] unique_name_in_owner = true layout_mode = 2 text = "select a bag item for details." horizontal_alignment = 1 autowrap_mode = 2 -[node name="LogbookSection" type="VBoxContainer" parent="MenuPanel/Margin/Layout/Content"] +[node name="LogbookSection" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content"] unique_name_in_owner = true visible = false layout_mode = 1 @@ -438,18 +1019,18 @@ grow_horizontal = 2 grow_vertical = 2 theme_override_constants/separation = 7 -[node name="LogbookEmpty" type="Label" parent="MenuPanel/Margin/Layout/Content/LogbookSection"] +[node name="LogbookEmpty" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/LogbookSection"] unique_name_in_owner = true layout_mode = 2 text = "no species discovered yet." horizontal_alignment = 1 -[node name="LogbookScroll" type="ScrollContainer" parent="MenuPanel/Margin/Layout/Content/LogbookSection"] +[node name="LogbookScroll" type="ScrollContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/LogbookSection"] layout_mode = 2 size_flags_vertical = 3 horizontal_scroll_mode = 0 -[node name="LogbookGrid" type="GridContainer" parent="MenuPanel/Margin/Layout/Content/LogbookSection/LogbookScroll"] +[node name="LogbookGrid" type="GridContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/MenuPanel/Margin/Layout/Content/LogbookSection/LogbookScroll"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -457,58 +1038,51 @@ theme_override_constants/h_separation = 7 theme_override_constants/v_separation = 7 columns = 4 -[node name="SaleConfirmation" type="PanelContainer" parent="MenuPanel/Margin/Layout/Content"] +[node name="SaleConfirmation" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"] unique_name_in_owner = true visible = false z_index = 40 -layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -320.0 -offset_top = -160.0 -offset_right = 320.0 -offset_bottom = 160.0 -grow_horizontal = 2 -grow_vertical = 2 +layout_mode = 0 +offset_left = 320.0 +offset_top = 200.0 +offset_right = 960.0 +offset_bottom = 520.0 -[node name="ConfirmationMargin" type="MarginContainer" parent="MenuPanel/Margin/Layout/Content/SaleConfirmation"] +[node name="ConfirmationMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/SaleConfirmation"] layout_mode = 2 theme_override_constants/margin_left = 22 theme_override_constants/margin_top = 20 theme_override_constants/margin_right = 22 theme_override_constants/margin_bottom = 20 -[node name="ConfirmationLayout" type="VBoxContainer" parent="MenuPanel/Margin/Layout/Content/SaleConfirmation/ConfirmationMargin"] +[node name="ConfirmationLayout" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/SaleConfirmation/ConfirmationMargin"] layout_mode = 2 theme_override_constants/separation = 12 -[node name="ConfirmationMessage" type="Label" parent="MenuPanel/Margin/Layout/Content/SaleConfirmation/ConfirmationMargin/ConfirmationLayout"] +[node name="ConfirmationMessage" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/SaleConfirmation/ConfirmationMargin/ConfirmationLayout"] unique_name_in_owner = true layout_mode = 2 autowrap_mode = 2 horizontal_alignment = 1 -[node name="ConfirmationButtons" type="HBoxContainer" parent="MenuPanel/Margin/Layout/Content/SaleConfirmation/ConfirmationMargin/ConfirmationLayout"] +[node name="ConfirmationButtons" type="HBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/SaleConfirmation/ConfirmationMargin/ConfirmationLayout"] layout_mode = 2 alignment = 1 -[node name="ConfirmSaleButton" type="Button" parent="MenuPanel/Margin/Layout/Content/SaleConfirmation/ConfirmationMargin/ConfirmationLayout/ConfirmationButtons"] +[node name="ConfirmSaleButton" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/SaleConfirmation/ConfirmationMargin/ConfirmationLayout/ConfirmationButtons"] unique_name_in_owner = true layout_mode = 2 text = "confirm" theme_type_variation = &"DangerButton" 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="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/SaleConfirmation/ConfirmationMargin/ConfirmationLayout/ConfirmationButtons"] unique_name_in_owner = true layout_mode = 2 text = "cancel" custom_minimum_size = Vector2(170, 64) -[node name="NavigationCluster" type="Control" parent="."] +[node name="NavigationCluster" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"] unique_name_in_owner = true layout_mode = 0 offset_left = 260.0 @@ -518,21 +1092,20 @@ offset_bottom = 110.0 mouse_filter = 1 script = ExtResource("5_cluster") profile = ExtResource("4_profile") -desktop_reference_size = Vector2(760, 96) -compact_reference_size = Vector2(610, 74) +desktop_reference_size = Vector2(620, 100) +compact_reference_size = Vector2(620, 100) -[node name="InventoryTab" type="Button" parent="NavigationCluster"] +[node name="InventoryTab" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/NavigationCluster"] unique_name_in_owner = true -custom_minimum_size = Vector2(148, 138) layout_mode = 0 toggle_mode = true text = "cooler" script = ExtResource("6_bubble") profile = ExtResource("4_profile") -neutral_size = Vector2(148, 138) -desktop_anchor = Vector2(118, 68) -compact_anchor = Vector2(118, 68) -compact_minimum_size = Vector2(84, 78) +neutral_size = Vector2(124, 120) +desktop_anchor = Vector2(116, 60) +compact_anchor = Vector2(118, 73.3333) +compact_minimum_size = Vector2(84, 82) minimum_font_size = 16 maximum_font_size = 27 horizontal_amplitude = 1.2 @@ -542,18 +1115,17 @@ motion_phase = 0.35 deformation_amplitude = 0.012 deformation_period = 6.4 -[node name="BagTab" type="Button" parent="NavigationCluster"] +[node name="BagTab" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/NavigationCluster"] unique_name_in_owner = true -custom_minimum_size = Vector2(122, 116) layout_mode = 0 toggle_mode = true text = "bag" script = ExtResource("6_bubble") profile = ExtResource("4_profile") -neutral_size = Vector2(122, 116) -desktop_anchor = Vector2(300, 62) -compact_anchor = Vector2(300, 62) -compact_minimum_size = Vector2(70, 68) +neutral_size = Vector2(124, 120) +desktop_anchor = Vector2(248, 60) +compact_anchor = Vector2(251.333, 73.3333) +compact_minimum_size = Vector2(84, 82) minimum_font_size = 16 maximum_font_size = 25 horizontal_amplitude = 1.0 @@ -563,18 +1135,17 @@ motion_phase = 1.65 deformation_amplitude = 0.011 deformation_period = 6.0 -[node name="LogbookTab" type="Button" parent="NavigationCluster"] +[node name="LogbookTab" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/NavigationCluster"] unique_name_in_owner = true -custom_minimum_size = Vector2(158, 146) layout_mode = 0 toggle_mode = true text = "logbook" script = ExtResource("6_bubble") profile = ExtResource("4_profile") -neutral_size = Vector2(158, 146) -desktop_anchor = Vector2(478, 70) -compact_anchor = Vector2(478, 70) -compact_minimum_size = Vector2(88, 80) +neutral_size = Vector2(124, 120) +desktop_anchor = Vector2(380, 60) +compact_anchor = Vector2(384.667, 73.3333) +compact_minimum_size = Vector2(84, 82) minimum_font_size = 16 maximum_font_size = 27 horizontal_amplitude = 1.3 @@ -584,17 +1155,16 @@ motion_phase = 2.85 deformation_amplitude = 0.012 deformation_period = 6.7 -[node name="CloseButton" type="Button" parent="NavigationCluster"] +[node name="CloseButton" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/NavigationCluster"] unique_name_in_owner = true -custom_minimum_size = Vector2(112, 106) layout_mode = 0 text = "close" script = ExtResource("6_bubble") profile = ExtResource("4_profile") -neutral_size = Vector2(112, 106) -desktop_anchor = Vector2(652, 61) -compact_anchor = Vector2(652, 61) -compact_minimum_size = Vector2(66, 64) +neutral_size = Vector2(110, 106) +desktop_anchor = Vector2(504, 57) +compact_anchor = Vector2(512.667, 73.3333) +compact_minimum_size = Vector2(76, 74) minimum_font_size = 15 maximum_font_size = 23 horizontal_amplitude = 1.0