From e5bd7aa4d1bf4e9f89f06d8109c77df683a342e9 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Mon, 20 Jul 2026 17:47:05 +0800 Subject: [PATCH] feat(settings): add player voice volume and voice input type options - Add player voice volume slider and voice input type combo in settings UI. - Add localization strings for player voice and voice input types. - Add config overloads for const char* default values. - Implement voice input types (PTT, always, off) in world scene. - Refactor WorldScene member order and add load_config method. - Update audio engine to use player voice volume. - Downgrade some logging to debug. --- assets/lang/en_US.json | 4 +++ assets/lang/zh_CN.json | 4 +++ include/Cubed/audio/audio_engine.hpp | 1 + include/Cubed/config.hpp | 8 ++++++ include/Cubed/scene/settings_scene.hpp | 1 + include/Cubed/scene/world_scene.hpp | 15 ++++++----- src/audio/audio_buffer.cpp | 10 +++----- src/audio/audio_engine.cpp | 7 +++++- src/audio/audio_recording.cpp | 6 +++++ src/gameplay/client_player.cpp | 3 +-- src/scene/settings_scene.cpp | 3 +++ src/scene/world_scene.cpp | 35 +++++++++++++++++++------- src/ui/settings_ui.cpp | 28 ++++++++++++++++++++- 13 files changed, 100 insertions(+), 25 deletions(-) diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index ad7571a..877c47e 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -17,11 +17,15 @@ "settings.distance": "Distance: {distance}", "settings.music_volume": "Music: {music}", "settings.sfx_volume": "SFX: {sfx}", + "settings.player_voice": "Player Voice: {volume}", "settings.fullscreen": "fullscreen: {state}", "settings.aniso": "Aniso: {aniso}", "settings.vsync": "V-Sync: {state}", "settings.language": "Language: {lang}", "settings.restart_game_info": "You need to restart the game to apply this changes.", + "settings.voice_input": "Voice Input: {type}", + "voice_input.ptt": "PTT", + "voice_input.always": "always", "common.on": "on", "common.off": "off", "hostgame.create_a_new_world": "Create A New World", diff --git a/assets/lang/zh_CN.json b/assets/lang/zh_CN.json index 2407686..0b789b6 100644 --- a/assets/lang/zh_CN.json +++ b/assets/lang/zh_CN.json @@ -17,11 +17,15 @@ "settings.distance": "距离:{distance}", "settings.music_volume": "音乐:{music}", "settings.sfx_volume": "音效:{sfx}", + "settings.player_voice": "玩家语音:{volume}", "settings.fullscreen": "全屏:{state}", "settings.aniso": "各向异性过滤:{aniso}", "settings.vsync": "垂直同步: {state}", "settings.language": "语言: {lang}", "settings.restart_game_info": "您需要重启游戏以应用这些更改。", + "settings.voice_input": "语音输入: {type}", + "voice_input.ptt": "按键通话", + "voice_input.always": "始终", "common.on": "开", "common.off": "关", "hostgame.create_a_new_world": "创建新世界", diff --git a/include/Cubed/audio/audio_engine.hpp b/include/Cubed/audio/audio_engine.hpp index 1010ef2..56e6933 100644 --- a/include/Cubed/audio/audio_engine.hpp +++ b/include/Cubed/audio/audio_engine.hpp @@ -71,6 +71,7 @@ private: bool m_underwater = false; float m_music_volume = 1.0f; float m_sfx_volume = 1.0f; + float m_player_voice_volume = 1.0f; std::unique_ptr m_voice_source; std::unique_ptr m_low_pass_filter; diff --git a/include/Cubed/config.hpp b/include/Cubed/config.hpp index 540ee3c..3ba918d 100644 --- a/include/Cubed/config.hpp +++ b/include/Cubed/config.hpp @@ -57,6 +57,14 @@ public: save_to_file(); } + std::string get(std::string_view key, const char* default_value) { + return get(key, std::string(default_value)); + } + + void set(std::string_view key, const char* val) { + set(key, std::string(val)); + } + private: toml::table m_tbl; bool m_init = false; diff --git a/include/Cubed/scene/settings_scene.hpp b/include/Cubed/scene/settings_scene.hpp index ad7aafa..19322a8 100644 --- a/include/Cubed/scene/settings_scene.hpp +++ b/include/Cubed/scene/settings_scene.hpp @@ -8,6 +8,7 @@ struct SliderVariable { float mouse_sensitivity = 0.15f; float sfx = 1.0f; float music = 0.5f; + float player_voice = 1.0f; int rendering_distance = 24; }; diff --git a/include/Cubed/scene/world_scene.hpp b/include/Cubed/scene/world_scene.hpp index 94d7a7b..459153d 100644 --- a/include/Cubed/scene/world_scene.hpp +++ b/include/Cubed/scene/world_scene.hpp @@ -9,6 +9,7 @@ #include "Cubed/ui/pasue_menu_ui_manager.hpp" #include "Cubed/ui/world_ui_manager.hpp" namespace Cubed { +enum class VoiceInputType { OFF, PTT, ALWAYS }; class SceneManager; class WorldScene : public Scene { public: @@ -39,12 +40,6 @@ public: void handle_chat_message(ChatMessage& message); private: - bool handle_mouse_move_event(const MouseMoveEvent& e) override; - bool handle_mouse_button_event(const MouseButtonEvent& e) override; - bool handle_window_resize_event(const WindowResizeEvent& e) override; - bool handle_mouse_wheel_event(const MouseWheelEvent& e) override; - bool handle_key_event(const KeyEvent& e) override; - bool handle_text_input_event(const TextInputEvent&) override; SceneManager& m_scene_manager; DevPanel m_dev_panel; Camera m_camera; @@ -59,5 +54,13 @@ private: WorldUIManager m_hud_ui; ErrorUI m_error_ui; const Argument& m_argument; + VoiceInputType m_input_type; + bool handle_mouse_move_event(const MouseMoveEvent& e) override; + bool handle_mouse_button_event(const MouseButtonEvent& e) override; + bool handle_window_resize_event(const WindowResizeEvent& e) override; + bool handle_mouse_wheel_event(const MouseWheelEvent& e) override; + bool handle_key_event(const KeyEvent& e) override; + bool handle_text_input_event(const TextInputEvent&) override; + void load_config(); }; } // namespace Cubed \ No newline at end of file diff --git a/src/audio/audio_buffer.cpp b/src/audio/audio_buffer.cpp index 8f26068..a02d47e 100644 --- a/src/audio/audio_buffer.cpp +++ b/src/audio/audio_buffer.cpp @@ -13,9 +13,7 @@ float AudioBuffer::duration() const { return m_duration; } uint32_t AudioBuffer::channels() const { return m_channels; } void AudioBuffer::set_data(const AudioData& data) { - Logger::info("buffer={} valid={}", m_buffer, (int)alIsBuffer(m_buffer)); - Logger::info("buffer={} isBuffer={}", m_buffer, (int)alIsBuffer(m_buffer)); ALenum format; if (data.channels == 1) { format = AL_FORMAT_MONO16; @@ -24,9 +22,9 @@ void AudioBuffer::set_data(const AudioData& data) { } m_channels = data.channels; - Logger::info("channels={} rate={} samples={} bytes={} format={}", - data.channels, data.sample_rate, data.pcm.size(), - data.pcm.size() * sizeof(int16_t), format); + Logger::debug("channels={} rate={} samples={} bytes={} format={}", + data.channels, data.sample_rate, data.pcm.size(), + data.pcm.size() * sizeof(int16_t), format); alBufferData(m_buffer, format, data.pcm.data(), static_cast(data.pcm.size() * sizeof(int16_t)), static_cast(data.sample_rate)); @@ -35,7 +33,7 @@ void AudioBuffer::set_data(const AudioData& data) { alGetBufferi(m_buffer, AL_SIZE, &size); check_al_error(); - Logger::info("buffer size={}", size); + Logger::debug("buffer size={}", size); m_duration = static_cast(data.pcm.size()) / (data.channels * data.sample_rate); } diff --git a/src/audio/audio_engine.cpp b/src/audio/audio_engine.cpp index 08b8744..fddc45d 100644 --- a/src/audio/audio_engine.cpp +++ b/src/audio/audio_engine.cpp @@ -94,7 +94,7 @@ void AudioEngine::init() { m_recording.init(); m_music_volume = m_config.get("volume.music", 1.0f); m_sfx_volume = m_config.get("volume.SFX", 1.0f); - + m_player_voice_volume = m_config.get("volume.player_voice", 1.0f); m_sounds.init(); m_bgm = std::make_unique(m_music_volume); @@ -103,6 +103,7 @@ void AudioEngine::init() { m_fade_map.try_emplace("bgm", m_bgm.get(), 5.0f, 2.0f); m_voice_source = std::make_unique(); + m_voice_source->set_volume(m_player_voice_volume); ALCint max_mono = 0; alcGetIntegerv(device, ALC_MONO_SOURCES, 1, &max_mono); @@ -216,9 +217,13 @@ void AudioEngine::update() { void AudioEngine::reload_config() { m_music_volume = m_config.get("volume.music", 1.0f); m_sfx_volume = m_config.get("volume.SFX", 1.0f); + m_player_voice_volume = m_config.get("volume.player_voice", 1.0f); if (m_bgm) { m_bgm->set_target_volume(m_music_volume); } + if (m_voice_source) { + m_voice_source->set_volume(m_player_voice_volume); + } } void AudioEngine::underwater_change(bool underwater) { diff --git a/src/audio/audio_recording.cpp b/src/audio/audio_recording.cpp index f7566f5..e827529 100644 --- a/src/audio/audio_recording.cpp +++ b/src/audio/audio_recording.cpp @@ -35,6 +35,9 @@ void AudioRecording::init() { } void AudioRecording::start() { + if (m_recording) { + return; + } ALCint samples; alcGetIntegerv(m_capture, ALC_CAPTURE_SAMPLES, 1, &samples); @@ -46,6 +49,9 @@ void AudioRecording::start() { } void AudioRecording::stop() { + if (!m_recording) { + return; + } alcCaptureStop(m_capture); m_recording = false; } diff --git a/src/gameplay/client_player.cpp b/src/gameplay/client_player.cpp index b520e99..cd704a4 100644 --- a/src/gameplay/client_player.cpp +++ b/src/gameplay/client_player.cpp @@ -653,7 +653,6 @@ void ClientPlayer::init(std::string_view name) { glm::ivec3 block = glm::floor(m_player_pos); block.y -= 1; BlockType id = m_world.get_block_tpye(block); - Logger::info("player Block {} Walk Sound", id); if (id == 0) { return; } @@ -661,7 +660,7 @@ void ClientPlayer::init(std::string_view name) { std::string sound = "block/" + name + "/walk.ogg"; auto& audio = m_world.get_audio(); audio.play_3d(sound, m_player_pos); - Logger::info("Player block {} walk sound", name); + Logger::debug("Player block {} walk sound", name); }); } diff --git a/src/scene/settings_scene.cpp b/src/scene/settings_scene.cpp index 2e8088a..3c5df7e 100644 --- a/src/scene/settings_scene.cpp +++ b/src/scene/settings_scene.cpp @@ -29,6 +29,8 @@ void SettingsScene::on_enter() { m_slider_variable.sfx = config.get("volume.SFX", m_slider_variable.sfx); m_slider_variable.rendering_distance = config.get( "world.rendering_distance", m_slider_variable.rendering_distance); + m_slider_variable.player_voice = + config.get("vloume.player_voice", m_slider_variable.player_voice); } void SettingsScene::on_leave() { save_and_apply(); @@ -54,6 +56,7 @@ void SettingsScene::save_and_apply() { m_slider_variable.rendering_distance); config.set("volume.SFX", m_slider_variable.sfx); config.set("volume.music", m_slider_variable.music); + config.set("volume.player_voice", m_slider_variable.player_voice); config.save_to_file(); auto& app = m_scene_manager.app(); app.audio().reload_config(); diff --git a/src/scene/world_scene.cpp b/src/scene/world_scene.cpp index e916e22..69805c9 100644 --- a/src/scene/world_scene.cpp +++ b/src/scene/world_scene.cpp @@ -115,7 +115,7 @@ bool WorldScene::handle_event(const Event& e) { } void WorldScene::on_enter() { auto& param = m_scene_manager.world_scene_param(); - + load_config(); m_error_ui.init(); if (param.host_game) { @@ -163,6 +163,7 @@ void WorldScene::on_re_enter() { m_error_ui.on_re_enter(); m_pasue_menu.on_re_enter(); m_client_world.reload_config(); + load_config(); auto width = m_scene_manager.app().renderer().window_width(); auto height = m_scene_manager.app().renderer().window_height(); @@ -170,6 +171,20 @@ void WorldScene::on_re_enter() { WindowResizeEvent{static_cast(width), static_cast(height)}); } +void WorldScene::load_config() { + auto type = m_scene_manager.app().config().get("voice_input", "PTT"); + if (type == "off") { + m_input_type = VoiceInputType::OFF; + m_client_world.get_audio().audio_recording().stop(); + } else if (type == "PTT") { + m_input_type = VoiceInputType::PTT; + m_client_world.get_audio().audio_recording().stop(); + } else if (type == "always") { + m_input_type = VoiceInputType::ALWAYS; + m_client_world.get_audio().audio_recording().start(); + } +} + bool WorldScene::handle_mouse_move_event(const MouseMoveEvent& e) { if (m_chatting) { return true; @@ -291,14 +306,16 @@ bool WorldScene::handle_key_event(const KeyEvent& e) { } if (e.key == Key::V) { - auto& recording = m_client_world.get_audio().audio_recording(); - if (e.action == KeyAction::PRESS) { - recording.start(); - return true; - } - if (e.action == KeyAction::RELEASE) { - recording.stop(); - return true; + if (m_input_type == VoiceInputType::PTT) { + auto& recording = m_client_world.get_audio().audio_recording(); + if (e.action == KeyAction::PRESS) { + recording.start(); + return true; + } + if (e.action == KeyAction::RELEASE) { + recording.stop(); + return true; + } } } diff --git a/src/ui/settings_ui.cpp b/src/ui/settings_ui.cpp index d0a584b..bafa5a4 100644 --- a/src/ui/settings_ui.cpp +++ b/src/ui/settings_ui.cpp @@ -69,15 +69,41 @@ void SettingsUI::init() { sfx.set_slider(&v.sfx, 0.0f, 1.0f); set_default_slider_image(sfx); sfx.set_slider_text("settings.sfx_volume", "sfx"); + + auto& player_voice = layout.add_child(); + player_voice.set_slider(&v.player_voice, 0.0f, 1.0f); + set_default_slider_image(player_voice); + player_voice.set_slider_text("settings.player_voice", "volume"); } auto& config = m_scene.scene_manager().app().config(); + { + auto& combo = layout.add_child(); + auto type = config.get("voice_input", "PTT"); + if (type == "off") { + combo.set_index(0); + } else if (type == "PTT") { + combo.set_index(1); + } else if (type == "always") { + combo.set_index(2); + } + combo.set_combo_text("settings.voice_input", "type"); + std::vector comb; + comb.emplace_back(tr("common.off"), + [&config]() { config.set("voice_input", "off"); }); + comb.emplace_back(tr("voice_input.ptt"), + [&config]() { config.set("voice_input", "PTT"); }); + comb.emplace_back(tr("voice_input.always"), + [&config]() { config.set("voice_input", "always"); }); + combo.set_default_image(texture_manager); + combo.set_combos(comb); + } { bool full = config.get("window.fullscreen", false); auto& fullscreen = layout.add_child(); fullscreen.set_index(!full ? 0 : 1); fullscreen.set_combo_text("settings.fullscreen", "state"); - std::vector>> comb; + std::vector comb; comb.emplace_back(tr("common.off"), [&config, this]() { config.set("window.fullscreen", false); m_scene.scene_manager().app().window().reload_config();