mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
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.
This commit is contained in:
@@ -17,11 +17,15 @@
|
|||||||
"settings.distance": "Distance: {distance}",
|
"settings.distance": "Distance: {distance}",
|
||||||
"settings.music_volume": "Music: {music}",
|
"settings.music_volume": "Music: {music}",
|
||||||
"settings.sfx_volume": "SFX: {sfx}",
|
"settings.sfx_volume": "SFX: {sfx}",
|
||||||
|
"settings.player_voice": "Player Voice: {volume}",
|
||||||
"settings.fullscreen": "fullscreen: {state}",
|
"settings.fullscreen": "fullscreen: {state}",
|
||||||
"settings.aniso": "Aniso: {aniso}",
|
"settings.aniso": "Aniso: {aniso}",
|
||||||
"settings.vsync": "V-Sync: {state}",
|
"settings.vsync": "V-Sync: {state}",
|
||||||
"settings.language": "Language: {lang}",
|
"settings.language": "Language: {lang}",
|
||||||
"settings.restart_game_info": "You need to restart the game to apply this changes.",
|
"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.on": "on",
|
||||||
"common.off": "off",
|
"common.off": "off",
|
||||||
"hostgame.create_a_new_world": "Create A New World",
|
"hostgame.create_a_new_world": "Create A New World",
|
||||||
|
|||||||
@@ -17,11 +17,15 @@
|
|||||||
"settings.distance": "距离:{distance}",
|
"settings.distance": "距离:{distance}",
|
||||||
"settings.music_volume": "音乐:{music}",
|
"settings.music_volume": "音乐:{music}",
|
||||||
"settings.sfx_volume": "音效:{sfx}",
|
"settings.sfx_volume": "音效:{sfx}",
|
||||||
|
"settings.player_voice": "玩家语音:{volume}",
|
||||||
"settings.fullscreen": "全屏:{state}",
|
"settings.fullscreen": "全屏:{state}",
|
||||||
"settings.aniso": "各向异性过滤:{aniso}",
|
"settings.aniso": "各向异性过滤:{aniso}",
|
||||||
"settings.vsync": "垂直同步: {state}",
|
"settings.vsync": "垂直同步: {state}",
|
||||||
"settings.language": "语言: {lang}",
|
"settings.language": "语言: {lang}",
|
||||||
"settings.restart_game_info": "您需要重启游戏以应用这些更改。",
|
"settings.restart_game_info": "您需要重启游戏以应用这些更改。",
|
||||||
|
"settings.voice_input": "语音输入: {type}",
|
||||||
|
"voice_input.ptt": "按键通话",
|
||||||
|
"voice_input.always": "始终",
|
||||||
"common.on": "开",
|
"common.on": "开",
|
||||||
"common.off": "关",
|
"common.off": "关",
|
||||||
"hostgame.create_a_new_world": "创建新世界",
|
"hostgame.create_a_new_world": "创建新世界",
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ private:
|
|||||||
bool m_underwater = false;
|
bool m_underwater = false;
|
||||||
float m_music_volume = 1.0f;
|
float m_music_volume = 1.0f;
|
||||||
float m_sfx_volume = 1.0f;
|
float m_sfx_volume = 1.0f;
|
||||||
|
float m_player_voice_volume = 1.0f;
|
||||||
|
|
||||||
std::unique_ptr<AudioStreamSource> m_voice_source;
|
std::unique_ptr<AudioStreamSource> m_voice_source;
|
||||||
std::unique_ptr<AudioFilter> m_low_pass_filter;
|
std::unique_ptr<AudioFilter> m_low_pass_filter;
|
||||||
|
|||||||
@@ -57,6 +57,14 @@ public:
|
|||||||
save_to_file();
|
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:
|
private:
|
||||||
toml::table m_tbl;
|
toml::table m_tbl;
|
||||||
bool m_init = false;
|
bool m_init = false;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ struct SliderVariable {
|
|||||||
float mouse_sensitivity = 0.15f;
|
float mouse_sensitivity = 0.15f;
|
||||||
float sfx = 1.0f;
|
float sfx = 1.0f;
|
||||||
float music = 0.5f;
|
float music = 0.5f;
|
||||||
|
float player_voice = 1.0f;
|
||||||
int rendering_distance = 24;
|
int rendering_distance = 24;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "Cubed/ui/pasue_menu_ui_manager.hpp"
|
#include "Cubed/ui/pasue_menu_ui_manager.hpp"
|
||||||
#include "Cubed/ui/world_ui_manager.hpp"
|
#include "Cubed/ui/world_ui_manager.hpp"
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
enum class VoiceInputType { OFF, PTT, ALWAYS };
|
||||||
class SceneManager;
|
class SceneManager;
|
||||||
class WorldScene : public Scene {
|
class WorldScene : public Scene {
|
||||||
public:
|
public:
|
||||||
@@ -39,12 +40,6 @@ public:
|
|||||||
void handle_chat_message(ChatMessage& message);
|
void handle_chat_message(ChatMessage& message);
|
||||||
|
|
||||||
private:
|
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;
|
SceneManager& m_scene_manager;
|
||||||
DevPanel m_dev_panel;
|
DevPanel m_dev_panel;
|
||||||
Camera m_camera;
|
Camera m_camera;
|
||||||
@@ -59,5 +54,13 @@ private:
|
|||||||
WorldUIManager m_hud_ui;
|
WorldUIManager m_hud_ui;
|
||||||
ErrorUI m_error_ui;
|
ErrorUI m_error_ui;
|
||||||
const Argument& m_argument;
|
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
|
} // namespace Cubed
|
||||||
@@ -13,9 +13,7 @@ float AudioBuffer::duration() const { return m_duration; }
|
|||||||
uint32_t AudioBuffer::channels() const { return m_channels; }
|
uint32_t AudioBuffer::channels() const { return m_channels; }
|
||||||
|
|
||||||
void AudioBuffer::set_data(const AudioData& data) {
|
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;
|
ALenum format;
|
||||||
if (data.channels == 1) {
|
if (data.channels == 1) {
|
||||||
format = AL_FORMAT_MONO16;
|
format = AL_FORMAT_MONO16;
|
||||||
@@ -24,7 +22,7 @@ void AudioBuffer::set_data(const AudioData& data) {
|
|||||||
}
|
}
|
||||||
m_channels = data.channels;
|
m_channels = data.channels;
|
||||||
|
|
||||||
Logger::info("channels={} rate={} samples={} bytes={} format={}",
|
Logger::debug("channels={} rate={} samples={} bytes={} format={}",
|
||||||
data.channels, data.sample_rate, data.pcm.size(),
|
data.channels, data.sample_rate, data.pcm.size(),
|
||||||
data.pcm.size() * sizeof(int16_t), format);
|
data.pcm.size() * sizeof(int16_t), format);
|
||||||
alBufferData(m_buffer, format, data.pcm.data(),
|
alBufferData(m_buffer, format, data.pcm.data(),
|
||||||
@@ -35,7 +33,7 @@ void AudioBuffer::set_data(const AudioData& data) {
|
|||||||
alGetBufferi(m_buffer, AL_SIZE, &size);
|
alGetBufferi(m_buffer, AL_SIZE, &size);
|
||||||
check_al_error();
|
check_al_error();
|
||||||
|
|
||||||
Logger::info("buffer size={}", size);
|
Logger::debug("buffer size={}", size);
|
||||||
m_duration = static_cast<float>(data.pcm.size()) /
|
m_duration = static_cast<float>(data.pcm.size()) /
|
||||||
(data.channels * data.sample_rate);
|
(data.channels * data.sample_rate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ void AudioEngine::init() {
|
|||||||
m_recording.init();
|
m_recording.init();
|
||||||
m_music_volume = m_config.get("volume.music", 1.0f);
|
m_music_volume = m_config.get("volume.music", 1.0f);
|
||||||
m_sfx_volume = m_config.get("volume.SFX", 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_sounds.init();
|
||||||
|
|
||||||
m_bgm = std::make_unique<AudioSource>(m_music_volume);
|
m_bgm = std::make_unique<AudioSource>(m_music_volume);
|
||||||
@@ -103,6 +103,7 @@ void AudioEngine::init() {
|
|||||||
|
|
||||||
m_fade_map.try_emplace("bgm", m_bgm.get(), 5.0f, 2.0f);
|
m_fade_map.try_emplace("bgm", m_bgm.get(), 5.0f, 2.0f);
|
||||||
m_voice_source = std::make_unique<AudioStreamSource>();
|
m_voice_source = std::make_unique<AudioStreamSource>();
|
||||||
|
m_voice_source->set_volume(m_player_voice_volume);
|
||||||
ALCint max_mono = 0;
|
ALCint max_mono = 0;
|
||||||
|
|
||||||
alcGetIntegerv(device, ALC_MONO_SOURCES, 1, &max_mono);
|
alcGetIntegerv(device, ALC_MONO_SOURCES, 1, &max_mono);
|
||||||
@@ -216,9 +217,13 @@ void AudioEngine::update() {
|
|||||||
void AudioEngine::reload_config() {
|
void AudioEngine::reload_config() {
|
||||||
m_music_volume = m_config.get("volume.music", 1.0f);
|
m_music_volume = m_config.get("volume.music", 1.0f);
|
||||||
m_sfx_volume = m_config.get("volume.SFX", 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) {
|
if (m_bgm) {
|
||||||
m_bgm->set_target_volume(m_music_volume);
|
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) {
|
void AudioEngine::underwater_change(bool underwater) {
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ void AudioRecording::init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AudioRecording::start() {
|
void AudioRecording::start() {
|
||||||
|
if (m_recording) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ALCint samples;
|
ALCint samples;
|
||||||
|
|
||||||
alcGetIntegerv(m_capture, ALC_CAPTURE_SAMPLES, 1, &samples);
|
alcGetIntegerv(m_capture, ALC_CAPTURE_SAMPLES, 1, &samples);
|
||||||
@@ -46,6 +49,9 @@ void AudioRecording::start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AudioRecording::stop() {
|
void AudioRecording::stop() {
|
||||||
|
if (!m_recording) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
alcCaptureStop(m_capture);
|
alcCaptureStop(m_capture);
|
||||||
m_recording = false;
|
m_recording = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -653,7 +653,6 @@ void ClientPlayer::init(std::string_view name) {
|
|||||||
glm::ivec3 block = glm::floor(m_player_pos);
|
glm::ivec3 block = glm::floor(m_player_pos);
|
||||||
block.y -= 1;
|
block.y -= 1;
|
||||||
BlockType id = m_world.get_block_tpye(block);
|
BlockType id = m_world.get_block_tpye(block);
|
||||||
Logger::info("player Block {} Walk Sound", id);
|
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -661,7 +660,7 @@ void ClientPlayer::init(std::string_view name) {
|
|||||||
std::string sound = "block/" + name + "/walk.ogg";
|
std::string sound = "block/" + name + "/walk.ogg";
|
||||||
auto& audio = m_world.get_audio();
|
auto& audio = m_world.get_audio();
|
||||||
audio.play_3d(sound, m_player_pos);
|
audio.play_3d(sound, m_player_pos);
|
||||||
Logger::info("Player block {} walk sound", name);
|
Logger::debug("Player block {} walk sound", name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ void SettingsScene::on_enter() {
|
|||||||
m_slider_variable.sfx = config.get("volume.SFX", m_slider_variable.sfx);
|
m_slider_variable.sfx = config.get("volume.SFX", m_slider_variable.sfx);
|
||||||
m_slider_variable.rendering_distance = config.get(
|
m_slider_variable.rendering_distance = config.get(
|
||||||
"world.rendering_distance", m_slider_variable.rendering_distance);
|
"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() {
|
void SettingsScene::on_leave() {
|
||||||
save_and_apply();
|
save_and_apply();
|
||||||
@@ -54,6 +56,7 @@ void SettingsScene::save_and_apply() {
|
|||||||
m_slider_variable.rendering_distance);
|
m_slider_variable.rendering_distance);
|
||||||
config.set("volume.SFX", m_slider_variable.sfx);
|
config.set("volume.SFX", m_slider_variable.sfx);
|
||||||
config.set("volume.music", m_slider_variable.music);
|
config.set("volume.music", m_slider_variable.music);
|
||||||
|
config.set("volume.player_voice", m_slider_variable.player_voice);
|
||||||
config.save_to_file();
|
config.save_to_file();
|
||||||
auto& app = m_scene_manager.app();
|
auto& app = m_scene_manager.app();
|
||||||
app.audio().reload_config();
|
app.audio().reload_config();
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ bool WorldScene::handle_event(const Event& e) {
|
|||||||
}
|
}
|
||||||
void WorldScene::on_enter() {
|
void WorldScene::on_enter() {
|
||||||
auto& param = m_scene_manager.world_scene_param();
|
auto& param = m_scene_manager.world_scene_param();
|
||||||
|
load_config();
|
||||||
m_error_ui.init();
|
m_error_ui.init();
|
||||||
|
|
||||||
if (param.host_game) {
|
if (param.host_game) {
|
||||||
@@ -163,6 +163,7 @@ void WorldScene::on_re_enter() {
|
|||||||
m_error_ui.on_re_enter();
|
m_error_ui.on_re_enter();
|
||||||
m_pasue_menu.on_re_enter();
|
m_pasue_menu.on_re_enter();
|
||||||
m_client_world.reload_config();
|
m_client_world.reload_config();
|
||||||
|
load_config();
|
||||||
auto width = m_scene_manager.app().renderer().window_width();
|
auto width = m_scene_manager.app().renderer().window_width();
|
||||||
auto height = m_scene_manager.app().renderer().window_height();
|
auto height = m_scene_manager.app().renderer().window_height();
|
||||||
|
|
||||||
@@ -170,6 +171,20 @@ void WorldScene::on_re_enter() {
|
|||||||
WindowResizeEvent{static_cast<int>(width), static_cast<int>(height)});
|
WindowResizeEvent{static_cast<int>(width), static_cast<int>(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) {
|
bool WorldScene::handle_mouse_move_event(const MouseMoveEvent& e) {
|
||||||
if (m_chatting) {
|
if (m_chatting) {
|
||||||
return true;
|
return true;
|
||||||
@@ -291,6 +306,7 @@ bool WorldScene::handle_key_event(const KeyEvent& e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (e.key == Key::V) {
|
if (e.key == Key::V) {
|
||||||
|
if (m_input_type == VoiceInputType::PTT) {
|
||||||
auto& recording = m_client_world.get_audio().audio_recording();
|
auto& recording = m_client_world.get_audio().audio_recording();
|
||||||
if (e.action == KeyAction::PRESS) {
|
if (e.action == KeyAction::PRESS) {
|
||||||
recording.start();
|
recording.start();
|
||||||
@@ -301,6 +317,7 @@ bool WorldScene::handle_key_event(const KeyEvent& e) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_paused) {
|
if (m_paused) {
|
||||||
if (m_pasue_menu.handle_event(e)) {
|
if (m_pasue_menu.handle_event(e)) {
|
||||||
|
|||||||
@@ -69,15 +69,41 @@ void SettingsUI::init() {
|
|||||||
sfx.set_slider(&v.sfx, 0.0f, 1.0f);
|
sfx.set_slider(&v.sfx, 0.0f, 1.0f);
|
||||||
set_default_slider_image(sfx);
|
set_default_slider_image(sfx);
|
||||||
sfx.set_slider_text("settings.sfx_volume", "sfx");
|
sfx.set_slider_text("settings.sfx_volume", "sfx");
|
||||||
|
|
||||||
|
auto& player_voice = layout.add_child<Slider>();
|
||||||
|
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& config = m_scene.scene_manager().app().config();
|
||||||
|
{
|
||||||
|
auto& combo = layout.add_child<ComboButton>();
|
||||||
|
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<ComboPair> 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);
|
bool full = config.get("window.fullscreen", false);
|
||||||
auto& fullscreen = layout.add_child<ComboButton>();
|
auto& fullscreen = layout.add_child<ComboButton>();
|
||||||
fullscreen.set_index(!full ? 0 : 1);
|
fullscreen.set_index(!full ? 0 : 1);
|
||||||
fullscreen.set_combo_text("settings.fullscreen", "state");
|
fullscreen.set_combo_text("settings.fullscreen", "state");
|
||||||
std::vector<std::pair<std::string, std::function<void()>>> comb;
|
std::vector<ComboPair> comb;
|
||||||
comb.emplace_back(tr("common.off"), [&config, this]() {
|
comb.emplace_back(tr("common.off"), [&config, this]() {
|
||||||
config.set("window.fullscreen", false);
|
config.set("window.fullscreen", false);
|
||||||
m_scene.scene_manager().app().window().reload_config();
|
m_scene.scene_manager().app().window().reload_config();
|
||||||
|
|||||||
Reference in New Issue
Block a user