diff --git a/assets/scenes/scene_1.symtres b/assets/scenes/scene_1.symtres index 0aa6809..9d93d90 100755 --- a/assets/scenes/scene_1.symtres +++ b/assets/scenes/scene_1.symtres @@ -1,6 +1,7 @@ Scene_Config { debug_draw_color : 0.800 0.400 0.100 1.000 + background_music_filename : sounds/scene_background_music_default.ogg fog_type : 1 fog_density : 0.1000 fog_color : 0.310 0.412 0.529 @@ -9,6 +10,7 @@ Scene_Config fog_max_distance : 450.0000 cleanup_func : scene_1_cleanup init_func : scene_1_init + background_music_volume : 0.0100 debug_draw_enabled : false debug_draw_mode : 0 next_scene : test diff --git a/assets/sounds/scene_background_music_default.ogg b/assets/sounds/scene_background_music_default.ogg new file mode 100644 index 0000000..65021f5 Binary files /dev/null and b/assets/sounds/scene_background_music_default.ogg differ diff --git a/src/common/version.h b/src/common/version.h index 1426ccd..bcd23c8 100755 --- a/src/common/version.h +++ b/src/common/version.h @@ -4,7 +4,7 @@ /* Auto generated version file. DO NOT MODIFY */ #define SYMMETRY_VERSION_MAJOR 0 #define SYMMETRY_VERSION_MINOR 2 -#define SYMMETRY_VERSION_REVISION 358 +#define SYMMETRY_VERSION_REVISION 359 #define SYMMETRY_VERSION_BRANCH "dev" #endif \ No newline at end of file diff --git a/src/game/editor.c b/src/game/editor.c index 21bdfec..b43b729 100755 --- a/src/game/editor.c +++ b/src/game/editor.c @@ -2196,17 +2196,8 @@ void editor_window_property_inspector(struct nk_context* context, struct Editor* { if(strncmp(sound_source_filename_buffer, sound_source->source_buffer->filename, MAX_FILENAME_LEN) != 0) { - struct Sound_Source_Buffer* new_source_buffer = sound_source_buffer_create(sound, sound_source_filename_buffer, ST_WAV_STREAM); - if(new_source_buffer) - { - sound_source_buffer_stop_all(sound, sound_source->source_buffer); - sound_source_instance_destroy(sound, sound_source->source_instance); - sound_source->source_instance = sound_source_instance_create(sound, new_source_buffer, true); - sound_source->source_buffer = new_source_buffer; - sound_source->base.transform.is_modified = true; // Fake a transformation so that post-update the new sound source position is updated - if(playing) - sound_source_instance_play(sound, sound_source->source_instance); - } + if(sound_source_buffer_set(sound, sound_source, sound_source_filename_buffer, ST_WAV) && playing) + sound_source_instance_play(sound, sound_source->source_instance); } sound_source_filename_copied = false; nk_contextual_close(context); @@ -2628,12 +2619,10 @@ void editor_window_settings_scene(struct nk_context* context, struct Editor* edi next_scene_filename_copied = true; } - nk_tooltip(context, "Enter the name of the scene file without extension"); int edit_flags = NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD | NK_EDIT_SIG_ENTER; int next_scene_edit_state = nk_edit_string_zero_terminated(context, edit_flags, next_scene_filename_buffer, MAX_FILENAME_LEN, NULL); if(next_scene_edit_state & NK_EDIT_COMMITED) { - scene_save(scene, scene->filename, DIRT_INSTALL); strncpy(scene->next_level_filename, next_scene_filename_buffer, MAX_FILENAME_LEN); nk_edit_unfocus(context); } @@ -2656,14 +2645,9 @@ void editor_window_settings_scene(struct nk_context* context, struct Editor* edi if(scene_init_edit_state & NK_EDIT_COMMITED) { if(scene_init_func_assign(scene, init_func_name_buffer)) - { nk_edit_unfocus(context); - scene_save(scene, scene->filename, DIRT_INSTALL); - } else - { init_func_name_copied = false; - } } else if(scene_init_edit_state & NK_EDIT_DEACTIVATED && init_func_name_copied) { @@ -2684,20 +2668,44 @@ void editor_window_settings_scene(struct nk_context* context, struct Editor* edi if(cleanup_func_edit_state & NK_EDIT_COMMITED) { if(scene_cleanup_func_assign(scene, cleanup_func_name_buffer)) - { - scene_save(scene, scene->filename, DIRT_INSTALL); nk_edit_unfocus(context); - } else - { cleanup_func_name_copied = false; - } } else if(cleanup_func_edit_state & NK_EDIT_DEACTIVATED && cleanup_func_name_copied) { cleanup_func_name_copied = false; } + /* Background Music */ + nk_layout_row_dynamic(context, row_height, 2); + nk_label(context, "Background Music Filename", LABEL_FLAGS_ALIGN_LEFT); + static char background_music_filename_buffer[MAX_FILENAME_LEN]; + static bool background_music_filename_copied = false; + if(!background_music_filename_copied) + { + strncpy(background_music_filename_buffer, scene->background_music_buffer->filename, MAX_FILENAME_LEN); + background_music_filename_copied = true; + } + + int background_music_filename_edit_state = nk_edit_string_zero_terminated(context, edit_flags, background_music_filename_buffer, MAX_FILENAME_LEN, NULL); + if(background_music_filename_edit_state & NK_EDIT_COMMITED) + { + if(scene_background_music_set(scene, background_music_filename_buffer)) + nk_edit_unfocus; + else + background_music_filename_copied = false; + } + else + { + background_music_filename_copied = false; + } + + nk_layout_row_dynamic(context, row_height, 1); + float new_volume = scene->background_music_volume; + if((new_volume = nk_propertyf(context, "Music Volume", 0.f, scene->background_music_volume, 1.f, 0.1f, 0.1f)) != scene->background_music_volume) + scene_background_music_volume_set(scene, new_volume); + /* Render Settings */ struct Render_Settings* render_settings = &game_state->renderer->settings; if(nk_tree_push(context, NK_TREE_TAB, "Fog", NK_MAXIMIZED)) diff --git a/src/game/scene.c b/src/game/scene.c index f1973fd..d0a556d 100755 --- a/src/game/scene.c +++ b/src/game/scene.c @@ -104,6 +104,9 @@ void scene_init(struct Scene* scene) editor_camera_init(game_state->editor, game_state->cvars); editor_init_entities(game_state->editor); + scene->background_music_volume = 0.1f; + scene_background_music_set(scene, "sounds/scene_background_music_default.ogg"); + if(game_state->game_mode == GAME_MODE_PAUSE) game_state->game_mode = GAME_MODE_GAME; scene->active_camera_index = game_state_get()->game_mode == GAME_MODE_GAME ? CAM_GAME : CAM_EDITOR; @@ -113,6 +116,41 @@ void scene_init(struct Scene* scene) scene_cleanup_func_assign(scene, "scene_func_stub"); } +bool scene_background_music_set(struct Scene* scene, const char* filename) +{ + struct Sound* sound = game_state_get()->sound; + scene->background_music_buffer = sound_source_buffer_create(sound, filename, ST_WAV_STREAM); + if(scene->background_music_buffer) + { + scene->background_music_instance = sound_source_instance_create(sound, scene->background_music_buffer, false); + if(scene->background_music_instance != 0) + { + sound_source_instance_volume_set(sound, scene->background_music_instance, scene->background_music_volume); + sound_source_instance_loop_set(sound, scene->background_music_instance, true); + sound_source_instance_play(sound, scene->background_music_instance); + return true; + } + else + { + log_error("scene:background_music_set", "Failed to create instance for scene background music file '%s'", filename); + return false; + } + } + else + { + log_error("scene:background_music_set", "Failed to create buffer from scene background music file '%s'", filename); + return false; + } +} + +void scene_background_music_volume_set(struct Scene* scene, float new_volume) +{ + struct Sound* sound = game_state_get()->sound; + scene->background_music_volume = fmaxf(0.f, new_volume); + if(sound_source_instance_is_valid(sound, scene->background_music_instance)) + sound_source_instance_volume_set(sound, scene->background_music_instance, scene->background_music_volume); +} + bool scene_init_func_assign(struct Scene* scene, const char* init_func_name) { struct Game_State* game_state = game_state_get(); @@ -216,6 +254,22 @@ bool scene_load(struct Scene* scene, const char* filename, int directory_type) if(hashmap_value_exists(scene_data, "next_scene")) strncpy(scene->next_level_filename, hashmap_value_exists(scene_data, "next_scene") ? hashmap_str_get(scene_data, "next_scene") : "NONE", MAX_FILENAME_LEN); + if(hashmap_value_exists(scene_data, "background_music_filename")) + { + const char* background_music_filename = hashmap_str_get(scene_data, "background_music_filename"); + if(!scene_background_music_set(scene, background_music_filename)) + { + log_error("scene:load", "Faield to set scene background music to '%s'. Reverting to default", background_music_filename); + scene_background_music_set(scene, "sounds/scene_background_default_music.ogg"); + } + } + + if(hashmap_value_exists(scene_data, "background_music_volume")) + { + float new_volume = hashmap_float_get(scene_data, "background_music_volume"); + scene_background_music_volume_set(scene, new_volume); + } + num_objects_loaded++; } break; @@ -329,6 +383,8 @@ bool scene_save(struct Scene* scene, const char* filename, int directory_type) if(scene->init) hashmap_str_set(scene_data, "init_func", scene->init_func_name); if(scene->cleanup) hashmap_str_set(scene_data, "cleanup_func", scene->cleanup_func_name); hashmap_str_set(scene_data, "next_scene", scene->next_level_filename != '\0' ? scene->next_level_filename : "NONE"); + hashmap_str_set(scene_data, "background_music_filename", scene->background_music_buffer->filename); + hashmap_float_set(scene_data, "background_music_volume", scene->background_music_volume); // Player struct Parser_Object* player_object = parser_object_new(parser, PO_PLAYER); @@ -465,6 +521,12 @@ void scene_destroy(struct Scene* scene) player_destroy(&scene->player); entity_reset(&scene->root_entity, 0); scene->root_entity.flags &= ~EF_ACTIVE; + + struct Sound* sound = game_state_get()->sound; + sound_source_instance_destroy(sound, scene->background_music_instance); + sound_source_buffer_destroy(sound, scene->background_music_buffer); + scene->background_music_buffer = NULL; + scene->background_music_instance = -1; } void scene_update(struct Scene* scene, float dt) diff --git a/src/game/scene.h b/src/game/scene.h index 80b7614..448f8a6 100755 --- a/src/game/scene.h +++ b/src/game/scene.h @@ -12,25 +12,28 @@ typedef void (*Scene_Func)(struct Scene* scene); struct Scene { - char filename[MAX_FILENAME_LEN]; - char next_level_filename[MAX_FILENAME_LEN]; - struct Entity root_entity; - struct Player player; - struct Entity entities[MAX_SCENE_ENTITIES]; - struct Static_Mesh static_meshes[MAX_SCENE_STATIC_MESHES]; - struct Camera cameras[MAX_SCENE_CAMERAS]; - struct Light lights[MAX_SCENE_LIGHTS]; - struct Sound_Source sound_sources[MAX_SCENE_SOUND_SOURCES]; - struct Enemy enemies[MAX_SCENE_ENEMIES]; - struct Trigger triggers[MAX_SCENE_TRIGGERS]; - struct Door doors[MAX_SCENE_DOORS]; - struct Pickup pickups[MAX_SCENE_PICKUPS]; - char entity_archetypes[MAX_SCENE_ENTITY_ARCHETYPES][MAX_FILENAME_LEN]; - int active_camera_index; - char init_func_name[MAX_HASH_KEY_LEN]; - char cleanup_func_name[MAX_HASH_KEY_LEN]; - Scene_Func init; - Scene_Func cleanup; + char filename[MAX_FILENAME_LEN]; + char next_level_filename[MAX_FILENAME_LEN]; + struct Entity root_entity; + struct Player player; + struct Entity entities[MAX_SCENE_ENTITIES]; + struct Static_Mesh static_meshes[MAX_SCENE_STATIC_MESHES]; + struct Camera cameras[MAX_SCENE_CAMERAS]; + struct Light lights[MAX_SCENE_LIGHTS]; + struct Sound_Source sound_sources[MAX_SCENE_SOUND_SOURCES]; + struct Enemy enemies[MAX_SCENE_ENEMIES]; + struct Trigger triggers[MAX_SCENE_TRIGGERS]; + struct Door doors[MAX_SCENE_DOORS]; + struct Pickup pickups[MAX_SCENE_PICKUPS]; + char entity_archetypes[MAX_SCENE_ENTITY_ARCHETYPES][MAX_FILENAME_LEN]; + int active_camera_index; + char init_func_name[MAX_HASH_KEY_LEN]; + char cleanup_func_name[MAX_HASH_KEY_LEN]; + struct Sound_Source_Buffer* background_music_buffer; + int background_music_instance; + float background_music_volume; + Scene_Func init; + Scene_Func cleanup; }; void scene_init(struct Scene* scene); @@ -42,6 +45,8 @@ void scene_update_physics(struct Scene* scene, float fixed_dt); void scene_post_update(struct Scene* scene); bool scene_cleanup_func_assign(struct Scene* scene, const char* cleanup_func_name); bool scene_init_func_assign(struct Scene* scene, const char* init_func_name); +bool scene_background_music_set(struct Scene* scene, const char* filename); +void scene_background_music_volume_set(struct Scene* scene, float new_volume); struct Entity* scene_entity_duplicate(struct Scene* scene, struct Entity* entity); struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent); diff --git a/src/game/sound_source.c b/src/game/sound_source.c index 3132eae..50869d2 100644 --- a/src/game/sound_source.c +++ b/src/game/sound_source.c @@ -56,10 +56,10 @@ void sound_source_update_position(struct Sound* sound, struct Sound_Source* enti } } -void sound_source_buffer_set(struct Sound* sound, struct Sound_Source* entity, const char* filename, int type) +bool sound_source_buffer_set(struct Sound* sound, struct Sound_Source* entity, const char* filename, int type) { if(strncmp(filename, entity->source_buffer->filename, MAX_FILENAME_LEN) == 0) - return; + return true; struct Sound_Source_Buffer* new_buffer = sound_source_buffer_create(sound, filename, type); if(new_buffer) @@ -69,10 +69,12 @@ void sound_source_buffer_set(struct Sound* sound, struct Sound_Source* entity, c entity->type = type; entity->source_instance = sound_source_instance_create(sound, entity->source_buffer, true); sound_source_apply_params_to_instance(sound, entity); + return true; } else { log_error("sound_source:buffer_set", "Failed to set buffer for %s", entity->base.name); + return false; } } diff --git a/src/game/sound_source.h b/src/game/sound_source.h index 038cedf..16e1800 100644 --- a/src/game/sound_source.h +++ b/src/game/sound_source.h @@ -11,7 +11,7 @@ void sound_source_pause(struct Sound* sound, struct Sound_Source* entity); void sound_source_stop(struct Sound* sound, struct Sound_Source* entity); bool sound_source_is_paused(struct Sound* sound, struct Sound_Source* entity); void sound_source_update_position(struct Sound* sound, struct Sound_Source* entity); -void sound_source_buffer_set(struct Sound* sound, struct Sound_Source* entity, const char* filename, int type); +bool sound_source_buffer_set(struct Sound* sound, struct Sound_Source* entity, const char* filename, int type); void sound_source_validate_instance(struct Sound* sound, struct Sound_Source* entity); void sound_source_apply_params_to_instance(struct Sound* sound, struct Sound_Source* entity); diff --git a/src/system/sound.c b/src/system/sound.c index 999ba0b..c627625 100755 --- a/src/system/sound.c +++ b/src/system/sound.c @@ -126,12 +126,12 @@ uint sound_source_instance_create(struct Sound* sound, struct Sound_Source_Buffe if(is3d) { source_instance = Soloud_play3dEx(sound->soloud_context, - source->type == ST_WAV ? source->wav : source->wavstream, - 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, - 1.f, - true, - 0); + source->type == ST_WAV ? source->wav : source->wavstream, + 0.f, 0.f, 0.f, + 0.f, 0.f, 0.f, + 1.f, + true, + 0); } else { diff --git a/todo.txt b/todo.txt index 67966db..8d5b870 100644 --- a/todo.txt +++ b/todo.txt @@ -5,6 +5,7 @@ Todo: - Disbale all player actions when scene cleared dialog or scene restart dialog are active - Enemies getting hit by bullets - Memory utils that provide allocation tracking + - Background music track per scene specified in scene properties - Remove excessive repitition in scene and editor code that handles multiple entity types - Allow switching to editor mode when game is in pause mode - Rendering Additions: