diff --git a/audio_paths.nvgt b/audio_paths.nvgt index ba7cfdb..4a19e16 100644 --- a/audio_paths.nvgt +++ b/audio_paths.nvgt @@ -3,23 +3,23 @@ // Resolves an audio path with optional extension fallback. // Checks exact path first, then ".ogg", then ".wav". string resolve_audio_path(const string audioPath) { - if (audioPath == "") { - return ""; - } + if (audioPath == "") { + return ""; + } - if (file_exists(audioPath)) { - return audioPath; - } + if (file_exists(audioPath)) { + return audioPath; + } - string oggPath = audioPath + ".ogg"; - if (file_exists(oggPath)) { - return oggPath; - } + string oggPath = audioPath + ".ogg"; + if (file_exists(oggPath)) { + return oggPath; + } - string wavPath = audioPath + ".wav"; - if (file_exists(wavPath)) { - return wavPath; - } + string wavPath = audioPath + ".wav"; + if (file_exists(wavPath)) { + return wavPath; + } - return ""; + return ""; } diff --git a/crash_logger.nvgt b/crash_logger.nvgt index eb73657..358dcbb 100644 --- a/crash_logger.nvgt +++ b/crash_logger.nvgt @@ -1,58 +1,64 @@ // Crash and log helpers. string log_format_timestamp() { - datetime dt; - string stamp = dt.format(DATE_TIME_FORMAT_RFC1123); - return "[" + stamp + "]"; + datetime dt; + string stamp = dt.format(DATE_TIME_FORMAT_RFC1123); + return "[" + stamp + "]"; } -string log_flatten_multiline(const string&in text) { - string result = ""; - bool lastWasSeparator = false; +string log_flatten_multiline(const string& in text) { + string result = ""; + bool lastWasSeparator = false; - for (uint charIndex = 0; charIndex < text.length(); charIndex++) { - string ch = text.substr(charIndex, 1); - if (ch == "\r" || ch == "\n") { - if (!lastWasSeparator) { - result += " | "; - lastWasSeparator = true; - } - continue; - } + for (uint charIndex = 0; charIndex < text.length(); charIndex++) { + string ch = text.substr(charIndex, 1); + if (ch == "\r" || ch == "\n") { + if (!lastWasSeparator) { + result += " | "; + lastWasSeparator = true; + } + continue; + } - result += ch; - lastWasSeparator = false; - } + result += ch; + lastWasSeparator = false; + } - return result; + return result; } -bool log_append_line(const string&in logPath, const string&in message) { - file logFile; - if (!logFile.open(logPath, "ab")) { - return false; - } +bool log_append_line(const string& in logPath, const string& in message) { + file logFile; + if (!logFile.open(logPath, "ab")) { + return false; + } - // Keep log format as message then timestamp. - logFile.write(message + " " + log_format_timestamp() + "\r\n"); - logFile.close(); - return true; + // Keep log format as message then timestamp. + logFile.write(message + " " + log_format_timestamp() + "\r\n"); + logFile.close(); + return true; } -void log_unhandled_exception_to_file(const string&in logPath = "crash.log", const string&in context = "") { - string info = get_exception_info(); - string filePath = get_exception_file(); - int line = get_exception_line(); - string func = get_exception_function(); - string stack = log_flatten_multiline(last_exception_call_stack); +void log_unhandled_exception_to_file(const string& in logPath = "crash.log", const string& in context = "") { + string info = get_exception_info(); + string filePath = get_exception_file(); + int line = get_exception_line(); + string func = get_exception_function(); + string stack = log_flatten_multiline(last_exception_call_stack); - string message = "Unhandled exception"; - if (context != "") message += " (" + context + ")"; - if (info != "") message += ": " + info; - if (filePath != "") message += " at " + filePath; - if (line > 0) message += ":" + line; - if (func != "") message += " in " + func; - if (stack != "") message += " | stack: " + stack; + string message = "Unhandled exception"; + if (context != "") + message += " (" + context + ")"; + if (info != "") + message += ": " + info; + if (filePath != "") + message += " at " + filePath; + if (line > 0) + message += ":" + line; + if (func != "") + message += " in " + func; + if (stack != "") + message += " | stack: " + stack; - log_append_line(logPath, message); + log_append_line(logPath, message); } diff --git a/dict_utils.nvgt b/dict_utils.nvgt index 0a2e53e..b66fbd7 100644 --- a/dict_utils.nvgt +++ b/dict_utils.nvgt @@ -1,58 +1,72 @@ // Dictionary utility helpers. -double dict_get_number(dictionary@ data, const string&in key, double defaultValue) { - double value = 0.0; - if (@data is null) return defaultValue; - if (data.get(key, value)) return value; +double dict_get_number(dictionary @data, const string& in key, double defaultValue) { + double value = 0.0; + if (@data is null) + return defaultValue; + if (data.get(key, value)) + return value; - int valueInt = 0; - if (data.get(key, valueInt)) return valueInt; + int valueInt = 0; + if (data.get(key, valueInt)) + return valueInt; - string valueString = ""; - if (data.get(key, valueString)) { - return parse_int(valueString); - } + string valueString = ""; + if (data.get(key, valueString)) { + return parse_int(valueString); + } - return defaultValue; + return defaultValue; } -bool dict_get_bool(dictionary@ data, const string&in key, bool defaultValue) { - bool value = false; - if (@data is null) return defaultValue; - if (data.get(key, value)) return value; +bool dict_get_bool(dictionary @data, const string& in key, bool defaultValue) { + bool value = false; + if (@data is null) + return defaultValue; + if (data.get(key, value)) + return value; - int valueInt = 0; - if (data.get(key, valueInt)) return valueInt != 0; + int valueInt = 0; + if (data.get(key, valueInt)) + return valueInt != 0; - string valueString = ""; - if (data.get(key, valueString)) return valueString == "1" || valueString == "true"; + string valueString = ""; + if (data.get(key, valueString)) + return valueString == "1" || valueString == "true"; - return defaultValue; + return defaultValue; } -bool dict_has_keys(dictionary@ data) { - if (@data is null) return false; - string[]@ keys = data.get_keys(); - return @keys !is null && keys.length() > 0; +bool dict_has_keys(dictionary @data) { + if (@data is null) + return false; + string[] @keys = data.get_keys(); + return @keys !is null && keys.length() > 0; } -bool dict_has_number_key(dictionary@ data, const string&in key) { - double value = 0.0; - if (@data is null) return false; - if (data.get(key, value)) return true; +bool dict_has_number_key(dictionary @data, const string& in key) { + double value = 0.0; + if (@data is null) + return false; + if (data.get(key, value)) + return true; - int valueInt = 0; - if (data.get(key, valueInt)) return true; + int valueInt = 0; + if (data.get(key, valueInt)) + return true; - string valueString = ""; - if (data.get(key, valueString)) return valueString.length() > 0; + string valueString = ""; + if (data.get(key, valueString)) + return valueString.length() > 0; - return false; + return false; } -string[] dict_get_string_list(dictionary@ data, const string&in key) { - string[] result; - if (@data is null) return result; - if (!data.get(key, result)) return result; - return result; +string[] dict_get_string_list(dictionary @data, const string& in key) { + string[] result; + if (@data is null) + return result; + if (!data.get(key, result)) + return result; + return result; } diff --git a/docs_browser.nvgt b/docs_browser.nvgt index d149f89..aef886a 100644 --- a/docs_browser.nvgt +++ b/docs_browser.nvgt @@ -1,11 +1,11 @@ #include "audio_paths.nvgt" #include "file_viewer.nvgt" -funcdef void docs_browser_speak_callback(const string &in message, bool interrupt); +funcdef void docs_browser_speak_callback(const string& in message, bool interrupt); funcdef void docs_browser_tick_callback(); -docs_browser_speak_callback@ docsBrowserSpeakCallback = null; -docs_browser_tick_callback@ docsBrowserTickCallback = null; +docs_browser_speak_callback @docsBrowserSpeakCallback = null; +docs_browser_tick_callback @docsBrowserTickCallback = null; string docsBrowserDirectory = "files"; string docsBrowserMenuSoundDir = "sounds/menu"; @@ -16,189 +16,198 @@ string[] docsBrowserExtensions = {"md", "MD", "txt", "TXT"}; sound docsBrowserMoveSound; sound docsBrowserSelectSound; -void docs_browser_set_speak_callback(docs_browser_speak_callback@ callback) { - @docsBrowserSpeakCallback = @callback; +void docs_browser_set_speak_callback(docs_browser_speak_callback @callback) { + @docsBrowserSpeakCallback = @callback; } -void docs_browser_set_tick_callback(docs_browser_tick_callback@ callback) { - @docsBrowserTickCallback = @callback; +void docs_browser_set_tick_callback(docs_browser_tick_callback @callback) { + @docsBrowserTickCallback = @callback; } void docs_browser_set_docs_dir(const string docsDir) { - docsBrowserDirectory = docsDir; + docsBrowserDirectory = docsDir; } void docs_browser_set_menu_sound_dir(const string menuSoundDir) { - docsBrowserMenuSoundDir = menuSoundDir; + docsBrowserMenuSoundDir = menuSoundDir; } void docs_browser_set_wrap(bool wrap) { - docsBrowserWrap = wrap; + docsBrowserWrap = wrap; } -void docs_browser_set_extensions(string[]@ extensions) { - docsBrowserExtensions.resize(0); - if (@extensions is null) return; - for (uint extIndex = 0; extIndex < extensions.length(); extIndex++) { - docsBrowserExtensions.insert_last(extensions[extIndex]); - } +void docs_browser_set_extensions(string[] @extensions) { + docsBrowserExtensions.resize(0); + if (@extensions is null) + return; + for (uint extIndex = 0; extIndex < extensions.length(); extIndex++) { + docsBrowserExtensions.insert_last(extensions[extIndex]); + } } void docs_browser_reset_default_extensions() { - string[] defaults = {"md", "MD", "txt", "TXT"}; - docs_browser_set_extensions(defaults); + string[] defaults = {"md", "MD", "txt", "TXT"}; + docs_browser_set_extensions(defaults); } -void docs_browser_speak(const string &in message, bool interrupt) { - if (@docsBrowserSpeakCallback !is null) { - docsBrowserSpeakCallback(message, interrupt); - return; - } - screen_reader_speak(message, interrupt); +void docs_browser_speak(const string& in message, bool interrupt) { + if (@docsBrowserSpeakCallback !is null) { + docsBrowserSpeakCallback(message, interrupt); + return; + } + screen_reader_speak(message, interrupt); } void docs_browser_tick() { - if (@docsBrowserTickCallback !is null) { - docsBrowserTickCallback(); - } + if (@docsBrowserTickCallback !is null) { + docsBrowserTickCallback(); + } } -bool docs_browser_sort_case_insensitive(const string &in a, const string &in b) { - return a.lower() < b.lower(); +bool docs_browser_sort_case_insensitive(const string& in a, const string& in b) { + return a.lower() < b.lower(); } -void docs_browser_append_unique_case_insensitive(string[]@ items, const string&in value) { - string lowerValue = value.lower(); - for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) { - if (items[itemIndex].lower() == lowerValue) return; - } - items.insert_last(value); +void docs_browser_append_unique_case_insensitive(string[] @items, const string& in value) { + string lowerValue = value.lower(); + for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) { + if (items[itemIndex].lower() == lowerValue) + return; + } + items.insert_last(value); } -string docs_browser_collapse_spaces(const string&in text) { - string result = text; - while (result.find_first(" ") > -1) { - result = result.replace(" ", " ", true); - } - return result; +string docs_browser_collapse_spaces(const string& in text) { + string result = text; + while (result.find_first(" ") > -1) { + result = result.replace(" ", " ", true); + } + return result; } -string docs_browser_format_label(const string&in filename) { - string name = filename; - int dotPos = name.find_last_of("."); - if (dotPos > 0) { - name = name.substr(0, dotPos); - } +string docs_browser_format_label(const string& in filename) { + string name = filename; + int dotPos = name.find_last_of("."); + if (dotPos > 0) { + name = name.substr(0, dotPos); + } - name = name.replace("_", " ", true); - name = name.replace("-", " ", true); - name = docs_browser_collapse_spaces(name); - name = name.lower(); - name.trim_whitespace_this(); + name = name.replace("_", " ", true); + name = name.replace("-", " ", true); + name = docs_browser_collapse_spaces(name); + name = name.lower(); + name.trim_whitespace_this(); - if (name.length() == 0) return "Document"; - string first = name.substr(0, 1).upper(); - if (name.length() == 1) return first; - return first + name.substr(1); + if (name.length() == 0) + return "Document"; + string first = name.substr(0, 1).upper(); + if (name.length() == 1) + return first; + return first + name.substr(1); } -void docs_browser_collect_entries(string[]@ labels, string[]@ paths) { - labels.resize(0); - paths.resize(0); +void docs_browser_collect_entries(string[] @labels, string[] @paths) { + labels.resize(0); + paths.resize(0); - if (!directory_exists(docsBrowserDirectory)) return; + if (!directory_exists(docsBrowserDirectory)) + return; - string[] docFiles; - for (uint extIndex = 0; extIndex < docsBrowserExtensions.length(); extIndex++) { - string ext = docsBrowserExtensions[extIndex]; - if (ext == "") continue; - if (ext.substr(0, 1) == ".") { - ext = ext.substr(1); - } + string[] docFiles; + for (uint extIndex = 0; extIndex < docsBrowserExtensions.length(); extIndex++) { + string ext = docsBrowserExtensions[extIndex]; + if (ext == "") + continue; + if (ext.substr(0, 1) == ".") { + ext = ext.substr(1); + } - string[]@ found = find_files(docsBrowserDirectory + "/*." + ext); - if (@found is null) continue; - for (uint fileIndex = 0; fileIndex < found.length(); fileIndex++) { - docs_browser_append_unique_case_insensitive(docFiles, found[fileIndex]); - } - } + string[] @found = find_files(docsBrowserDirectory + "/*." + ext); + if (@found is null) + continue; + for (uint fileIndex = 0; fileIndex < found.length(); fileIndex++) { + docs_browser_append_unique_case_insensitive(docFiles, found[fileIndex]); + } + } - if (docFiles.length() > 1) { - docFiles.sort(docs_browser_sort_case_insensitive); - } + if (docFiles.length() > 1) { + docFiles.sort(docs_browser_sort_case_insensitive); + } - for (uint fileIndex = 0; fileIndex < docFiles.length(); fileIndex++) { - labels.insert_last(docs_browser_format_label(docFiles[fileIndex])); - paths.insert_last(docsBrowserDirectory + "/" + docFiles[fileIndex]); - } + for (uint fileIndex = 0; fileIndex < docFiles.length(); fileIndex++) { + labels.insert_last(docs_browser_format_label(docFiles[fileIndex])); + paths.insert_last(docsBrowserDirectory + "/" + docFiles[fileIndex]); + } } -void docs_browser_add_entries(string[]@ labels, string[]@ paths, int[]@ types, const int typeValue = 1) { - string[] docLabels; - string[] docPaths; - docs_browser_collect_entries(docLabels, docPaths); +void docs_browser_add_entries(string[] @labels, string[] @paths, int[] @types, const int typeValue = 1) { + string[] docLabels; + string[] docPaths; + docs_browser_collect_entries(docLabels, docPaths); - for (uint entryIndex = 0; entryIndex < docLabels.length(); entryIndex++) { - labels.insert_last(docLabels[entryIndex]); - paths.insert_last(docPaths[entryIndex]); - types.insert_last(typeValue); - } + for (uint entryIndex = 0; entryIndex < docLabels.length(); entryIndex++) { + labels.insert_last(docLabels[entryIndex]); + paths.insert_last(docPaths[entryIndex]); + types.insert_last(typeValue); + } } -void docs_browser_play_ui_sound(sound &inout soundObj, const string basePath) { - string soundPath = resolve_audio_path(basePath); - if (soundPath == "") return; +void docs_browser_play_ui_sound(sound& inout soundObj, const string basePath) { + string soundPath = resolve_audio_path(basePath); + if (soundPath == "") + return; - soundObj.close(); - if (!soundObj.load(soundPath)) return; - soundObj.play(); + soundObj.close(); + if (!soundObj.load(soundPath)) + return; + soundObj.play(); } void docs_browser_run_menu(const string menuTitle = "Documents") { - string[] labels; - string[] paths; - docs_browser_collect_entries(labels, paths); + string[] labels; + string[] paths; + docs_browser_collect_entries(labels, paths); - docs_browser_speak(menuTitle + ".", true); - if (labels.length() == 0) { - docs_browser_speak("No documents found.", true); - return; - } + docs_browser_speak(menuTitle + ".", true); + if (labels.length() == 0) { + docs_browser_speak("No documents found.", true); + return; + } - int selection = 0; - docs_browser_speak(labels[selection], true); + int selection = 0; + docs_browser_speak(labels[selection], true); - while (true) { - wait(5); - docs_browser_tick(); + while (true) { + wait(5); + docs_browser_tick(); - if (key_pressed(KEY_ESCAPE)) { - docs_browser_speak("Closed.", true); - return; - } + if (key_pressed(KEY_ESCAPE)) { + docs_browser_speak("Closed.", true); + return; + } - if (key_pressed(KEY_DOWN)) { - docs_browser_play_ui_sound(docsBrowserMoveSound, docsBrowserMenuSoundDir + "/menu_move"); - selection++; - if (selection >= int(labels.length())) { - selection = docsBrowserWrap ? 0 : int(labels.length()) - 1; - } - docs_browser_speak(labels[selection], true); - } + if (key_pressed(KEY_DOWN)) { + docs_browser_play_ui_sound(docsBrowserMoveSound, docsBrowserMenuSoundDir + "/menu_move"); + selection++; + if (selection >= int(labels.length())) { + selection = docsBrowserWrap ? 0 : int(labels.length()) - 1; + } + docs_browser_speak(labels[selection], true); + } - if (key_pressed(KEY_UP)) { - docs_browser_play_ui_sound(docsBrowserMoveSound, docsBrowserMenuSoundDir + "/menu_move"); - selection--; - if (selection < 0) { - selection = docsBrowserWrap ? int(labels.length()) - 1 : 0; - } - docs_browser_speak(labels[selection], true); - } + if (key_pressed(KEY_UP)) { + docs_browser_play_ui_sound(docsBrowserMoveSound, docsBrowserMenuSoundDir + "/menu_move"); + selection--; + if (selection < 0) { + selection = docsBrowserWrap ? int(labels.length()) - 1 : 0; + } + docs_browser_speak(labels[selection], true); + } - if (key_pressed(KEY_RETURN)) { - docs_browser_play_ui_sound(docsBrowserSelectSound, docsBrowserMenuSoundDir + "/menu_select"); - file_viewer_file(paths[selection], labels[selection], true); - docs_browser_speak(labels[selection], true); - } - } + if (key_pressed(KEY_RETURN)) { + docs_browser_play_ui_sound(docsBrowserSelectSound, docsBrowserMenuSoundDir + "/menu_select"); + file_viewer_file(paths[selection], labels[selection], true); + docs_browser_speak(labels[selection], true); + } + } } diff --git a/file_viewer.nvgt b/file_viewer.nvgt index 9a72846..21c9c4c 100644 --- a/file_viewer.nvgt +++ b/file_viewer.nvgt @@ -3,83 +3,76 @@ // Reusable text/file viewer based on NVGT audio_form. // Returns edited text in edit mode when user confirms. string file_viewer(string content, string title = "Text Reader", bool readOnly = true) { - audio_form f; - f.create_window(title, false, true); + audio_form f; + f.create_window(title, false, true); - int textControl = f.create_input_box( - (readOnly ? "Document (read only)" : "Document (editable)"), - content, - "", - 0, - readOnly, - true, - true - ); + int textControl = f.create_input_box((readOnly ? "Document (read only)" : "Document (editable)"), content, "", 0, + readOnly, true, true); - int okButton = -1; - int closeButton = -1; - if (readOnly) { - closeButton = f.create_button("&Close", true, true); - } else { - okButton = f.create_button("&OK", true); - closeButton = f.create_button("&Cancel", false, true); - } + int okButton = -1; + int closeButton = -1; + if (readOnly) { + closeButton = f.create_button("&Close", true, true); + } else { + okButton = f.create_button("&OK", true); + closeButton = f.create_button("&Cancel", false, true); + } - f.focus(textControl); + f.focus(textControl); - while (true) { - f.monitor(); - wait(5); + while (true) { + f.monitor(); + wait(5); - if (!readOnly && okButton != -1 && f.is_pressed(okButton)) { - return f.get_text(textControl); - } + if (!readOnly && okButton != -1 && f.is_pressed(okButton)) { + return f.get_text(textControl); + } - if (closeButton != -1 && f.is_pressed(closeButton)) { - return ""; - } + if (closeButton != -1 && f.is_pressed(closeButton)) { + return ""; + } - if (key_pressed(KEY_ESCAPE)) { - return ""; - } - } + if (key_pressed(KEY_ESCAPE)) { + return ""; + } + } - return ""; + return ""; } string file_viewer_lines(string[] lines, string title = "Text Reader", bool readOnly = true) { - string content = join(lines, "\n"); - return file_viewer(content, title, readOnly); + string content = join(lines, "\n"); + return file_viewer(content, title, readOnly); } // Opens a file in the viewer. In edit mode, saves on confirm. // Returns edited text when saved or empty string when canceled/failure. string file_viewer_file(string filePath, string title = "", bool readOnly = true) { - file f; - if (!f.open(filePath, "rb")) { - screen_reader_speak("Failed to open file: " + filePath, true); - return ""; - } + file f; + if (!f.open(filePath, "rb")) { + screen_reader_speak("Failed to open file: " + filePath, true); + return ""; + } - string content = f.read(); - f.close(); + string content = f.read(); + f.close(); - if (title == "") { - title = filePath; - } + if (title == "") { + title = filePath; + } - string result = file_viewer(content, title, readOnly); + string result = file_viewer(content, title, readOnly); - if (!readOnly && result != "") { - if (f.open(filePath, "wb")) { - f.write(result); - f.close(); - screen_reader_speak("File saved successfully", true); - return result; - } + if (!readOnly && result != "") { + if (f.open(filePath, "wb")) { + f.write(result); + f.close(); + screen_reader_speak("File saved successfully", true); + return result; + } - screen_reader_speak("Failed to save file", true); - } + screen_reader_speak("Failed to save file", true); + } - return result; + return result; } diff --git a/learn_sounds.nvgt b/learn_sounds.nvgt index de5d4a9..ec366a2 100644 --- a/learn_sounds.nvgt +++ b/learn_sounds.nvgt @@ -1,12 +1,12 @@ #include "audio_paths.nvgt" -funcdef void learn_sounds_speak_callback(const string &in message, bool interrupt); +funcdef void learn_sounds_speak_callback(const string& in message, bool interrupt); funcdef void learn_sounds_tick_callback(); funcdef void learn_sounds_setup_callback(); -learn_sounds_speak_callback@ learnSoundsSpeakCallback = null; -learn_sounds_tick_callback@ learnSoundsTickCallback = null; -learn_sounds_setup_callback@ learnSoundsSetupCallback = null; +learn_sounds_speak_callback @learnSoundsSpeakCallback = null; +learn_sounds_tick_callback @learnSoundsTickCallback = null; +learn_sounds_setup_callback @learnSoundsSetupCallback = null; string[] learnSoundsSkipList; string[] learnSoundsDescriptionPaths; @@ -22,319 +22,390 @@ sound learnSoundsPreviewSound; sound learnSoundsMoveSound; sound learnSoundsSelectSound; -void learn_sounds_set_speak_callback(learn_sounds_speak_callback@ callback) { - @learnSoundsSpeakCallback = @callback; +void learn_sounds_set_speak_callback(learn_sounds_speak_callback @callback) { + @learnSoundsSpeakCallback = @callback; } -void learn_sounds_set_tick_callback(learn_sounds_tick_callback@ callback) { - @learnSoundsTickCallback = @callback; +void learn_sounds_set_tick_callback(learn_sounds_tick_callback @callback) { + @learnSoundsTickCallback = @callback; } -void learn_sounds_set_setup_callback(learn_sounds_setup_callback@ callback) { - @learnSoundsSetupCallback = @callback; - learnSoundsSetupApplied = false; +void learn_sounds_set_setup_callback(learn_sounds_setup_callback @callback) { + @learnSoundsSetupCallback = @callback; + learnSoundsSetupApplied = false; } void learn_sounds_set_root_dir(const string rootDir) { - learnSoundsRootDir = rootDir; + learnSoundsRootDir = rootDir; } void learn_sounds_set_menu_sound_dir(const string menuSoundDir) { - learnSoundsMenuSoundDir = menuSoundDir; + learnSoundsMenuSoundDir = menuSoundDir; } void learn_sounds_set_wrap(bool wrap) { - learnSoundsWrap = wrap; + learnSoundsWrap = wrap; } void learn_sounds_set_play_select_sound(bool playSelectSound) { - learnSoundsPlaySelectSound = playSelectSound; + learnSoundsPlaySelectSound = playSelectSound; } void learn_sounds_clear_skip_entries() { - learnSoundsSkipList.resize(0); + learnSoundsSkipList.resize(0); } void learn_sounds_add_skip_entry(const string entry) { - if (entry == "") { - return; - } - learnSoundsSkipList.insert_last(entry); + if (entry == "") { + return; + } + learnSoundsSkipList.insert_last(entry); } void learn_sounds_clear_descriptions() { - learnSoundsDescriptionPaths.resize(0); - learnSoundsDescriptionTexts.resize(0); + learnSoundsDescriptionPaths.resize(0); + learnSoundsDescriptionTexts.resize(0); } void learn_sounds_add_description(const string soundPath, const string description) { - if (soundPath == "") { - return; - } - learnSoundsDescriptionPaths.insert_last(soundPath); - learnSoundsDescriptionTexts.insert_last(description); + if (soundPath == "") { + return; + } + learnSoundsDescriptionPaths.insert_last(soundPath); + learnSoundsDescriptionTexts.insert_last(description); } void learn_sounds_reset_configuration() { - learn_sounds_clear_skip_entries(); - learn_sounds_clear_descriptions(); - learnSoundsSetupApplied = false; + learn_sounds_clear_skip_entries(); + learn_sounds_clear_descriptions(); + learnSoundsSetupApplied = false; } -void learn_sounds_speak(const string &in message, bool interrupt) { - if (@learnSoundsSpeakCallback !is null) { - learnSoundsSpeakCallback(message, interrupt); - return; - } - screen_reader_speak(message, interrupt); +void learn_sounds_speak(const string& in message, bool interrupt) { + if (@learnSoundsSpeakCallback !is null) { + learnSoundsSpeakCallback(message, interrupt); + return; + } + screen_reader_speak(message, interrupt); } void learn_sounds_tick() { - if (@learnSoundsTickCallback !is null) { - learnSoundsTickCallback(); - } + if (@learnSoundsTickCallback !is null) { + learnSoundsTickCallback(); + } } void learn_sounds_apply_setup_once() { - if (learnSoundsSetupApplied) { - return; - } + if (learnSoundsSetupApplied) { + return; + } - if (@learnSoundsSetupCallback !is null) { - learnSoundsSetupCallback(); - } + if (@learnSoundsSetupCallback !is null) { + learnSoundsSetupCallback(); + } - learnSoundsSetupApplied = true; + learnSoundsSetupApplied = true; } -string learn_sounds_normalize_path(const string&in path) { - return path.replace("\\", "/", true); +string learn_sounds_normalize_path(const string& in path) { + return path.replace("\\", "/", true); } -bool learn_sounds_is_directory_skip_entry(const string&in entry) { - if (entry.length() == 0) return false; - if (entry.substr(entry.length() - 1) == "/") return true; - return directory_exists(entry); +bool learn_sounds_is_directory_skip_entry(const string& in entry) { + if (entry.length() == 0) + return false; + if (entry.substr(entry.length() - 1) == "/") + return true; + return directory_exists(entry); } -bool learn_sounds_should_skip_path(const string&in path) { - string normalizedPath = learn_sounds_normalize_path(path); - for (uint skipIndex = 0; skipIndex < learnSoundsSkipList.length(); skipIndex++) { - string entry = learn_sounds_normalize_path(learnSoundsSkipList[skipIndex]); - if (entry.length() == 0) continue; +bool learn_sounds_should_skip_path(const string& in path) { + string normalizedPath = learn_sounds_normalize_path(path); + for (uint skipIndex = 0; skipIndex < learnSoundsSkipList.length(); skipIndex++) { + string entry = learn_sounds_normalize_path(learnSoundsSkipList[skipIndex]); + if (entry.length() == 0) + continue; - bool isDirectory = learn_sounds_is_directory_skip_entry(entry); - if (isDirectory) { - if (entry.substr(entry.length() - 1) != "/") entry += "/"; - if (normalizedPath.length() >= entry.length() && - normalizedPath.substr(0, entry.length()) == entry) { - return true; - } - continue; - } + bool isDirectory = learn_sounds_is_directory_skip_entry(entry); + if (isDirectory) { + if (entry.substr(entry.length() - 1) != "/") + entry += "/"; + if (normalizedPath.length() >= entry.length() && normalizedPath.substr(0, entry.length()) == entry) { + return true; + } + continue; + } - if (normalizedPath == entry) return true; + if (normalizedPath == entry) + return true; - if (entry.find_first("/") < 0 && entry.find_first("\\") < 0) { - if (normalizedPath.length() >= entry.length() + 1 && - normalizedPath.substr(normalizedPath.length() - entry.length()) == entry) { - return true; - } - } - } - return false; + if (entry.find_first("/") < 0 && entry.find_first("\\") < 0) { + if (normalizedPath.length() >= entry.length() + 1 && + normalizedPath.substr(normalizedPath.length() - entry.length()) == entry) { + return true; + } + } + } + return false; } -string learn_sounds_get_description(const string&in path) { - string normalizedPath = learn_sounds_normalize_path(path); - uint descriptionCount = learnSoundsDescriptionPaths.length(); - if (learnSoundsDescriptionTexts.length() < descriptionCount) { - descriptionCount = learnSoundsDescriptionTexts.length(); - } +string learn_sounds_get_description(const string& in path) { + string normalizedPath = learn_sounds_normalize_path(path); + uint descriptionCount = learnSoundsDescriptionPaths.length(); + if (learnSoundsDescriptionTexts.length() < descriptionCount) { + descriptionCount = learnSoundsDescriptionTexts.length(); + } - for (uint descriptionIndex = 0; descriptionIndex < descriptionCount; descriptionIndex++) { - if (learn_sounds_normalize_path(learnSoundsDescriptionPaths[descriptionIndex]) == normalizedPath) { - return learnSoundsDescriptionTexts[descriptionIndex]; - } - } + for (uint descriptionIndex = 0; descriptionIndex < descriptionCount; descriptionIndex++) { + if (learn_sounds_normalize_path(learnSoundsDescriptionPaths[descriptionIndex]) == normalizedPath) { + return learnSoundsDescriptionTexts[descriptionIndex]; + } + } - return ""; + return ""; } -void learn_sounds_gather_files_recursive(const string&in basePath, string[]@ outFiles) { - string[]@ oggFiles = find_files(basePath + "/*.ogg"); - if (@oggFiles !is null) { - for (uint fileIndex = 0; fileIndex < oggFiles.length(); fileIndex++) { - outFiles.insert_last(basePath + "/" + oggFiles[fileIndex]); - } - } - - string[]@ oggUpperFiles = find_files(basePath + "/*.OGG"); - if (@oggUpperFiles !is null) { - for (uint fileIndex = 0; fileIndex < oggUpperFiles.length(); fileIndex++) { - outFiles.insert_last(basePath + "/" + oggUpperFiles[fileIndex]); - } - } - - string[]@ wavFiles = find_files(basePath + "/*.wav"); - if (@wavFiles !is null) { - for (uint fileIndex = 0; fileIndex < wavFiles.length(); fileIndex++) { - outFiles.insert_last(basePath + "/" + wavFiles[fileIndex]); - } - } - - string[]@ wavUpperFiles = find_files(basePath + "/*.WAV"); - if (@wavUpperFiles !is null) { - for (uint fileIndex = 0; fileIndex < wavUpperFiles.length(); fileIndex++) { - outFiles.insert_last(basePath + "/" + wavUpperFiles[fileIndex]); - } - } - - string[]@ folders = find_directories(basePath + "/*"); - if (@folders !is null) { - for (uint folderIndex = 0; folderIndex < folders.length(); folderIndex++) { - learn_sounds_gather_files_recursive(basePath + "/" + folders[folderIndex], outFiles); - } - } +bool learn_sounds_contains_path_ci(string[] @paths, const string& in path) { + string normalizedPath = learn_sounds_normalize_path(path).lower(); + for (uint pathIndex = 0; pathIndex < paths.length(); pathIndex++) { + if (learn_sounds_normalize_path(paths[pathIndex]).lower() == normalizedPath) { + return true; + } + } + return false; } -bool learn_sounds_sort_case_insensitive(const string &in a, const string &in b) { - return a.lower() < b.lower(); +void learn_sounds_add_path_if_missing(string[] @paths, const string& in path) { + if (learn_sounds_contains_path_ci(paths, path)) { + return; + } + paths.insert_last(path); } -string learn_sounds_collapse_spaces(const string&in text) { - string result = text; - while (result.find_first(" ") > -1) { - result = result.replace(" ", " ", true); - } - return result; +bool learn_sounds_has_audio_extension(const string& in path) { + string lowerPath = path.lower(); + if (lowerPath.length() < 4) + return false; + string suffix = lowerPath.substr(lowerPath.length() - 4); + return suffix == ".ogg" || suffix == ".wav"; } -string learn_sounds_label_from_path(const string&in soundPath) { - string normalizedPath = learn_sounds_normalize_path(soundPath); - int slashPos = normalizedPath.find_last_of("/"); - string name = (slashPos >= 0) ? normalizedPath.substr(slashPos + 1) : normalizedPath; +void learn_sounds_gather_files_from_pack(const string& in basePath, string[] @outFiles) { + pack @activePack = cast(sound_default_pack); + if (@activePack is null) + return; - string lowerName = name.lower(); - if (lowerName.length() > 4 && lowerName.substr(lowerName.length() - 4) == ".ogg") { - name = name.substr(0, name.length() - 4); - } else if (lowerName.length() > 4 && lowerName.substr(lowerName.length() - 4) == ".wav") { - name = name.substr(0, name.length() - 4); - } + string[] @packFiles = activePack.list_files(); + if (@packFiles is null) + return; - name = name.replace("_", " ", true); - name = name.replace("-", " ", true); - name = learn_sounds_collapse_spaces(name); - name = name.lower(); - name.trim_whitespace_this(); + string normalizedBasePath = learn_sounds_normalize_path(basePath); + if (normalizedBasePath != "" && normalizedBasePath.substr(normalizedBasePath.length() - 1) != "/") { + normalizedBasePath += "/"; + } + string normalizedBasePathLower = normalizedBasePath.lower(); - if (name.length() == 0) return "Sound"; - return name; + for (uint fileIndex = 0; fileIndex < packFiles.length(); fileIndex++) { + string normalizedPath = learn_sounds_normalize_path(packFiles[fileIndex]); + if (normalizedPath.find("./") == 0) { + normalizedPath = normalizedPath.substr(2); + } + + if (!learn_sounds_has_audio_extension(normalizedPath)) { + continue; + } + + if (normalizedBasePathLower != "") { + if (normalizedPath.length() < normalizedBasePathLower.length()) { + continue; + } + if (normalizedPath.substr(0, normalizedBasePathLower.length()).lower() != normalizedBasePathLower) { + continue; + } + } + + learn_sounds_add_path_if_missing(outFiles, normalizedPath); + } } -void learn_sounds_collect_entries(string[]@ labels, string[]@ soundPaths) { - labels.resize(0); - soundPaths.resize(0); +void learn_sounds_gather_files_recursive(const string& in basePath, string[] @outFiles) { + string[] @oggFiles = find_files(basePath + "/*.ogg"); + if (@oggFiles !is null) { + for (uint fileIndex = 0; fileIndex < oggFiles.length(); fileIndex++) { + learn_sounds_add_path_if_missing(outFiles, basePath + "/" + oggFiles[fileIndex]); + } + } - if (!directory_exists(learnSoundsRootDir)) { - return; - } + string[] @oggUpperFiles = find_files(basePath + "/*.OGG"); + if (@oggUpperFiles !is null) { + for (uint fileIndex = 0; fileIndex < oggUpperFiles.length(); fileIndex++) { + learn_sounds_add_path_if_missing(outFiles, basePath + "/" + oggUpperFiles[fileIndex]); + } + } - string[] discoveredFiles; - learn_sounds_gather_files_recursive(learnSoundsRootDir, discoveredFiles); - if (discoveredFiles.length() > 1) { - discoveredFiles.sort(learn_sounds_sort_case_insensitive); - } + string[] @wavFiles = find_files(basePath + "/*.wav"); + if (@wavFiles !is null) { + for (uint fileIndex = 0; fileIndex < wavFiles.length(); fileIndex++) { + learn_sounds_add_path_if_missing(outFiles, basePath + "/" + wavFiles[fileIndex]); + } + } - for (uint fileIndex = 0; fileIndex < discoveredFiles.length(); fileIndex++) { - string soundPath = learn_sounds_normalize_path(discoveredFiles[fileIndex]); - if (learn_sounds_should_skip_path(soundPath)) { - continue; - } + string[] @wavUpperFiles = find_files(basePath + "/*.WAV"); + if (@wavUpperFiles !is null) { + for (uint fileIndex = 0; fileIndex < wavUpperFiles.length(); fileIndex++) { + learn_sounds_add_path_if_missing(outFiles, basePath + "/" + wavUpperFiles[fileIndex]); + } + } - string label = learn_sounds_label_from_path(soundPath); - string description = learn_sounds_get_description(soundPath); - if (description.length() > 0) { - label += " - " + description; - } - - labels.insert_last(label); - soundPaths.insert_last(soundPath); - } + string[] @folders = find_directories(basePath + "/*"); + if (@folders !is null) { + for (uint folderIndex = 0; folderIndex < folders.length(); folderIndex++) { + learn_sounds_gather_files_recursive(basePath + "/" + folders[folderIndex], outFiles); + } + } } -void learn_sounds_play_ui_sound(sound &inout soundObj, const string basePath) { - string soundPath = resolve_audio_path(basePath); - if (soundPath == "") { - return; - } +bool learn_sounds_sort_case_insensitive(const string& in a, const string& in b) { + return a.lower() < b.lower(); +} - soundObj.close(); - if (!soundObj.load(soundPath)) { - return; - } - soundObj.play(); +string learn_sounds_collapse_spaces(const string& in text) { + string result = text; + while (result.find_first(" ") > -1) { + result = result.replace(" ", " ", true); + } + return result; +} + +string learn_sounds_label_from_path(const string& in soundPath) { + string normalizedPath = learn_sounds_normalize_path(soundPath); + int slashPos = normalizedPath.find_last_of("/"); + string name = (slashPos >= 0) ? normalizedPath.substr(slashPos + 1) : normalizedPath; + + string lowerName = name.lower(); + if (lowerName.length() > 4 && lowerName.substr(lowerName.length() - 4) == ".ogg") { + name = name.substr(0, name.length() - 4); + } else if (lowerName.length() > 4 && lowerName.substr(lowerName.length() - 4) == ".wav") { + name = name.substr(0, name.length() - 4); + } + + name = name.replace("_", " ", true); + name = name.replace("-", " ", true); + name = learn_sounds_collapse_spaces(name); + name = name.lower(); + name.trim_whitespace_this(); + + if (name.length() == 0) + return "Sound"; + return name; +} + +void learn_sounds_collect_entries(string[] @labels, string[] @soundPaths) { + labels.resize(0); + soundPaths.resize(0); + + string[] discoveredFiles; + if (directory_exists(learnSoundsRootDir)) { + learn_sounds_gather_files_recursive(learnSoundsRootDir, discoveredFiles); + } + learn_sounds_gather_files_from_pack(learnSoundsRootDir, discoveredFiles); + if (discoveredFiles.length() > 1) { + discoveredFiles.sort(learn_sounds_sort_case_insensitive); + } + + for (uint fileIndex = 0; fileIndex < discoveredFiles.length(); fileIndex++) { + string soundPath = learn_sounds_normalize_path(discoveredFiles[fileIndex]); + if (learn_sounds_should_skip_path(soundPath)) { + continue; + } + + string label = learn_sounds_label_from_path(soundPath); + string description = learn_sounds_get_description(soundPath); + if (description.length() > 0) { + label += " - " + description; + } + + labels.insert_last(label); + soundPaths.insert_last(soundPath); + } +} + +void learn_sounds_play_ui_sound(sound& inout soundObj, const string basePath) { + soundObj.close(); + + // Avoid file_exists()-only path checks so packaged Android assets can still load. + if (soundObj.load(basePath)) { + soundObj.play(); + return; + } + + if (soundObj.load(basePath + ".ogg")) { + soundObj.play(); + return; + } + + if (!soundObj.load(basePath + ".wav")) { + return; + } + + soundObj.play(); } void learn_sounds_run_menu() { - learn_sounds_apply_setup_once(); + learn_sounds_apply_setup_once(); - string[] labels; - string[] soundPaths; - learn_sounds_collect_entries(labels, soundPaths); + string[] labels; + string[] soundPaths; + learn_sounds_collect_entries(labels, soundPaths); - learn_sounds_speak("Learn sounds.", true); - if (labels.length() == 0) { - learn_sounds_speak("No sounds available.", true); - return; - } + learn_sounds_speak("Learn sounds.", true); + if (labels.length() == 0) { + learn_sounds_speak("No sounds available.", true); + return; + } - int selection = 0; - learn_sounds_speak(labels[selection], true); + int selection = 0; + learn_sounds_speak(labels[selection], true); - while (true) { - wait(5); - learn_sounds_tick(); + while (true) { + wait(5); + learn_sounds_tick(); - if (key_pressed(KEY_ESCAPE)) { - learn_sounds_speak("Closed.", true); - return; - } + if (key_pressed(KEY_ESCAPE)) { + learn_sounds_speak("Closed.", true); + return; + } - if (key_pressed(KEY_DOWN)) { - learn_sounds_play_ui_sound(learnSoundsMoveSound, learnSoundsMenuSoundDir + "/menu_move"); - selection++; - if (selection >= int(labels.length())) { - selection = learnSoundsWrap ? 0 : int(labels.length()) - 1; - } - learn_sounds_speak(labels[selection], true); - } + if (key_pressed(KEY_DOWN)) { + learn_sounds_play_ui_sound(learnSoundsMoveSound, learnSoundsMenuSoundDir + "/menu_move"); + selection++; + if (selection >= int(labels.length())) { + selection = learnSoundsWrap ? 0 : int(labels.length()) - 1; + } + learn_sounds_speak(labels[selection], true); + } - if (key_pressed(KEY_UP)) { - learn_sounds_play_ui_sound(learnSoundsMoveSound, learnSoundsMenuSoundDir + "/menu_move"); - selection--; - if (selection < 0) { - selection = learnSoundsWrap ? int(labels.length()) - 1 : 0; - } - learn_sounds_speak(labels[selection], true); - } + if (key_pressed(KEY_UP)) { + learn_sounds_play_ui_sound(learnSoundsMoveSound, learnSoundsMenuSoundDir + "/menu_move"); + selection--; + if (selection < 0) { + selection = learnSoundsWrap ? int(labels.length()) - 1 : 0; + } + learn_sounds_speak(labels[selection], true); + } - if (key_pressed(KEY_RETURN)) { - if (learnSoundsPlaySelectSound) { - learn_sounds_play_ui_sound(learnSoundsSelectSound, learnSoundsMenuSoundDir + "/menu_select"); - } - string selectedPath = soundPaths[selection]; - if (!file_exists(selectedPath)) { - learn_sounds_speak("Sound not found.", true); - continue; - } + if (key_pressed(KEY_RETURN)) { + if (learnSoundsPlaySelectSound) { + learn_sounds_play_ui_sound(learnSoundsSelectSound, learnSoundsMenuSoundDir + "/menu_select"); + } + string selectedPath = soundPaths[selection]; - learnSoundsPreviewSound.close(); - if (!learnSoundsPreviewSound.load(selectedPath)) { - learn_sounds_speak("Unable to load sound.", true); - continue; - } - learnSoundsPreviewSound.play(); - } - } + learnSoundsPreviewSound.close(); + if (!learnSoundsPreviewSound.load(selectedPath)) { + learn_sounds_speak("Unable to load sound.", true); + continue; + } + learnSoundsPreviewSound.play(); + } + } } diff --git a/menu_helpers.nvgt b/menu_helpers.nvgt index 05a1917..e4aec32 100644 --- a/menu_helpers.nvgt +++ b/menu_helpers.nvgt @@ -3,120 +3,150 @@ // Applies common menu sounds from a directory. // Looks for both .ogg and .wav files automatically. -void menu_apply_default_sounds(menu@ menuRef, const string soundDir = "sounds/menu") { - if (@menuRef is null) { - return; - } +void menu_apply_default_sounds(menu @menuRef, const string soundDir = "sounds/menu") { + if (@menuRef is null) { + return; + } - menuRef.click_sound = resolve_audio_path(soundDir + "/menu_move"); - menuRef.select_sound = resolve_audio_path(soundDir + "/menu_select"); - menuRef.edge_sound = resolve_audio_path(soundDir + "/menu_edge"); - menuRef.wrap_sound = resolve_audio_path(soundDir + "/menu_wrap"); - menuRef.open_sound = resolve_audio_path(soundDir + "/menu_open"); - menuRef.close_sound = resolve_audio_path(soundDir + "/menu_close"); + menuRef.click_sound = resolve_audio_path(soundDir + "/menu_move"); + menuRef.select_sound = resolve_audio_path(soundDir + "/menu_select"); + menuRef.edge_sound = resolve_audio_path(soundDir + "/menu_edge"); + menuRef.wrap_sound = resolve_audio_path(soundDir + "/menu_wrap"); + menuRef.open_sound = resolve_audio_path(soundDir + "/menu_open"); + menuRef.close_sound = resolve_audio_path(soundDir + "/menu_close"); } // Minimal blocking list menu. // Returns selected index or -1 on empty input/escape. -int menu_run_simple(const string introText, string[]@ options, bool wrap = true, int startIndex = 0, const string soundDir = "sounds/menu") { - if (@options is null || options.length() == 0) { - return -1; - } +int menu_run_simple(const string introText, string[] @options, bool wrap = true, int startIndex = 0, + const string soundDir = "sounds/menu") { + if (@options is null || options.length() == 0) { + return -1; + } - menu menuRef; - menu_apply_default_sounds(menuRef, soundDir); - menuRef.intro_text = introText; - menuRef.wrap = wrap; - menuRef.focus_first_item = true; - menuRef.add_items(options); + menu menuRef; + menu_apply_default_sounds(menuRef, soundDir); + menuRef.intro_text = introText; + menuRef.wrap = wrap; + menuRef.focus_first_item = true; + menuRef.add_items(options); - if (startIndex >= 0 && startIndex < int(options.length())) { - menuRef.focused_item = startIndex; - } + if (startIndex >= 0 && startIndex < int(options.length())) { + menuRef.focused_item = startIndex; + } - return menuRef.run(); + return menuRef.run(); } // Returns a-z for menu prefix filtering, or empty string when no letter key was pressed. string menu_get_filter_letter() { - if (key_pressed(KEY_A)) return "a"; - if (key_pressed(KEY_B)) return "b"; - if (key_pressed(KEY_C)) return "c"; - if (key_pressed(KEY_D)) return "d"; - if (key_pressed(KEY_E)) return "e"; - if (key_pressed(KEY_F)) return "f"; - if (key_pressed(KEY_G)) return "g"; - if (key_pressed(KEY_H)) return "h"; - if (key_pressed(KEY_I)) return "i"; - if (key_pressed(KEY_J)) return "j"; - if (key_pressed(KEY_K)) return "k"; - if (key_pressed(KEY_L)) return "l"; - if (key_pressed(KEY_M)) return "m"; - if (key_pressed(KEY_N)) return "n"; - if (key_pressed(KEY_O)) return "o"; - if (key_pressed(KEY_P)) return "p"; - if (key_pressed(KEY_Q)) return "q"; - if (key_pressed(KEY_R)) return "r"; - if (key_pressed(KEY_S)) return "s"; - if (key_pressed(KEY_T)) return "t"; - if (key_pressed(KEY_U)) return "u"; - if (key_pressed(KEY_V)) return "v"; - if (key_pressed(KEY_W)) return "w"; - if (key_pressed(KEY_X)) return "x"; - if (key_pressed(KEY_Y)) return "y"; - if (key_pressed(KEY_Z)) return "z"; - return ""; + if (key_pressed(KEY_A)) + return "a"; + if (key_pressed(KEY_B)) + return "b"; + if (key_pressed(KEY_C)) + return "c"; + if (key_pressed(KEY_D)) + return "d"; + if (key_pressed(KEY_E)) + return "e"; + if (key_pressed(KEY_F)) + return "f"; + if (key_pressed(KEY_G)) + return "g"; + if (key_pressed(KEY_H)) + return "h"; + if (key_pressed(KEY_I)) + return "i"; + if (key_pressed(KEY_J)) + return "j"; + if (key_pressed(KEY_K)) + return "k"; + if (key_pressed(KEY_L)) + return "l"; + if (key_pressed(KEY_M)) + return "m"; + if (key_pressed(KEY_N)) + return "n"; + if (key_pressed(KEY_O)) + return "o"; + if (key_pressed(KEY_P)) + return "p"; + if (key_pressed(KEY_Q)) + return "q"; + if (key_pressed(KEY_R)) + return "r"; + if (key_pressed(KEY_S)) + return "s"; + if (key_pressed(KEY_T)) + return "t"; + if (key_pressed(KEY_U)) + return "u"; + if (key_pressed(KEY_V)) + return "v"; + if (key_pressed(KEY_W)) + return "w"; + if (key_pressed(KEY_X)) + return "x"; + if (key_pressed(KEY_Y)) + return "y"; + if (key_pressed(KEY_Z)) + return "z"; + return ""; } // Applies a prefix filter to menu options. -void menu_apply_prefix_filter(const string &in filterText, const string[]@ options, int[]@ filteredIndices, string[]@ filteredOptions) { - filteredIndices.resize(0); - filteredOptions.resize(0); +void menu_apply_prefix_filter(const string& in filterText, const string[] @options, int[] @filteredIndices, + string[] @filteredOptions) { + filteredIndices.resize(0); + filteredOptions.resize(0); - if (@options is null) { - return; - } + if (@options is null) { + return; + } - string filterLower = filterText.lower(); - for (uint optionIndex = 0; optionIndex < options.length(); optionIndex++) { - if (filterLower.length() == 0) { - filteredIndices.insert_last(optionIndex); - filteredOptions.insert_last(options[optionIndex]); - continue; - } + string filterLower = filterText.lower(); + for (uint optionIndex = 0; optionIndex < options.length(); optionIndex++) { + if (filterLower.length() == 0) { + filteredIndices.insert_last(optionIndex); + filteredOptions.insert_last(options[optionIndex]); + continue; + } - string optionLower = options[optionIndex].lower(); - if (optionLower.length() >= filterLower.length() && optionLower.substr(0, filterLower.length()) == filterLower) { - filteredIndices.insert_last(optionIndex); - filteredOptions.insert_last(options[optionIndex]); - } - } + string optionLower = options[optionIndex].lower(); + if (optionLower.length() >= filterLower.length() && + optionLower.substr(0, filterLower.length()) == filterLower) { + filteredIndices.insert_last(optionIndex); + filteredOptions.insert_last(options[optionIndex]); + } + } } // Updates filter text from keyboard input and reapplies filtering. -bool menu_update_prefix_filter(string &inout filterText, const string[]@ options, int[]@ filteredIndices, string[]@ filteredOptions, int &inout selection) { - bool filterChanged = false; +bool menu_update_prefix_filter(string& inout filterText, const string[] @options, int[] @filteredIndices, + string[] @filteredOptions, int& inout selection) { + bool filterChanged = false; - if (key_pressed(KEY_BACK) && filterText.length() > 0) { - filterText = filterText.substr(0, filterText.length() - 1); - filterChanged = true; - } + if (key_pressed(KEY_BACK) && filterText.length() > 0) { + filterText = filterText.substr(0, filterText.length() - 1); + filterChanged = true; + } - string filterLetter = menu_get_filter_letter(); - if (filterLetter != "") { - filterText += filterLetter; - filterChanged = true; - } + string filterLetter = menu_get_filter_letter(); + if (filterLetter != "") { + filterText += filterLetter; + filterChanged = true; + } - if (filterChanged) { - menu_apply_prefix_filter(filterText, options, filteredIndices, filteredOptions); - if (selection < 0) { - selection = 0; - } - if (selection >= int(filteredOptions.length())) { - selection = 0; - } - } + if (filterChanged) { + menu_apply_prefix_filter(filterText, options, filteredIndices, filteredOptions); + if (selection < 0) { + selection = 0; + } + if (selection >= int(filteredOptions.length())) { + selection = 0; + } + } - return filterChanged; + return filterChanged; } diff --git a/menu_music.nvgt b/menu_music.nvgt index c1d11e4..2531178 100644 --- a/menu_music.nvgt +++ b/menu_music.nvgt @@ -1,30 +1,30 @@ #include "music.nvgt" // Resume paused menu music when possible, otherwise start a new track. -void menu_music_resume_or_play(music_manager &inout manager, const string track, const int fadeInMs = 0) { - if (manager.resume(fadeInMs)) { - return; - } +void menu_music_resume_or_play(music_manager& inout manager, const string track, const int fadeInMs = 0) { + if (manager.resume(fadeInMs)) { + return; + } - if (manager.playing) { - // Normalize state before fading back up. - manager.pause(0, true); - manager.resume(fadeInMs); - return; - } + if (manager.playing) { + // Normalize state before fading back up. + manager.pause(0, true); + manager.resume(fadeInMs); + return; + } - manager.play(track); + manager.play(track); } // Pause menu music. Blocking is enabled by default so fade-out fully completes. -bool menu_music_pause(music_manager &inout manager, const int fadeOutMs = 0, const bool blocking = true) { - if (!manager.playing) { - return false; - } - return manager.pause(fadeOutMs, blocking); +bool menu_music_pause(music_manager& inout manager, const int fadeOutMs = 0, const bool blocking = true) { + if (!manager.playing) { + return false; + } + return manager.pause(fadeOutMs, blocking); } // Stop menu music and reset playback state. -void menu_music_stop(music_manager &inout manager, const int fadeOutMs = 0, const bool blocking = false) { - manager.stop(fadeOutMs, blocking); +void menu_music_stop(music_manager& inout manager, const int fadeOutMs = 0, const bool blocking = false) { + manager.stop(fadeOutMs, blocking); } diff --git a/multikey.nvgt b/multikey.nvgt index 38e1f7c..2e4a0b3 100644 --- a/multikey.nvgt +++ b/multikey.nvgt @@ -1,5 +1,5 @@ // Multikey input helpers. -bool check_key_down(array@ keys) { +bool check_key_down(array @keys) { // True when at least one key in the set is currently down. if (keys is null || keys.length() == 0) { return false; @@ -14,7 +14,7 @@ bool check_key_down(array@ keys) { return false; } -bool check_all_keys(array@ keys) { +bool check_all_keys(array @keys) { // True only when every key in the set is currently down. if (keys is null || keys.length() == 0) { return false; diff --git a/name_sanitize.nvgt b/name_sanitize.nvgt index 44f07ce..a47ccc8 100644 --- a/name_sanitize.nvgt +++ b/name_sanitize.nvgt @@ -1,101 +1,105 @@ // Name and filename sanitizing helpers. string normalize_name_whitespace(string name) { - string result = ""; - bool lastWasSpace = true; + string result = ""; + bool lastWasSpace = true; - for (uint charIndex = 0; charIndex < name.length(); charIndex++) { - string ch = name.substr(charIndex, 1); - bool isSpace = (ch == " " || ch == "\t" || ch == "\r" || ch == "\n"); - if (isSpace) { - if (!lastWasSpace) { - result += " "; - lastWasSpace = true; - } - continue; - } + for (uint charIndex = 0; charIndex < name.length(); charIndex++) { + string ch = name.substr(charIndex, 1); + bool isSpace = (ch == " " || ch == "\t" || ch == "\r" || ch == "\n"); + if (isSpace) { + if (!lastWasSpace) { + result += " "; + lastWasSpace = true; + } + continue; + } - result += ch; - lastWasSpace = false; - } + result += ch; + lastWasSpace = false; + } - if (result.length() > 0 && result.substr(result.length() - 1) == " ") { - result = result.substr(0, result.length() - 1); - } + if (result.length() > 0 && result.substr(result.length() - 1) == " ") { + result = result.substr(0, result.length() - 1); + } - return result; + return result; } -bool is_windows_reserved_filename(const string&in upperName) { - if (upperName == "CON" || upperName == "PRN" || upperName == "AUX" || upperName == "NUL") return true; +bool is_windows_reserved_filename(const string& in upperName) { + if (upperName == "CON" || upperName == "PRN" || upperName == "AUX" || upperName == "NUL") + return true; - if (upperName.length() == 4 && upperName.substr(0, 3) == "COM") { - int num = parse_int(upperName.substr(3)); - if (num >= 1 && num <= 9) return true; - } + if (upperName.length() == 4 && upperName.substr(0, 3) == "COM") { + int num = parse_int(upperName.substr(3)); + if (num >= 1 && num <= 9) + return true; + } - if (upperName.length() == 4 && upperName.substr(0, 3) == "LPT") { - int num = parse_int(upperName.substr(3)); - if (num >= 1 && num <= 9) return true; - } + if (upperName.length() == 4 && upperName.substr(0, 3) == "LPT") { + int num = parse_int(upperName.substr(3)); + if (num >= 1 && num <= 9) + return true; + } - return false; + return false; } string sanitize_filename_base(string name, const int maxLength = 40, const string fallback = "item") { - string normalized = normalize_name_whitespace(name); - string result = ""; - bool lastSeparator = false; + string normalized = normalize_name_whitespace(name); + string result = ""; + bool lastSeparator = false; - for (uint charIndex = 0; charIndex < normalized.length(); charIndex++) { - string ch = normalized.substr(charIndex, 1); - bool isUpper = (ch >= "A" && ch <= "Z"); - bool isLower = (ch >= "a" && ch <= "z"); - bool isDigit = (ch >= "0" && ch <= "9"); + for (uint charIndex = 0; charIndex < normalized.length(); charIndex++) { + string ch = normalized.substr(charIndex, 1); + bool isUpper = (ch >= "A" && ch <= "Z"); + bool isLower = (ch >= "a" && ch <= "z"); + bool isDigit = (ch >= "0" && ch <= "9"); - if (isUpper || isLower || isDigit) { - result += ch; - lastSeparator = false; - continue; - } + if (isUpper || isLower || isDigit) { + result += ch; + lastSeparator = false; + continue; + } - if (ch == " " || ch == "_" || ch == "-") { - if (!lastSeparator && result.length() > 0) { - result += "_"; - lastSeparator = true; - } - } - } + if (ch == " " || ch == "_" || ch == "-") { + if (!lastSeparator && result.length() > 0) { + result += "_"; + lastSeparator = true; + } + } + } - while (result.length() > 0 && result.substr(result.length() - 1) == "_") { - result = result.substr(0, result.length() - 1); - } + while (result.length() > 0 && result.substr(result.length() - 1) == "_") { + result = result.substr(0, result.length() - 1); + } - if (result.length() == 0) { - result = fallback; - } + if (result.length() == 0) { + result = fallback; + } - if (result.length() > maxLength) { - result = result.substr(0, maxLength); - } + if (result.length() > maxLength) { + result = result.substr(0, maxLength); + } - while (result.length() > 0 && result.substr(result.length() - 1) == "_") { - result = result.substr(0, result.length() - 1); - } + while (result.length() > 0 && result.substr(result.length() - 1) == "_") { + result = result.substr(0, result.length() - 1); + } - string upperName = result.upper(); - if (upperName == "." || upperName == "..") { - result = fallback; - upperName = result.upper(); - } + string upperName = result.upper(); + if (upperName == "." || upperName == "..") { + result = fallback; + upperName = result.upper(); + } - if (is_windows_reserved_filename(upperName)) { - result = "file_" + result; - } + if (is_windows_reserved_filename(upperName)) { + result = "file_" + result; + } - return result; + return result; } -string build_filename_from_name(const string&in name, const string&in extension = ".dat", const int maxBaseLength = 40, const string fallback = "item") { - return sanitize_filename_base(name, maxBaseLength, fallback) + extension; +string build_filename_from_name(const string& in name, const string& in extension = ".dat", + const int maxBaseLength = 40, const string fallback = "item") { + return sanitize_filename_base(name, maxBaseLength, fallback) + extension; } diff --git a/notifications.nvgt b/notifications.nvgt index 1234de7..2bb93fb 100644 --- a/notifications.nvgt +++ b/notifications.nvgt @@ -1,6 +1,6 @@ #include "audio_paths.nvgt" -funcdef void notification_speak_callback(const string &in message, bool interrupt); +funcdef void notification_speak_callback(const string& in message, bool interrupt); string[] notificationsHistory; string[] notificationsQueue; @@ -13,163 +13,176 @@ timer notificationsDelayTimer; sound notificationsSound; bool notificationsWaitingForSound = false; string notificationsSoundPath = "sounds/notify"; -notification_speak_callback@ notificationsSpeakCallback = null; +notification_speak_callback @notificationsSpeakCallback = null; -void notifications_set_speak_callback(notification_speak_callback@ callback) { - @notificationsSpeakCallback = @callback; +void notifications_set_speak_callback(notification_speak_callback @callback) { + @notificationsSpeakCallback = @callback; } void notifications_set_sound_path(const string soundPath) { - notificationsSoundPath = soundPath; + notificationsSoundPath = soundPath; } void notifications_set_delay_ms(int delayMs) { - if (delayMs < 0) { - delayMs = 0; - } - notificationsDelayMs = delayMs; + if (delayMs < 0) { + delayMs = 0; + } + notificationsDelayMs = delayMs; } void notifications_set_max_history(int maxCount) { - if (maxCount < 1) { - maxCount = 1; - } - notificationsMaxHistory = maxCount; + if (maxCount < 1) { + maxCount = 1; + } + notificationsMaxHistory = maxCount; - while (notificationsHistory.length() > uint(notificationsMaxHistory)) { - notificationsHistory.remove_at(0); - } + while (notificationsHistory.length() > uint(notificationsMaxHistory)) { + notificationsHistory.remove_at(0); + } - if (notificationsHistory.length() == 0) { - notificationsCurrentIndex = -1; - } else if (notificationsCurrentIndex >= int(notificationsHistory.length())) { - notificationsCurrentIndex = notificationsHistory.length() - 1; - } + if (notificationsHistory.length() == 0) { + notificationsCurrentIndex = -1; + } else if (notificationsCurrentIndex >= int(notificationsHistory.length())) { + notificationsCurrentIndex = notificationsHistory.length() - 1; + } } void notifications_clear() { - notificationsHistory.resize(0); - notificationsQueue.resize(0); - notificationsCurrentIndex = -1; - notificationsActive = false; - notificationsWaitingForSound = false; - notificationsSound.close(); + notificationsHistory.resize(0); + notificationsQueue.resize(0); + notificationsCurrentIndex = -1; + notificationsActive = false; + notificationsWaitingForSound = false; + notificationsSound.close(); } -void notifications_speak(const string &in message, bool interrupt) { - if (@notificationsSpeakCallback !is null) { - notificationsSpeakCallback(message, interrupt); - return; - } - screen_reader_speak(message, interrupt); +void notifications_speak(const string& in message, bool interrupt) { + if (@notificationsSpeakCallback !is null) { + notificationsSpeakCallback(message, interrupt); + return; + } + screen_reader_speak(message, interrupt); } -void notifications_enqueue(const string &in message) { - notificationsQueue.insert_last(message); - notificationsHistory.insert_last(message); +void notifications_enqueue(const string& in message) { + notificationsQueue.insert_last(message); + notificationsHistory.insert_last(message); - while (notificationsHistory.length() > uint(notificationsMaxHistory)) { - notificationsHistory.remove_at(0); - } + while (notificationsHistory.length() > uint(notificationsMaxHistory)) { + notificationsHistory.remove_at(0); + } - notificationsCurrentIndex = notificationsHistory.length() - 1; + notificationsCurrentIndex = notificationsHistory.length() - 1; } bool notifications_try_play_sound() { - string resolvedPath = resolve_audio_path(notificationsSoundPath); - if (resolvedPath == "") { - return false; - } + notificationsSound.close(); - notificationsSound.close(); - if (!notificationsSound.load(resolvedPath)) { - return false; - } + // Avoid file_exists()-only checks so packaged Android assets can still load. + if (notificationsSound.load(notificationsSoundPath)) { + notificationsSound.play(); + return true; + } - notificationsSound.play(); - return true; + string oggPath = notificationsSoundPath + ".ogg"; + if (notificationsSound.load(oggPath)) { + notificationsSound.play(); + return true; + } + + string wavPath = notificationsSoundPath + ".wav"; + if (!notificationsSound.load(wavPath)) { + return false; + } + + notificationsSound.play(); + return true; } void notifications_update() { - if (notificationsQueue.length() == 0) { - if (notificationsActive && notificationsDelayTimer.elapsed >= notificationsDelayMs) { - notificationsActive = false; - } - return; - } + if (notificationsQueue.length() == 0) { + if (notificationsActive && notificationsDelayTimer.elapsed >= notificationsDelayMs) { + notificationsActive = false; + } + return; + } - if (notificationsActive && notificationsDelayTimer.elapsed < notificationsDelayMs) { - return; - } + if (notificationsActive && notificationsDelayTimer.elapsed < notificationsDelayMs) { + return; + } - if (notificationsWaitingForSound) { - if (notificationsSound.playing) { - return; - } + if (notificationsWaitingForSound) { + if (notificationsSound.playing) { + return; + } - notifications_speak(notificationsQueue[0], true); - notificationsQueue.remove_at(0); - notificationsWaitingForSound = false; - notificationsActive = true; - notificationsDelayTimer.restart(); - return; - } + notifications_speak(notificationsQueue[0], true); + notificationsQueue.remove_at(0); + notificationsWaitingForSound = false; + notificationsActive = true; + notificationsDelayTimer.restart(); + return; + } - if (notifications_try_play_sound()) { - notificationsWaitingForSound = true; - return; - } + if (notifications_try_play_sound()) { + notificationsWaitingForSound = true; + return; + } - notifications_speak(notificationsQueue[0], true); - notificationsQueue.remove_at(0); - notificationsActive = true; - notificationsDelayTimer.restart(); + notifications_speak(notificationsQueue[0], true); + notificationsQueue.remove_at(0); + notificationsActive = true; + notificationsDelayTimer.restart(); } void notifications_check_keys() { - if (key_pressed(KEY_LEFTBRACKET)) { - if (notificationsHistory.length() == 0) { - notifications_speak("No notifications.", true); - return; - } + if (key_pressed(KEY_LEFTBRACKET)) { + if (notificationsHistory.length() == 0) { + notifications_speak("No notifications.", true); + return; + } - notificationsCurrentIndex--; - if (notificationsCurrentIndex < 0) { - notificationsCurrentIndex = 0; - notifications_speak("Oldest notification. " + notificationsHistory[notificationsCurrentIndex], true); - return; - } + notificationsCurrentIndex--; + if (notificationsCurrentIndex < 0) { + notificationsCurrentIndex = 0; + notifications_speak("Oldest notification. " + notificationsHistory[notificationsCurrentIndex], true); + return; + } - int position = notificationsCurrentIndex + 1; - notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " + notificationsHistory.length(), true); - return; - } + int position = notificationsCurrentIndex + 1; + notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " + + notificationsHistory.length(), + true); + return; + } - if (key_pressed(KEY_RIGHTBRACKET)) { - if (notificationsHistory.length() == 0) { - notifications_speak("No notifications.", true); - return; - } + if (key_pressed(KEY_RIGHTBRACKET)) { + if (notificationsHistory.length() == 0) { + notifications_speak("No notifications.", true); + return; + } - notificationsCurrentIndex++; - if (notificationsCurrentIndex >= int(notificationsHistory.length())) { - notificationsCurrentIndex = notificationsHistory.length() - 1; - notifications_speak("Newest notification. " + notificationsHistory[notificationsCurrentIndex], true); - return; - } + notificationsCurrentIndex++; + if (notificationsCurrentIndex >= int(notificationsHistory.length())) { + notificationsCurrentIndex = notificationsHistory.length() - 1; + notifications_speak("Newest notification. " + notificationsHistory[notificationsCurrentIndex], true); + return; + } - int position = notificationsCurrentIndex + 1; - notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " + notificationsHistory.length(), true); - return; - } + int position = notificationsCurrentIndex + 1; + notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " + + notificationsHistory.length(), + true); + return; + } - if (key_pressed(KEY_BACKSLASH)) { - if (notificationsHistory.length() == 0) { - notifications_speak("No notifications.", true); - return; - } + if (key_pressed(KEY_BACKSLASH)) { + if (notificationsHistory.length() == 0) { + notifications_speak("No notifications.", true); + return; + } - notificationsCurrentIndex = notificationsHistory.length() - 1; - notifications_speak(notificationsHistory[notificationsCurrentIndex], true); - } + notificationsCurrentIndex = notificationsHistory.length() - 1; + notifications_speak(notificationsHistory[notificationsCurrentIndex], true); + } } diff --git a/save_utils.nvgt b/save_utils.nvgt index 1f4b2b2..d424aa4 100644 --- a/save_utils.nvgt +++ b/save_utils.nvgt @@ -1,101 +1,102 @@ // Generic save/file helpers. -bool save_utils_sort_string_case_insensitive(const string &in a, const string &in b) { - return a.lower() < b.lower(); +bool save_utils_sort_string_case_insensitive(const string& in a, const string& in b) { + return a.lower() < b.lower(); } -string[] list_files_with_extension(const string&in extension, const string&in directory = "") { - string[] result; - if (extension == "") return result; +string[] list_files_with_extension(const string& in extension, const string& in directory = "") { + string[] result; + if (extension == "") + return result; - string dirPrefix = directory; - if (dirPrefix != "" && dirPrefix.substr(dirPrefix.length() - 1) != "/") { - dirPrefix += "/"; - } + string dirPrefix = directory; + if (dirPrefix != "" && dirPrefix.substr(dirPrefix.length() - 1) != "/") { + dirPrefix += "/"; + } - string[]@ items = glob(dirPrefix + "*" + extension); - if (@items is null) return result; + string[] @items = glob(dirPrefix + "*" + extension); + if (@items is null) + return result; - for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) { - string item = items[itemIndex]; - if (item.length() >= extension.length() && - item.substr(item.length() - extension.length()) == extension) { - result.insert_last(item); - } - } + for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) { + string item = items[itemIndex]; + if (item.length() >= extension.length() && item.substr(item.length() - extension.length()) == extension) { + result.insert_last(item); + } + } - if (result.length() > 1) { - result.sort(save_utils_sort_string_case_insensitive); - } - return result; + if (result.length() > 1) { + result.sort(save_utils_sort_string_case_insensitive); + } + return result; } -bool has_files_with_extension(const string&in extension, const string&in directory = "") { - return list_files_with_extension(extension, directory).length() > 0; +bool has_files_with_extension(const string& in extension, const string& in directory = "") { + return list_files_with_extension(extension, directory).length() > 0; } -string strip_file_extension(const string&in filename, const string&in extension) { - if (extension != "" && - filename.length() >= extension.length() && - filename.substr(filename.length() - extension.length()) == extension) { - return filename.substr(0, filename.length() - extension.length()); - } - return filename; +string strip_file_extension(const string& in filename, const string& in extension) { + if (extension != "" && filename.length() >= extension.length() && + filename.substr(filename.length() - extension.length()) == extension) { + return filename.substr(0, filename.length() - extension.length()); + } + return filename; } -bool save_string_file(const string&in filename, const string&in data) { - if (data.length() == 0) { - return false; - } +bool save_string_file(const string& in filename, const string& in data) { + if (data.length() == 0) { + return false; + } - file outFile; - if (!outFile.open(filename, "wb")) { - return false; - } + file outFile; + if (!outFile.open(filename, "wb")) { + return false; + } - if (outFile.write(data) < data.length()) { - outFile.close(); - return false; - } + if (outFile.write(data) < data.length()) { + outFile.close(); + return false; + } - outFile.close(); - return true; + outFile.close(); + return true; } -bool read_string_file(const string&in filename, string&out data, const bool allowEmpty = false) { - file inFile; - if (!inFile.open(filename, "rb")) { - return false; - } +bool read_string_file(const string& in filename, string& out data, const bool allowEmpty = false) { + file inFile; + if (!inFile.open(filename, "rb")) { + return false; + } - data = inFile.read(); - inFile.close(); - return allowEmpty || data.length() > 0; + data = inFile.read(); + inFile.close(); + return allowEmpty || data.length() > 0; } -string encrypt_string_aes(const string&in rawData, const string&in key) { - return string_aes_encrypt(rawData, key); +string encrypt_string_aes(const string& in rawData, const string& in key) { + return string_aes_encrypt(rawData, key); } -string decrypt_string_aes(const string&in encryptedData, const string&in key) { - return string_aes_decrypt(encryptedData, key); +string decrypt_string_aes(const string& in encryptedData, const string& in key) { + return string_aes_decrypt(encryptedData, key); } -bool save_encrypted_file(const string&in filename, const string&in rawData, const string&in key) { - string encryptedData = encrypt_string_aes(rawData, key); - return save_string_file(filename, encryptedData); +bool save_encrypted_file(const string& in filename, const string& in rawData, const string& in key) { + string encryptedData = encrypt_string_aes(rawData, key); + return save_string_file(filename, encryptedData); } -bool read_encrypted_file(const string&in filename, const string&in key, string&out rawData, const bool allowPlaintextFallback = true) { - string encryptedData = ""; - if (!read_string_file(filename, encryptedData, false)) { - return false; - } +bool read_encrypted_file(const string& in filename, const string& in key, string& out rawData, + const bool allowPlaintextFallback = true) { + string encryptedData = ""; + if (!read_string_file(filename, encryptedData, false)) { + return false; + } - rawData = decrypt_string_aes(encryptedData, key); - if (rawData.length() == 0 && allowPlaintextFallback) { - rawData = encryptedData; - } + rawData = decrypt_string_aes(encryptedData, key); + if (rawData.length() == 0 && allowPlaintextFallback) { + rawData = encryptedData; + } - return rawData.length() > 0; + return rawData.length() > 0; } diff --git a/speech_history.nvgt b/speech_history.nvgt index 9b4b27a..298a9e9 100644 --- a/speech_history.nvgt +++ b/speech_history.nvgt @@ -7,100 +7,102 @@ int speechHistoryCurrentIndex = -1; bool speechHistoryDeduplicate = true; void speech_history_set_max_entries(int maxEntries) { - if (maxEntries < 1) { - maxEntries = 1; - } + if (maxEntries < 1) { + maxEntries = 1; + } - speechHistoryMaxEntries = maxEntries; - while (speechHistory.length() > uint(speechHistoryMaxEntries)) { - speechHistory.remove_at(0); - } + speechHistoryMaxEntries = maxEntries; + while (speechHistory.length() > uint(speechHistoryMaxEntries)) { + speechHistory.remove_at(0); + } - if (speechHistory.length() == 0) { - speechHistoryCurrentIndex = -1; - } else if (speechHistoryCurrentIndex >= int(speechHistory.length())) { - speechHistoryCurrentIndex = speechHistory.length() - 1; - } + if (speechHistory.length() == 0) { + speechHistoryCurrentIndex = -1; + } else if (speechHistoryCurrentIndex >= int(speechHistory.length())) { + speechHistoryCurrentIndex = speechHistory.length() - 1; + } } void speech_history_clear() { - speechHistory.resize(0); - speechHistoryCurrentIndex = -1; + speechHistory.resize(0); + speechHistoryCurrentIndex = -1; } void speech_history_set_deduplicate(bool deduplicate) { - speechHistoryDeduplicate = deduplicate; + speechHistoryDeduplicate = deduplicate; } -void speech_history_add(const string &in message) { - if (message == "") { - return; - } +void speech_history_add(const string& in message) { + if (message == "") { + return; + } - if (speechHistoryDeduplicate) { - for (uint messageIndex = 0; messageIndex < speechHistory.length(); messageIndex++) { - if (speechHistory[messageIndex] == message) { - speechHistoryCurrentIndex = messageIndex; - return; - } - } - } + if (speechHistoryDeduplicate) { + for (uint messageIndex = 0; messageIndex < speechHistory.length(); messageIndex++) { + if (speechHistory[messageIndex] == message) { + speechHistoryCurrentIndex = messageIndex; + return; + } + } + } - speechHistory.insert_last(message); - while (speechHistory.length() > uint(speechHistoryMaxEntries)) { - speechHistory.remove_at(0); - } + speechHistory.insert_last(message); + while (speechHistory.length() > uint(speechHistoryMaxEntries)) { + speechHistory.remove_at(0); + } - speechHistoryCurrentIndex = speechHistory.length() - 1; + speechHistoryCurrentIndex = speechHistory.length() - 1; } -void speak_with_history(const string &in message, bool interrupt) { - speech_history_add(message); - screen_reader_speak(message, interrupt); +void speak_with_history(const string& in message, bool interrupt) { + speech_history_add(message); + screen_reader_speak(message, interrupt); } void check_speech_history_keys() { - // Comma: older. - if (key_pressed(KEY_COMMA)) { - if (speechHistory.length() == 0) { - screen_reader_speak("No speech history.", true); - return; - } + // Comma: older. + if (key_pressed(KEY_COMMA)) { + if (speechHistory.length() == 0) { + screen_reader_speak("No speech history.", true); + return; + } - speechHistoryCurrentIndex--; - if (speechHistoryCurrentIndex < 0) { - speechHistoryCurrentIndex = 0; - screen_reader_speak("Oldest message. " + speechHistory[speechHistoryCurrentIndex], true); - return; - } + speechHistoryCurrentIndex--; + if (speechHistoryCurrentIndex < 0) { + speechHistoryCurrentIndex = 0; + screen_reader_speak("Oldest message. " + speechHistory[speechHistoryCurrentIndex], true); + return; + } - int position = speechHistoryCurrentIndex + 1; - screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(), true); - return; - } + int position = speechHistoryCurrentIndex + 1; + screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(), + true); + return; + } - // Period: newer. - if (key_pressed(KEY_PERIOD)) { - if (speechHistory.length() == 0) { - screen_reader_speak("No speech history.", true); - return; - } + // Period: newer. + if (key_pressed(KEY_PERIOD)) { + if (speechHistory.length() == 0) { + screen_reader_speak("No speech history.", true); + return; + } - speechHistoryCurrentIndex++; - if (speechHistoryCurrentIndex >= int(speechHistory.length())) { - speechHistoryCurrentIndex = speechHistory.length() - 1; - screen_reader_speak("Newest message. " + speechHistory[speechHistoryCurrentIndex], true); - return; - } + speechHistoryCurrentIndex++; + if (speechHistoryCurrentIndex >= int(speechHistory.length())) { + speechHistoryCurrentIndex = speechHistory.length() - 1; + screen_reader_speak("Newest message. " + speechHistory[speechHistoryCurrentIndex], true); + return; + } - int position = speechHistoryCurrentIndex + 1; - screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(), true); - } + int position = speechHistoryCurrentIndex + 1; + screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(), + true); + } } string speech_history_latest() { - if (speechHistory.length() == 0) { - return ""; - } - return speechHistory[speechHistory.length() - 1]; + if (speechHistory.length() == 0) { + return ""; + } + return speechHistory[speechHistory.length() - 1]; } diff --git a/text_reader_compat.nvgt b/text_reader_compat.nvgt index 393bd2c..616f5df 100644 --- a/text_reader_compat.nvgt +++ b/text_reader_compat.nvgt @@ -2,13 +2,13 @@ // Optional compatibility aliases for projects that still call text_reader*. string text_reader(string content, string title = "Text Reader", bool readOnly = true) { - return file_viewer(content, title, readOnly); + return file_viewer(content, title, readOnly); } string text_reader_lines(string[] lines, string title = "Text Reader", bool readOnly = true) { - return file_viewer_lines(lines, title, readOnly); + return file_viewer_lines(lines, title, readOnly); } string text_reader_file(string filePath, string title = "", bool readOnly = true) { - return file_viewer_file(filePath, title, readOnly); + return file_viewer_file(filePath, title, readOnly); } diff --git a/ui.nvgt b/ui.nvgt index c1f054b..6a6b1c0 100644 --- a/ui.nvgt +++ b/ui.nvgt @@ -4,51 +4,52 @@ string uiDefaultWindowTitle = ""; bool uiUsePromptAsDialogTitle = true; void ui_set_default_window_title(const string windowTitle) { - uiDefaultWindowTitle = windowTitle; + uiDefaultWindowTitle = windowTitle; } void ui_set_use_prompt_as_dialog_title(const bool enabled) { - uiUsePromptAsDialogTitle = enabled; + uiUsePromptAsDialogTitle = enabled; } string ui_resolve_dialog_title(const string title, const string prompt) { - if (uiUsePromptAsDialogTitle && prompt != "") { - return prompt; - } + if (uiUsePromptAsDialogTitle && prompt != "") { + return prompt; + } - string dialogTitle = title; - if (dialogTitle == "") { - dialogTitle = prompt; - } - return dialogTitle; + string dialogTitle = title; + if (dialogTitle == "") { + dialogTitle = prompt; + } + return dialogTitle; } void ui_restore_window(const string windowTitle = "") { - string resolvedTitle = windowTitle; - if (resolvedTitle == "") { - resolvedTitle = uiDefaultWindowTitle; - } + string resolvedTitle = windowTitle; + if (resolvedTitle == "") { + resolvedTitle = uiDefaultWindowTitle; + } - if (resolvedTitle != "") { - show_window(resolvedTitle); - } + if (resolvedTitle != "") { + show_window(resolvedTitle); + } } -string ui_input_box(const string title, const string prompt, const string defaultValue = "", const string windowTitle = "") { - string dialogTitle = ui_resolve_dialog_title(title, prompt); - string result = virtual_input_box(dialogTitle, prompt, defaultValue); - ui_restore_window(windowTitle); - return result; +string ui_input_box(const string title, const string prompt, const string defaultValue = "", + const string windowTitle = "") { + string dialogTitle = ui_resolve_dialog_title(title, prompt); + string result = virtual_input_box(dialogTitle, prompt, defaultValue); + ui_restore_window(windowTitle); + return result; } int ui_question(const string title, const string prompt, const string windowTitle = "", const bool canCancel = false) { - string dialogTitle = ui_resolve_dialog_title(title, prompt); - int result = virtual_question(dialogTitle, prompt, canCancel); - ui_restore_window(windowTitle); - return result; + string dialogTitle = ui_resolve_dialog_title(title, prompt); + int result = virtual_question(dialogTitle, prompt, canCancel); + ui_restore_window(windowTitle); + return result; } void ui_info_box(const string title, const string heading, const string message, const string windowTitle = "") { - virtual_info_box(title, heading, message); - ui_restore_window(windowTitle); + virtual_info_box(title, heading, message); + ui_restore_window(windowTitle); } diff --git a/volume_controls.nvgt b/volume_controls.nvgt index 5fc97ff..ad616c5 100644 --- a/volume_controls.nvgt +++ b/volume_controls.nvgt @@ -6,91 +6,98 @@ float volumeControlsMaxDb = 0.0f; float volumeControlsMinDb = -60.0f; float volumeControlsStepDb = 3.0f; float volumeControlsCurrentDb = 0.0f; -volume_controls_apply_callback@ volumeControlsApplyCallback = null; +volume_controls_apply_callback @volumeControlsApplyCallback = null; -void volume_controls_set_apply_callback(volume_controls_apply_callback@ callback) { - @volumeControlsApplyCallback = @callback; +void volume_controls_set_apply_callback(volume_controls_apply_callback @callback) { + @volumeControlsApplyCallback = @callback; } void volume_controls_configure(float minDb = -60.0f, float maxDb = 0.0f, float stepDb = 3.0f, float initialDb = 0.0f) { - volumeControlsMinDb = minDb; - volumeControlsMaxDb = maxDb; - if (volumeControlsMaxDb < volumeControlsMinDb) { - float temp = volumeControlsMaxDb; - volumeControlsMaxDb = volumeControlsMinDb; - volumeControlsMinDb = temp; - } + volumeControlsMinDb = minDb; + volumeControlsMaxDb = maxDb; + if (volumeControlsMaxDb < volumeControlsMinDb) { + float temp = volumeControlsMaxDb; + volumeControlsMaxDb = volumeControlsMinDb; + volumeControlsMinDb = temp; + } - if (stepDb <= 0.0f) { - stepDb = 1.0f; - } - volumeControlsStepDb = stepDb; + if (stepDb <= 0.0f) { + stepDb = 1.0f; + } + volumeControlsStepDb = stepDb; - volume_controls_set_current_db(initialDb, false); + volume_controls_set_current_db(initialDb, false); } int volume_controls_percent_from_db(float volumeDb) { - float range = volumeControlsMaxDb - volumeControlsMinDb; - if (range <= 0.0f) return 100; + float range = volumeControlsMaxDb - volumeControlsMinDb; + if (range <= 0.0f) + return 100; - float normalized = (volumeDb - volumeControlsMinDb) / range; - int volumePercent = int(normalized * 100.0f + 0.5f); - if (volumePercent < 0) volumePercent = 0; - if (volumePercent > 100) volumePercent = 100; - return volumePercent; + float normalized = (volumeDb - volumeControlsMinDb) / range; + int volumePercent = int(normalized * 100.0f + 0.5f); + if (volumePercent < 0) + volumePercent = 0; + if (volumePercent > 100) + volumePercent = 100; + return volumePercent; } void volume_controls_apply(float volumeDb) { - if (@volumeControlsApplyCallback !is null) { - volumeControlsApplyCallback(volumeDb); - return; - } + if (@volumeControlsApplyCallback !is null) { + volumeControlsApplyCallback(volumeDb); + return; + } - // Default engine-global apply behavior when no callback is provided. - sound_master_volume = volumeDb; + // Default engine-global apply behavior when no callback is provided. + sound_master_volume = volumeDb; } void volume_controls_set_current_db(float volumeDb, bool announce = true) { - float clamped = volumeDb; - if (clamped > volumeControlsMaxDb) clamped = volumeControlsMaxDb; - if (clamped < volumeControlsMinDb) clamped = volumeControlsMinDb; + float clamped = volumeDb; + if (clamped > volumeControlsMaxDb) + clamped = volumeControlsMaxDb; + if (clamped < volumeControlsMinDb) + clamped = volumeControlsMinDb; - if (clamped == volumeControlsCurrentDb) return; + if (clamped == volumeControlsCurrentDb) + return; - volumeControlsCurrentDb = clamped; - volume_controls_apply(volumeControlsCurrentDb); + volumeControlsCurrentDb = clamped; + volume_controls_apply(volumeControlsCurrentDb); - if (announce) { - int volumePercent = volume_controls_percent_from_db(volumeControlsCurrentDb); - screen_reader_speak("Volume " + volumePercent + ".", true); - } + if (announce) { + int volumePercent = volume_controls_percent_from_db(volumeControlsCurrentDb); + screen_reader_speak("Volume " + volumePercent + ".", true); + } } void volume_controls_init_at_max(bool announce = false) { - volume_controls_set_current_db(volumeControlsMaxDb, announce); + volume_controls_set_current_db(volumeControlsMaxDb, announce); } float volume_controls_get_current_db() { - return volumeControlsCurrentDb; + return volumeControlsCurrentDb; } void volume_controls_handle_keys(int downKey = KEY_PAGEDOWN, int upKey = KEY_PAGEUP, bool announce = true) { - if (key_pressed(downKey)) { - volume_controls_set_current_db(volumeControlsCurrentDb - volumeControlsStepDb, announce); - } - if (key_pressed(upKey)) { - volume_controls_set_current_db(volumeControlsCurrentDb + volumeControlsStepDb, announce); - } + if (key_pressed(downKey)) { + volume_controls_set_current_db(volumeControlsCurrentDb - volumeControlsStepDb, announce); + } + if (key_pressed(upKey)) { + volume_controls_set_current_db(volumeControlsCurrentDb + volumeControlsStepDb, announce); + } } -void safe_destroy_sound_in_pool(sound_pool@ poolRef, int &inout handle) { - if (handle == -1) return; - if (@poolRef is null) { - handle = -1; - return; - } - if (poolRef.sound_is_active(handle)) { - poolRef.destroy_sound(handle); - } - handle = -1; +void safe_destroy_sound_in_pool(sound_pool @poolRef, int& inout handle) { + if (handle == -1) + return; + if (@poolRef is null) { + handle = -1; + return; + } + if (poolRef.sound_is_active(handle)) { + poolRef.destroy_sound(handle); + } + handle = -1; }