Refactor Debug menu, and add Party Menu for saves

This commit is contained in:
Luke Hubmayer-Werner 2023-12-06 16:32:40 +10:30
parent 48c6ed2c3b
commit 923e2f463e
22 changed files with 306 additions and 145 deletions

View File

@ -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=""

View File

@ -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

55
main.gd
View File

@ -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():

View File

@ -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

View File

@ -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"

View File

@ -1,4 +1,5 @@
extends Node
#warning-ignore-all:return_value_discarded
signal rom_loaded

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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')

View File

@ -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

17
widgets/SaveSlotSelect.gd Normal file
View File

@ -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)

View File

@ -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

View File

@ -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')