Updated several components. I really gotta remember I split this off into a submodule.

This commit is contained in:
Storm Dragon
2026-02-22 19:27:16 -05:00
parent 44f13b1aeb
commit 8825bc38d7
16 changed files with 1197 additions and 1046 deletions
+15 -9
View File
@@ -6,7 +6,7 @@ string log_format_timestamp() {
return "[" + stamp + "]"; return "[" + stamp + "]";
} }
string log_flatten_multiline(const string&in text) { string log_flatten_multiline(const string& in text) {
string result = ""; string result = "";
bool lastWasSeparator = false; bool lastWasSeparator = false;
@@ -27,7 +27,7 @@ string log_flatten_multiline(const string&in text) {
return result; return result;
} }
bool log_append_line(const string&in logPath, const string&in message) { bool log_append_line(const string& in logPath, const string& in message) {
file logFile; file logFile;
if (!logFile.open(logPath, "ab")) { if (!logFile.open(logPath, "ab")) {
return false; return false;
@@ -39,7 +39,7 @@ bool log_append_line(const string&in logPath, const string&in message) {
return true; return true;
} }
void log_unhandled_exception_to_file(const string&in logPath = "crash.log", const string&in context = "") { void log_unhandled_exception_to_file(const string& in logPath = "crash.log", const string& in context = "") {
string info = get_exception_info(); string info = get_exception_info();
string filePath = get_exception_file(); string filePath = get_exception_file();
int line = get_exception_line(); int line = get_exception_line();
@@ -47,12 +47,18 @@ void log_unhandled_exception_to_file(const string&in logPath = "crash.log", cons
string stack = log_flatten_multiline(last_exception_call_stack); string stack = log_flatten_multiline(last_exception_call_stack);
string message = "Unhandled exception"; string message = "Unhandled exception";
if (context != "") message += " (" + context + ")"; if (context != "")
if (info != "") message += ": " + info; message += " (" + context + ")";
if (filePath != "") message += " at " + filePath; if (info != "")
if (line > 0) message += ":" + line; message += ": " + info;
if (func != "") message += " in " + func; if (filePath != "")
if (stack != "") message += " | stack: " + stack; 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);
} }
+34 -20
View File
@@ -1,12 +1,15 @@
// Dictionary utility helpers. // Dictionary utility helpers.
double dict_get_number(dictionary@ data, const string&in key, double defaultValue) { double dict_get_number(dictionary @data, const string& in key, double defaultValue) {
double value = 0.0; double value = 0.0;
if (@data is null) return defaultValue; if (@data is null)
if (data.get(key, value)) return value; return defaultValue;
if (data.get(key, value))
return value;
int valueInt = 0; int valueInt = 0;
if (data.get(key, valueInt)) return valueInt; if (data.get(key, valueInt))
return valueInt;
string valueString = ""; string valueString = "";
if (data.get(key, valueString)) { if (data.get(key, valueString)) {
@@ -16,43 +19,54 @@ double dict_get_number(dictionary@ data, const string&in key, double defaultValu
return defaultValue; return defaultValue;
} }
bool dict_get_bool(dictionary@ data, const string&in key, bool defaultValue) { bool dict_get_bool(dictionary @data, const string& in key, bool defaultValue) {
bool value = false; bool value = false;
if (@data is null) return defaultValue; if (@data is null)
if (data.get(key, value)) return value; return defaultValue;
if (data.get(key, value))
return value;
int valueInt = 0; int valueInt = 0;
if (data.get(key, valueInt)) return valueInt != 0; if (data.get(key, valueInt))
return valueInt != 0;
string valueString = ""; string valueString = "";
if (data.get(key, valueString)) return valueString == "1" || valueString == "true"; if (data.get(key, valueString))
return valueString == "1" || valueString == "true";
return defaultValue; return defaultValue;
} }
bool dict_has_keys(dictionary@ data) { bool dict_has_keys(dictionary @data) {
if (@data is null) return false; if (@data is null)
string[]@ keys = data.get_keys(); return false;
string[] @keys = data.get_keys();
return @keys !is null && keys.length() > 0; return @keys !is null && keys.length() > 0;
} }
bool dict_has_number_key(dictionary@ data, const string&in key) { bool dict_has_number_key(dictionary @data, const string& in key) {
double value = 0.0; double value = 0.0;
if (@data is null) return false; if (@data is null)
if (data.get(key, value)) return true; return false;
if (data.get(key, value))
return true;
int valueInt = 0; int valueInt = 0;
if (data.get(key, valueInt)) return true; if (data.get(key, valueInt))
return true;
string valueString = ""; string valueString = "";
if (data.get(key, valueString)) return valueString.length() > 0; 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[] dict_get_string_list(dictionary @data, const string& in key) {
string[] result; string[] result;
if (@data is null) return result; if (@data is null)
if (!data.get(key, result)) return result; return result;
if (!data.get(key, result))
return result;
return result; return result;
} }
+33 -24
View File
@@ -1,11 +1,11 @@
#include "audio_paths.nvgt" #include "audio_paths.nvgt"
#include "file_viewer.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(); funcdef void docs_browser_tick_callback();
docs_browser_speak_callback@ docsBrowserSpeakCallback = null; docs_browser_speak_callback @docsBrowserSpeakCallback = null;
docs_browser_tick_callback@ docsBrowserTickCallback = null; docs_browser_tick_callback @docsBrowserTickCallback = null;
string docsBrowserDirectory = "files"; string docsBrowserDirectory = "files";
string docsBrowserMenuSoundDir = "sounds/menu"; string docsBrowserMenuSoundDir = "sounds/menu";
@@ -16,11 +16,11 @@ string[] docsBrowserExtensions = {"md", "MD", "txt", "TXT"};
sound docsBrowserMoveSound; sound docsBrowserMoveSound;
sound docsBrowserSelectSound; sound docsBrowserSelectSound;
void docs_browser_set_speak_callback(docs_browser_speak_callback@ callback) { void docs_browser_set_speak_callback(docs_browser_speak_callback @callback) {
@docsBrowserSpeakCallback = @callback; @docsBrowserSpeakCallback = @callback;
} }
void docs_browser_set_tick_callback(docs_browser_tick_callback@ callback) { void docs_browser_set_tick_callback(docs_browser_tick_callback @callback) {
@docsBrowserTickCallback = @callback; @docsBrowserTickCallback = @callback;
} }
@@ -36,9 +36,10 @@ void docs_browser_set_wrap(bool wrap) {
docsBrowserWrap = wrap; docsBrowserWrap = wrap;
} }
void docs_browser_set_extensions(string[]@ extensions) { void docs_browser_set_extensions(string[] @extensions) {
docsBrowserExtensions.resize(0); docsBrowserExtensions.resize(0);
if (@extensions is null) return; if (@extensions is null)
return;
for (uint extIndex = 0; extIndex < extensions.length(); extIndex++) { for (uint extIndex = 0; extIndex < extensions.length(); extIndex++) {
docsBrowserExtensions.insert_last(extensions[extIndex]); docsBrowserExtensions.insert_last(extensions[extIndex]);
} }
@@ -49,7 +50,7 @@ void docs_browser_reset_default_extensions() {
docs_browser_set_extensions(defaults); docs_browser_set_extensions(defaults);
} }
void docs_browser_speak(const string &in message, bool interrupt) { void docs_browser_speak(const string& in message, bool interrupt) {
if (@docsBrowserSpeakCallback !is null) { if (@docsBrowserSpeakCallback !is null) {
docsBrowserSpeakCallback(message, interrupt); docsBrowserSpeakCallback(message, interrupt);
return; return;
@@ -63,19 +64,20 @@ void docs_browser_tick() {
} }
} }
bool docs_browser_sort_case_insensitive(const string &in a, const string &in b) { bool docs_browser_sort_case_insensitive(const string& in a, const string& in b) {
return a.lower() < b.lower(); return a.lower() < b.lower();
} }
void docs_browser_append_unique_case_insensitive(string[]@ items, const string&in value) { void docs_browser_append_unique_case_insensitive(string[] @items, const string& in value) {
string lowerValue = value.lower(); string lowerValue = value.lower();
for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) { for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) {
if (items[itemIndex].lower() == lowerValue) return; if (items[itemIndex].lower() == lowerValue)
return;
} }
items.insert_last(value); items.insert_last(value);
} }
string docs_browser_collapse_spaces(const string&in text) { string docs_browser_collapse_spaces(const string& in text) {
string result = text; string result = text;
while (result.find_first(" ") > -1) { while (result.find_first(" ") > -1) {
result = result.replace(" ", " ", true); result = result.replace(" ", " ", true);
@@ -83,7 +85,7 @@ string docs_browser_collapse_spaces(const string&in text) {
return result; return result;
} }
string docs_browser_format_label(const string&in filename) { string docs_browser_format_label(const string& in filename) {
string name = filename; string name = filename;
int dotPos = name.find_last_of("."); int dotPos = name.find_last_of(".");
if (dotPos > 0) { if (dotPos > 0) {
@@ -96,28 +98,33 @@ string docs_browser_format_label(const string&in filename) {
name = name.lower(); name = name.lower();
name.trim_whitespace_this(); name.trim_whitespace_this();
if (name.length() == 0) return "Document"; if (name.length() == 0)
return "Document";
string first = name.substr(0, 1).upper(); string first = name.substr(0, 1).upper();
if (name.length() == 1) return first; if (name.length() == 1)
return first;
return first + name.substr(1); return first + name.substr(1);
} }
void docs_browser_collect_entries(string[]@ labels, string[]@ paths) { void docs_browser_collect_entries(string[] @labels, string[] @paths) {
labels.resize(0); labels.resize(0);
paths.resize(0); paths.resize(0);
if (!directory_exists(docsBrowserDirectory)) return; if (!directory_exists(docsBrowserDirectory))
return;
string[] docFiles; string[] docFiles;
for (uint extIndex = 0; extIndex < docsBrowserExtensions.length(); extIndex++) { for (uint extIndex = 0; extIndex < docsBrowserExtensions.length(); extIndex++) {
string ext = docsBrowserExtensions[extIndex]; string ext = docsBrowserExtensions[extIndex];
if (ext == "") continue; if (ext == "")
continue;
if (ext.substr(0, 1) == ".") { if (ext.substr(0, 1) == ".") {
ext = ext.substr(1); ext = ext.substr(1);
} }
string[]@ found = find_files(docsBrowserDirectory + "/*." + ext); string[] @found = find_files(docsBrowserDirectory + "/*." + ext);
if (@found is null) continue; if (@found is null)
continue;
for (uint fileIndex = 0; fileIndex < found.length(); fileIndex++) { for (uint fileIndex = 0; fileIndex < found.length(); fileIndex++) {
docs_browser_append_unique_case_insensitive(docFiles, found[fileIndex]); docs_browser_append_unique_case_insensitive(docFiles, found[fileIndex]);
} }
@@ -133,7 +140,7 @@ void docs_browser_collect_entries(string[]@ labels, string[]@ paths) {
} }
} }
void docs_browser_add_entries(string[]@ labels, string[]@ paths, int[]@ types, const int typeValue = 1) { void docs_browser_add_entries(string[] @labels, string[] @paths, int[] @types, const int typeValue = 1) {
string[] docLabels; string[] docLabels;
string[] docPaths; string[] docPaths;
docs_browser_collect_entries(docLabels, docPaths); docs_browser_collect_entries(docLabels, docPaths);
@@ -145,12 +152,14 @@ void docs_browser_add_entries(string[]@ labels, string[]@ paths, int[]@ types, c
} }
} }
void docs_browser_play_ui_sound(sound &inout soundObj, const string basePath) { void docs_browser_play_ui_sound(sound& inout soundObj, const string basePath) {
string soundPath = resolve_audio_path(basePath); string soundPath = resolve_audio_path(basePath);
if (soundPath == "") return; if (soundPath == "")
return;
soundObj.close(); soundObj.close();
if (!soundObj.load(soundPath)) return; if (!soundObj.load(soundPath))
return;
soundObj.play(); soundObj.play();
} }
+2 -9
View File
@@ -6,15 +6,8 @@ string file_viewer(string content, string title = "Text Reader", bool readOnly =
audio_form f; audio_form f;
f.create_window(title, false, true); f.create_window(title, false, true);
int textControl = f.create_input_box( int textControl = f.create_input_box((readOnly ? "Document (read only)" : "Document (editable)"), content, "", 0,
(readOnly ? "Document (read only)" : "Document (editable)"), readOnly, true, true);
content,
"",
0,
readOnly,
true,
true
);
int okButton = -1; int okButton = -1;
int closeButton = -1; int closeButton = -1;
+118 -47
View File
@@ -1,12 +1,12 @@
#include "audio_paths.nvgt" #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_tick_callback();
funcdef void learn_sounds_setup_callback(); funcdef void learn_sounds_setup_callback();
learn_sounds_speak_callback@ learnSoundsSpeakCallback = null; learn_sounds_speak_callback @learnSoundsSpeakCallback = null;
learn_sounds_tick_callback@ learnSoundsTickCallback = null; learn_sounds_tick_callback @learnSoundsTickCallback = null;
learn_sounds_setup_callback@ learnSoundsSetupCallback = null; learn_sounds_setup_callback @learnSoundsSetupCallback = null;
string[] learnSoundsSkipList; string[] learnSoundsSkipList;
string[] learnSoundsDescriptionPaths; string[] learnSoundsDescriptionPaths;
@@ -22,15 +22,15 @@ sound learnSoundsPreviewSound;
sound learnSoundsMoveSound; sound learnSoundsMoveSound;
sound learnSoundsSelectSound; sound learnSoundsSelectSound;
void learn_sounds_set_speak_callback(learn_sounds_speak_callback@ callback) { void learn_sounds_set_speak_callback(learn_sounds_speak_callback @callback) {
@learnSoundsSpeakCallback = @callback; @learnSoundsSpeakCallback = @callback;
} }
void learn_sounds_set_tick_callback(learn_sounds_tick_callback@ callback) { void learn_sounds_set_tick_callback(learn_sounds_tick_callback @callback) {
@learnSoundsTickCallback = @callback; @learnSoundsTickCallback = @callback;
} }
void learn_sounds_set_setup_callback(learn_sounds_setup_callback@ callback) { void learn_sounds_set_setup_callback(learn_sounds_setup_callback @callback) {
@learnSoundsSetupCallback = @callback; @learnSoundsSetupCallback = @callback;
learnSoundsSetupApplied = false; learnSoundsSetupApplied = false;
} }
@@ -81,7 +81,7 @@ void learn_sounds_reset_configuration() {
learnSoundsSetupApplied = false; learnSoundsSetupApplied = false;
} }
void learn_sounds_speak(const string &in message, bool interrupt) { void learn_sounds_speak(const string& in message, bool interrupt) {
if (@learnSoundsSpeakCallback !is null) { if (@learnSoundsSpeakCallback !is null) {
learnSoundsSpeakCallback(message, interrupt); learnSoundsSpeakCallback(message, interrupt);
return; return;
@@ -107,33 +107,37 @@ void learn_sounds_apply_setup_once() {
learnSoundsSetupApplied = true; learnSoundsSetupApplied = true;
} }
string learn_sounds_normalize_path(const string&in path) { string learn_sounds_normalize_path(const string& in path) {
return path.replace("\\", "/", true); return path.replace("\\", "/", true);
} }
bool learn_sounds_is_directory_skip_entry(const string&in entry) { bool learn_sounds_is_directory_skip_entry(const string& in entry) {
if (entry.length() == 0) return false; if (entry.length() == 0)
if (entry.substr(entry.length() - 1) == "/") return true; return false;
if (entry.substr(entry.length() - 1) == "/")
return true;
return directory_exists(entry); return directory_exists(entry);
} }
bool learn_sounds_should_skip_path(const string&in path) { bool learn_sounds_should_skip_path(const string& in path) {
string normalizedPath = learn_sounds_normalize_path(path); string normalizedPath = learn_sounds_normalize_path(path);
for (uint skipIndex = 0; skipIndex < learnSoundsSkipList.length(); skipIndex++) { for (uint skipIndex = 0; skipIndex < learnSoundsSkipList.length(); skipIndex++) {
string entry = learn_sounds_normalize_path(learnSoundsSkipList[skipIndex]); string entry = learn_sounds_normalize_path(learnSoundsSkipList[skipIndex]);
if (entry.length() == 0) continue; if (entry.length() == 0)
continue;
bool isDirectory = learn_sounds_is_directory_skip_entry(entry); bool isDirectory = learn_sounds_is_directory_skip_entry(entry);
if (isDirectory) { if (isDirectory) {
if (entry.substr(entry.length() - 1) != "/") entry += "/"; if (entry.substr(entry.length() - 1) != "/")
if (normalizedPath.length() >= entry.length() && entry += "/";
normalizedPath.substr(0, entry.length()) == entry) { if (normalizedPath.length() >= entry.length() && normalizedPath.substr(0, entry.length()) == entry) {
return true; return true;
} }
continue; continue;
} }
if (normalizedPath == entry) return true; if (normalizedPath == entry)
return true;
if (entry.find_first("/") < 0 && entry.find_first("\\") < 0) { if (entry.find_first("/") < 0 && entry.find_first("\\") < 0) {
if (normalizedPath.length() >= entry.length() + 1 && if (normalizedPath.length() >= entry.length() + 1 &&
@@ -145,7 +149,7 @@ bool learn_sounds_should_skip_path(const string&in path) {
return false; return false;
} }
string learn_sounds_get_description(const string&in path) { string learn_sounds_get_description(const string& in path) {
string normalizedPath = learn_sounds_normalize_path(path); string normalizedPath = learn_sounds_normalize_path(path);
uint descriptionCount = learnSoundsDescriptionPaths.length(); uint descriptionCount = learnSoundsDescriptionPaths.length();
if (learnSoundsDescriptionTexts.length() < descriptionCount) { if (learnSoundsDescriptionTexts.length() < descriptionCount) {
@@ -161,36 +165,99 @@ string learn_sounds_get_description(const string&in path) {
return ""; return "";
} }
void learn_sounds_gather_files_recursive(const string&in basePath, string[]@ outFiles) { bool learn_sounds_contains_path_ci(string[] @paths, const string& in path) {
string[]@ oggFiles = find_files(basePath + "/*.ogg"); 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;
}
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);
}
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";
}
void learn_sounds_gather_files_from_pack(const string& in basePath, string[] @outFiles) {
pack @activePack = cast<pack @>(sound_default_pack);
if (@activePack is null)
return;
string[] @packFiles = activePack.list_files();
if (@packFiles is null)
return;
string normalizedBasePath = learn_sounds_normalize_path(basePath);
if (normalizedBasePath != "" && normalizedBasePath.substr(normalizedBasePath.length() - 1) != "/") {
normalizedBasePath += "/";
}
string normalizedBasePathLower = normalizedBasePath.lower();
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_gather_files_recursive(const string& in basePath, string[] @outFiles) {
string[] @oggFiles = find_files(basePath + "/*.ogg");
if (@oggFiles !is null) { if (@oggFiles !is null) {
for (uint fileIndex = 0; fileIndex < oggFiles.length(); fileIndex++) { for (uint fileIndex = 0; fileIndex < oggFiles.length(); fileIndex++) {
outFiles.insert_last(basePath + "/" + oggFiles[fileIndex]); learn_sounds_add_path_if_missing(outFiles, basePath + "/" + oggFiles[fileIndex]);
} }
} }
string[]@ oggUpperFiles = find_files(basePath + "/*.OGG"); string[] @oggUpperFiles = find_files(basePath + "/*.OGG");
if (@oggUpperFiles !is null) { if (@oggUpperFiles !is null) {
for (uint fileIndex = 0; fileIndex < oggUpperFiles.length(); fileIndex++) { for (uint fileIndex = 0; fileIndex < oggUpperFiles.length(); fileIndex++) {
outFiles.insert_last(basePath + "/" + oggUpperFiles[fileIndex]); learn_sounds_add_path_if_missing(outFiles, basePath + "/" + oggUpperFiles[fileIndex]);
} }
} }
string[]@ wavFiles = find_files(basePath + "/*.wav"); string[] @wavFiles = find_files(basePath + "/*.wav");
if (@wavFiles !is null) { if (@wavFiles !is null) {
for (uint fileIndex = 0; fileIndex < wavFiles.length(); fileIndex++) { for (uint fileIndex = 0; fileIndex < wavFiles.length(); fileIndex++) {
outFiles.insert_last(basePath + "/" + wavFiles[fileIndex]); learn_sounds_add_path_if_missing(outFiles, basePath + "/" + wavFiles[fileIndex]);
} }
} }
string[]@ wavUpperFiles = find_files(basePath + "/*.WAV"); string[] @wavUpperFiles = find_files(basePath + "/*.WAV");
if (@wavUpperFiles !is null) { if (@wavUpperFiles !is null) {
for (uint fileIndex = 0; fileIndex < wavUpperFiles.length(); fileIndex++) { for (uint fileIndex = 0; fileIndex < wavUpperFiles.length(); fileIndex++) {
outFiles.insert_last(basePath + "/" + wavUpperFiles[fileIndex]); learn_sounds_add_path_if_missing(outFiles, basePath + "/" + wavUpperFiles[fileIndex]);
} }
} }
string[]@ folders = find_directories(basePath + "/*"); string[] @folders = find_directories(basePath + "/*");
if (@folders !is null) { if (@folders !is null) {
for (uint folderIndex = 0; folderIndex < folders.length(); folderIndex++) { for (uint folderIndex = 0; folderIndex < folders.length(); folderIndex++) {
learn_sounds_gather_files_recursive(basePath + "/" + folders[folderIndex], outFiles); learn_sounds_gather_files_recursive(basePath + "/" + folders[folderIndex], outFiles);
@@ -198,11 +265,11 @@ void learn_sounds_gather_files_recursive(const string&in basePath, string[]@ out
} }
} }
bool learn_sounds_sort_case_insensitive(const string &in a, const string &in b) { bool learn_sounds_sort_case_insensitive(const string& in a, const string& in b) {
return a.lower() < b.lower(); return a.lower() < b.lower();
} }
string learn_sounds_collapse_spaces(const string&in text) { string learn_sounds_collapse_spaces(const string& in text) {
string result = text; string result = text;
while (result.find_first(" ") > -1) { while (result.find_first(" ") > -1) {
result = result.replace(" ", " ", true); result = result.replace(" ", " ", true);
@@ -210,7 +277,7 @@ string learn_sounds_collapse_spaces(const string&in text) {
return result; return result;
} }
string learn_sounds_label_from_path(const string&in soundPath) { string learn_sounds_label_from_path(const string& in soundPath) {
string normalizedPath = learn_sounds_normalize_path(soundPath); string normalizedPath = learn_sounds_normalize_path(soundPath);
int slashPos = normalizedPath.find_last_of("/"); int slashPos = normalizedPath.find_last_of("/");
string name = (slashPos >= 0) ? normalizedPath.substr(slashPos + 1) : normalizedPath; string name = (slashPos >= 0) ? normalizedPath.substr(slashPos + 1) : normalizedPath;
@@ -228,20 +295,20 @@ string learn_sounds_label_from_path(const string&in soundPath) {
name = name.lower(); name = name.lower();
name.trim_whitespace_this(); name.trim_whitespace_this();
if (name.length() == 0) return "Sound"; if (name.length() == 0)
return "Sound";
return name; return name;
} }
void learn_sounds_collect_entries(string[]@ labels, string[]@ soundPaths) { void learn_sounds_collect_entries(string[] @labels, string[] @soundPaths) {
labels.resize(0); labels.resize(0);
soundPaths.resize(0); soundPaths.resize(0);
if (!directory_exists(learnSoundsRootDir)) {
return;
}
string[] discoveredFiles; string[] discoveredFiles;
if (directory_exists(learnSoundsRootDir)) {
learn_sounds_gather_files_recursive(learnSoundsRootDir, discoveredFiles); learn_sounds_gather_files_recursive(learnSoundsRootDir, discoveredFiles);
}
learn_sounds_gather_files_from_pack(learnSoundsRootDir, discoveredFiles);
if (discoveredFiles.length() > 1) { if (discoveredFiles.length() > 1) {
discoveredFiles.sort(learn_sounds_sort_case_insensitive); discoveredFiles.sort(learn_sounds_sort_case_insensitive);
} }
@@ -263,16 +330,24 @@ void learn_sounds_collect_entries(string[]@ labels, string[]@ soundPaths) {
} }
} }
void learn_sounds_play_ui_sound(sound &inout soundObj, const string basePath) { void learn_sounds_play_ui_sound(sound& inout soundObj, const string basePath) {
string soundPath = resolve_audio_path(basePath); soundObj.close();
if (soundPath == "") {
// Avoid file_exists()-only path checks so packaged Android assets can still load.
if (soundObj.load(basePath)) {
soundObj.play();
return; return;
} }
soundObj.close(); if (soundObj.load(basePath + ".ogg")) {
if (!soundObj.load(soundPath)) { soundObj.play();
return; return;
} }
if (!soundObj.load(basePath + ".wav")) {
return;
}
soundObj.play(); soundObj.play();
} }
@@ -324,10 +399,6 @@ void learn_sounds_run_menu() {
learn_sounds_play_ui_sound(learnSoundsSelectSound, learnSoundsMenuSoundDir + "/menu_select"); learn_sounds_play_ui_sound(learnSoundsSelectSound, learnSoundsMenuSoundDir + "/menu_select");
} }
string selectedPath = soundPaths[selection]; string selectedPath = soundPaths[selection];
if (!file_exists(selectedPath)) {
learn_sounds_speak("Sound not found.", true);
continue;
}
learnSoundsPreviewSound.close(); learnSoundsPreviewSound.close();
if (!learnSoundsPreviewSound.load(selectedPath)) { if (!learnSoundsPreviewSound.load(selectedPath)) {
+61 -31
View File
@@ -3,7 +3,7 @@
// Applies common menu sounds from a directory. // Applies common menu sounds from a directory.
// Looks for both .ogg and .wav files automatically. // Looks for both .ogg and .wav files automatically.
void menu_apply_default_sounds(menu@ menuRef, const string soundDir = "sounds/menu") { void menu_apply_default_sounds(menu @menuRef, const string soundDir = "sounds/menu") {
if (@menuRef is null) { if (@menuRef is null) {
return; return;
} }
@@ -18,7 +18,8 @@ void menu_apply_default_sounds(menu@ menuRef, const string soundDir = "sounds/me
// Minimal blocking list menu. // Minimal blocking list menu.
// Returns selected index or -1 on empty input/escape. // 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") { 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) { if (@options is null || options.length() == 0) {
return -1; return -1;
} }
@@ -39,37 +40,64 @@ int menu_run_simple(const string introText, string[]@ options, bool wrap = true,
// Returns a-z for menu prefix filtering, or empty string when no letter key was pressed. // Returns a-z for menu prefix filtering, or empty string when no letter key was pressed.
string menu_get_filter_letter() { string menu_get_filter_letter() {
if (key_pressed(KEY_A)) return "a"; if (key_pressed(KEY_A))
if (key_pressed(KEY_B)) return "b"; return "a";
if (key_pressed(KEY_C)) return "c"; if (key_pressed(KEY_B))
if (key_pressed(KEY_D)) return "d"; return "b";
if (key_pressed(KEY_E)) return "e"; if (key_pressed(KEY_C))
if (key_pressed(KEY_F)) return "f"; return "c";
if (key_pressed(KEY_G)) return "g"; if (key_pressed(KEY_D))
if (key_pressed(KEY_H)) return "h"; return "d";
if (key_pressed(KEY_I)) return "i"; if (key_pressed(KEY_E))
if (key_pressed(KEY_J)) return "j"; return "e";
if (key_pressed(KEY_K)) return "k"; if (key_pressed(KEY_F))
if (key_pressed(KEY_L)) return "l"; return "f";
if (key_pressed(KEY_M)) return "m"; if (key_pressed(KEY_G))
if (key_pressed(KEY_N)) return "n"; return "g";
if (key_pressed(KEY_O)) return "o"; if (key_pressed(KEY_H))
if (key_pressed(KEY_P)) return "p"; return "h";
if (key_pressed(KEY_Q)) return "q"; if (key_pressed(KEY_I))
if (key_pressed(KEY_R)) return "r"; return "i";
if (key_pressed(KEY_S)) return "s"; if (key_pressed(KEY_J))
if (key_pressed(KEY_T)) return "t"; return "j";
if (key_pressed(KEY_U)) return "u"; if (key_pressed(KEY_K))
if (key_pressed(KEY_V)) return "v"; return "k";
if (key_pressed(KEY_W)) return "w"; if (key_pressed(KEY_L))
if (key_pressed(KEY_X)) return "x"; return "l";
if (key_pressed(KEY_Y)) return "y"; if (key_pressed(KEY_M))
if (key_pressed(KEY_Z)) return "z"; 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 ""; return "";
} }
// Applies a prefix filter to menu options. // Applies a prefix filter to menu options.
void menu_apply_prefix_filter(const string &in filterText, const string[]@ options, int[]@ filteredIndices, string[]@ filteredOptions) { void menu_apply_prefix_filter(const string& in filterText, const string[] @options, int[] @filteredIndices,
string[] @filteredOptions) {
filteredIndices.resize(0); filteredIndices.resize(0);
filteredOptions.resize(0); filteredOptions.resize(0);
@@ -86,7 +114,8 @@ void menu_apply_prefix_filter(const string &in filterText, const string[]@ optio
} }
string optionLower = options[optionIndex].lower(); string optionLower = options[optionIndex].lower();
if (optionLower.length() >= filterLower.length() && optionLower.substr(0, filterLower.length()) == filterLower) { if (optionLower.length() >= filterLower.length() &&
optionLower.substr(0, filterLower.length()) == filterLower) {
filteredIndices.insert_last(optionIndex); filteredIndices.insert_last(optionIndex);
filteredOptions.insert_last(options[optionIndex]); filteredOptions.insert_last(options[optionIndex]);
} }
@@ -94,7 +123,8 @@ void menu_apply_prefix_filter(const string &in filterText, const string[]@ optio
} }
// Updates filter text from keyboard input and reapplies filtering. // 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 menu_update_prefix_filter(string& inout filterText, const string[] @options, int[] @filteredIndices,
string[] @filteredOptions, int& inout selection) {
bool filterChanged = false; bool filterChanged = false;
if (key_pressed(KEY_BACK) && filterText.length() > 0) { if (key_pressed(KEY_BACK) && filterText.length() > 0) {
+3 -3
View File
@@ -1,7 +1,7 @@
#include "music.nvgt" #include "music.nvgt"
// Resume paused menu music when possible, otherwise start a new track. // 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) { void menu_music_resume_or_play(music_manager& inout manager, const string track, const int fadeInMs = 0) {
if (manager.resume(fadeInMs)) { if (manager.resume(fadeInMs)) {
return; return;
} }
@@ -17,7 +17,7 @@ void menu_music_resume_or_play(music_manager &inout manager, const string track,
} }
// Pause menu music. Blocking is enabled by default so fade-out fully completes. // 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) { bool menu_music_pause(music_manager& inout manager, const int fadeOutMs = 0, const bool blocking = true) {
if (!manager.playing) { if (!manager.playing) {
return false; return false;
} }
@@ -25,6 +25,6 @@ bool menu_music_pause(music_manager &inout manager, const int fadeOutMs = 0, con
} }
// Stop menu music and reset playback state. // Stop menu music and reset playback state.
void menu_music_stop(music_manager &inout manager, const int fadeOutMs = 0, const bool blocking = false) { void menu_music_stop(music_manager& inout manager, const int fadeOutMs = 0, const bool blocking = false) {
manager.stop(fadeOutMs, blocking); manager.stop(fadeOutMs, blocking);
} }
+2 -2
View File
@@ -1,5 +1,5 @@
// Multikey input helpers. // Multikey input helpers.
bool check_key_down(array<int>@ keys) { bool check_key_down(array<int> @keys) {
// True when at least one key in the set is currently down. // True when at least one key in the set is currently down.
if (keys is null || keys.length() == 0) { if (keys is null || keys.length() == 0) {
return false; return false;
@@ -14,7 +14,7 @@ bool check_key_down(array<int>@ keys) {
return false; return false;
} }
bool check_all_keys(array<int>@ keys) { bool check_all_keys(array<int> @keys) {
// True only when every key in the set is currently down. // True only when every key in the set is currently down.
if (keys is null || keys.length() == 0) { if (keys is null || keys.length() == 0) {
return false; return false;
+9 -5
View File
@@ -26,17 +26,20 @@ string normalize_name_whitespace(string name) {
return result; return result;
} }
bool is_windows_reserved_filename(const string&in upperName) { bool is_windows_reserved_filename(const string& in upperName) {
if (upperName == "CON" || upperName == "PRN" || upperName == "AUX" || upperName == "NUL") return true; if (upperName == "CON" || upperName == "PRN" || upperName == "AUX" || upperName == "NUL")
return true;
if (upperName.length() == 4 && upperName.substr(0, 3) == "COM") { if (upperName.length() == 4 && upperName.substr(0, 3) == "COM") {
int num = parse_int(upperName.substr(3)); int num = parse_int(upperName.substr(3));
if (num >= 1 && num <= 9) return true; if (num >= 1 && num <= 9)
return true;
} }
if (upperName.length() == 4 && upperName.substr(0, 3) == "LPT") { if (upperName.length() == 4 && upperName.substr(0, 3) == "LPT") {
int num = parse_int(upperName.substr(3)); int num = parse_int(upperName.substr(3));
if (num >= 1 && num <= 9) return true; if (num >= 1 && num <= 9)
return true;
} }
return false; return false;
@@ -96,6 +99,7 @@ string sanitize_filename_base(string name, const int maxLength = 40, const strin
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") { 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; return sanitize_filename_base(name, maxBaseLength, fallback) + extension;
} }
+25 -12
View File
@@ -1,6 +1,6 @@
#include "audio_paths.nvgt" #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[] notificationsHistory;
string[] notificationsQueue; string[] notificationsQueue;
@@ -13,9 +13,9 @@ timer notificationsDelayTimer;
sound notificationsSound; sound notificationsSound;
bool notificationsWaitingForSound = false; bool notificationsWaitingForSound = false;
string notificationsSoundPath = "sounds/notify"; string notificationsSoundPath = "sounds/notify";
notification_speak_callback@ notificationsSpeakCallback = null; notification_speak_callback @notificationsSpeakCallback = null;
void notifications_set_speak_callback(notification_speak_callback@ callback) { void notifications_set_speak_callback(notification_speak_callback @callback) {
@notificationsSpeakCallback = @callback; @notificationsSpeakCallback = @callback;
} }
@@ -56,7 +56,7 @@ void notifications_clear() {
notificationsSound.close(); notificationsSound.close();
} }
void notifications_speak(const string &in message, bool interrupt) { void notifications_speak(const string& in message, bool interrupt) {
if (@notificationsSpeakCallback !is null) { if (@notificationsSpeakCallback !is null) {
notificationsSpeakCallback(message, interrupt); notificationsSpeakCallback(message, interrupt);
return; return;
@@ -64,7 +64,7 @@ void notifications_speak(const string &in message, bool interrupt) {
screen_reader_speak(message, interrupt); screen_reader_speak(message, interrupt);
} }
void notifications_enqueue(const string &in message) { void notifications_enqueue(const string& in message) {
notificationsQueue.insert_last(message); notificationsQueue.insert_last(message);
notificationsHistory.insert_last(message); notificationsHistory.insert_last(message);
@@ -76,13 +76,22 @@ void notifications_enqueue(const string &in message) {
} }
bool notifications_try_play_sound() { bool notifications_try_play_sound() {
string resolvedPath = resolve_audio_path(notificationsSoundPath); notificationsSound.close();
if (resolvedPath == "") {
return false; // Avoid file_exists()-only checks so packaged Android assets can still load.
if (notificationsSound.load(notificationsSoundPath)) {
notificationsSound.play();
return true;
} }
notificationsSound.close(); string oggPath = notificationsSoundPath + ".ogg";
if (!notificationsSound.load(resolvedPath)) { if (notificationsSound.load(oggPath)) {
notificationsSound.play();
return true;
}
string wavPath = notificationsSoundPath + ".wav";
if (!notificationsSound.load(wavPath)) {
return false; return false;
} }
@@ -141,7 +150,9 @@ void notifications_check_keys() {
} }
int position = notificationsCurrentIndex + 1; int position = notificationsCurrentIndex + 1;
notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " + notificationsHistory.length(), true); notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " +
notificationsHistory.length(),
true);
return; return;
} }
@@ -159,7 +170,9 @@ void notifications_check_keys() {
} }
int position = notificationsCurrentIndex + 1; int position = notificationsCurrentIndex + 1;
notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " + notificationsHistory.length(), true); notifications_speak(notificationsHistory[notificationsCurrentIndex] + " " + position + " of " +
notificationsHistory.length(),
true);
return; return;
} }
+18 -17
View File
@@ -1,25 +1,26 @@
// Generic save/file helpers. // Generic save/file helpers.
bool save_utils_sort_string_case_insensitive(const string &in a, const string &in b) { bool save_utils_sort_string_case_insensitive(const string& in a, const string& in b) {
return a.lower() < b.lower(); return a.lower() < b.lower();
} }
string[] list_files_with_extension(const string&in extension, const string&in directory = "") { string[] list_files_with_extension(const string& in extension, const string& in directory = "") {
string[] result; string[] result;
if (extension == "") return result; if (extension == "")
return result;
string dirPrefix = directory; string dirPrefix = directory;
if (dirPrefix != "" && dirPrefix.substr(dirPrefix.length() - 1) != "/") { if (dirPrefix != "" && dirPrefix.substr(dirPrefix.length() - 1) != "/") {
dirPrefix += "/"; dirPrefix += "/";
} }
string[]@ items = glob(dirPrefix + "*" + extension); string[] @items = glob(dirPrefix + "*" + extension);
if (@items is null) return result; if (@items is null)
return result;
for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) { for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) {
string item = items[itemIndex]; string item = items[itemIndex];
if (item.length() >= extension.length() && if (item.length() >= extension.length() && item.substr(item.length() - extension.length()) == extension) {
item.substr(item.length() - extension.length()) == extension) {
result.insert_last(item); result.insert_last(item);
} }
} }
@@ -30,20 +31,19 @@ string[] list_files_with_extension(const string&in extension, const string&in di
return result; return result;
} }
bool has_files_with_extension(const string&in extension, const string&in directory = "") { bool has_files_with_extension(const string& in extension, const string& in directory = "") {
return list_files_with_extension(extension, directory).length() > 0; return list_files_with_extension(extension, directory).length() > 0;
} }
string strip_file_extension(const string&in filename, const string&in extension) { string strip_file_extension(const string& in filename, const string& in extension) {
if (extension != "" && if (extension != "" && filename.length() >= extension.length() &&
filename.length() >= extension.length() &&
filename.substr(filename.length() - extension.length()) == extension) { filename.substr(filename.length() - extension.length()) == extension) {
return filename.substr(0, filename.length() - extension.length()); return filename.substr(0, filename.length() - extension.length());
} }
return filename; return filename;
} }
bool save_string_file(const string&in filename, const string&in data) { bool save_string_file(const string& in filename, const string& in data) {
if (data.length() == 0) { if (data.length() == 0) {
return false; return false;
} }
@@ -62,7 +62,7 @@ bool save_string_file(const string&in filename, const string&in data) {
return true; return true;
} }
bool read_string_file(const string&in filename, string&out data, const bool allowEmpty = false) { bool read_string_file(const string& in filename, string& out data, const bool allowEmpty = false) {
file inFile; file inFile;
if (!inFile.open(filename, "rb")) { if (!inFile.open(filename, "rb")) {
return false; return false;
@@ -73,20 +73,21 @@ bool read_string_file(const string&in filename, string&out data, const bool allo
return allowEmpty || data.length() > 0; return allowEmpty || data.length() > 0;
} }
string encrypt_string_aes(const string&in rawData, const string&in key) { string encrypt_string_aes(const string& in rawData, const string& in key) {
return string_aes_encrypt(rawData, key); return string_aes_encrypt(rawData, key);
} }
string decrypt_string_aes(const string&in encryptedData, const string&in key) { string decrypt_string_aes(const string& in encryptedData, const string& in key) {
return string_aes_decrypt(encryptedData, key); return string_aes_decrypt(encryptedData, key);
} }
bool save_encrypted_file(const string&in filename, const string&in rawData, const string&in key) { bool save_encrypted_file(const string& in filename, const string& in rawData, const string& in key) {
string encryptedData = encrypt_string_aes(rawData, key); string encryptedData = encrypt_string_aes(rawData, key);
return save_string_file(filename, encryptedData); 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) { bool read_encrypted_file(const string& in filename, const string& in key, string& out rawData,
const bool allowPlaintextFallback = true) {
string encryptedData = ""; string encryptedData = "";
if (!read_string_file(filename, encryptedData, false)) { if (!read_string_file(filename, encryptedData, false)) {
return false; return false;
+6 -4
View File
@@ -32,7 +32,7 @@ void speech_history_set_deduplicate(bool deduplicate) {
speechHistoryDeduplicate = deduplicate; speechHistoryDeduplicate = deduplicate;
} }
void speech_history_add(const string &in message) { void speech_history_add(const string& in message) {
if (message == "") { if (message == "") {
return; return;
} }
@@ -54,7 +54,7 @@ void speech_history_add(const string &in message) {
speechHistoryCurrentIndex = speechHistory.length() - 1; speechHistoryCurrentIndex = speechHistory.length() - 1;
} }
void speak_with_history(const string &in message, bool interrupt) { void speak_with_history(const string& in message, bool interrupt) {
speech_history_add(message); speech_history_add(message);
screen_reader_speak(message, interrupt); screen_reader_speak(message, interrupt);
} }
@@ -75,7 +75,8 @@ void check_speech_history_keys() {
} }
int position = speechHistoryCurrentIndex + 1; int position = speechHistoryCurrentIndex + 1;
screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(), true); screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(),
true);
return; return;
} }
@@ -94,7 +95,8 @@ void check_speech_history_keys() {
} }
int position = speechHistoryCurrentIndex + 1; int position = speechHistoryCurrentIndex + 1;
screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(), true); screen_reader_speak(speechHistory[speechHistoryCurrentIndex] + " " + position + " of " + speechHistory.length(),
true);
} }
} }
+2 -1
View File
@@ -34,7 +34,8 @@ void ui_restore_window(const string windowTitle = "") {
} }
} }
string ui_input_box(const string title, const string prompt, const string defaultValue = "", const string windowTitle = "") { 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 dialogTitle = ui_resolve_dialog_title(title, prompt);
string result = virtual_input_box(dialogTitle, prompt, defaultValue); string result = virtual_input_box(dialogTitle, prompt, defaultValue);
ui_restore_window(windowTitle); ui_restore_window(windowTitle);
+17 -10
View File
@@ -6,9 +6,9 @@ float volumeControlsMaxDb = 0.0f;
float volumeControlsMinDb = -60.0f; float volumeControlsMinDb = -60.0f;
float volumeControlsStepDb = 3.0f; float volumeControlsStepDb = 3.0f;
float volumeControlsCurrentDb = 0.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) { void volume_controls_set_apply_callback(volume_controls_apply_callback @callback) {
@volumeControlsApplyCallback = @callback; @volumeControlsApplyCallback = @callback;
} }
@@ -31,12 +31,15 @@ void volume_controls_configure(float minDb = -60.0f, float maxDb = 0.0f, float s
int volume_controls_percent_from_db(float volumeDb) { int volume_controls_percent_from_db(float volumeDb) {
float range = volumeControlsMaxDb - volumeControlsMinDb; float range = volumeControlsMaxDb - volumeControlsMinDb;
if (range <= 0.0f) return 100; if (range <= 0.0f)
return 100;
float normalized = (volumeDb - volumeControlsMinDb) / range; float normalized = (volumeDb - volumeControlsMinDb) / range;
int volumePercent = int(normalized * 100.0f + 0.5f); int volumePercent = int(normalized * 100.0f + 0.5f);
if (volumePercent < 0) volumePercent = 0; if (volumePercent < 0)
if (volumePercent > 100) volumePercent = 100; volumePercent = 0;
if (volumePercent > 100)
volumePercent = 100;
return volumePercent; return volumePercent;
} }
@@ -52,10 +55,13 @@ void volume_controls_apply(float volumeDb) {
void volume_controls_set_current_db(float volumeDb, bool announce = true) { void volume_controls_set_current_db(float volumeDb, bool announce = true) {
float clamped = volumeDb; float clamped = volumeDb;
if (clamped > volumeControlsMaxDb) clamped = volumeControlsMaxDb; if (clamped > volumeControlsMaxDb)
if (clamped < volumeControlsMinDb) clamped = volumeControlsMinDb; clamped = volumeControlsMaxDb;
if (clamped < volumeControlsMinDb)
clamped = volumeControlsMinDb;
if (clamped == volumeControlsCurrentDb) return; if (clamped == volumeControlsCurrentDb)
return;
volumeControlsCurrentDb = clamped; volumeControlsCurrentDb = clamped;
volume_controls_apply(volumeControlsCurrentDb); volume_controls_apply(volumeControlsCurrentDb);
@@ -83,8 +89,9 @@ void volume_controls_handle_keys(int downKey = KEY_PAGEDOWN, int upKey = KEY_PAG
} }
} }
void safe_destroy_sound_in_pool(sound_pool@ poolRef, int &inout handle) { void safe_destroy_sound_in_pool(sound_pool @poolRef, int& inout handle) {
if (handle == -1) return; if (handle == -1)
return;
if (@poolRef is null) { if (@poolRef is null) {
handle = -1; handle = -1;
return; return;