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 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" ) func _initialize() -> void: call_deferred("_run") func _run() -> void: if OS.has_environment("NETFISHING_TEST_CREATE_ROOT"): var data_root := PlayerDataRoot.new() root.add_child(data_root) var result: Dictionary = data_root.create_unbound_root( OS.get_environment("NETFISHING_TEST_CREATE_ROOT") ) assert(bool(result.get("ok", false))) data_root.queue_free() print("Logbook portable test root: PASS") quit() return _validate_catalog() await _validate_page() print("Logbook validation: PASS") quit() func _validate_catalog() -> void: var expected_ids: Array[StringName] = [ &"bluegill", &"bass", &"carp", &"sunfish", &"catfish_blue", &"catfish_channel", &"catfish_flathead", &"catfish_white", ] assert(LogbookCatalog.CATALOG_ORDER == expected_ids) for index: int in expected_ids.size(): var fish := CatalogResource.get_fish_by_id(expected_ids[index]) assert(fish != null) assert(LogbookCatalog.facts_for(fish.id) != "unknown") assert(not LogbookCatalog.facts_for(fish.id).is_empty()) assert( LogbookCatalog.facts_for(fish.id) == LogbookCatalog.facts_for(fish.id).to_lower() ) var expected_category: WaterType.Type = ( WaterType.Type.SALT_WATER if expected_ids[index] in [&"bass", &"sunfish"] else WaterType.Type.FRESH_WATER ) assert( LogbookCatalog.category_for(fish) == expected_category ) assert(LogbookCatalog.catalog_number(fish.id) == index + 1) assert( LogbookCatalog.empty_state(WaterType.Type.SALT_WATER) == "No saltwater catches cataloged yet." ) 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) await process_frame page.setup(collection, inventory, CatalogResource) page.activate() await process_frame assert(page.get("_category") == WaterType.Type.FRESH_WATER) assert((page.get("_catalog_grid") as GridContainer).columns == 5) var initial_detail_body := page.get("_detail_body") as VBoxContainer assert(not initial_detail_body.get_parent() is ScrollContainer) assert( page.call("_entry_label_text", "flathead catfish") == "flathead\ncatfish" ) var shared_material: Material var silhouette_count: int = 0 for category: WaterType.Type in [ WaterType.Type.FRESH_WATER, WaterType.Type.SALT_WATER, ]: page.call("_select_category", category) await create_timer(0.25).timeout var entries: Dictionary = page.get("_entry_buttons") assert(entries.size() == (6 if category == WaterType.Type.FRESH_WATER else 2)) 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.id) ) 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 == LogbookPortraitType.ENTRY_FRAME_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)) 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 == 8) page.call("_select_category", WaterType.Type.OTHER) await create_timer(0.25).timeout assert((page.get("_entry_buttons") as Dictionary).is_empty()) assert( (page.get("_empty_state") as Label).text == "No entries available." ) page.call("_select_category", WaterType.Type.FRESH_WATER) await create_timer(0.25).timeout var bluegill = CatalogResource.get_fish_by_id(&"bluegill") page.call("_select_entry", &"unknown_1", StringName()) assert( (page.get("_entry_buttons") as Dictionary) .get(&"unknown_1") != null ) collection.mark_discovered(&"bluegill") 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.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) page.call("_select_entry", &"bluegill", &"bluegill") await process_frame assert(_detail_text(page).contains("number owned\n1")) assert(_detail_text(page).contains("number caught\nunknown")) assert(_detail_text(page).contains("body of water\nfresh water")) assert(_detail_text(page).contains("catalog number\n#001")) 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) 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 <= 860.0 and overlay_artwork.custom_minimum_size.y <= 480.0 ) (page.get("_portrait_overlay_backdrop") as Button).pressed.emit() await process_frame assert(not portrait_overlay.visible) inventory.remove_catch_by_id(fish_catch.catch_id) await process_frame assert(_detail_text(page).contains("number owned\n0")) 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 _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 in [ "fish facts", "catalog number", "rarity", "body of water", "time of day", "weight range", "value range", "number caught", "number owned", ]: 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", "weight range", "value range", "number caught", "number owned", ] for node: Node in detail_body.find_children("*", "Label", true, false): var label := node as Label 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 == "#001": 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