From 414ad4eeda33825c82adef200e88501c1715e877 Mon Sep 17 00:00:00 2001 From: Nordup Date: Sun, 29 Jun 2025 01:26:39 +0700 Subject: [PATCH] gate icon and undiscoverable mode --- app/scenes/app.tscn | 2 +- app/scenes/components/bookmark.tscn | 6 ++--- app/scenes/components/result.tscn | 8 +++--- app/scripts/api/discover_gate.gd | 5 ++++ app/scripts/api/featured_gates.gd | 4 +-- app/scripts/bookmark_saver.gd | 36 +++++++++++++------------- app/scripts/loading/config_base.gd | 4 +-- app/scripts/loading/config_gate.gd | 19 +++++++++++--- app/scripts/loading/gate_loader.gd | 20 +++++++++++++- app/scripts/resources/bookmarks.gd | 6 ++--- app/scripts/resources/gate.gd | 13 +++++++--- app/scripts/resources/gate_events.gd | 5 ++++ app/scripts/ui/hint.gd | 4 +-- app/scripts/ui/menu/bookmark_ui.gd | 4 +-- app/scripts/ui/menu/menu.gd | 3 +-- app/scripts/ui/menu/star.gd | 1 + app/scripts/ui/search/result.gd | 19 +++++++++----- app/scripts/ui/world/loading_status.gd | 1 + 18 files changed, 108 insertions(+), 52 deletions(-) diff --git a/app/scenes/app.tscn b/app/scenes/app.tscn index 72fa964..37d4a9f 100644 --- a/app/scenes/app.tscn +++ b/app/scenes/app.tscn @@ -34,7 +34,7 @@ visible = false [node name="BookmarkSaver" type="Node" parent="."] script = ExtResource("5_ev0ch") save_dir = "user://resources" -image_save_dir = "user://images" +icon_save_dir = "user://icons" bookmarks = ExtResource("6_rupvx") [node name="Api" type="Node" parent="."] diff --git a/app/scenes/components/bookmark.tscn b/app/scenes/components/bookmark.tscn index 5873bd1..5e1f787 100644 --- a/app/scenes/components/bookmark.tscn +++ b/app/scenes/components/bookmark.tscn @@ -31,7 +31,7 @@ corner_radius_top_right = 20 corner_radius_bottom_right = 20 corner_radius_bottom_left = 20 -[node name="Bookmark" type="Control" node_paths=PackedStringArray("image", "title", "button", "button_special")] +[node name="Bookmark" type="Control" node_paths=PackedStringArray("icon", "title", "button", "button_special")] clip_children = 1 custom_minimum_size = Vector2(180, 100) layout_mode = 3 @@ -40,7 +40,7 @@ offset_right = 180.0 offset_bottom = 100.0 script = ExtResource("1_bpkqj") gate_events = ExtResource("2_7i5yr") -image = NodePath("Mask/Image") +icon = NodePath("Mask/Icon") title = NodePath("Title") button = NodePath("Button") button_special = NodePath("ButtonSpecial") @@ -86,7 +86,7 @@ grow_horizontal = 2 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_od0ga") -[node name="Image" type="TextureRect" parent="Mask"] +[node name="Icon" type="TextureRect" parent="Mask"] custom_minimum_size = Vector2(87, 87) layout_mode = 1 anchors_preset = 15 diff --git a/app/scenes/components/result.tscn b/app/scenes/components/result.tscn index ce0ac7f..886a794 100644 --- a/app/scenes/components/result.tscn +++ b/app/scenes/components/result.tscn @@ -28,7 +28,7 @@ font = ExtResource("4_tevcf") font_size = 15 font_color = Color(0.431373, 0.435294, 0.494118, 1) -[node name="Result" type="Button" node_paths=PackedStringArray("url", "title", "description", "image")] +[node name="Result" type="Button" node_paths=PackedStringArray("url", "title", "description", "icon")] custom_minimum_size = Vector2(850, 100) offset_bottom = 100.0 mouse_default_cursor_shape = 2 @@ -36,12 +36,14 @@ theme_override_styles/focus = ExtResource("1_bqxb5") theme_override_styles/hover = ExtResource("1_bqxb5") theme_override_styles/pressed = ExtResource("1_bqxb5") theme_override_styles/normal = ExtResource("2_agglm") +icon = Object(TextureRect,"_import_path":NodePath(""),"unique_name_in_owner":false,"process_mode":0,"process_priority":0,"process_physics_priority":0,"process_thread_group":0,"physics_interpolation_mode":2,"auto_translate_mode":0,"editor_description":"","visible":true,"modulate":Color(1, 1, 1, 1),"self_modulate":Color(1, 1, 1, 1),"show_behind_parent":false,"top_level":false,"clip_children":0,"light_mask":1,"visibility_layer":1,"z_index":0,"z_as_relative":true,"y_sort_enabled":false,"texture_filter":0,"texture_repeat":0,"material":null,"use_parent_material":false,"clip_contents":false,"custom_minimum_size":Vector2(87, 87),"layout_direction":0,"layout_mode":1,"anchors_preset":15,"anchor_left":0.0,"anchor_top":0.0,"anchor_right":1.0,"anchor_bottom":1.0,"offset_left":0.0,"offset_top":0.0,"offset_right":0.0,"offset_bottom":0.0,"grow_horizontal":2,"grow_vertical":2,"rotation":0.0,"scale":Vector2(1, 1),"pivot_offset":Vector2(0, 0),"size_flags_horizontal":4,"size_flags_vertical":4,"size_flags_stretch_ratio":1.0,"localize_numeral_system":true,"tooltip_text":"","focus_neighbor_left":NodePath(""),"focus_neighbor_top":NodePath(""),"focus_neighbor_right":NodePath(""),"focus_neighbor_bottom":NodePath(""),"focus_next":NodePath(""),"focus_previous":NodePath(""),"focus_mode":0,"mouse_filter":1,"mouse_force_pass_scroll_events":true,"mouse_default_cursor_shape":0,"shortcut_context":null,"theme":null,"theme_type_variation":&"","texture":ExtResource("5_a6pb2"),"expand_mode":1,"stretch_mode":5,"flip_h":false,"flip_v":false,"script":null) + script = ExtResource("1_b6nfm") gate_events = ExtResource("2_wgd6i") url = NodePath("VBoxContainer/Url") title = NodePath("VBoxContainer/Title") description = NodePath("VBoxContainer/Description") -image = NodePath("Mask/Image") +icon = NodePath("Mask/Icon") [node name="Mask" type="Panel" parent="."] clip_children = 1 @@ -56,7 +58,7 @@ size_flags_vertical = 4 mouse_filter = 1 theme_override_styles/panel = SubResource("StyleBoxFlat_6os7t") -[node name="Image" type="TextureRect" parent="Mask"] +[node name="Icon" type="TextureRect" parent="Mask"] custom_minimum_size = Vector2(87, 87) layout_mode = 1 anchors_preset = 15 diff --git a/app/scripts/api/discover_gate.gd b/app/scripts/api/discover_gate.gd index d34829d..c419d5c 100644 --- a/app/scripts/api/discover_gate.gd +++ b/app/scripts/api/discover_gate.gd @@ -9,10 +9,15 @@ func _ready() -> void: func send_discover_gate(c_url: String, c_gate: ConfigGate) -> void: + if not c_gate.discoverable: + Debug.logclr("Gate is not discoverable", Color.DIM_GRAY) + return + var body = {} body.url = c_url body.title = c_gate.title body.description = c_gate.description + body.icon = c_gate.icon_url body.image = c_gate.image_url body.resource_pack = c_gate.resource_pack_url body.libraries = c_gate.libraries diff --git a/app/scripts/api/featured_gates.gd b/app/scripts/api/featured_gates.gd index 775722c..f664167 100644 --- a/app/scripts/api/featured_gates.gd +++ b/app/scripts/api/featured_gates.gd @@ -38,7 +38,7 @@ func featured_gates_request() -> void: func star_gate(gate_d: Dictionary) -> void: - var image_path = await FileDownloader.download(gate_d["image"]) - var gate = Gate.create(gate_d["url"], gate_d["title"], gate_d["description"], image_path, "", "") + var icon_path = await FileDownloader.download(gate_d["icon"]) + var gate = Gate.create(gate_d["url"], gate_d["title"], gate_d["description"], icon_path, "", "", "") bookmarks.star(gate, true) diff --git a/app/scripts/bookmark_saver.gd b/app/scripts/bookmark_saver.gd index 7fdf117..94bffea 100644 --- a/app/scripts/bookmark_saver.gd +++ b/app/scripts/bookmark_saver.gd @@ -1,7 +1,7 @@ extends Node @export_dir var save_dir: String -@export_dir var image_save_dir: String +@export_dir var icon_save_dir: String @export var bookmarks: Bookmarks @onready var path = save_dir + "/" + bookmarks.resource_path.get_file() @@ -11,7 +11,7 @@ func _ready() -> void: load_bookmarks() bookmarks.ready() - bookmarks.save_image.connect(save_image) + bookmarks.save_icon.connect(save_icon) bookmarks.on_star.connect(func(_gate, _featured): save_bookmarks()) bookmarks.on_unstar.connect(func(_gate): save_bookmarks()) bookmarks.on_update.connect(func(_gate): save_bookmarks()) @@ -32,29 +32,29 @@ func save_bookmarks() -> void: ResourceSaver.save(bookmarks, path) -func save_image(gate: Gate) -> void: - if not FileAccess.file_exists(gate.image): return - if not DirAccess.dir_exists_absolute(image_save_dir): - DirAccess.make_dir_recursive_absolute(image_save_dir) +func save_icon(gate: Gate) -> void: + if not FileAccess.file_exists(gate.icon): return + if not DirAccess.dir_exists_absolute(icon_save_dir): + DirAccess.make_dir_recursive_absolute(icon_save_dir) - var new_path = image_save_dir + "/" + gate.image.get_file() - if new_path == gate.image: return - DirAccess.copy_absolute(gate.image, new_path) - gate.image = new_path + var new_path = icon_save_dir + "/" + gate.icon.get_file() + if new_path == gate.icon: return + DirAccess.copy_absolute(gate.icon, new_path) + gate.icon = new_path -func clear_image_folder() -> void: - if not DirAccess.dir_exists_absolute(image_save_dir): return +func clear_icon_folder() -> void: + if not DirAccess.dir_exists_absolute(icon_save_dir): return - var used_images: Array[String] = [] + var used_icons: Array[String] = [] for gate in bookmarks.gates.values(): - used_images.append(gate.image.get_file()) + used_icons.append(gate.icon.get_file()) - for file in DirAccess.get_files_at(image_save_dir): - if not file in used_images: - DirAccess.remove_absolute(image_save_dir + "/" + file) + for file in DirAccess.get_files_at(icon_save_dir): + if not file in used_icons: + DirAccess.remove_absolute(icon_save_dir + "/" + file) func _exit_tree() -> void: save_bookmarks() - clear_image_folder() + clear_icon_folder() diff --git a/app/scripts/loading/config_base.gd b/app/scripts/loading/config_base.gd index 271f2e9..e696b88 100644 --- a/app/scripts/loading/config_base.gd +++ b/app/scripts/loading/config_base.gd @@ -21,8 +21,8 @@ func get_string(section: String, key: String) -> String: return value -func get_value(section: String, key: String) -> Variant: - var value: Variant +func get_value(section: String, key: String, default: Variant = null) -> Variant: + var value: Variant = default if config.has_section_key(section, key): value = config.get_value(section, key) # Debug.logr(key + "=" + str(value)) diff --git a/app/scripts/loading/config_gate.gd b/app/scripts/loading/config_gate.gd index 08ad854..22d07a7 100644 --- a/app/scripts/loading/config_gate.gd +++ b/app/scripts/loading/config_gate.gd @@ -3,19 +3,30 @@ class_name ConfigGate const SECTION = "gate" +const KEY_TITLE = "title" +const KEY_DESCRIPTION = "description" +const KEY_ICON = "icon" +const KEY_IMAGE = "image" +const KEY_RESOURCE_PACK = "resource_pack" +const KEY_DISCOVERABLE = "discoverable" + var title: String var description: String +var icon_url: String var image_url: String var resource_pack_url: String +var discoverable: bool var libraries: PackedStringArray func _init(path: String, base_url: String) -> void: super._init(path) - title = get_string(SECTION, "title") - description = get_string(SECTION, "description") - image_url = Url.join(base_url, get_string(SECTION, "image")) - resource_pack_url = Url.join(base_url, get_string(SECTION, "resource_pack")) + title = get_string(SECTION, KEY_TITLE) + description = get_string(SECTION, KEY_DESCRIPTION) + icon_url = Url.join(base_url, get_string(SECTION, KEY_ICON)) + image_url = Url.join(base_url, get_string(SECTION, KEY_IMAGE)) + resource_pack_url = Url.join(base_url, get_string(SECTION, KEY_RESOURCE_PACK)) + discoverable = get_value(SECTION, KEY_DISCOVERABLE, true) libraries = get_libraries(base_url) diff --git a/app/scripts/loading/gate_loader.gd b/app/scripts/loading/gate_loader.gd index f5f22d5..d594426 100644 --- a/app/scripts/loading/gate_loader.gd +++ b/app/scripts/loading/gate_loader.gd @@ -11,6 +11,10 @@ var load_resources_done: bool var shared_libs_count: int = -1 var shared_libs_done: int +# Show progress when resource pack is started loading +var resource_pack_url: String +var resource_pack_started_loading: bool + func _ready() -> void: FileDownloader.progress.connect(on_progress) @@ -26,15 +30,22 @@ func load_gate(config_url: String) -> void: if c_gate.load_result != OK: return error(GateEvents.GateError.INVALID_CONFIG) gate_events.gate_config_loaded_emit(config_url, c_gate) - gate = Gate.create(config_url, c_gate.title, c_gate.description, "", "", "") + gate = Gate.create(config_url, c_gate.title, c_gate.description, "", "", "", "") gate_events.gate_info_loaded_emit(gate) # Download all in parallel + load_icon(c_gate) load_image(c_gate) load_resources(c_gate) load_shared_libs(c_gate, config_url) +func load_icon(c_gate: ConfigGate) -> void: + gate.icon = await FileDownloader.download(c_gate.icon_url) + gate_events.gate_icon_loaded_emit(gate) + # Finish without icon + + func load_image(c_gate: ConfigGate) -> void: gate.image = await FileDownloader.download(c_gate.image_url) gate_events.gate_image_loaded_emit(gate) @@ -42,6 +53,7 @@ func load_image(c_gate: ConfigGate) -> void: func load_resources(c_gate: ConfigGate) -> void: + resource_pack_url = c_gate.resource_pack_url gate.resource_pack = await FileDownloader.download(c_gate.resource_pack_url) if gate.resource_pack.is_empty(): return error(GateEvents.GateError.MISSING_PACK) @@ -81,6 +93,12 @@ func error(code: GateEvents.GateError) -> void: func on_progress(url: String, body_size: int, downloaded_bytes: int) -> void: + if url == resource_pack_url and not resource_pack_started_loading and body_size > 0: + resource_pack_started_loading = true + + if not resource_pack_started_loading: + return + gate_events.download_progress_emit(url, body_size, downloaded_bytes) diff --git a/app/scripts/resources/bookmarks.gd b/app/scripts/resources/bookmarks.gd index 6dd091e..248c143 100644 --- a/app/scripts/resources/bookmarks.gd +++ b/app/scripts/resources/bookmarks.gd @@ -5,7 +5,7 @@ signal on_ready() signal on_star(gate: Gate, featured: bool) signal on_unstar(gate: Gate) signal on_update(gate: Gate) -signal save_image(gate: Gate) +signal save_icon(gate: Gate) @export var starred_gates: Array[Gate] @@ -34,7 +34,7 @@ func update(gate: Gate) -> void: starred_gates.erase(replace) starred_gates.append(gate) - save_image.emit(gate) + save_icon.emit(gate) on_update.emit(gate) @@ -44,7 +44,7 @@ func star(gate: Gate, featured: bool = false) -> void: gates[gate.url] = gate starred_gates.append(gate) - save_image.emit(gate) + save_icon.emit(gate) on_star.emit(gate, featured) diff --git a/app/scripts/resources/gate.gd b/app/scripts/resources/gate.gd index 100f694..fde5d34 100644 --- a/app/scripts/resources/gate.gd +++ b/app/scripts/resources/gate.gd @@ -5,20 +5,27 @@ class_name Gate set(value): url = Url.fix_gate_url(value) @export var title: String + @export var description: String + +@export_file("*.png", "*.jpg") var icon: String: + get: return icon if not icon.is_empty() else image + set(value): icon = value + @export_file("*.png", "*.jpg") var image: String + var resource_pack: String -# local path where libs downloaded -var shared_libs_dir: String +var shared_libs_dir: String # local path where libs downloaded -static func create(_url: String, _title: String, _description: String, +static func create(_url: String, _title: String, _description: String, _icon: String, _image: String, _resource_pack: String, _shared_libs_dir: String) -> Gate: var gate = Gate.new() gate.url = _url gate.title = _title gate.description = _description + gate.icon = _icon gate.image = _image gate.resource_pack = _resource_pack gate.shared_libs_dir = _shared_libs_dir diff --git a/app/scripts/resources/gate_events.gd b/app/scripts/resources/gate_events.gd index fb34586..656c730 100644 --- a/app/scripts/resources/gate_events.gd +++ b/app/scripts/resources/gate_events.gd @@ -5,6 +5,7 @@ signal search(query: String) signal open_gate(url: String) signal gate_config_loaded(url: String, config: ConfigGate) signal gate_info_loaded(gate: Gate) +signal gate_icon_loaded(gate: Gate) # might be empty icon signal gate_image_loaded(gate: Gate) # might be empty image signal gate_loaded(gate: Gate) signal gate_entered @@ -51,6 +52,10 @@ func gate_info_loaded_emit(gate: Gate) -> void: gate_info_loaded.emit(gate) +func gate_icon_loaded_emit(gate: Gate) -> void: + gate_icon_loaded.emit(gate) + + func gate_image_loaded_emit(gate: Gate) -> void: gate_image_loaded.emit(gate) diff --git a/app/scripts/ui/hint.gd b/app/scripts/ui/hint.gd index 7a2e2d6..a031e02 100644 --- a/app/scripts/ui/hint.gd +++ b/app/scripts/ui/hint.gd @@ -8,8 +8,8 @@ extends Control func _ready() -> void: visible = false if key.is_empty() or button == null: Debug.logerr("hint has empty vars") - var first = DataSaver.get_value(section, key) - if first == null or not first: show_hint() + var is_shown = DataSaver.get_value(section, key, false) + if not is_shown: show_hint() func _notification(what: int) -> void: diff --git a/app/scripts/ui/menu/bookmark_ui.gd b/app/scripts/ui/menu/bookmark_ui.gd index a231146..11aba17 100644 --- a/app/scripts/ui/menu/bookmark_ui.gd +++ b/app/scripts/ui/menu/bookmark_ui.gd @@ -2,7 +2,7 @@ extends Control class_name BookmarkUI @export var gate_events: GateEvents -@export var image: TextureRect +@export var icon: TextureRect @export var title: Label @export var button: Button @export var button_special: Button @@ -23,7 +23,7 @@ func fill(gate: Gate, special: bool = false) -> void: url = gate.url title.text = "Unnamed" if gate.title.is_empty() else gate.title - image.texture = FileTools.load_external_tex(gate.image) + icon.texture = FileTools.load_external_tex(gate.icon) func on_pressed() -> void: diff --git a/app/scripts/ui/menu/menu.gd b/app/scripts/ui/menu/menu.gd index f823a91..df68432 100644 --- a/app/scripts/ui/menu/menu.gd +++ b/app/scripts/ui/menu/menu.gd @@ -29,8 +29,7 @@ func scale_content() -> void: func set_initial_screen() -> void: - var last_screen = DataSaver.get_value("settings", "last_screen") - if last_screen == null: last_screen = 0 + var last_screen = DataSaver.get_value("settings", "last_screen", 0) DisplayServer.window_set_current_screen(last_screen) Debug.logclr("Initial screen: %d" % [last_screen], Debug.SILENT_CLR) diff --git a/app/scripts/ui/menu/star.gd b/app/scripts/ui/menu/star.gd index ce88e9f..ab9a5cf 100644 --- a/app/scripts/ui/menu/star.gd +++ b/app/scripts/ui/menu/star.gd @@ -18,6 +18,7 @@ func _ready() -> void: gate_events.search.connect(func(_query): hide_buttons()) gate_events.exit_gate.connect(hide_buttons) gate_events.gate_info_loaded.connect(update_info) + gate_events.gate_icon_loaded.connect(update_info) gate_events.gate_image_loaded.connect(update_info) diff --git a/app/scripts/ui/search/result.gd b/app/scripts/ui/search/result.gd index 4ecab3d..bdb227a 100644 --- a/app/scripts/ui/search/result.gd +++ b/app/scripts/ui/search/result.gd @@ -1,23 +1,30 @@ extends Control class_name SearchResult +const KEY_URL = "url" +const KEY_TITLE = "title" +const KEY_DESCRIPTION = "description" +const KEY_ICON = "icon" +const KEY_IMAGE = "image" + @export var gate_events: GateEvents @export var url: Label @export var title: Label @export var description: RichTextLabel -@export var image: TextureRect +@export var icon: TextureRect func fill(gate: Dictionary) -> void: if gate == null: return - url.text = gate["url"] - title.text = "Unnamed" if gate["title"].is_empty() else gate["title"] - description.text = gate["description"] + url.text = gate[KEY_URL] + title.text = "Unnamed" if gate[KEY_TITLE].is_empty() else gate[KEY_TITLE] + description.text = gate[KEY_DESCRIPTION] - var image_path = await FileDownloader.download(gate["image"]) - image.texture = FileTools.load_external_tex(image_path) + var icon_url = gate[KEY_ICON] if not gate[KEY_ICON].is_empty() else gate[KEY_IMAGE] + var icon_path = await FileDownloader.download(icon_url) + icon.texture = FileTools.load_external_tex(icon_path) func _on_button_pressed() -> void: diff --git a/app/scripts/ui/world/loading_status.gd b/app/scripts/ui/world/loading_status.gd index be430ad..dc0f3f8 100644 --- a/app/scripts/ui/world/loading_status.gd +++ b/app/scripts/ui/world/loading_status.gd @@ -115,6 +115,7 @@ func on_gate_entered() -> void: func on_gate_error(code: GateEvents.GateError) -> void: + gate_events.download_progress.disconnect(show_progress) match code: GateEvents.GateError.NOT_FOUND: set_progress("Gate not found", ProgressStatus.ERROR)