Expand fish catalog and add bait system
This commit is contained in:
parent
43f57e56a0
commit
954042fd1d
134 changed files with 3134 additions and 127 deletions
|
|
@ -232,7 +232,9 @@ func toggle_chat() -> void:
|
|||
func refocus_gameplay() -> void:
|
||||
close_chat()
|
||||
_controller_refocused = true
|
||||
get_viewport().gui_release_focus()
|
||||
var current_viewport: Viewport = get_viewport()
|
||||
if current_viewport != null:
|
||||
current_viewport.gui_release_focus()
|
||||
|
||||
|
||||
func toggle_focus() -> void:
|
||||
|
|
|
|||
|
|
@ -290,7 +290,9 @@ func close_shop(
|
|||
_closing = true
|
||||
_transaction_in_progress = false
|
||||
hide()
|
||||
get_viewport().gui_release_focus()
|
||||
var current_viewport: Viewport = get_viewport()
|
||||
if current_viewport != null:
|
||||
current_viewport.gui_release_focus()
|
||||
if _fishing_spot != null and is_instance_valid(_fishing_spot):
|
||||
_fishing_spot.set_local_menu_input_suppressed(INPUT_OWNER, false)
|
||||
if (
|
||||
|
|
@ -426,15 +428,23 @@ func _refresh_supplies() -> void:
|
|||
FishingShopStockType.get_price(item_id),
|
||||
_bag.get_quantity(item_id),
|
||||
]
|
||||
if FishingShopStockType.is_bait_topoff(item_id):
|
||||
button.text = "%s\n$%d each • %d/%d" % [
|
||||
item.display_name,
|
||||
FishingShopStockType.get_price(item_id),
|
||||
_bag.get_quantity(item_id),
|
||||
FishingShopStockType.WORM_MAX_STACK,
|
||||
]
|
||||
button.tooltip_text = item.description
|
||||
button.disabled = (
|
||||
_transaction_in_progress
|
||||
or _closing
|
||||
or _network_shop == null
|
||||
or not _network_shop.can_request_purchase()
|
||||
or not _bag.can_add_item(item_id, 1)
|
||||
or FishingShopStockType.get_purchase_quantity(item_id, _bag.get_quantity(item_id)) <= 0
|
||||
or not _bag.can_add_item(item_id, FishingShopStockType.get_purchase_quantity(item_id, _bag.get_quantity(item_id)))
|
||||
or not _wallet.can_afford(
|
||||
FishingShopStockType.get_price(item_id)
|
||||
FishingShopStockType.get_price(item_id) * FishingShopStockType.get_purchase_quantity(item_id, _bag.get_quantity(item_id))
|
||||
)
|
||||
)
|
||||
button.tooltip_text = (
|
||||
|
|
@ -574,10 +584,12 @@ func _purchase_supply(item_id: StringName) -> void:
|
|||
if _transaction_in_progress or not _is_transaction_context_valid():
|
||||
_feedback.text = "unable to complete purchase."
|
||||
return
|
||||
if not _bag.can_add_item(item_id, 1):
|
||||
var owned: int = _bag.get_quantity(item_id)
|
||||
var quantity: int = FishingShopStockType.get_purchase_quantity(item_id, owned)
|
||||
if quantity <= 0 or not _bag.can_add_item(item_id, quantity):
|
||||
_feedback.text = "Your Bag is full."
|
||||
return
|
||||
if not _wallet.can_afford(FishingShopStockType.get_price(item_id)):
|
||||
if not _wallet.can_afford(FishingShopStockType.get_price(item_id) * quantity):
|
||||
_feedback.text = "Not enough fish coin."
|
||||
return
|
||||
if _network_shop == null:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,40 @@ const CATALOG_ORDER: Array[StringName] = [
|
|||
&"salmon_coho",
|
||||
&"salmon_pink",
|
||||
&"salmon_sockeye",
|
||||
&"anchovy_european",
|
||||
&"anchovy_northern",
|
||||
&"chub_european",
|
||||
&"chub_flame",
|
||||
&"chub_lake",
|
||||
&"goldfish",
|
||||
&"goldfish_bubbleeye",
|
||||
&"grouper_gulf",
|
||||
&"grouper_red",
|
||||
&"mackerel_atlantic",
|
||||
&"mackerel_cero",
|
||||
&"mackerel_chub",
|
||||
&"mackerel_king",
|
||||
&"mackerel_spanish",
|
||||
&"marlin_black",
|
||||
&"marlin_blue",
|
||||
&"marlin_white",
|
||||
&"pomfret_black",
|
||||
&"pomfret_chinese",
|
||||
&"pomfret_golden",
|
||||
&"pomfret_white",
|
||||
&"sailfish",
|
||||
&"sauger",
|
||||
&"saugeye",
|
||||
&"snapper_lane",
|
||||
&"snapper_mangrove",
|
||||
&"snapper_mutton",
|
||||
&"snapper_red",
|
||||
&"swordfish",
|
||||
&"trout_cutthroat",
|
||||
&"trout_golden",
|
||||
&"trout_rainbow",
|
||||
&"trout_steelhead",
|
||||
&"walleye",
|
||||
]
|
||||
|
||||
# Short presentation notes are kept here with the catalog contract rather
|
||||
|
|
@ -107,6 +141,142 @@ const FISH_FACTS: Dictionary[StringName, String] = {
|
|||
"sockeye salmon feed heavily on plankton at sea. adults turn vivid red "
|
||||
+ "as they return inland to spawn."
|
||||
),
|
||||
&"anchovy_european": (
|
||||
"european anchovies form dense schools and feed by filtering tiny "
|
||||
+ "plankton from coastal water."
|
||||
),
|
||||
&"anchovy_northern": (
|
||||
"northern anchovies gather in huge schools along the pacific coast "
|
||||
+ "and filter plankton with their fine gill rakers."
|
||||
),
|
||||
&"chub_european": (
|
||||
"european chub are adaptable river fish. adults often patrol "
|
||||
+ "shallows and feed on insects, small fish, and fruit."
|
||||
),
|
||||
&"chub_flame": (
|
||||
"flame chubs prefer cool, clear streams. their bright breeding colors "
|
||||
+ "make a small fish easy to spot in spring water."
|
||||
),
|
||||
&"chub_lake": (
|
||||
"lake chubs school in cold northern water and use their small mouths "
|
||||
+ "to pick insects and other tiny prey from the current."
|
||||
),
|
||||
&"goldfish": (
|
||||
"goldfish can tolerate a surprisingly wide range of conditions. "
|
||||
+ "their wild relatives often live in slow, weedy water."
|
||||
),
|
||||
&"goldfish_bubbleeye": (
|
||||
"bubble-eye goldfish have delicate fluid-filled sacs beneath their "
|
||||
+ "eyes, making careful handling especially important."
|
||||
),
|
||||
&"grouper_gulf": (
|
||||
"gulf grouper are ambush predators that use a sudden gulp to pull "
|
||||
+ "prey into their cavernous mouths."
|
||||
),
|
||||
&"grouper_red": (
|
||||
"red grouper excavate shelters in reef rubble. the hollows they make "
|
||||
+ "can become hiding places for many smaller animals."
|
||||
),
|
||||
&"mackerel_atlantic": (
|
||||
"atlantic mackerel travel in fast schools across the north atlantic "
|
||||
+ "and feed on plankton and small schooling fish."
|
||||
),
|
||||
&"mackerel_cero": (
|
||||
"cero mackerel are streamlined coastal hunters. sharp teeth help "
|
||||
+ "them slash through schools of smaller fish."
|
||||
),
|
||||
&"mackerel_chub": (
|
||||
"chub mackerel school near the surface and follow plankton blooms. "
|
||||
+ "their dark wavy bars help identify them at a glance."
|
||||
),
|
||||
&"mackerel_king": (
|
||||
"king mackerel are swift coastal predators. their pointed teeth and "
|
||||
+ "long body are built for sudden bursts of speed."
|
||||
),
|
||||
&"mackerel_spanish": (
|
||||
"spanish mackerel hunt in warm coastal waters and often travel in "
|
||||
+ "loose schools while chasing baitfish."
|
||||
),
|
||||
&"marlin_black": (
|
||||
"black marlin are powerful billfish that spend much of their lives "
|
||||
+ "in warm open ocean and can make blistering runs."
|
||||
),
|
||||
&"marlin_blue": (
|
||||
"blue marlin are highly migratory open-ocean hunters. their long bill "
|
||||
+ "helps them stun prey before turning back to feed."
|
||||
),
|
||||
&"marlin_white": (
|
||||
"white marlin favor warm offshore water and use their rounded dorsal "
|
||||
+ "fin and bill to weave through schools of prey."
|
||||
),
|
||||
&"pomfret_black": (
|
||||
"black pomfret have a deep, laterally compressed body that lets them "
|
||||
+ "maneuver neatly through open water."
|
||||
),
|
||||
&"pomfret_chinese": (
|
||||
"chinese pomfret are silvery schooling fish with a tall, flattened "
|
||||
+ "body and long sickle-shaped fins."
|
||||
),
|
||||
&"pomfret_golden": (
|
||||
"golden pomfret are warm-water swimmers whose golden sheen is most "
|
||||
+ "noticeable along the fins and flanks."
|
||||
),
|
||||
&"pomfret_white": (
|
||||
"white pomfret gather over coastal grounds and use their compact, "
|
||||
+ "deep bodies to turn quickly while feeding."
|
||||
),
|
||||
&"sailfish": (
|
||||
"sailfish raise their enormous dorsal fin while herding baitfish. "
|
||||
+ "they are among the fastest fish in the sea."
|
||||
),
|
||||
&"sauger": (
|
||||
"sauger favor turbid rivers and reservoirs. their mottled backs "
|
||||
+ "blend into the dim, shifting light near the bottom."
|
||||
),
|
||||
&"saugeye": (
|
||||
"saugeye are a fertile hybrid of sauger and walleye. they combine "
|
||||
+ "traits from both parent species and often grow quickly."
|
||||
),
|
||||
&"snapper_lane": (
|
||||
"lane snapper use reef structure for cover and hunt small crustaceans "
|
||||
+ "and fish when the light begins to fade."
|
||||
),
|
||||
&"snapper_mangrove": (
|
||||
"mangrove snapper shelter among roots and docks when young, then "
|
||||
+ "move toward reefs as they grow."
|
||||
),
|
||||
&"snapper_mutton": (
|
||||
"mutton snapper have canine teeth that help them pick crabs, shrimp, "
|
||||
+ "and other hard-shelled prey from the reef."
|
||||
),
|
||||
&"snapper_red": (
|
||||
"red snapper gather around reefs, wrecks, and ledges. their diet "
|
||||
+ "includes small fish, shrimp, and squid."
|
||||
),
|
||||
&"swordfish": (
|
||||
"swordfish are fast, wide-ranging predators with a flattened bill. "
|
||||
+ "they can cross deep water and warm surface layers in one day."
|
||||
),
|
||||
&"trout_cutthroat": (
|
||||
"cutthroat trout take their name from the red slash beneath the jaw. "
|
||||
+ "many populations rely on cold, well-oxygenated streams."
|
||||
),
|
||||
&"trout_golden": (
|
||||
"golden trout evolved in clear, high-elevation california streams. "
|
||||
+ "their bright flanks stand out against rocky alpine water."
|
||||
),
|
||||
&"trout_rainbow": (
|
||||
"rainbow trout are adaptable stream hunters. the pink lateral stripe "
|
||||
+ "is especially vivid when the fish is in breeding condition."
|
||||
),
|
||||
&"trout_steelhead": (
|
||||
"steelhead are the ocean-going form of rainbow trout. adults can "
|
||||
+ "leave fresh water and later return to spawn."
|
||||
),
|
||||
&"walleye": (
|
||||
"walleye have light-sensitive eyes that help them hunt in murky water "
|
||||
+ "and around dusk. their reflective layer gives the eyes a pale glow."
|
||||
),
|
||||
}
|
||||
|
||||
static func category_for(fish: FishDataType) -> WaterType.Type:
|
||||
|
|
|
|||
|
|
@ -150,7 +150,9 @@ func open_page(preserved_endpoint: String = "") -> void:
|
|||
func close_page() -> void:
|
||||
_clear_edit_state()
|
||||
hide()
|
||||
get_viewport().gui_release_focus()
|
||||
var current_viewport: Viewport = get_viewport()
|
||||
if current_viewport != null:
|
||||
current_viewport.gui_release_focus()
|
||||
|
||||
|
||||
func get_endpoint_text() -> String:
|
||||
|
|
|
|||
|
|
@ -495,7 +495,9 @@ func _finish_close(reason: CloseReason, restore_controls: bool) -> void:
|
|||
hide()
|
||||
if _fishing_spot != null and is_instance_valid(_fishing_spot):
|
||||
_fishing_spot.set_local_menu_input_suppressed(INPUT_OWNER, false)
|
||||
get_viewport().gui_release_focus()
|
||||
var current_viewport: Viewport = get_viewport()
|
||||
if current_viewport != null:
|
||||
current_viewport.gui_release_focus()
|
||||
if restore_controls:
|
||||
_restore_controls()
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -145,7 +145,6 @@ const SALE_CONFIRMATION_SIZE := Vector2(520.0, 190.0)
|
|||
@onready var _cooler_inner_liner: PanelContainer = %CoolerInnerLiner
|
||||
@onready var _cooler_water_surface: ColorRect = %WaterSurface
|
||||
@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
|
||||
|
|
@ -190,6 +189,7 @@ const SALE_CONFIRMATION_SIZE := Vector2(520.0, 190.0)
|
|||
@onready var _lures_filter: Button = %LuresFilter
|
||||
@onready var _tackle_empty: Label = %TackleEmpty
|
||||
@onready var _tackle_detail_text: Label = %TackleDetailText
|
||||
@onready var _tackle_equip_button: Button = %TackleEquipButton
|
||||
@onready var _tackle_item_list: VBoxContainer = %TackleItemList
|
||||
@onready var _bag_outer_wall: PanelContainer = %BagOuterWall
|
||||
@onready var _bag_inner_liner: PanelContainer = %BagInnerLiner
|
||||
|
|
@ -368,6 +368,7 @@ func _ready() -> void:
|
|||
)
|
||||
_bait_filter.pressed.connect(_set_tackle_view.bind(TackleView.BAIT))
|
||||
_lures_filter.pressed.connect(_set_tackle_view.bind(TackleView.LURES))
|
||||
_tackle_equip_button.pressed.connect(_toggle_active_bait)
|
||||
_logbook_tab.pressed.connect(
|
||||
_show_section.bind(Section.LOGBOOK)
|
||||
)
|
||||
|
|
@ -566,6 +567,8 @@ func setup(
|
|||
_fishing_spot.bite_activated.connect(_on_bite_activated)
|
||||
if not _bag.contents_changed.is_connected(_on_bag_changed):
|
||||
_bag.contents_changed.connect(_on_bag_changed)
|
||||
if not _player.active_bait_changed.is_connected(_on_active_bait_changed):
|
||||
_player.active_bait_changed.connect(_on_active_bait_changed)
|
||||
if not _hotbar.slots_changed.is_connected(_on_hotbar_changed):
|
||||
_hotbar.slots_changed.connect(_on_hotbar_changed)
|
||||
if not _cooler_capacity.capacity_changed.is_connected(
|
||||
|
|
@ -1369,12 +1372,14 @@ func _update_tackle_detail() -> void:
|
|||
else null
|
||||
)
|
||||
if item == null:
|
||||
_tackle_equip_button.visible = false
|
||||
_tackle_detail_text.text = (
|
||||
"Select bait for details."
|
||||
if _tackle_view == TackleView.BAIT
|
||||
else "Select a lure for details."
|
||||
)
|
||||
return
|
||||
_tackle_equip_button.visible = item.is_bait()
|
||||
var quantity: int = _bag.get_quantity(item.item_id) if _bag != null else 0
|
||||
var assigned_slot: int = -1
|
||||
if _hotbar != null:
|
||||
|
|
@ -1397,6 +1402,30 @@ func _update_tackle_detail() -> void:
|
|||
item.description,
|
||||
]
|
||||
)
|
||||
if item.is_bait():
|
||||
_tackle_equip_button.text = (
|
||||
"dequip %s" % item.display_name
|
||||
if _player != null and _player.active_bait_id == item.item_id
|
||||
else "equip %s" % item.display_name
|
||||
)
|
||||
_tackle_equip_button.disabled = quantity <= 0
|
||||
|
||||
|
||||
func _toggle_active_bait() -> void:
|
||||
if _player == null or _item_catalog == null:
|
||||
return
|
||||
var item: ItemDataType = _item_catalog.get_item_by_id(_selected_tackle_item_id)
|
||||
if item == null or not item.is_bait():
|
||||
return
|
||||
if _player.active_bait_id == item.item_id:
|
||||
_player.unequip_bait()
|
||||
else:
|
||||
_player.equip_bait(item)
|
||||
_update_tackle_detail()
|
||||
|
||||
|
||||
func _on_active_bait_changed(_item_id: StringName) -> void:
|
||||
_update_tackle_detail()
|
||||
|
||||
|
||||
func _apply_cooler_control_styles() -> void:
|
||||
|
|
@ -1948,7 +1977,9 @@ func _begin_menu_exit(reason: CloseReason, restore_controls: bool) -> void:
|
|||
_catalog_logbook.deactivate()
|
||||
elif _current_section == Section.NET:
|
||||
_the_net_page.deactivate()
|
||||
get_viewport().gui_release_focus()
|
||||
var current_viewport: Viewport = get_viewport()
|
||||
if current_viewport != null:
|
||||
current_viewport.gui_release_focus()
|
||||
var generation: int = _transition_generation
|
||||
var closing_generation: int = _menu_generation
|
||||
_presentation_tween = create_tween().set_parallel(true)
|
||||
|
|
@ -2003,7 +2034,9 @@ func _finish_close(
|
|||
_presentation_scale_root.scale = Vector2.ONE
|
||||
visible = false
|
||||
set_process(false)
|
||||
get_viewport().gui_release_focus()
|
||||
var current_viewport: Viewport = get_viewport()
|
||||
if current_viewport != null:
|
||||
current_viewport.gui_release_focus()
|
||||
if _fishing_spot != null and is_instance_valid(_fishing_spot):
|
||||
_fishing_spot.set_local_menu_input_suppressed(INPUT_OWNER, false)
|
||||
if restore_controls:
|
||||
|
|
@ -2062,7 +2095,9 @@ func _begin_page_transition(section: Section) -> void:
|
|||
_cancel_page_tween()
|
||||
_page_transitioning = true
|
||||
_set_content_interactive(false)
|
||||
get_viewport().gui_release_focus()
|
||||
var current_viewport: Viewport = get_viewport()
|
||||
if current_viewport != null:
|
||||
current_viewport.gui_release_focus()
|
||||
var outgoing_section: Section = _current_section
|
||||
var outgoing_inventory: bool = _is_inventory_section(outgoing_section)
|
||||
var incoming_inventory: bool = _is_inventory_section(section)
|
||||
|
|
@ -2722,7 +2757,6 @@ func _refresh_inventory() -> void:
|
|||
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)
|
||||
|
|
@ -3600,7 +3634,9 @@ func _release_focus_from(node: Node, fallback: Control) -> void:
|
|||
)
|
||||
):
|
||||
return
|
||||
get_viewport().gui_release_focus()
|
||||
var current_viewport: Viewport = get_viewport()
|
||||
if current_viewport != null:
|
||||
current_viewport.gui_release_focus()
|
||||
if (
|
||||
visible
|
||||
and not _transitioning
|
||||
|
|
|
|||
|
|
@ -167,21 +167,6 @@ 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
|
||||
|
|
@ -705,12 +690,21 @@ theme_override_constants/margin_top = 20
|
|||
theme_override_constants/margin_right = 20
|
||||
theme_override_constants/margin_bottom = 20
|
||||
|
||||
[node name="TackleDetailText" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/TackleBoxPage/TackleDetailPanel/Margin"]
|
||||
[node name="Layout" type="VBoxContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/TackleBoxPage/TackleDetailPanel/Margin"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="TackleDetailText" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/TackleBoxPage/TackleDetailPanel/Margin/Layout"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Select bait or a lure for details."
|
||||
autowrap_mode = 2
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="TackleEquipButton" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/TackleBoxPage/TackleDetailPanel/Margin/Layout"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
custom_minimum_size = Vector2(0, 44)
|
||||
text = "equip worms"
|
||||
|
||||
[node name="LogbookPage" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"]
|
||||
unique_name_in_owner = true
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ class_name ProfilePage
|
|||
extends Control
|
||||
|
||||
const CHECK_DEBOUNCE_SECONDS: float = 0.4
|
||||
const OPTION_GRID_COLUMNS: int = 6
|
||||
const ControllerMappingManagerType = preload(
|
||||
"res://settings/controller_mapping_manager.gd"
|
||||
)
|
||||
|
|
@ -513,7 +514,7 @@ func _build_feature_preview_options(options: Array) -> void:
|
|||
scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_AUTO
|
||||
_option_list.add_child(scroll)
|
||||
var grid := GridContainer.new()
|
||||
grid.columns = 4
|
||||
grid.columns = OPTION_GRID_COLUMNS
|
||||
grid.add_theme_constant_override("h_separation", 8)
|
||||
grid.add_theme_constant_override("v_separation", 8)
|
||||
grid.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
|
|
@ -591,7 +592,7 @@ func _feature_preview_texture(
|
|||
|
||||
func _build_fur_color_options(options: Array) -> void:
|
||||
var grid := GridContainer.new()
|
||||
grid.columns = 4
|
||||
grid.columns = OPTION_GRID_COLUMNS
|
||||
grid.add_theme_constant_override("h_separation", 10)
|
||||
grid.add_theme_constant_override("v_separation", 10)
|
||||
_option_list.add_child(grid)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue