diff --git a/export_presets.cfg b/export_presets.cfg index e75b911..5dd398d 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -16,7 +16,7 @@ script_encryption_key="" custom_template/debug="" custom_template/release="" variant/export_type=0 -vram_texture_compression/for_desktop=true +vram_texture_compression/for_desktop=false vram_texture_compression/for_mobile=false html/export_icon=true html/custom_html_shell="" diff --git a/globals.gd b/globals.gd index 8d42c01..2cb864c 100644 --- a/globals.gd +++ b/globals.gd @@ -2,6 +2,43 @@ extends Node const INDEX_FORMAT := Image.FORMAT_L8 +enum Menu { + LOADER, + MAIN, + LOAD_SAVE, + WORLD_MAP, + FIELD_MAP, + PARTY, + SHOP, + BATTLE, + DEBUG, + DEBUG_AUDIO_SYSTEM, + DEBUG_BATTLE_SPRITES, +} + +const MENUS = { + Menu.PARTY: ['res://widgets/PartyMenu.tscn', 'Party Menu'], + Menu.BATTLE: ['res://widgets/BattleScene.tscn', 'Battle'], + Menu.LOAD_SAVE: ['res://widgets/SaveSlotSelect.tscn', 'Load Save'], + Menu.DEBUG: ['res://test/debug_menu.tscn', 'Debug Menu'], + Menu.DEBUG_BATTLE_SPRITES: ['res://test/battle_sprites.tscn', 'Battle Sprites'], + Menu.DEBUG_AUDIO_SYSTEM: ['res://test/audio_system.tscn', 'Audio'], + Menu.WORLD_MAP: ['res://test/worldmap_system.tscn', 'World Map'], +} + +const INITIAL_MENUS = [ + Menu.LOAD_SAVE, +] + +const POST_ROM_MENUS = [ + Menu.DEBUG, + Menu.WORLD_MAP, + Menu.PARTY, + Menu.BATTLE, + Menu.DEBUG_BATTLE_SPRITES, + Menu.DEBUG_AUDIO_SYSTEM, +] + const FOLDER_ICON := preload('res://theme/icons/file_folder.tres') const ALLOWED_EXTS := PoolStringArray(['bin', 'iso', 'sfc', 'smc', 'srm', 'gba']) const CD_EXTS := PoolStringArray(['bin', 'iso']) # If you have a weird disc image format, you can mount it yourself, leave me out of it diff --git a/main.gd b/main.gd index 05307a6..b14f149 100644 --- a/main.gd +++ b/main.gd @@ -1,43 +1,46 @@ extends Control +#warning-ignore-all:return_value_discarded -enum Menu { - LOADER, - MAIN, - LOAD_SAVE, - WORLD_MAP, - FIELD_MAP, - PARTY, - SHOP, - BATTLE, - DEBUG, - DEBUG_AUDIO_SYSTEM, - DEBUG_BATTLE_SPRITES, -} +const globals = preload('res://globals.gd') # Make LSP shut up about non-const +const Menu = globals.Menu +var packed_menus = {} var menus = {} var active_menu_stack = [] +func instantiate_menu_list(menu_list) -> void: + for key in menu_list: + packed_menus[key] = load(globals.MENUS[key][0]) + menus[key] = packed_menus[key].instance() + var is_rom_loaded := false -func _rom_loaded() -> void: - menus[Menu.PARTY] = preload('res://widgets/PartyMenu.tscn').instance() - menus[Menu.WORLD_MAP] = preload('res://test/worldmap_system.tscn').instance() - menus[Menu.DEBUG] = preload('res://test/debug_menu.tscn').instance() - menus[Menu.DEBUG].connect('pressed_worldmap', self, 'push_menu', [Menu.WORLD_MAP]) - menus[Menu.DEBUG].connect('pressed_party', self, 'push_menu', [Menu.PARTY]) - menus[Menu.DEBUG].connect('pressed_battle_sprites', self, 'push_menu', [Menu.DEBUG_BATTLE_SPRITES]) - menus[Menu.DEBUG].connect('pressed_audio', self, 'push_menu', [Menu.DEBUG_AUDIO_SYSTEM]) - menus[Menu.DEBUG_AUDIO_SYSTEM] = preload('res://test/audio_system.tscn').instance() - menus[Menu.DEBUG_BATTLE_SPRITES] = preload('res://test/battle_sprites.tscn').instance() +func _on_rom_loaded() -> void: + instantiate_menu_list(globals.POST_ROM_MENUS) + menus[Menu.DEBUG].connect('button_pressed', self, 'push_menu') is_rom_loaded = true +var is_savefile_loaded := false +func _on_savefile_loaded(dicts) -> void: + push_menu(Menu.LOAD_SAVE) + menus[Menu.LOAD_SAVE].set_data(dicts) + menus[Menu.LOAD_SAVE].connect('slot_activated', self, '_on_saveslot_loaded') + +func _on_saveslot_loaded(dict) -> void: + push_menu(Menu.PARTY) + menus[Menu.PARTY].update_labels(dict) + func _ready() -> void: if OS.get_name() != 'HTML5' or !OS.has_feature('JavaScript'): - menus[Menu.LOADER] = preload('res://widgets/RomSelect.tscn').instance() + packed_menus[Menu.LOADER] = preload('res://widgets/RomSelect.tscn') else: - menus[Menu.LOADER] = preload('res://widgets/WebFileSelect.tscn').instance() + packed_menus[Menu.LOADER] = preload('res://widgets/WebFileSelect.tscn') + menus[Menu.LOADER] = packed_menus[Menu.LOADER].instance() push_menu(Menu.LOADER) - RomLoader.connect('rom_loaded', self, '_rom_loaded') + instantiate_menu_list(globals.INITIAL_MENUS) + + RomLoader.connect('rom_loaded', self, '_on_rom_loaded') menus[Menu.LOADER].connect('continue_pressed', self, 'push_debug_menu') + menus[Menu.LOADER].connect('savefile_loaded', self, '_on_savefile_loaded') Common.update_window_scale() func push_debug_menu(): diff --git a/main.tscn b/main.tscn index 815731c..1e6903d 100644 --- a/main.tscn +++ b/main.tscn @@ -1,7 +1,6 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=3 format=2] [ext_resource path="res://theme/menu_theme.tres" type="Theme" id=1] -[ext_resource path="res://widgets/ColorMenu.tscn" type="PackedScene" id=4] [ext_resource path="res://main.gd" type="Script" id=5] [node name="main" type="Control"] @@ -11,7 +10,3 @@ margin_right = -640.0 margin_bottom = -360.0 theme = ExtResource( 1 ) script = ExtResource( 5 ) - -[node name="ColorMenu" parent="." instance=ExtResource( 4 )] -margin_left = 384.0 -margin_right = 469.0 diff --git a/project.godot b/project.godot index 10c4365..bb192e5 100644 --- a/project.godot +++ b/project.godot @@ -66,5 +66,7 @@ texture={ quality/driver/driver_name="GLES2" 2d/snapping/use_gpu_pixel_snap=true +vram_compression/import_s3tc=false +vram_compression/import_etc2=false environment/default_clear_color=Color( 0, 0, 0, 1 ) environment/default_environment="res://default_env.tres" diff --git a/scripts/loaders/RomLoader.gd b/scripts/loaders/RomLoader.gd index 25d7528..ea35a82 100644 --- a/scripts/loaders/RomLoader.gd +++ b/scripts/loaders/RomLoader.gd @@ -1,4 +1,5 @@ extends Node +#warning-ignore-all:return_value_discarded signal rom_loaded diff --git a/scripts/loaders/SaveLoader.gd b/scripts/loaders/SaveLoader.gd index 69df707..3c9073b 100644 --- a/scripts/loaders/SaveLoader.gd +++ b/scripts/loaders/SaveLoader.gd @@ -121,6 +121,39 @@ func get_save_slot(sram: File, slot_id: int) -> StreamPeerBuffer: buffer.set_data_array(sram.get_buffer(0x700)) return buffer +func load_save_dicts_from_buffer(sram: StreamPeerBuffer) -> Array: + # Pulls four lots of 0x700 bytes from the current buffer position + var dicts := [] + var slot_buffer := StreamPeerBuffer.new() + for slot_id in 4: + slot_buffer.set_data_array(sram.get_data(0x700)[1]) + slot_buffer.seek(0) + dicts.append(load_save_slot(slot_buffer)) + # Won't seek just in case + sram.get_data(0x1FF8-0x1C00) + for slot_id in 4: + dicts[slot_id].slot_in_use = (sram.get_u16() == SLOT_IN_USE) + return dicts + +func load_save_dicts_from_bytes(sram: PoolByteArray) -> Array: + var buffer := StreamPeerBuffer.new() + buffer.set_data_array(sram) + return load_save_dicts_from_buffer(buffer) + +func load_save_dicts_from_file(sram: File) -> Array: + # Pulls four lots of 0x700 bytes from the current buffer position + var dicts := [] + var slot_buffer := StreamPeerBuffer.new() + for slot_id in 4: + slot_buffer.set_data_array(sram.get_buffer(0x700)) + slot_buffer.seek(0) + dicts.append(load_save_slot(slot_buffer)) + # Won't seek just in case + sram.get_buffer(0x1FF8-0x1C00) + for slot_id in 4: + dicts[slot_id].slot_in_use = (sram.get_16() == SLOT_IN_USE) + return dicts + func save_slot(sram: File, slot_id: int, slot: StreamPeerBuffer): sram.seek(0x700 * slot_id) sram.store_buffer(slot.data_array) diff --git a/scripts/loaders/SpriteLoader.gd b/scripts/loaders/SpriteLoader.gd index f042301..ae253d9 100644 --- a/scripts/loaders/SpriteLoader.gd +++ b/scripts/loaders/SpriteLoader.gd @@ -1,4 +1,5 @@ extends Node +const globals = preload('res://globals.gd') # Make LSP shut up about non-const # Portability for GLES2 vs GLES3 stuff const INDEX_FORMAT := globals.INDEX_FORMAT diff --git a/scripts/loaders/gba/graphics.gd b/scripts/loaders/gba/graphics.gd index 02bac05..7509aa9 100644 --- a/scripts/loaders/gba/graphics.gd +++ b/scripts/loaders/gba/graphics.gd @@ -1,3 +1,4 @@ +const globals = preload('res://globals.gd') # Make LSP shut up about non-const const INDEX_FORMAT := globals.INDEX_FORMAT static func ByteArray(size: int) -> PoolByteArray: diff --git a/scripts/loaders/snes/graphics.gd b/scripts/loaders/snes/graphics.gd index 875aba7..a5d0ae9 100644 --- a/scripts/loaders/snes/graphics.gd +++ b/scripts/loaders/snes/graphics.gd @@ -1,3 +1,4 @@ +const globals = preload('res://globals.gd') # Make LSP shut up about non-const var INDEX_FORMAT := globals.INDEX_FORMAT static func ByteArray(size: int) -> PoolByteArray: diff --git a/test/debug_menu.gd b/test/debug_menu.gd index 1ae7b30..422fe88 100644 --- a/test/debug_menu.gd +++ b/test/debug_menu.gd @@ -1,18 +1,18 @@ extends Control +#warning-ignore-all:return_value_discarded -signal pressed_worldmap -signal pressed_party -signal pressed_battle_sprites -signal pressed_audio +signal button_pressed(menu) -func _on_btn_worldmap_pressed() -> void: - emit_signal('pressed_worldmap') +onready var buttons := $'%buttons' +func _ready() -> void: + for key in globals.POST_ROM_MENUS: + if key == globals.Menu.DEBUG: + continue + var menu = globals.MENUS[key] + var btn := Button.new() + btn.text = menu[1] + btn.connect('pressed', self, '_on_btn_pressed', [key]) + buttons.add_child(btn) -func _on_btn_party_pressed() -> void: - emit_signal('pressed_party') - -func _on_btn_battle_sprites_pressed() -> void: - emit_signal('pressed_battle_sprites') - -func _on_btn_audio_pressed() -> void: - emit_signal('pressed_audio') +func _on_btn_pressed(menu) -> void: + emit_signal('button_pressed', menu) diff --git a/test/debug_menu.tscn b/test/debug_menu.tscn index 22ccb48..a8a6d83 100644 --- a/test/debug_menu.tscn +++ b/test/debug_menu.tscn @@ -16,9 +16,9 @@ anchor_bottom = 1.0 [node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"] margin_left = 110.0 -margin_top = 45.0 +margin_top = 101.0 margin_right = 273.0 -margin_bottom = 194.0 +margin_bottom = 138.0 [node name="Label" type="Label" parent="CenterContainer/VBoxContainer"] margin_right = 163.0 @@ -27,31 +27,9 @@ text = "DEBUG MENU Press [backspace] to return" align = 1 -[node name="btn_worldmap" type="Button" parent="CenterContainer/VBoxContainer"] +[node name="buttons" type="GridContainer" parent="CenterContainer/VBoxContainer"] +unique_name_in_owner = true margin_top = 37.0 margin_right = 163.0 -margin_bottom = 59.0 -text = "World Map" - -[node name="btn_party" type="Button" parent="CenterContainer/VBoxContainer"] -margin_top = 67.0 -margin_right = 163.0 -margin_bottom = 89.0 -text = "Party Menu" - -[node name="btn_battle_sprites" type="Button" parent="CenterContainer/VBoxContainer"] -margin_top = 97.0 -margin_right = 163.0 -margin_bottom = 119.0 -text = "Battle Sprites" - -[node name="btn_audio" type="Button" parent="CenterContainer/VBoxContainer"] -margin_top = 127.0 -margin_right = 163.0 -margin_bottom = 149.0 -text = "Audio" - -[connection signal="pressed" from="CenterContainer/VBoxContainer/btn_worldmap" to="." method="_on_btn_worldmap_pressed"] -[connection signal="pressed" from="CenterContainer/VBoxContainer/btn_party" to="." method="_on_btn_party_pressed"] -[connection signal="pressed" from="CenterContainer/VBoxContainer/btn_battle_sprites" to="." method="_on_btn_battle_sprites_pressed"] -[connection signal="pressed" from="CenterContainer/VBoxContainer/btn_audio" to="." method="_on_btn_audio_pressed"] +margin_bottom = 37.0 +columns = 2 diff --git a/test_scene.gd b/test_scene.gd index d4a629c..f8be555 100644 --- a/test_scene.gd +++ b/test_scene.gd @@ -1,10 +1,26 @@ extends Control +#warning-ignore-all:return_value_discarded + const palette_mat := preload('res://palette_mat.tres') var save_slots = [] var save_slot_dicts = [] func _ready(): - Engine.set_target_fps(60) + RomLoader.connect('rom_loaded', self, '_on_rom_loaded') +# RomLoader.load_snes_rom('/home/luke/code/FF/ffv romhacks/Final Fantasy V (Japan).sfc') + RomLoader.load_snes_rom('/home/luke/code/FF/ffv romhacks/Final Fantasy V (Japan) [En by RPGe v1.1].sfc') + +func _on_rom_loaded(): + party_menu() +# monster_sprites() +# battle_bgs() +# jobs_and_abilities() + +func party_menu(): + var PartyMenu = preload('res://widgets/PartyMenu.tscn').instance() +# PartyMenu.margin_right = 320.0 + PartyMenu.margin_right = 384.0 + add_child(PartyMenu) var save_file := File.new() #var error := save_file.open('test.srm', File.READ) var error := save_file.open('/home/luke/.config/Mesen2/Saves/FF5_SCC_WepTweaks_Inus_Dash.srm', File.READ) @@ -22,9 +38,10 @@ func _ready(): # save_slot_dicts.append(SaveLoader.get_struct(buffer, 'Save_slot')) var data = save_slot_dicts[0] data.characters[2].equipped_abilities[3] = 0x9B - $PartyMenu.update_labels(data) + PartyMenu.update_labels(data) ThemeManager.set_menu_color_555(data.config.menu_color_r, data.config.menu_color_g, data.config.menu_color_b) +func monster_sprites(): var monster_box := GridContainer.new() monster_box.columns = 8 add_child(monster_box) @@ -35,6 +52,7 @@ func _ready(): t.material.set_shader_param('palette', mon.palette) monster_box.add_child(t) +func battle_bgs(): var bbg := SpinBox.new() bbg.max_value = len(SpriteLoader.battle_backgrounds) - 1 bbg.connect('value_changed', $BattleScene, 'set_bg') @@ -43,13 +61,12 @@ func _ready(): bbg.align = LineEdit.ALIGN_RIGHT add_child(bbg) - # var lbl = Label.new() - # for i in 22: - # lbl.text = lbl.text + '%s - %s\n' % [StringLoader.get_job_name(i), StringLoader.get_job_desc(i)] - # for i in 78: - # lbl.text = lbl.text + '\n%s - %s' % [StringLoader.get_ability_name(i), StringLoader.get_ability_desc(i)] - # for i in range(128, 161): - # lbl.text = lbl.text + '\n%s - %s' % [StringLoader.get_ability_name(i), StringLoader.get_ability_desc(i)] - # add_child(lbl) - - +func jobs_and_abilities(): + var lbl = Label.new() + for i in 22: + lbl.text = lbl.text + '%s - %s\n' % [StringLoader.get_job_name(i), StringLoader.get_job_desc(i)] + for i in 78: + lbl.text = lbl.text + '\n%s - %s' % [StringLoader.get_ability_name(i), StringLoader.get_ability_desc(i)] + for i in range(128, 161): + lbl.text = lbl.text + '\n%s - %s' % [StringLoader.get_ability_name(i), StringLoader.get_ability_desc(i)] + add_child(lbl) diff --git a/test_scene.tscn b/test_scene.tscn index c4369d0..d945662 100644 --- a/test_scene.tscn +++ b/test_scene.tscn @@ -1,32 +1,10 @@ -[gd_scene load_steps=8 format=2] +[gd_scene load_steps=3 format=2] -[ext_resource path="res://widgets/PartyMenu.tscn" type="PackedScene" id=1] -[ext_resource path="res://test/worldmap_system.tscn" type="PackedScene" id=2] [ext_resource path="res://test_scene.gd" type="Script" id=3] -[ext_resource path="res://test/battle_sprites.tscn" type="PackedScene" id=4] -[ext_resource path="res://test/audio_system.tscn" type="PackedScene" id=5] [ext_resource path="res://theme/menu_theme.tres" type="Theme" id=6] -[ext_resource path="res://widgets/BattleScene.tscn" type="PackedScene" id=7] -[node name="Control" type="Control"] +[node name="test_scene" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 theme = ExtResource( 6 ) script = ExtResource( 3 ) - -[node name="audio_system" parent="." instance=ExtResource( 5 )] -position = Vector2( 0, 160 ) - -[node name="worldmap_system" parent="." instance=ExtResource( 2 )] -visible = false -position = Vector2( -600, -550 ) - -[node name="battle_sprites" parent="." instance=ExtResource( 4 )] -visible = false - -[node name="PartyMenu" parent="." instance=ExtResource( 1 )] -visible = false -margin_right = 320.0 - -[node name="BattleScene" parent="." instance=ExtResource( 7 )] -visible = false diff --git a/widgets/PartyMenu.tscn b/widgets/PartyMenu.tscn index 90e8c0d..29e87f6 100644 --- a/widgets/PartyMenu.tscn +++ b/widgets/PartyMenu.tscn @@ -37,15 +37,15 @@ margin_bottom = 224.0 anchor_left = 1.0 anchor_right = 1.0 anchor_bottom = 1.0 -margin_left = -72.0 +margin_left = -64.0 size_flags_horizontal = 8 size_flags_vertical = 8 custom_constants/separation = 0 alignment = 2 [node name="panel_menu" type="PanelContainer" parent="rightside"] -margin_left = 16.0 -margin_right = 72.0 +margin_left = 8.0 +margin_right = 64.0 margin_bottom = 36.0 rect_min_size = Vector2( 56, 0 ) size_flags_horizontal = 8 @@ -69,9 +69,9 @@ margin_bottom = 28.0 text = "Ability" [node name="panel_menu2" type="PanelContainer" parent="rightside"] -margin_left = 16.0 +margin_left = 8.0 margin_top = 36.0 -margin_right = 72.0 +margin_right = 64.0 margin_bottom = 128.0 rect_min_size = Vector2( 56, 0 ) size_flags_horizontal = 8 @@ -120,14 +120,13 @@ text = "Save" [node name="spacer" type="Control" parent="rightside"] margin_top = 128.0 -margin_right = 72.0 +margin_right = 64.0 margin_bottom = 168.0 size_flags_vertical = 3 [node name="panel_time" type="PanelContainer" parent="rightside"] -margin_left = 8.0 margin_top = 168.0 -margin_right = 72.0 +margin_right = 64.0 margin_bottom = 204.0 rect_min_size = Vector2( 64, 0 ) size_flags_horizontal = 8 @@ -149,32 +148,32 @@ unique_name_in_owner = true margin_top = 14.0 margin_right = 56.0 margin_bottom = 28.0 -text = "0:00" +text = "000:00:00" align = 2 [node name="panel_gil" type="PanelContainer" parent="rightside"] margin_top = 204.0 -margin_right = 72.0 +margin_right = 64.0 margin_bottom = 240.0 -rect_min_size = Vector2( 72, 0 ) +rect_min_size = Vector2( 64, 0 ) [node name="VBoxContainer" type="VBoxContainer" parent="rightside/panel_gil"] margin_left = 4.0 margin_top = 4.0 -margin_right = 68.0 +margin_right = 60.0 margin_bottom = 32.0 custom_constants/separation = 0 [node name="lbl_gilcount" type="Label" parent="rightside/panel_gil/VBoxContainer"] unique_name_in_owner = true -margin_right = 64.0 +margin_right = 56.0 margin_bottom = 14.0 -text = "0" +text = "0000000" align = 2 [node name="GIL" type="Label" parent="rightside/panel_gil/VBoxContainer"] margin_top = 14.0 -margin_right = 64.0 +margin_right = 56.0 margin_bottom = 28.0 text = "Gil" align = 2 diff --git a/widgets/PartyMenuCharacter.tscn b/widgets/PartyMenuCharacter.tscn index 9574710..09cc4a1 100644 --- a/widgets/PartyMenuCharacter.tscn +++ b/widgets/PartyMenuCharacter.tscn @@ -129,9 +129,9 @@ text = "LV" [node name="lbl_lv_cur" type="Label" parent="ref0"] unique_name_in_owner = true -margin_left = 32.0 +margin_left = 24.0 margin_top = 12.0 -margin_right = 56.0 +margin_right = 48.0 margin_bottom = 26.0 text = "26" align = 2 @@ -149,9 +149,9 @@ border_color = Color( 1, 0.501961, 0, 1 ) unique_name_in_owner = true anchor_top = 1.0 anchor_bottom = 1.0 -margin_left = 40.0 +margin_left = 32.0 margin_top = -24.0 -margin_right = 56.0 +margin_right = 48.0 border_color = Color( 0, 1, 0, 1 ) [node name="PC" parent="ref0" instance=ExtResource( 2 )] @@ -162,6 +162,14 @@ margin_left = 168.0 margin_right = 252.0 margin_bottom = 50.0 +[node name="Panel" type="Panel" parent="ref_commands"] +modulate = Color( 1, 1, 1, 0.501961 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = -4.0 +margin_top = -3.0 +margin_bottom = 3.0 + [node name="l1" type="Label" parent="ref_commands"] margin_left = 12.0 margin_right = 84.0 diff --git a/widgets/RomSelect.gd b/widgets/RomSelect.gd index e92b704..0681c8a 100644 --- a/widgets/RomSelect.gd +++ b/widgets/RomSelect.gd @@ -2,13 +2,18 @@ extends PanelContainer #warning-ignore-all:return_value_discarded signal continue_pressed +signal savefile_loaded(dicts) +const globals = preload('res://globals.gd') # Make LSP shut up about non-const const FOLDER_ICON := globals.FOLDER_ICON const ALLOWED_EXTS := globals.ALLOWED_EXTS const CD_EXTS := globals.CD_EXTS const EXT_ICONS := globals.EXT_ICONS const TYPE_DESCS := globals.TYPE_DESCS +enum {SELECT_ROM, SELECT_SAVE, COMPLETE} +var current_mode = SELECT_ROM + var cached_cd_bin_paths := {} var dir := Directory.new() var home_path := '' @@ -109,7 +114,18 @@ func load_file(entry: String): var ext = entry.rsplit('.', true, 1)[1].to_lower() match ext: 'sfc', 'smc': - RomLoader.load_snes_rom(filename) + if current_mode == SELECT_ROM: + RomLoader.load_snes_rom(filename) + 'srm': + if current_mode == SELECT_ROM: + return + var file := File.new() + match file.open(filename, File.READ): + OK: + emit_signal('savefile_loaded', SaveLoader.load_save_dicts_from_file(file)) + _set_mode(COMPLETE) + var err: + print_debug('Error loading savefile: %s - %d'%[filename, err]) func activate_entry(entry: String, _index: int = -1): var curr_dir := dir.get_current_dir() @@ -168,7 +184,11 @@ func view_entry(entry: String, index: int = -1): lbl_filesize_content.text = human_size lbl_fileinfo_header.modulate = active_modulate_color if prodcode else inactive_modulate_color lbl_fileinfo_content.text = prodcode - btn_ok.disabled = (ext != 'sfc' and ext != 'smc') # Only allow opening snes roms for now + match current_mode: + SELECT_ROM: + btn_ok.disabled = (ext != 'sfc' and ext != 'smc') # Only allow opening snes roms for now + SELECT_SAVE, COMPLETE: + btn_ok.disabled = (ext != 'srm') func init_labels(): lbl_filename_header.modulate = inactive_modulate_color @@ -197,6 +217,20 @@ func _ready() -> void: print(ProjectSettings.globalize_path('user://')) print(ProjectSettings.globalize_path(dir.get_current_dir())) +func _set_mode(new_mode) -> void: + match new_mode: + SELECT_ROM: + $'%lbl_prompt'.text = "Select a ROM from your device's storage" + btn_continue.disabled = true + SELECT_SAVE: + $'%lbl_prompt'.text = "Select a save file from your device's storage" + btn_continue.disabled = false + COMPLETE: + $'%lbl_prompt'.text = "Save file loaded, press Continue" + btn_continue.disabled = false + current_mode = new_mode + update_view() + init_labels() func _on_ItemList_item_activated(index: int) -> void: activate_entry(itemlist.get_item_text(index), index) @@ -205,8 +239,7 @@ func _on_ItemList_item_selected(index: int) -> void: view_entry(itemlist.get_item_text(index), index) func _on_rom_loaded() -> void: - $'%lbl_prompt'.text = "Select a save file from your device's storage" - btn_continue.disabled = false + _set_mode(SELECT_SAVE) func _on_continue_pressed() -> void: emit_signal('continue_pressed') diff --git a/widgets/SaveSlot.gd b/widgets/SaveSlot.gd index 4087483..9d5ea65 100644 --- a/widgets/SaveSlot.gd +++ b/widgets/SaveSlot.gd @@ -1,7 +1,12 @@ extends PanelContainer +#warning-ignore-all:shadowed_variable +signal clicked + const PC := preload('res://PC.tscn') var PCs = [] +var data := {} + var dummy_data := { 'characters': [ {'character_id': 0}, @@ -10,8 +15,9 @@ var dummy_data := { {'character_id': 3}, ], 'game_time_frames': randi() % 0x01000000, - 'character_names': ['Butz', 'Lenna', 'Galuf', 'Faris', 'Krile'], - 'config': {'menu_color_r': randi()%32, 'menu_color_g': randi()%32, 'menu_color_b': randi()%32} + 'character_names_decoded': ['Butz', 'Lenna', 'Galuf', 'Faris', 'Krile'], + 'config': {'menu_color_r': randi()%32, 'menu_color_g': randi()%32, 'menu_color_b': randi()%32}, + 'slot_in_use': true, } func _init_dummy(): @@ -24,6 +30,7 @@ func _init_dummy(): dummy_data.characters.shuffle() func set_data(data: Dictionary): + self.data = data self.material.set_shader_param('MenuBGColour', Color(data.config.menu_color_r/31.0, data.config.menu_color_g/31.0, data.config.menu_color_b/31.0)) for i in 4: var char_id: int = data.characters[i].character_id @@ -33,8 +40,10 @@ func set_data(data: Dictionary): PCs[i].texture = SpriteLoader.strip_textures[sprite_id] $'%lbl_level_num'.text = '%d' % data.characters[0].level $'%lbl_gametime'.text = Common.game_time_frames_to_hhmm(data.game_time_frames) - $'%lbl_name'.text = data.character_names[data.characters[0].character_id] + $'%lbl_name'.text = data.character_names_decoded[data.characters[0].character_id] $'%lbl_hp'.text = '%d/%4d' % [data.characters[0].hp_current, data.characters[0].hp_max] + $HBoxContainer.visible = data.slot_in_use + $lbl_not_in_use.visible = !data.slot_in_use # Called when the node enters the scene tree for the first time. func _ready() -> void: @@ -48,6 +57,9 @@ func _ready() -> void: set_data(dummy_data) -# Called every frame. 'delta' is the elapsed time since the previous frame. -#func _process(delta: float) -> void: -# pass +func _input(event: InputEvent) -> void: + if (event is InputEventMouseButton or event is InputEventScreenTouch) and event.pressed: + if get_rect().has_point(event.position): +# print(event.position) + get_tree().set_input_as_handled() + emit_signal('clicked') diff --git a/widgets/SaveSlot.tscn b/widgets/SaveSlot.tscn index 1c21a4e..bb12624 100644 --- a/widgets/SaveSlot.tscn +++ b/widgets/SaveSlot.tscn @@ -92,3 +92,14 @@ margin_bottom = 36.0 size_flags_vertical = 9 text = "1345/1345" align = 2 + +[node name="lbl_not_in_use" type="Label" parent="."] +visible = false +margin_left = 4.0 +margin_top = 15.0 +margin_right = 220.0 +margin_bottom = 29.0 +rect_min_size = Vector2( 0, 36 ) +text = "Not In Use" +align = 1 +valign = 1 diff --git a/widgets/SaveSlotSelect.gd b/widgets/SaveSlotSelect.gd new file mode 100644 index 0000000..ff813e6 --- /dev/null +++ b/widgets/SaveSlotSelect.gd @@ -0,0 +1,17 @@ +extends PanelContainer +#warning-ignore-all:shadowed_variable +signal slot_activated(dict) + +onready var slots := [$'%SaveSlot1', $'%SaveSlot2', $'%SaveSlot3', $'%SaveSlot4'] + +var dicts := [] +func set_data(dicts: Array) -> void: + self.dicts = dicts + for i in 4: + slots[i].set_data(dicts[i]) + slots[i].connect('clicked', self, 'load_slot', [i]) + +func load_slot(id: int) -> void: + var dict = self.dicts[id] + if dict.slot_in_use: + emit_signal('slot_activated', dict) diff --git a/widgets/SaveSlotSelect.tscn b/widgets/SaveSlotSelect.tscn index 60d3ca3..7f8470b 100644 --- a/widgets/SaveSlotSelect.tscn +++ b/widgets/SaveSlotSelect.tscn @@ -1,10 +1,12 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=4 format=2] [ext_resource path="res://theme/menu_theme.tres" type="Theme" id=1] [ext_resource path="res://widgets/SaveSlot.tscn" type="PackedScene" id=2] +[ext_resource path="res://widgets/SaveSlotSelect.gd" type="Script" id=3] [node name="SaveSlotSelect" type="PanelContainer"] theme = ExtResource( 1 ) +script = ExtResource( 3 ) [node name="VBoxContainer" type="VBoxContainer" parent="."] margin_left = 4.0 @@ -19,21 +21,25 @@ margin_bottom = 22.0 text = "New Game" [node name="SaveSlot1" parent="VBoxContainer" instance=ExtResource( 2 )] +unique_name_in_owner = true margin_top = 22.0 margin_right = 224.0 margin_bottom = 66.0 [node name="SaveSlot2" parent="VBoxContainer" instance=ExtResource( 2 )] +unique_name_in_owner = true margin_top = 66.0 margin_right = 224.0 margin_bottom = 110.0 [node name="SaveSlot3" parent="VBoxContainer" instance=ExtResource( 2 )] +unique_name_in_owner = true margin_top = 110.0 margin_right = 224.0 margin_bottom = 154.0 [node name="SaveSlot4" parent="VBoxContainer" instance=ExtResource( 2 )] +unique_name_in_owner = true margin_top = 154.0 margin_right = 224.0 margin_bottom = 198.0 diff --git a/widgets/WebFileSelect.gd b/widgets/WebFileSelect.gd index 6a39195..0ff4de3 100644 --- a/widgets/WebFileSelect.gd +++ b/widgets/WebFileSelect.gd @@ -2,13 +2,18 @@ extends PanelContainer #warning-ignore-all:return_value_discarded signal continue_pressed +signal savefile_loaded(dicts) +const globals = preload('res://globals.gd') # Make LSP shut up about non-const const FOLDER_ICON := globals.FOLDER_ICON const ALLOWED_EXTS := globals.ALLOWED_EXTS const CD_EXTS := globals.CD_EXTS const EXT_ICONS := globals.EXT_ICONS const TYPE_DESCS := globals.TYPE_DESCS +enum {SELECT_ROM, SELECT_SAVE, COMPLETE} +var current_mode = SELECT_ROM + var uploaded_files := {} # filename: data var uploaded_files_types := {} # filename: type @@ -68,7 +73,12 @@ func load_file(entry: String): var ext = entry.rsplit('.', true, 1)[1].to_lower() match ext: 'sfc', 'smc': - RomLoader.load_snes_rom_from_bytes(uploaded_files[entry]) + if current_mode == SELECT_ROM: + RomLoader.load_snes_rom_from_bytes(uploaded_files[entry]) + 'srm': + if current_mode != SELECT_ROM: + emit_signal('savefile_loaded', SaveLoader.load_save_dicts_from_bytes(uploaded_files[entry])) + _set_mode(COMPLETE) func activate_entry(entry: String, _index: int = -1): load_file(entry) @@ -108,7 +118,11 @@ func view_entry(entry: String, _index: int = -1): lbl_filesize_content.text = human_size lbl_fileinfo_header.modulate = active_modulate_color if prodcode else inactive_modulate_color lbl_fileinfo_content.text = prodcode - btn_ok.disabled = (ext != 'sfc' and ext != 'smc') # Only allow opening snes roms for now + match current_mode: + SELECT_ROM: + btn_ok.disabled = (ext != 'sfc' and ext != 'smc') # Only allow opening snes roms for now + SELECT_SAVE, COMPLETE: + btn_ok.disabled = (ext != 'srm') func init_labels(): lbl_filename_header.modulate = inactive_modulate_color @@ -123,6 +137,7 @@ func init_labels(): func _upload_file(filename: String, file_type: String, data): # data is Javascript ArrayBuffer, which should be castable to PoolByteArray uploaded_files[filename] = data uploaded_files_types[filename] = file_type + print('uploaded "%s" with filesize %d bytes'%[filename, len(data)]) update_view() func _ready() -> void: @@ -135,6 +150,20 @@ func _ready() -> void: RomLoader.connect('rom_loaded', self, '_on_rom_loaded') HTML5.connect('uploaded_file', self, '_upload_file') +func _set_mode(new_mode) -> void: + match new_mode: + SELECT_ROM: + $'%lbl_prompt'.text = "Select a ROM from your device's storage" + btn_continue.disabled = true + SELECT_SAVE: + $'%lbl_prompt'.text = "Select a save file from your device's storage" + btn_continue.disabled = false + COMPLETE: + $'%lbl_prompt'.text = "Save file loaded, press Continue" + btn_continue.disabled = false + current_mode = new_mode + update_view() + init_labels() func _on_ItemList_item_activated(index: int) -> void: activate_entry(itemlist.get_item_text(index), index) @@ -146,8 +175,7 @@ func _on_btn_upload_pressed() -> void: HTML5.upload_file() func _on_rom_loaded() -> void: - $'%lbl_prompt'.text = "Select a save file from your device's storage" - btn_continue.disabled = false + _set_mode(SELECT_SAVE) func _on_continue_pressed() -> void: emit_signal('continue_pressed')