From c1d8b5d3fde6cf270e11b722348eb4fcb5daab15 Mon Sep 17 00:00:00 2001 From: Luke Hubmayer-Werner Date: Wed, 2 Aug 2023 13:33:37 +0930 Subject: [PATCH] Improve ROM selection menu Add greyed out buttons for deeper paths you just came up from Fix edge cases with root path Make .bin files show as a binary icon until identified as a valid CD image, then cache the filename for future visits in this session --- theme/ThemeElements.png | Bin 816 -> 775 bytes theme/icon_binary.tres | 7 ++ widgets/RomSelect.gd | 122 ++++++++++++++++++++++++-------- widgets/RomSelect.tscn | 150 ++++++++++++++++++++++++++++++++-------- 4 files changed, 219 insertions(+), 60 deletions(-) create mode 100644 theme/icon_binary.tres diff --git a/theme/ThemeElements.png b/theme/ThemeElements.png index 9cc03bf421e5ab2dfa88bf3c977d90bfe45409d6..483f06d4ef12603313d50b7461251721d0f1bd0f 100644 GIT binary patch delta 752 zcmVZH~|usFF%F>mO43`D${Q3?|48q3k%aPSzvwHBJIT&I(qoY zvg?G$2!28bM(~73ZLNP6V2J4}L$`&+=>Qd;%VRpw&%QimjIZy{=)e>MYfH#Z=IWx@7~ZABfnz^2KT!<3!I7zb`B zp-PVzqAF-S-`;>SilM zOQm?qr8P;Z0?%-u^`%m*4iNd*@;fn+__{^I>xrpIKCx8}R(^c*a}Oa~l#=EIC++aP zo51<3*?+^&ixIkJBeF549i^G)Txby>@(Knf$MZZm!;EyyQ?hE?Iih;_bx?c@giEF1 zASngftf$X~M|XzbXyrI5UC07|gH-$9R;!?$xN~Fy6QsxY2=RAV;I8zj%ZS=8`YtC) z#?7*=RKk&XFV6{c89c4mfy1+5%kiGyE@`8YuxXrCf}s$VpRK~RbIfo34^F-9=u+Z@ z6t|uC9mn8}Y~Q+2bylzGNJ~wyX=)kUs`XnYypRuQ?Cb!yjX2)(o4f0^_S)_0ru+&B iJ;#>P@MyDtt^5J;kt09`OlMgD0000INqhB$jym62c3JQk!FTAu2%hk$wfbuVhM4|k>b7Kd zIzW}@e47sRtFOJ3@%Fq&2c{TUTUuW2COIX@&K*KzVvMLQ&wx-yr5+x4(J*rgku6Jf zrdz*(RbsHOi-6)tu%r0e@H%$n&rMsc6ZQJ3qzFX=8-KHc>Ayz$|mfYHJQz3%m#6 z2_cI0R+v6z!FI*5A`WX{)8xp>RGh{r2TmxVNRJmH6SO=(-mg=_SZ|f_T|yGFAD?u^ zv+ka>+&i;W2_yYvt7xSb`i)Lij29~*5p%5VJq9wj7*NYKF2wd`dm{ppro29@gm2EN zHA?8)@_)^RO6cDY&F#fGVS;yau@sALwnDU2il?<+SH3|%xOny=I>G1p5FQ$jr`2os$*eOUfOm6Q6C23Lrf#*K%4dS zx$s#QjFZxZEbuo-HvVE3)Yo$|kne`)9^WIxpMPb69^_p{)DF=PIY}~3mTk2XYL4;H zJz+wrlc)7MaQJTc{xoz+8;ykJQzaM*QT^E}Tsz17*8kwt+m0?JK9J&e@P6PJypio& z7ffg6nvSGcf=yG)*k;ymneae9AhFXIxNXGop5M8 String: if n > 0x100000000: @@ -26,6 +47,13 @@ static func get_human_size(n: int) -> String: return '%.1f KiB' % (n/float(0x400)) return '%d B' % n +static func tokenize_path(path: String) -> PoolStringArray: + return path.rstrip('/').split('/', true) # Allow empty means '/' will return [''] + +static func join_path(tokens) -> String: + var path = '/'.join(tokens) + return path if path else '/' + func update_view(): var error = dir.list_dir_begin(true, true) if error != OK: @@ -35,44 +63,59 @@ func update_view(): for child in folder_buttons.get_children(): child.queue_free() var path = ProjectSettings.globalize_path(dir.get_current_dir()) - var cur_path: Array = path.split('/') + var cur_path: Array = tokenize_path(path) var l := len(cur_path) for i in l: - var subpath = '/'.join(cur_path.slice(0, i)) var btn := Button.new() - btn.connect('pressed', self, 'activate_entry', [subpath]) + btn.connect('pressed', self, 'activate_entry', [join_path(cur_path.slice(0, i))]) btn.text = cur_path[i] folder_buttons.add_child(btn) if i == 0: btn.text += '/' if i == l-1: - btn.icon = folder_icon - folder_buttons_scroller.set_h_scroll(9999) - folder_buttons_scroller.ensure_control_visible(folder_buttons_scroller.get_h_scrollbar()) - folder_buttons_scroller.get_h_scrollbar().update() + btn.icon = FOLDER_ICON + if last_dir.begins_with(path): # i.e. we jumped up a level or more + var last_path: Array = tokenize_path(last_dir) + var l2 := len(last_path) + for i in range(l, l2): + var btn := Button.new() + btn.connect('pressed', self, 'activate_entry', [join_path(last_path.slice(0, i))]) + btn.text = last_path[i] + btn.modulate = inactive_modulate_color + folder_buttons.add_child(btn) + # Doesn't work thanks to frame delay + # folder_buttons_scroller.set_h_scroll(9999) + # folder_buttons_scroller.ensure_control_visible(folder_buttons_scroller.get_h_scrollbar()) + # folder_buttons_scroller.get_h_scrollbar().update() itemlist.clear() var directories := PoolStringArray() + var current_dir := dir.get_current_dir() var files := [] while true: var entry := dir.get_next() if len(entry) == 0: break - if dir.current_is_dir(): + var filename := current_dir + '/' + entry + if filename in cached_cd_bin_paths: + files.append([entry, EXT_ICONS.iso]) + elif dir.current_is_dir(): directories.append(entry) elif '.' in entry: var extension = entry.rsplit('.', true, 1)[1] - if extension in allowed_exts: - files.append([entry, ext_icons.get(extension)]) + if extension in ALLOWED_EXTS: + files.append([entry, EXT_ICONS.get(extension)]) directories.sort() files.sort() for entry in directories: - itemlist.add_item(entry, folder_icon) + itemlist.add_item(entry, FOLDER_ICON) for entry in files: itemlist.add_item(entry[0], entry[1]) - # itemlist.sort_items_by_text() -func activate_entry(entry: String): +func activate_entry(entry: String, _index: int = -1): + var curr_dir := dir.get_current_dir() + if not self.last_dir.begins_with(curr_dir): + self.last_dir = curr_dir if dir.dir_exists(entry): var error := dir.change_dir(entry) if error == OK: @@ -82,21 +125,26 @@ func activate_entry(entry: String): elif dir.file_exists(entry): pass # Load the file -func view_entry(entry: String): +func view_entry(entry: String, index: int = -1): + init_labels() + lbl_filename_header.modulate = active_modulate_color + lbl_filename_content.text = entry + lbl_filetype_header.modulate = active_modulate_color if dir.dir_exists(entry): - file_info.text = 'Filename:\n %s/\nType: Folder' % entry + lbl_filetype_content.text = 'Folder' elif dir.file_exists(entry): var file := File.new() - var error := file.open(dir.get_current_dir() + '/' + entry, File.READ) + var filename := dir.get_current_dir() + '/' + entry + var error := file.open(filename, File.READ) if error != OK: print_debug(error) return var size = file.get_len() var human_size = get_human_size(size) var ext = entry.rsplit('.', true, 1)[1].to_lower() - var type = {'iso': 'CD-ROM Image', 'bin': 'Binary', 'sfc': 'SNES ROM', 'gba': 'GBA ROM', 'srm': 'SNES Savefile'}.get(ext, 'Unknown') + var type = TYPE_DESCS.get(ext, 'Unknown') var prodcode := '' - if ext in ['iso', 'bin']: + if ext in CD_EXTS: var cd := RomLoader.loader_cd_image.new(file) for key in cd.directory: var s = key.trim_prefix('./') @@ -104,11 +152,29 @@ func view_entry(entry: String): if re_match: prodcode = '%s\n %s\n %s' % [cd.pvd.system_identifier.strip_edges(), cd.pvd.volume_identifier.strip_edges(), re_match.get_string(1)] type = 'PSX CD-ROM Image' + cached_cd_bin_paths[filename] = prodcode + if index >= 0: + itemlist.set_item_icon(index, EXT_ICONS.iso) break var info = ('Info:\n %s' % prodcode) if prodcode else '' - file_info.text = 'Filename:\n %s\nType:\n %s\nSize:\n %s\n%s' % [entry, type, human_size, info] + lbl_filetype_content.text = type + lbl_filesize_header.modulate = active_modulate_color + lbl_filesize_content.text = human_size + lbl_fileinfo_header.modulate = active_modulate_color if prodcode else inactive_modulate_color + lbl_fileinfo_content.text = prodcode + +func init_labels(): + lbl_filename_header.modulate = inactive_modulate_color + lbl_filename_content.text = '' + lbl_filetype_header.modulate = inactive_modulate_color + lbl_filetype_content.text = '' + lbl_filesize_header.modulate = inactive_modulate_color + lbl_filesize_content.text = '' + lbl_fileinfo_header.modulate = inactive_modulate_color + lbl_fileinfo_content.text = '' func _ready() -> void: + init_labels() if OS.has_feature('windows'): home_path = OS.get_environment('USERPROFILE') else: @@ -120,14 +186,10 @@ func _ready() -> void: print(ProjectSettings.globalize_path('user://')) print(ProjectSettings.globalize_path(dir.get_current_dir())) -#func _process(_delta): - #vscroller.set_margin(MARGIN_TOP, 4) - #vscroller.set_margin(MARGIN_BOTTOM, -4) - func _on_ItemList_item_activated(index: int) -> void: - activate_entry(itemlist.get_item_text(index)) + activate_entry(itemlist.get_item_text(index), index) func _on_ItemList_item_selected(index: int) -> void: - view_entry(itemlist.get_item_text(index)) + view_entry(itemlist.get_item_text(index), index) diff --git a/widgets/RomSelect.tscn b/widgets/RomSelect.tscn index 8d6c47c..335e643 100644 --- a/widgets/RomSelect.tscn +++ b/widgets/RomSelect.tscn @@ -4,26 +4,27 @@ [ext_resource path="res://widgets/RomSelect.gd" type="Script" id=2] [node name="RomSelect" type="PanelContainer"] -margin_right = 8.0 -margin_bottom = 8.0 +margin_right = 480.0 +margin_bottom = 360.0 +rect_min_size = Vector2( 360, 360 ) theme = ExtResource( 1 ) script = ExtResource( 2 ) [node name="VBoxContainer" type="VBoxContainer" parent="."] margin_left = 4.0 margin_top = 4.0 -margin_right = 352.0 -margin_bottom = 225.0 +margin_right = 476.0 +margin_bottom = 356.0 custom_constants/separation = 4 [node name="Label" type="Label" parent="VBoxContainer"] -margin_right = 348.0 +margin_right = 472.0 margin_bottom = 14.0 text = "Select a ROM from your device's storage" [node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"] margin_top = 18.0 -margin_right = 348.0 +margin_right = 472.0 margin_bottom = 49.0 rect_min_size = Vector2( 0, 31 ) scroll_vertical_enabled = false @@ -33,46 +34,135 @@ custom_constants/separation = 4 [node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] margin_top = 53.0 -margin_right = 348.0 -margin_bottom = 221.0 +margin_right = 472.0 +margin_bottom = 352.0 +size_flags_vertical = 3 [node name="PanelContainer" type="PanelContainer" parent="VBoxContainer/HBoxContainer"] -margin_right = 200.0 -margin_bottom = 168.0 +margin_right = 278.0 +margin_bottom = 299.0 rect_min_size = Vector2( 200, 0 ) +size_flags_horizontal = 3 +size_flags_stretch_ratio = 1.5 [node name="ItemList" type="ItemList" parent="VBoxContainer/HBoxContainer/PanelContainer"] margin_left = 4.0 margin_top = 4.0 -margin_right = 196.0 -margin_bottom = 164.0 +margin_right = 274.0 +margin_bottom = 295.0 rect_min_size = Vector2( 120, 160 ) [node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] -margin_left = 208.0 -margin_right = 348.0 -margin_bottom = 168.0 +margin_left = 286.0 +margin_right = 472.0 +margin_bottom = 299.0 +size_flags_horizontal = 3 -[node name="file_info" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer"] -margin_right = 140.0 -margin_bottom = 138.0 +[node name="lbl_filename" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer"] +margin_right = 186.0 +margin_bottom = 14.0 +rect_min_size = Vector2( 140, 0 ) +size_flags_vertical = 1 +text = "Filename:" + +[node name="mc" type="MarginContainer" parent="VBoxContainer/HBoxContainer/VBoxContainer"] +margin_top = 22.0 +margin_right = 186.0 +margin_bottom = 36.0 +custom_constants/margin_top = 0 +custom_constants/margin_left = 24 +custom_constants/margin_bottom = 0 + +[node name="filename" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer/mc"] +margin_left = 24.0 +margin_right = 186.0 +margin_bottom = 14.0 rect_min_size = Vector2( 140, 0 ) size_flags_vertical = 3 -text = "Filename: - myfile.iso -Size: - 400 KiB -Type: - CD-ROM image +text = "Test" +autowrap = true -PLAYSTATION -SCEA_000.00" +[node name="lbl_type" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer"] +margin_top = 44.0 +margin_right = 186.0 +margin_bottom = 58.0 +rect_min_size = Vector2( 140, 0 ) +size_flags_vertical = 1 +text = "Type:" + +[node name="mc2" type="MarginContainer" parent="VBoxContainer/HBoxContainer/VBoxContainer"] +margin_top = 66.0 +margin_right = 186.0 +margin_bottom = 80.0 +custom_constants/margin_top = 0 +custom_constants/margin_left = 24 +custom_constants/margin_bottom = 0 + +[node name="filetype" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer/mc2"] +margin_left = 24.0 +margin_right = 186.0 +margin_bottom = 14.0 +rect_min_size = Vector2( 140, 0 ) +size_flags_vertical = 1 +text = "Test" +autowrap = true + +[node name="lbl_size" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer"] +margin_top = 88.0 +margin_right = 186.0 +margin_bottom = 102.0 +rect_min_size = Vector2( 140, 0 ) +size_flags_vertical = 1 +text = "Size:" + +[node name="mc3" type="MarginContainer" parent="VBoxContainer/HBoxContainer/VBoxContainer"] +margin_top = 110.0 +margin_right = 186.0 +margin_bottom = 124.0 +custom_constants/margin_top = 0 +custom_constants/margin_left = 24 +custom_constants/margin_bottom = 0 + +[node name="filesize" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer/mc3"] +margin_left = 24.0 +margin_right = 186.0 +margin_bottom = 14.0 +rect_min_size = Vector2( 140, 0 ) +size_flags_vertical = 1 +text = "Test" +autowrap = true + +[node name="lbl_info" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer"] +margin_top = 132.0 +margin_right = 186.0 +margin_bottom = 146.0 +rect_min_size = Vector2( 140, 0 ) +size_flags_vertical = 1 +text = "Info:" + +[node name="mc4" type="MarginContainer" parent="VBoxContainer/HBoxContainer/VBoxContainer"] +margin_top = 154.0 +margin_right = 186.0 +margin_bottom = 269.0 +size_flags_vertical = 3 +custom_constants/margin_top = 0 +custom_constants/margin_left = 24 +custom_constants/margin_bottom = 0 + +[node name="fileinfo" type="Label" parent="VBoxContainer/HBoxContainer/VBoxContainer/mc4"] +margin_left = 24.0 +margin_right = 186.0 +margin_bottom = 115.0 +rect_min_size = Vector2( 140, 0 ) +size_flags_vertical = 3 +text = "Test" +autowrap = true [node name="btn_ok" type="Button" parent="VBoxContainer/HBoxContainer/VBoxContainer"] -margin_left = 57.0 -margin_top = 146.0 -margin_right = 82.0 -margin_bottom = 168.0 +margin_left = 80.0 +margin_top = 277.0 +margin_right = 105.0 +margin_bottom = 299.0 size_flags_horizontal = 4 size_flags_vertical = 8 disabled = true