From 71deb80dbd74848993e2d1c3c830910c756a2e8e Mon Sep 17 00:00:00 2001 From: Luke Hubmayer-Werner Date: Fri, 25 Dec 2020 23:11:09 +1030 Subject: [PATCH] Handle per-chart metadata for rgt files (and pre-empt breakage for sm files) --- scripts/FileLoader.gd | 79 ++++++++++++++++++++++++++---------------- scripts/Menu.gd | 38 +++++++++++--------- scripts/NoteHandler.gd | 5 +-- 3 files changed, 74 insertions(+), 48 deletions(-) diff --git a/scripts/FileLoader.gd b/scripts/FileLoader.gd index 72b25bf..7409212 100644 --- a/scripts/FileLoader.gd +++ b/scripts/FileLoader.gd @@ -272,8 +272,9 @@ class RGT: chart_ids.append(line.lstrip('[').rstrip(']')) lines.append([]) elif !line.empty(): - lines[-1].append(line) + lines[-1].push_back(line) file.close() + print('Parsing chart: ', filename) match format: Format.RGTS: @@ -290,15 +291,19 @@ class RGT: return charts return format - static func parse_rgtx(lines): + static func parse_rgtx(lines: PoolStringArray): return [] # To be implemented later const beats_per_measure = 4.0 # TODO: Bit of an ugly hack, need to revisit this later - static func parse_rgts(lines): - var notes = [] - var slide_ids = {} - var slide_stars = {} # Multiple stars might link to one star. We only care about linking for the spin speed. - var last_star = [] + static func parse_rgts(lines: PoolStringArray): + var metadata := {} + var num_taps := 0 + var num_holds := 0 + var num_slides := 0 + var notes := [] + var slide_ids := {} + var slide_stars := {} # Multiple stars might link to one star. We only care about linking for the spin speed. + var last_star := [] for i in Rules.COLS: last_star.append(null) @@ -306,23 +311,26 @@ class RGT: if len(line) < 4: # shortest legal line would be like '1:1t' continue var s = line.split(':') - var time = float(s[0]) * beats_per_measure - var note_hits = [] - var note_nonhits = [] + var time := float(s[0]) * beats_per_measure + var note_hits := [] + var note_nonhits := [] for i in range(1, len(s)): var n = s[i] - var column = int(n[0]) + var column := int(n[0]) var ntype = n[1] n = n.substr(2) match ntype: 't': # tap note_hits.append(Note.NoteTap.new(time, column)) + num_taps += 1 'b': # break note_hits.append(Note.NoteTap.new(time, column, true)) + num_taps += 1 'h': # hold var duration = float(n) * beats_per_measure note_hits.append(Note.NoteHold.new(time, column, duration)) + num_holds += 1 's': # slide star var star = Note.NoteStar.new(time, column) note_hits.append(star) @@ -334,6 +342,7 @@ class RGT: var slide = Note.NoteSlide.new(time, column) slide_ids[slide_id] = slide note_nonhits.append(slide) + num_slides += 1 'e': # slide end var slide_type = n[0] # numeric digit, left as str just in case var slide_id = int(n.substr(1)) @@ -359,7 +368,10 @@ class RGT: for note in note_hits: # Set multihit on each one note.double_hit = true notes += note_hits + note_nonhits - return notes + metadata['num_taps'] = num_taps + metadata['num_holds'] = num_holds + metadata['num_slides'] = num_slides + return [metadata, notes] class SM: @@ -490,14 +502,17 @@ class SM: metadata['num_mines'] = num_mines return [metadata, notes] - static func load_file(filename): + static func load_file(filename: String) -> Array: + # Output is [metadata, [[meta0, chart0], ..., [metaN, chartN]]] # Technically, declarations end with a semicolon instead of a linebreak. # This is a PITA to do correctly in GDScript and the files in our collection are well-behaved with linebreaks anyway, so we won't bother. var file := File.new() - var err := file.open(filename, File.READ) - if err != OK: - print(err) - return err + match file.open(filename, File.READ): + OK: + pass + var err: + print_debug('Error loading file: ', err) + return [] var length = file.get_len() var lines = [[]] # First list will be header, then every subsequent one is a chart while (file.get_position() < (length-1)): # Could probably replace this with file.eof_reached() @@ -594,8 +609,9 @@ func load_filelist(filelist: Array, directory=''): key += 1 'sm': # Stepmania, multiple charts var res = SM.load_file(filename) - for k in res: - charts[k] = res[k] + for chart in res[1]: + var diff = chart[0].difficulty_str + charts[diff] = chart[1] _: pass return charts @@ -652,19 +668,22 @@ func init_directory(directory: String): func save_json(filename: String, data: Dictionary): filename = userroot + filename var dir = filename.rsplit('/', true, 1)[0] - var err = FileLoader.init_directory(dir) - if err != OK: - print('Error making directory for JSON file: ', err, ERROR_CODES[err]) - return err + match FileLoader.init_directory(dir): + OK: + pass + var err: + print_debug('Error making directory for JSON file: ', err, ERROR_CODES[err]) + return err var json = JSON.print(data) var file = File.new() - err = file.open(filename, File.WRITE) - if err != OK: - print('Error saving JSON file: ', err, ERROR_CODES[err]) - return err - file.store_string(json) - file.close() - return OK + match file.open(filename, File.WRITE): + OK: + file.store_string(json) + file.close() + return OK + var err: + print_debug('Error saving JSON file: ', err, ERROR_CODES[err]) + return err func load_json(filename: String): var file = File.new() diff --git a/scripts/Menu.gd b/scripts/Menu.gd index cb25e6a..541f2a8 100644 --- a/scripts/Menu.gd +++ b/scripts/Menu.gd @@ -45,10 +45,13 @@ func save_score() -> int: var data = {'score_data': scorescreen_score_data, 'song_key': scorescreen_song_key} var dt = scorescreen_datetime var filename = 'scores/%04d%02d%02dT%02d%02d%02d.json'%[dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second] - var err = FileLoader.save_json(filename, data) - if err == OK: - scorescreen_saved = true - return err + match FileLoader.save_json(filename, data): + OK: + scorescreen_saved = true + return OK + var err: + print_debug('Error saving score file %s'%filename) + return err func load_score(filename): var result = FileLoader.load_json('scores/%s'%filename) @@ -59,10 +62,9 @@ func load_score(filename): for key in result.score_data: var value = {} for k2 in result.score_data[key]: - if k2 == 'MISS': - value[k2] = result.score_data[key][k2] - else: - value[int(k2)] = result.score_data[key][k2] + if k2 != 'MISS': + k2 = int(k2) # Could use something more robust later + value[k2] = result.score_data[key][k2] data[int(key)] = value scorescreen_score_data = data scorescreen_song_key = result.song_key @@ -182,18 +184,17 @@ func _draw_chart_select(center: Vector2) -> Array: # TODO: This is relatively expensive so we probably want to calculate this stuff once instead of every frame - var all_notes = Library.get_song_charts(selected_song_key).values()[selected_difficulty] + var chart: Array = Library.get_song_charts(selected_song_key).values()[selected_difficulty] + var all_notes: Array = chart[1] + var meta: Dictionary = chart[0] var song_data = Library.all_songs[selected_song_key] - var note_counts = {Note.NOTE_TAP: 0, Note.NOTE_HOLD: 0, Note.NOTE_STAR: 0} - for note in all_notes: - if note.type in note_counts: - note_counts[note.type] += 1 draw_string_centered(TitleFont, Vector2(center.x-50, center.y+size+80), 'BPM:', Color(0.95, 0.95, 1.0)) draw_string_centered(TitleFont, Vector2(center.x+50, center.y+size+80), str(song_data.BPM), Color(0.95, 0.95, 1.0)) var notestrs = ['Taps:', 'Holds:', 'Slides:'] var notetypes = [0, 1, 2] + var note_counts = [meta.num_taps, meta.num_holds, meta.num_slides] for i in len(notestrs): draw_string_centered(TitleFont, Vector2(center.x-50, center.y+size+148+i*50), notestrs[i], Color(0.95, 0.95, 1.0)) draw_string_centered(TitleFont, Vector2(center.x+50, center.y+size+148+i*50), str(note_counts[notetypes[i]]), Color(0.95, 0.95, 1.0)) @@ -206,11 +207,16 @@ func _draw_score_screen(center: Vector2) -> Array: var touchrects = [] var songslist = genres[genres.keys()[selected_genre]] var song_key = scorescreen_song_key +# var song_data = Library.all_songs[song_key] + var chart: Array = Library.get_song_charts(selected_song_key).values()[selected_difficulty] + var all_notes: Array = chart[1] + var meta: Dictionary = chart[0] + var x = center.x var y = center.y - 200 var x_songtile = x - 120 var x_score = x + 120 - var x2 = x - 370 + var x2 = x - 360 var x_spacing = 124 var y_spacing = 42 var y1 = y @@ -223,7 +229,7 @@ func _draw_score_screen(center: Vector2) -> Array: draw_songtile(song_key, Vector2(x_songtile-size/2.0, y), size, false, selected_difficulty, 3) draw_string_centered(TitleFont, Vector2(x_songtile, y+size), Library.all_songs[song_key].title.n, Color(0.95, 0.95, 1.0)) - var notestrs = ['Taps:', 'Holds Hit:', 'Released:', 'Stars:', 'Slides:'] + var notestrs = ['Taps (%d):'%meta.num_taps, 'Holds (%d) Hit:'%meta.num_holds, 'Released:', 'Stars (%d):'%meta.num_slides, 'Slides:'] var notetypes = [0, 1, -1, 2, -2] var note_spacing = [0.0, 1.25, 2.25, 3.5, 4.5] var judgestrs = Array(Rules.JUDGEMENT_STRINGS + ['Miss']) @@ -248,7 +254,7 @@ func _draw_score_screen(center: Vector2) -> Array: var note_count = 0 # var y_row = y2+y_spacing*(i+1) var y_row = y2 + y_spacing * (note_spacing[i]+1) - draw_string_centered(TitleFont, Vector2(x2, y_row), notestrs[i], Color(0.95, 0.95, 1.0)) + draw_string_centered(TitleFont, Vector2(x2-20, y_row), notestrs[i], Color(0.95, 0.95, 1.0)) for j in len(judgestrs): var score if j == 0: diff --git a/scripts/NoteHandler.gd b/scripts/NoteHandler.gd index 6d5ab0a..4d50483 100644 --- a/scripts/NoteHandler.gd +++ b/scripts/NoteHandler.gd @@ -518,9 +518,10 @@ func load_track(song_key: String, difficulty_idx: int): active_notes = [] next_note_to_load = 0 all_notes = [] - for note in Library.get_song_charts(song_key).values()[difficulty_idx]: - all_notes.append(Note.copy_note(note)) var data = Library.all_songs[song_key] + var chart = Library.get_song_charts(song_key).values()[difficulty_idx] + for note in chart[1]: + all_notes.append(Note.copy_note(note)) bpm = data.BPM sync_offset_audio = data.audio_offsets[0] sync_offset_video = data.video_offsets[0]