1075 lines
33 KiB
GDScript
1075 lines
33 KiB
GDScript
extends SceneTree
|
|
|
|
const FishCatchType = preload("res://fish/fish_catch.gd")
|
|
const FishInventoryType = preload("res://inventory/fish_inventory.gd")
|
|
const FishPoolType = preload("res://fish/fish_pool.gd")
|
|
const CollectionLogType = preload("res://collection/collection_log.gd")
|
|
const FishDataType = preload("res://fish/fish_data.gd")
|
|
const FishQualityType = preload("res://fish/fish_quality.gd")
|
|
const LogbookPortraitType = preload(
|
|
"res://ui/components/logbook_portrait.gd"
|
|
)
|
|
const InventoryNotepadType = preload(
|
|
"res://ui/components/inventory_notepad.gd"
|
|
)
|
|
const LogbookPageScene = preload("res://ui/logbook_page.tscn")
|
|
const CatalogResource: FishPoolType = preload(
|
|
"res://fish/pools/fish_catalog.tres"
|
|
)
|
|
|
|
var _query_available_id: StringName
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("_run")
|
|
|
|
|
|
func _run() -> void:
|
|
if OS.has_environment("straywild_TEST_CREATE_ROOT"):
|
|
var data_root := PlayerDataRoot.new()
|
|
root.add_child(data_root)
|
|
var result: Dictionary = data_root.create_unbound_root(
|
|
OS.get_environment("straywild_TEST_CREATE_ROOT")
|
|
)
|
|
assert(bool(result.get("ok", false)))
|
|
data_root.queue_free()
|
|
print("Logbook portable test root: PASS")
|
|
quit()
|
|
return
|
|
_validate_catalog()
|
|
_validate_catalog_query()
|
|
await _validate_page()
|
|
print("Logbook validation: PASS")
|
|
quit()
|
|
|
|
|
|
func _validate_catalog() -> void:
|
|
assert(CatalogResource.candidates.size() == 316)
|
|
var ordered := LogbookCatalog.ordered_species(CatalogResource.candidates)
|
|
assert(ordered.size() == 314)
|
|
var previous_number: int = 0
|
|
var catalog_numbers: Dictionary[int, bool] = {}
|
|
for fish: FishDataType in CatalogResource.candidates:
|
|
assert(fish != null)
|
|
assert(fish.catalog_number > 0)
|
|
assert(not catalog_numbers.has(fish.catalog_number))
|
|
catalog_numbers[fish.catalog_number] = true
|
|
assert(not LogbookCatalog.facts_for(fish).is_empty())
|
|
assert(
|
|
LogbookCatalog.facts_for(fish)
|
|
== LogbookCatalog.facts_for(fish).to_lower()
|
|
)
|
|
assert(LogbookCatalog.facts_for(fish) != "unknown")
|
|
for fish: FishDataType in ordered:
|
|
assert(fish.active)
|
|
assert(fish.catalog_number > previous_number)
|
|
assert(LogbookCatalog.catalog_number(fish) == fish.catalog_number)
|
|
previous_number = fish.catalog_number
|
|
assert(
|
|
LogbookCatalog.empty_state(LogbookCatalog.Category.SALT_WATER)
|
|
== "No saltwater catches cataloged yet."
|
|
)
|
|
|
|
|
|
func _validate_catalog_query() -> void:
|
|
var collection := CollectionLogType.new()
|
|
var inventory := FishInventoryType.new()
|
|
var fresh_species: Array[FishDataType] = []
|
|
for fish: FishDataType in LogbookCatalog.ordered_species(
|
|
CatalogResource.candidates
|
|
):
|
|
if LogbookCatalog.category_for(fish) == LogbookCatalog.Category.FRESH_WATER:
|
|
fresh_species.append(fish)
|
|
assert(fresh_species.size() == 108)
|
|
var first := fresh_species[0]
|
|
var second := fresh_species[1]
|
|
var unknown := fresh_species[2]
|
|
for quality: int in FishQualityType.TIER_COUNT:
|
|
collection.record_catch(first.id, quality)
|
|
collection.record_catch(second.id, FishQualityType.Tier.BORING)
|
|
var held := _make_test_catch(first, true)
|
|
assert(inventory.add_catch(held))
|
|
|
|
var options := _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.CAUGHT
|
|
var filtered := LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered.size() == 2)
|
|
assert(first in filtered and second in filtered)
|
|
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.MISSING
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered.size() == fresh_species.size() - 2)
|
|
options["sort"] = LogbookCatalog.SortMode.CATALOG_NUMBER
|
|
options["descending"] = true
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered.front() == fresh_species.back())
|
|
assert(filtered.back() == unknown)
|
|
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.INCOMPLETE
|
|
options["descending"] = false
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered == [second])
|
|
|
|
options = _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.CAUGHT
|
|
options["sort"] = LogbookCatalog.SortMode.CATCH_COUNT
|
|
options["descending"] = true
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered == [first, second])
|
|
|
|
options = _default_query_options()
|
|
options["search"] = unknown.display_name
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered.is_empty())
|
|
options["search"] = str(unknown.catalog_number)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered == [unknown])
|
|
|
|
options = _default_query_options()
|
|
options["holding"] = LogbookCatalog.HoldingFilter.FAVORITED
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered == [first])
|
|
options["holding"] = LogbookCatalog.HoldingFilter.IN_COOLER
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered == [first])
|
|
|
|
options = _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.CAUGHT
|
|
options["group"] = String(first.collection_group)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(first in filtered)
|
|
for fish: FishDataType in filtered:
|
|
assert(fish.collection_group == first.collection_group)
|
|
|
|
options = _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.CAUGHT
|
|
options["rarity"] = (
|
|
int(first.rarity) + LogbookCatalog.RarityFilter.COMMON
|
|
)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(first in filtered)
|
|
for fish: FishDataType in filtered:
|
|
assert(fish.rarity == first.rarity)
|
|
|
|
options = _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.CAUGHT
|
|
options["method"] = (
|
|
int(first.collection_method) + LogbookCatalog.MethodFilter.FISHING
|
|
)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(first in filtered)
|
|
for fish: FishDataType in filtered:
|
|
assert(fish.collection_method == first.collection_method)
|
|
|
|
var first_season := -1
|
|
for season: int in 4:
|
|
if first.is_available_in_season(season):
|
|
first_season = season
|
|
break
|
|
assert(first_season >= 0)
|
|
options = _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.CAUGHT
|
|
options["season"] = (
|
|
first_season + LogbookCatalog.SeasonFilter.SPRING
|
|
)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(first in filtered)
|
|
for fish: FishDataType in filtered:
|
|
assert(fish.is_available_in_season(first_season))
|
|
|
|
var first_is_available_by_day := (
|
|
first.availability == null or first.availability.allow_day
|
|
)
|
|
options = _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.CAUGHT
|
|
options["time"] = (
|
|
LogbookCatalog.TimeFilter.DAY
|
|
if first_is_available_by_day
|
|
else LogbookCatalog.TimeFilter.NIGHT
|
|
)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(first in filtered)
|
|
|
|
options = _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.CAUGHT
|
|
options["sort"] = LogbookCatalog.SortMode.QUALITY_PROGRESS
|
|
options["descending"] = true
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered == [first, second])
|
|
for sort_mode: LogbookCatalog.SortMode in [
|
|
LogbookCatalog.SortMode.NAME,
|
|
LogbookCatalog.SortMode.RARITY,
|
|
LogbookCatalog.SortMode.VALUE,
|
|
LogbookCatalog.SortMode.WEIGHT,
|
|
]:
|
|
options = _default_query_options()
|
|
options["sort"] = sort_mode
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(filtered[0] in [first, second])
|
|
assert(filtered[1] in [first, second])
|
|
assert(filtered[0] != filtered[1])
|
|
assert(filtered[2] == unknown)
|
|
|
|
_query_available_id = second.id
|
|
options = _default_query_options()
|
|
options["availability"] = (
|
|
LogbookCatalog.AvailabilityFilter.AVAILABLE_NOW
|
|
)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
Callable(self, "_query_species_available_now"),
|
|
)
|
|
assert(filtered == [second])
|
|
|
|
_query_available_id = unknown.id
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.MISSING
|
|
options["rarity"] = (
|
|
int(unknown.rarity) + LogbookCatalog.RarityFilter.COMMON
|
|
)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
Callable(self, "_query_species_available_now"),
|
|
)
|
|
assert(filtered == [unknown])
|
|
|
|
options = _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.MISSING
|
|
options["group"] = String(unknown.collection_group)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(unknown in filtered)
|
|
assert(
|
|
String(unknown.collection_group)
|
|
in LogbookCatalog.available_groups(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
)
|
|
)
|
|
|
|
var unknown_is_available_by_day := (
|
|
unknown.availability == null or unknown.availability.allow_day
|
|
)
|
|
options = _default_query_options()
|
|
options["show"] = LogbookCatalog.DiscoveryFilter.MISSING
|
|
options["time"] = (
|
|
LogbookCatalog.TimeFilter.DAY
|
|
if unknown_is_available_by_day
|
|
else LogbookCatalog.TimeFilter.NIGHT
|
|
)
|
|
filtered = LogbookCatalog.filtered_species(
|
|
CatalogResource.candidates,
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
collection,
|
|
inventory,
|
|
options,
|
|
)
|
|
assert(unknown in filtered)
|
|
inventory.free()
|
|
collection.free()
|
|
|
|
|
|
func _default_query_options() -> Dictionary:
|
|
return {
|
|
"search": "",
|
|
"show": LogbookCatalog.DiscoveryFilter.ALL,
|
|
"sort": LogbookCatalog.SortMode.CATALOG_NUMBER,
|
|
"descending": false,
|
|
"availability": LogbookCatalog.AvailabilityFilter.ANY,
|
|
"season": LogbookCatalog.SeasonFilter.ANY,
|
|
"time": LogbookCatalog.TimeFilter.ANY,
|
|
"rarity": LogbookCatalog.RarityFilter.ANY,
|
|
"method": LogbookCatalog.MethodFilter.ANY,
|
|
"holding": LogbookCatalog.HoldingFilter.ANY,
|
|
"group": "",
|
|
}
|
|
|
|
|
|
func _make_test_catch(fish: FishDataType, favorited: bool) -> FishCatchType:
|
|
var fish_catch := FishCatchType.new()
|
|
fish_catch.fish = fish
|
|
fish_catch.fish_id = fish.id
|
|
fish_catch.weight_lb = fish.get_minimum_weight()
|
|
fish_catch.display_scale = fish.get_display_scale_for_weight(
|
|
fish_catch.weight_lb
|
|
)
|
|
fish_catch.quality = FishQualityType.Tier.BORING
|
|
fish_catch.sale_value = fish.get_sale_value_for_weight(fish_catch.weight_lb)
|
|
fish_catch.is_favorited = favorited
|
|
fish_catch.ensure_identity()
|
|
return fish_catch
|
|
|
|
|
|
func _query_species_available_now(fish: FishDataType) -> bool:
|
|
return fish != null and fish.id == _query_available_id
|
|
|
|
|
|
func _validate_page() -> void:
|
|
var collection := CollectionLogType.new()
|
|
var inventory := FishInventoryType.new()
|
|
root.add_child(collection)
|
|
root.add_child(inventory)
|
|
var page := LogbookPageScene.instantiate() as LogbookPage
|
|
root.add_child(page)
|
|
page.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
|
|
page.size = Vector2(1280.0, 720.0)
|
|
await process_frame
|
|
page.setup(collection, inventory, CatalogResource)
|
|
page.activate()
|
|
await process_frame
|
|
var outer_margin := page.get("_outer_margin") as MarginContainer
|
|
var book := page.get("_book") as Control
|
|
assert(outer_margin != null)
|
|
assert(book != null)
|
|
page.set_compact_presentation(true)
|
|
await process_frame
|
|
assert(outer_margin.get_theme_constant("margin_left") == 160)
|
|
assert(outer_margin.get_theme_constant("margin_right") == 160)
|
|
assert(outer_margin.get_theme_constant("margin_bottom") == 106)
|
|
assert(is_equal_approx(book.offset_top, 65.0))
|
|
page.call("_set_index_open", true, false)
|
|
await process_frame
|
|
_validate_index_content_bounds(page)
|
|
page.call("_set_index_open", false, false)
|
|
page.set_compact_presentation(false)
|
|
await process_frame
|
|
assert(outer_margin.get_theme_constant("margin_left") == 52)
|
|
assert(outer_margin.get_theme_constant("margin_right") == 52)
|
|
assert(outer_margin.get_theme_constant("margin_bottom") == 18)
|
|
assert(is_equal_approx(book.offset_top, 50.0))
|
|
assert(
|
|
page.get("_category") == LogbookCatalog.Category.FRESH_WATER
|
|
)
|
|
assert((page.get("_catalog_grid") as GridContainer).columns == 4)
|
|
var catalog_scroll := page.get("_catalog_scroll") as ScrollContainer
|
|
assert(catalog_scroll != null and catalog_scroll.follow_focus)
|
|
catalog_scroll.scroll_vertical = 37
|
|
await create_timer(0.2).timeout
|
|
assert(catalog_scroll.scroll_vertical == 37)
|
|
page.call(
|
|
"_set_controller_zone",
|
|
LogbookPage.ControllerZone.ENTRIES,
|
|
)
|
|
for _frame: int in 2:
|
|
await process_frame
|
|
var initial_entries: Array = (
|
|
page.get("_entry_buttons") as Dictionary
|
|
).values()
|
|
assert(initial_entries.size() > 4)
|
|
var final_entry := initial_entries.back() as Button
|
|
final_entry.grab_focus()
|
|
for _frame: int in 3:
|
|
await process_frame
|
|
assert(catalog_scroll.scroll_vertical > 0)
|
|
page.reset_controller_zone()
|
|
for _frame: int in 2:
|
|
await process_frame
|
|
var category_tabs: Array = page.get("_category_tabs") as Array
|
|
var category_tab_categories: Array = (
|
|
page.get("_category_tab_categories") as Array
|
|
)
|
|
assert(category_tab_categories == [
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
LogbookCatalog.Category.SALT_WATER,
|
|
LogbookCatalog.Category.SHELLFISH,
|
|
LogbookCatalog.Category.OTHER,
|
|
])
|
|
assert(category_tabs.size() == category_tab_categories.size())
|
|
assert(
|
|
LogbookCatalog.category_label(LogbookCatalog.Category.OTHER)
|
|
== "Insects"
|
|
)
|
|
for tab_node: Variant in category_tabs:
|
|
var category_tab := tab_node as Button
|
|
assert(category_tab.size == LogbookPage.LOGBOOK_TAB_SIZE)
|
|
var text_width: float = UtilityPageStyle.TuffyFont.get_string_size(
|
|
category_tab.text,
|
|
HORIZONTAL_ALIGNMENT_LEFT,
|
|
-1.0,
|
|
OrganizerTab.FONT_SIZE,
|
|
).x
|
|
assert(
|
|
text_width + LogbookPage.LOGBOOK_TAB_TEXT_SIDE_INSET * 2.0
|
|
<= category_tab.size.x
|
|
)
|
|
assert(
|
|
(category_tabs[0] as Button).get_parent().position.x
|
|
== LogbookPage.LOGBOOK_TAB_LEFT_INSET
|
|
)
|
|
var initial_detail_body := page.get("_detail_body") as VBoxContainer
|
|
assert(not initial_detail_body.get_parent() is ScrollContainer)
|
|
var index_tab := page.get("_index_tab") as Button
|
|
var index_body := page.get("_index_body") as VBoxContainer
|
|
assert(index_tab != null and index_body != null)
|
|
assert(index_tab.size == LogbookPage.INDEX_TAB_SIZE)
|
|
assert(
|
|
not index_tab.get_global_rect().intersects(
|
|
(category_tabs.back() as Button).get_global_rect()
|
|
)
|
|
)
|
|
page.call("_set_index_open", true, false)
|
|
await process_frame
|
|
assert(index_body.visible)
|
|
assert(not initial_detail_body.visible)
|
|
assert((page.get("_index_option_buttons") as Dictionary).size() == 10)
|
|
_validate_index_content_bounds(page)
|
|
page.call(
|
|
"_cycle_index_option",
|
|
&"show",
|
|
1,
|
|
)
|
|
await process_frame
|
|
assert((page.get("_entry_buttons") as Dictionary).is_empty())
|
|
assert(
|
|
(page.get("_empty_state") as Label).text
|
|
== "No entries match this index."
|
|
)
|
|
page.call("_reset_index")
|
|
await process_frame
|
|
assert((page.get("_entry_buttons") as Dictionary).size() == 108)
|
|
page.call("_set_index_open", false, false)
|
|
await process_frame
|
|
assert(not index_body.visible)
|
|
assert(initial_detail_body.visible)
|
|
assert(
|
|
page.call("_entry_label_text", "flathead catfish")
|
|
== "flathead\ncatfish"
|
|
)
|
|
|
|
var shared_material: Material
|
|
var silhouette_count: int = 0
|
|
var target_silhouette_area: float = (
|
|
LogbookPage.CATALOG_PORTRAIT_SIZE.x
|
|
* LogbookPage.CATALOG_PORTRAIT_SIZE.y
|
|
* LogbookPortraitType.UNIFORM_FOOTPRINT_AREA_RATIO
|
|
)
|
|
for category: LogbookCatalog.Category in [
|
|
LogbookCatalog.Category.FRESH_WATER,
|
|
LogbookCatalog.Category.SALT_WATER,
|
|
]:
|
|
page.call("_select_category", category)
|
|
await create_timer(0.25).timeout
|
|
var entries: Dictionary = page.get("_entry_buttons")
|
|
assert(
|
|
entries.size()
|
|
== (108 if category == LogbookCatalog.Category.FRESH_WATER else 202)
|
|
)
|
|
for fish: FishDataType in LogbookCatalog.ordered_species(
|
|
CatalogResource.candidates
|
|
):
|
|
if LogbookCatalog.category_for(fish) != category:
|
|
continue
|
|
var unknown_key := StringName(
|
|
"unknown_%d" % LogbookCatalog.catalog_number(fish)
|
|
)
|
|
var entry := entries.get(unknown_key) as Button
|
|
assert(entry != null)
|
|
assert(entry.text.is_empty())
|
|
assert(entry.tooltip_text.is_empty())
|
|
assert(entry.icon == null)
|
|
assert(entry.accessibility_name == "Unknown catalog entry")
|
|
assert(_has_visible_unknown_name(entry))
|
|
var portrait: LogbookPortraitType = _find_portrait(entry)
|
|
assert(portrait != null)
|
|
assert(portrait.source_texture == fish.display_texture)
|
|
assert(
|
|
portrait.custom_minimum_size.x
|
|
<= LogbookPage.CATALOG_PORTRAIT_SIZE.x
|
|
and portrait.custom_minimum_size.y
|
|
<= LogbookPage.CATALOG_PORTRAIT_SIZE.y
|
|
)
|
|
assert(portrait.get_parent() is CenterContainer)
|
|
assert(
|
|
(portrait.get_parent() as CenterContainer).custom_minimum_size
|
|
== LogbookPage.CATALOG_PORTRAIT_SIZE
|
|
)
|
|
assert(
|
|
portrait.expand_mode
|
|
== TextureRect.EXPAND_IGNORE_SIZE
|
|
)
|
|
assert(
|
|
portrait.stretch_mode
|
|
== TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
|
)
|
|
assert(portrait.material is ShaderMaterial)
|
|
if shared_material == null:
|
|
shared_material = portrait.material
|
|
else:
|
|
assert(portrait.material == shared_material)
|
|
assert(_texture_has_transparency(portrait.texture))
|
|
var silhouette_area: float = (
|
|
portrait.custom_minimum_size.x
|
|
* portrait.custom_minimum_size.y
|
|
)
|
|
assert(silhouette_area > 0.0)
|
|
assert(silhouette_area <= target_silhouette_area * 1.05)
|
|
assert(
|
|
silhouette_area >= target_silhouette_area * 0.9
|
|
or is_equal_approx(
|
|
portrait.custom_minimum_size.x,
|
|
LogbookPage.CATALOG_PORTRAIT_SIZE.x,
|
|
)
|
|
or is_equal_approx(
|
|
portrait.custom_minimum_size.y,
|
|
LogbookPage.CATALOG_PORTRAIT_SIZE.y,
|
|
)
|
|
)
|
|
silhouette_count += 1
|
|
for candidate: FishDataType in CatalogResource.candidates:
|
|
assert(not entry.text.contains(candidate.display_name))
|
|
assert(
|
|
not entry.tooltip_text.contains(
|
|
candidate.display_name
|
|
)
|
|
)
|
|
assert(
|
|
not entry.accessibility_name.contains(
|
|
candidate.display_name
|
|
)
|
|
)
|
|
assert(silhouette_count == 310)
|
|
|
|
page.call("_select_category", LogbookCatalog.Category.SHELLFISH)
|
|
await create_timer(0.25).timeout
|
|
assert((page.get("_entry_buttons") as Dictionary).size() == 3)
|
|
assert(
|
|
(page.get("_entry_buttons") as Dictionary).has(&"unknown_3902")
|
|
)
|
|
assert(
|
|
(page.get("_entry_buttons") as Dictionary).has(&"unknown_3906")
|
|
)
|
|
assert(
|
|
(page.get("_entry_buttons") as Dictionary).has(&"unknown_6406")
|
|
)
|
|
page.call("_select_category", LogbookCatalog.Category.OTHER)
|
|
await create_timer(0.25).timeout
|
|
assert((page.get("_entry_buttons") as Dictionary).size() == 1)
|
|
assert(
|
|
(page.get("_entry_buttons") as Dictionary).has(&"unknown_8001")
|
|
)
|
|
page.call("_select_category", LogbookCatalog.Category.FRESH_WATER)
|
|
await create_timer(0.25).timeout
|
|
|
|
var bluegill = CatalogResource.get_fish_by_id(&"bluegill")
|
|
var bluegill_unknown := StringName(
|
|
"unknown_%d" % bluegill.catalog_number
|
|
)
|
|
page.call("_select_entry", bluegill_unknown, StringName())
|
|
assert(
|
|
(page.get("_entry_buttons") as Dictionary)
|
|
.get(bluegill_unknown) != null
|
|
)
|
|
collection.mark_discovered(&"bluegill")
|
|
collection.mark_quality_discovered(
|
|
&"bluegill",
|
|
FishQualityType.Tier.BORING,
|
|
)
|
|
await process_frame
|
|
var entries: Dictionary = page.get("_entry_buttons")
|
|
var known := entries.get(&"bluegill") as Button
|
|
assert(known != null)
|
|
assert(known.custom_minimum_size.x == known.custom_minimum_size.y)
|
|
_validate_entry_bubble_styles(known)
|
|
assert(known.text.is_empty())
|
|
assert(known.icon == null)
|
|
assert(_has_visible_name(known, bluegill.display_name))
|
|
var known_portrait: LogbookPortraitType = _find_portrait(known)
|
|
assert(known_portrait != null)
|
|
assert(known_portrait.source_texture == bluegill.display_texture)
|
|
assert(known_portrait.material == null)
|
|
assert(known_portrait.get_parent() is CenterContainer)
|
|
assert(
|
|
(known_portrait.get_parent() as CenterContainer).custom_minimum_size
|
|
== LogbookPage.CATALOG_PORTRAIT_SIZE
|
|
)
|
|
assert(known.button_pressed)
|
|
_validate_handwritten_logbook_font(page)
|
|
|
|
var fish_catch := FishCatchType.new()
|
|
fish_catch.fish = bluegill
|
|
fish_catch.fish_id = bluegill.id
|
|
fish_catch.weight_lb = bluegill.get_minimum_weight()
|
|
fish_catch.display_scale = bluegill.get_display_scale_for_weight(
|
|
fish_catch.weight_lb
|
|
)
|
|
fish_catch.sale_value = bluegill.get_sale_value_for_weight(
|
|
fish_catch.weight_lb
|
|
)
|
|
fish_catch.ensure_identity()
|
|
inventory.add_catch(fish_catch)
|
|
collection.record_catch(fish_catch.fish_id, fish_catch.quality)
|
|
page.call("_select_entry", &"bluegill", &"bluegill")
|
|
await process_frame
|
|
assert(not _detail_text(page).contains("number owned"))
|
|
assert(_detail_text(page).contains("number caught\n1"))
|
|
assert(_detail_text(page).contains("body of water\nfresh water"))
|
|
assert(
|
|
_detail_text(page).contains(
|
|
"catalog number\n#%03d" % bluegill.catalog_number
|
|
)
|
|
)
|
|
assert(_detail_text(page).contains("fish facts\n"))
|
|
assert(_detail_text(page).contains(LogbookCatalog.facts_for(bluegill)))
|
|
_validate_detail_field_fonts(page)
|
|
_validate_handwritten_numeric_scale(page)
|
|
_validate_detail_content_bounds(page)
|
|
var detail_buttons: Array = page.get("_detail_buttons") as Array
|
|
assert(detail_buttons.size() == 4)
|
|
var portrait_detail := detail_buttons[0] as Button
|
|
var facts_detail := detail_buttons[1] as Button
|
|
var quality_detail := detail_buttons[2] as Button
|
|
var stats_detail := detail_buttons[3] as Button
|
|
assert(
|
|
quality_detail.custom_minimum_size
|
|
== LogbookPage.DETAIL_QUALITY_SECTION_SIZE
|
|
)
|
|
assert(
|
|
stats_detail.custom_minimum_size
|
|
== LogbookPage.DETAIL_STATS_SECTION_SIZE
|
|
)
|
|
assert(
|
|
quality_detail.size_flags_horizontal
|
|
== Control.SIZE_SHRINK_CENTER
|
|
)
|
|
assert(
|
|
stats_detail.size_flags_horizontal
|
|
== Control.SIZE_SHRINK_CENTER
|
|
)
|
|
assert(
|
|
stats_detail.size_flags_vertical & Control.SIZE_EXPAND == 0
|
|
)
|
|
assert(
|
|
portrait_detail.get_node(portrait_detail.focus_neighbor_right)
|
|
== facts_detail
|
|
)
|
|
assert(
|
|
portrait_detail.get_node(portrait_detail.focus_neighbor_bottom)
|
|
== quality_detail
|
|
)
|
|
assert(
|
|
facts_detail.get_node(facts_detail.focus_neighbor_left)
|
|
== portrait_detail
|
|
)
|
|
assert(
|
|
facts_detail.get_node(facts_detail.focus_neighbor_bottom)
|
|
== quality_detail
|
|
)
|
|
assert(
|
|
quality_detail.get_node(quality_detail.focus_neighbor_bottom)
|
|
== stats_detail
|
|
)
|
|
assert(
|
|
stats_detail.get_node(stats_detail.focus_neighbor_top)
|
|
== quality_detail
|
|
)
|
|
var portrait_button := page.get("_detail_portrait_button") as Button
|
|
assert(portrait_button != null)
|
|
portrait_button.pressed.emit()
|
|
await process_frame
|
|
var portrait_overlay := page.get("_portrait_overlay") as Control
|
|
assert(portrait_overlay.visible)
|
|
var overlay_artwork := (
|
|
page.get("_portrait_overlay_artwork") as LogbookPortraitType
|
|
)
|
|
assert(overlay_artwork.source_texture == bluegill.display_texture)
|
|
assert(
|
|
overlay_artwork.custom_minimum_size.x
|
|
<= LogbookPage.PORTRAIT_VIEW_MAX_SIZE.x
|
|
and overlay_artwork.custom_minimum_size.y
|
|
<= LogbookPage.PORTRAIT_VIEW_MAX_SIZE.y
|
|
)
|
|
var overlay_card := _find_overlay_card(portrait_overlay)
|
|
assert(overlay_card != null)
|
|
assert(overlay_card.size == LogbookPage.DETAIL_OVERLAY_CARD_SIZE)
|
|
assert(is_equal_approx(overlay_card.size.aspect(), 4.0 / 3.0))
|
|
(page.get("_portrait_overlay_backdrop") as Button).pressed.emit()
|
|
await process_frame
|
|
assert(not portrait_overlay.visible)
|
|
detail_buttons = page.get("_detail_buttons") as Array
|
|
assert(detail_buttons.size() == 4)
|
|
facts_detail = detail_buttons[1] as Button
|
|
facts_detail.pressed.emit()
|
|
await process_frame
|
|
var overlay_text := page.get("_portrait_overlay_text") as Label
|
|
assert(overlay_text.visible)
|
|
assert(
|
|
overlay_text.get_theme_font_size("font_size")
|
|
== LogbookPage.DETAIL_OVERLAY_TEXT_FONT_SIZE
|
|
)
|
|
assert(
|
|
overlay_text.horizontal_alignment
|
|
== HORIZONTAL_ALIGNMENT_LEFT
|
|
)
|
|
assert(
|
|
overlay_text.get_theme_font("font")
|
|
== UtilityPageStyle.TuffyFont
|
|
)
|
|
(page.get("_portrait_overlay_backdrop") as Button).pressed.emit()
|
|
await process_frame
|
|
|
|
quality_detail.pressed.emit()
|
|
await process_frame
|
|
var quality_view := page.get("_portrait_overlay_quality_view") as Control
|
|
assert(quality_view.visible)
|
|
var quality_text: String = _descendant_label_text(quality_view)
|
|
for quality: int in FishQualityType.TIER_COUNT:
|
|
assert(quality_text.contains(FishQualityType.display_name(quality)))
|
|
assert(quality_text.contains("●"))
|
|
assert(quality_text.contains("○"))
|
|
_validate_overlay_fonts(quality_view)
|
|
(page.get("_portrait_overlay_backdrop") as Button).pressed.emit()
|
|
await process_frame
|
|
|
|
stats_detail.pressed.emit()
|
|
await process_frame
|
|
var stats_view := page.get("_portrait_overlay_stats_view") as Control
|
|
assert(stats_view.visible)
|
|
var stats_text: String = _descendant_label_text(stats_view)
|
|
assert(stats_text.contains("catalog number"))
|
|
assert(stats_text.contains("number caught"))
|
|
assert(stats_text.contains("1"))
|
|
assert(stats_text.contains("seasons"))
|
|
assert(not stats_text.contains("number owned"))
|
|
_validate_overlay_fonts(stats_view)
|
|
(page.get("_portrait_overlay_backdrop") as Button).pressed.emit()
|
|
await process_frame
|
|
|
|
var live_index_options := page.get("_index_options") as Dictionary
|
|
live_index_options["holding"] = LogbookCatalog.HoldingFilter.IN_COOLER
|
|
page.call("_refresh_catalog")
|
|
await process_frame
|
|
assert(
|
|
(page.get("_entry_buttons") as Dictionary).keys()
|
|
== [&"bluegill"]
|
|
)
|
|
inventory.remove_catch_by_id(fish_catch.catch_id)
|
|
await process_frame
|
|
assert((page.get("_entry_buttons") as Dictionary).is_empty())
|
|
page.call("_reset_index")
|
|
await process_frame
|
|
assert(not _detail_text(page).contains("number owned"))
|
|
page.queue_free()
|
|
collection.queue_free()
|
|
inventory.queue_free()
|
|
|
|
|
|
func _detail_text(page: LogbookPage) -> String:
|
|
var values: PackedStringArray = []
|
|
var detail_body := page.get("_detail_body") as VBoxContainer
|
|
for node: Node in detail_body.find_children("*", "Label", true, false):
|
|
values.append((node as Label).text)
|
|
return "\n".join(values)
|
|
|
|
|
|
func _validate_index_content_bounds(page: LogbookPage) -> void:
|
|
var body := page.get("_index_body") as VBoxContainer
|
|
assert(body != null and body.visible)
|
|
var right_page := body.get_parent() as Control
|
|
assert(right_page != null)
|
|
var page_rect := right_page.get_global_rect()
|
|
var body_rect := body.get_global_rect()
|
|
var protected_rect := Rect2(
|
|
page_rect.position + Vector2(
|
|
LogbookPage.INDEX_CONTENT_LEFT_INSET,
|
|
LogbookPage.INDEX_CONTENT_TOP_INSET,
|
|
),
|
|
page_rect.size - Vector2(
|
|
LogbookPage.INDEX_CONTENT_LEFT_INSET
|
|
+ LogbookPage.INDEX_CONTENT_RIGHT_INSET,
|
|
LogbookPage.INDEX_CONTENT_TOP_INSET
|
|
+ LogbookPage.INDEX_CONTENT_BOTTOM_INSET,
|
|
),
|
|
)
|
|
assert(
|
|
body_rect.position.x
|
|
>= page_rect.position.x + LogbookPage.INDEX_CONTENT_LEFT_INSET - 1.0
|
|
)
|
|
assert(
|
|
body_rect.end.x
|
|
<= page_rect.end.x - LogbookPage.INDEX_CONTENT_RIGHT_INSET + 1.0
|
|
)
|
|
assert(
|
|
body_rect.position.y >= page_rect.position.y,
|
|
"Index starts above the authored page: body=%s page=%s"
|
|
% [body_rect, page_rect],
|
|
)
|
|
assert(
|
|
body_rect.end.y <= page_rect.end.y,
|
|
"Index extends below the authored page: body=%s page=%s"
|
|
% [body_rect, page_rect],
|
|
)
|
|
var controls: Array = page.get("_index_controls") as Array
|
|
for value: Variant in controls:
|
|
var control := value as Control
|
|
if control != null and control.visible:
|
|
assert(
|
|
protected_rect.grow(2.0).encloses(control.get_global_rect()),
|
|
"Index control crossed the authored right-page boundary: %s"
|
|
% control.name,
|
|
)
|
|
|
|
|
|
func _descendant_label_text(parent: Node) -> String:
|
|
var values: PackedStringArray = []
|
|
for node: Node in parent.find_children("*", "Label", true, false):
|
|
values.append((node as Label).text)
|
|
return "\n".join(values)
|
|
|
|
|
|
func _validate_overlay_fonts(parent: Node) -> void:
|
|
for node: Node in parent.find_children("*", "Label", true, false):
|
|
assert(
|
|
(node as Label).get_theme_font("font")
|
|
== UtilityPageStyle.TuffyFont
|
|
)
|
|
|
|
|
|
func _validate_detail_content_bounds(page: LogbookPage) -> void:
|
|
var detail_body := page.get("_detail_body") as VBoxContainer
|
|
var page_rect: Rect2 = (detail_body.get_parent() as Control).get_global_rect()
|
|
for node: Node in detail_body.find_children("*", "Label", true, false):
|
|
var label := node as Label
|
|
var label_rect: Rect2 = label.get_global_rect()
|
|
assert(
|
|
label_rect.position.y >= page_rect.position.y - 0.5,
|
|
"Label starts above logbook page: %s %s vs %s"
|
|
% [label.text, label_rect, page_rect],
|
|
)
|
|
assert(
|
|
label_rect.end.y <= page_rect.end.y + 0.5,
|
|
"Label ends below logbook page: %s %s vs %s"
|
|
% [label.text, label_rect, page_rect],
|
|
)
|
|
|
|
|
|
func _find_overlay_card(parent: Node) -> PanelContainer:
|
|
for node: Node in parent.find_children(
|
|
"*", "PanelContainer", true, false
|
|
):
|
|
var panel := node as PanelContainer
|
|
if panel.custom_minimum_size == LogbookPage.DETAIL_OVERLAY_CARD_SIZE:
|
|
return panel
|
|
return null
|
|
|
|
|
|
func _find_portrait(entry: Button) -> LogbookPortraitType:
|
|
var pending: Array[Node] = [entry]
|
|
while not pending.is_empty():
|
|
var node: Node = pending.pop_back()
|
|
if node is LogbookPortraitType:
|
|
return node as LogbookPortraitType
|
|
pending.append_array(node.get_children())
|
|
return null
|
|
|
|
|
|
func _has_visible_unknown_name(entry: Button) -> bool:
|
|
return _has_visible_name(entry, "???")
|
|
|
|
|
|
func _has_visible_name(entry: Button, expected_name: String) -> bool:
|
|
var pending: Array[Node] = [entry]
|
|
while not pending.is_empty():
|
|
var node: Node = pending.pop_back()
|
|
if node is Label and (node as Label).text == expected_name:
|
|
return true
|
|
pending.append_array(node.get_children())
|
|
return false
|
|
|
|
|
|
func _validate_handwritten_logbook_font(page: LogbookPage) -> void:
|
|
var detail_body := page.get("_detail_body") as VBoxContainer
|
|
for node: Node in detail_body.find_children("*", "Label", true, false):
|
|
var label := node as Label
|
|
if label.text.begins_with("quality collection"):
|
|
continue
|
|
if label.text in [
|
|
"fish facts",
|
|
"catalog number",
|
|
"rarity",
|
|
"body of water",
|
|
"time of day",
|
|
"seasons",
|
|
"weight range",
|
|
"value range",
|
|
"number caught",
|
|
]:
|
|
continue
|
|
assert(
|
|
label.get_theme_font("font")
|
|
== InventoryNotepadType.HANDWRITTEN_FONT
|
|
)
|
|
|
|
|
|
func _validate_detail_field_fonts(page: LogbookPage) -> void:
|
|
var detail_body := page.get("_detail_body") as VBoxContainer
|
|
var field_names: Array[String] = [
|
|
"fish facts",
|
|
"catalog number",
|
|
"rarity",
|
|
"body of water",
|
|
"time of day",
|
|
"seasons",
|
|
"weight range",
|
|
"value range",
|
|
"number caught",
|
|
]
|
|
for node: Node in detail_body.find_children("*", "Label", true, false):
|
|
var label := node as Label
|
|
if label.text.begins_with("quality collection"):
|
|
assert(label.get_theme_font("font") == UtilityPageStyle.TuffyFont)
|
|
continue
|
|
if label.text not in field_names:
|
|
continue
|
|
assert(label.get_theme_font("font") == UtilityPageStyle.TuffyFont)
|
|
if label.text != "fish facts":
|
|
assert(
|
|
label.horizontal_alignment
|
|
== HORIZONTAL_ALIGNMENT_CENTER
|
|
)
|
|
|
|
|
|
func _validate_handwritten_numeric_scale(page: LogbookPage) -> void:
|
|
var detail_body := page.get("_detail_body") as VBoxContainer
|
|
var text_value: Label
|
|
var numeric_value: Label
|
|
for node: Node in detail_body.find_children("*", "Label", true, false):
|
|
var label := node as Label
|
|
if label.text == "common":
|
|
text_value = label
|
|
elif label.text.begins_with("#"):
|
|
numeric_value = label
|
|
assert(text_value != null)
|
|
assert(numeric_value != null)
|
|
assert(
|
|
numeric_value.get_theme_font_size("font_size")
|
|
< text_value.get_theme_font_size("font_size")
|
|
)
|
|
|
|
|
|
func _validate_entry_bubble_styles(entry: Button) -> void:
|
|
var normal := entry.get_theme_stylebox("normal") as StyleBoxFlat
|
|
var hover := entry.get_theme_stylebox("hover") as StyleBoxFlat
|
|
var pressed := entry.get_theme_stylebox("pressed") as StyleBoxFlat
|
|
assert(normal != null)
|
|
assert(hover != null)
|
|
assert(pressed != null)
|
|
assert(is_zero_approx(normal.bg_color.a))
|
|
assert(hover.bg_color.a > 0.0)
|
|
assert(pressed.bg_color.a > 0.0)
|
|
assert(hover.border_width_left == 0)
|
|
assert(pressed.border_width_left == 0)
|
|
assert(hover.corner_radius_top_left == 51)
|
|
|
|
|
|
func _texture_has_transparency(texture: Texture2D) -> bool:
|
|
var image: Image = texture.get_image()
|
|
return image != null and image.detect_alpha() != Image.ALPHA_NONE
|