Files
libstorm-nvgt/learn_sounds.nvgt
2026-02-16 20:23:49 -05:00

341 lines
9.5 KiB
Plaintext

#include "audio_paths.nvgt"
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;
string[] learnSoundsSkipList;
string[] learnSoundsDescriptionPaths;
string[] learnSoundsDescriptionTexts;
string learnSoundsRootDir = "sounds";
string learnSoundsMenuSoundDir = "sounds/menu";
bool learnSoundsWrap = true;
bool learnSoundsPlaySelectSound = true;
bool learnSoundsSetupApplied = false;
sound learnSoundsPreviewSound;
sound learnSoundsMoveSound;
sound learnSoundsSelectSound;
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_setup_callback(learn_sounds_setup_callback@ callback) {
@learnSoundsSetupCallback = @callback;
learnSoundsSetupApplied = false;
}
void learn_sounds_set_root_dir(const string rootDir) {
learnSoundsRootDir = rootDir;
}
void learn_sounds_set_menu_sound_dir(const string menuSoundDir) {
learnSoundsMenuSoundDir = menuSoundDir;
}
void learn_sounds_set_wrap(bool wrap) {
learnSoundsWrap = wrap;
}
void learn_sounds_set_play_select_sound(bool playSelectSound) {
learnSoundsPlaySelectSound = playSelectSound;
}
void learn_sounds_clear_skip_entries() {
learnSoundsSkipList.resize(0);
}
void learn_sounds_add_skip_entry(const string entry) {
if (entry == "") {
return;
}
learnSoundsSkipList.insert_last(entry);
}
void learn_sounds_clear_descriptions() {
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);
}
void learn_sounds_reset_configuration() {
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_tick() {
if (@learnSoundsTickCallback !is null) {
learnSoundsTickCallback();
}
}
void learn_sounds_apply_setup_once() {
if (learnSoundsSetupApplied) {
return;
}
if (@learnSoundsSetupCallback !is null) {
learnSoundsSetupCallback();
}
learnSoundsSetupApplied = 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_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;
}
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;
}
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];
}
}
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_sort_case_insensitive(const string &in a, const string &in b) {
return a.lower() < b.lower();
}
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);
if (!directory_exists(learnSoundsRootDir)) {
return;
}
string[] discoveredFiles;
learn_sounds_gather_files_recursive(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) {
string soundPath = resolve_audio_path(basePath);
if (soundPath == "") {
return;
}
soundObj.close();
if (!soundObj.load(soundPath)) {
return;
}
soundObj.play();
}
void learn_sounds_run_menu() {
learn_sounds_apply_setup_once();
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;
}
int selection = 0;
learn_sounds_speak(labels[selection], true);
while (true) {
wait(5);
learn_sounds_tick();
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_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;
}
learnSoundsPreviewSound.close();
if (!learnSoundsPreviewSound.load(selectedPath)) {
learn_sounds_speak("Unable to load sound.", true);
continue;
}
learnSoundsPreviewSound.play();
}
}
}