Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
[submodule "C7/addons/markdownlabel"]
path = C7/addons/markdownlabel
url = https://github.com/daenvil/MarkdownLabel.git
ignore = all
75 changes: 44 additions & 31 deletions C7/Audio/AudioManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,33 @@ public partial class AudioManager : Node {
private PolyphonicAudioPlayer _polyUiAudioPlayer;
private PolyphonicAudioPlayer _polyAmbienceAudioPlayer;

public static string MasterBus = "Master";
public static string MusicBus = "Music";
public static string SfxAudioBus = "Sfx";
public static string UIAudioBus = "UI";
public static string AmbienceAudioBus = "Ambience";

private bool masterEnabled = true;
private bool musicEnabled = true;
private bool sfxAudioEnabled = true;
private bool uiAudioEnabled = true;
private bool ambienceAudioEnabled = true;

// Maps a bus to the settings key holding its volume. Public so settings UI
// can drive a bus without repeating the magic strings.
public static readonly Dictionary<string, string> BusVolumeKeys = new() {
{ MasterBus, C7Settings.Audio.MasterVolume },
{ MusicBus, C7Settings.Audio.MusicVolume },
{ SfxAudioBus, C7Settings.Audio.SfxAudioVolume },
{ UIAudioBus, C7Settings.Audio.UiAudioVolume },
{ AmbienceAudioBus, C7Settings.Audio.AmbienceAudioVolume },
};



public override void _Ready() {
log = LogManager.ForContext<AudioManager>();

masterEnabled = ConfigureVolume(C7Settings.Audio.MasterVolume, MasterBus);

musicEnabled = ConfigureVolume(C7Settings.Audio.MusicVolume, MusicBus);
_polyMusicPlayer = new PolyphonicAudioPlayer(musicPlayer, 2);

Expand All @@ -57,8 +61,7 @@ public override void _Ready() {

private bool ConfigureVolume(string volumeKey, string audioBus) {
try {
// A missing key means the user never set it, so fall back to full
// volume rather than letting int.Parse throw on null.
// A missing key means the user never set it: fall back to full volume
string volume = C7Settings.GetSettingsValueOrDefault(C7Settings.Audio.SectionName, volumeKey, "100");
float volumeDb = LogicalVolumeAsDecibel(int.Parse(volume));

Expand Down Expand Up @@ -99,33 +102,9 @@ public static float LogicalVolumeAsDecibel(int volume) {
// TODO: playlists, mixing, transitions
// See: https://www.youtube.com/watch?app=desktop&v=07Kyqqg31FI&t=346s

// TODO: polyphony via AudioStreamPolyphonic + AudioStreamPlaybackPolyphonic
// https://docs.godotengine.org/en/4.0/classes/class_audiostreampolyphonic.html

private long currentMusicId = AudioStreamPlaybackPolyphonic.InvalidId;

public void PlayMusic(string configKey) {
AudioStream stream = AudioLoader.Load(configKey);

if (stream == null)
return;

if (currentMusicId != AudioStreamPlaybackPolyphonic.InvalidId) {
_polyMusicPlayer.Stop(currentMusicId);
currentMusicId = AudioStreamPlaybackPolyphonic.InvalidId;
}

currentMusicId = _polyMusicPlayer.Play(stream);
}


public void StopMusic() {
if (currentMusicId != AudioStreamPlaybackPolyphonic.InvalidId) {
_polyMusicPlayer.Stop(currentMusicId);
currentMusicId = AudioStreamPlaybackPolyphonic.InvalidId;
}
}

/*
* Audio buses - general methods for managing audio buses
*/

/// <summary>
/// The user's volume for a bus, as a 0-100 percentage, or -1 if the bus is
Expand Down Expand Up @@ -164,6 +143,40 @@ private void SetBusVolumeDb(string bus, float volumeDb) {
AudioServer.SetBusVolumeDb(busIndex, volumeDb);
AudioServer.SetBusMute(busIndex, volumeDb == float.MinValue);
}


/*
* Music - only one track playing at any one point
*/

private long currentMusicId = AudioStreamPlaybackPolyphonic.InvalidId;

public void PlayMusic(string configKey) {
AudioStream stream = AudioLoader.Load(configKey);

if (stream == null)
return;

if (currentMusicId != AudioStreamPlaybackPolyphonic.InvalidId) {
_polyMusicPlayer.Stop(currentMusicId);
currentMusicId = AudioStreamPlaybackPolyphonic.InvalidId;
}

currentMusicId = _polyMusicPlayer.Play(stream);
}

public void StopMusic() {
if (currentMusicId != AudioStreamPlaybackPolyphonic.InvalidId) {
_polyMusicPlayer.Stop(currentMusicId);
currentMusicId = AudioStreamPlaybackPolyphonic.InvalidId;
}
}

/*
* Separate channels for SFX, UI, and Ambient sounds.
* Each one is polyphonic, able to play overlapping tracks.
*/

public void PlaySfxAudio(string configKey) {
var stream = AudioLoader.Load(configKey);
if (stream != null)
Expand Down
3 changes: 3 additions & 0 deletions C7/Audio/GlobalAudio.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public static class GlobalAudio {
public static AudioManager manager { get; set; }
}
1 change: 1 addition & 0 deletions C7/Audio/GlobalAudio.cs.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://cpge150wugit7
1 change: 1 addition & 0 deletions C7/Audio/PolyphonicAudioPlayer.cs.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://doyg1cxqfqnig
3 changes: 1 addition & 2 deletions C7/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,7 @@ private async Task InitializeGame() {
}

private void InitializeAudio() {
AudioManager audio = GetNode<AudioManager>("/root/GlobalAudioManager");
audio.StopMusic();
GlobalAudio.manager.StopMusic();
// TODO: switch to in-game playlist / music logic
}

Expand Down
15 changes: 13 additions & 2 deletions C7/Lua/civ3/audio.lua
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
-- Base paths
local SOUNDS = "Sounds/"
local MENU = SOUNDS .. "Menu/"
local AMBIENCE = SOUNDS .. "Ambience Sfx/"

-- Audio definitions
local audio = {}

audio.menu = {
main_menu_1 = MENU .. "Menu1.mp3"
audio.ambience = {
oriole = AMBIENCE .. "Oriole.wav"
}

audio.buttons = {
button_1 = SOUNDS .. "Button1.wav"
}

audio.extra = {
warrior = {
victory = SOUNDS .. "QualeWarriorVictory.wav"
}
}

audio.menu = {
main_menu_1 = MENU .. "Menu1.mp3"
}

audio.popups = {
advisor = SOUNDS .. "PopupAdvisor.wav",
console = SOUNDS .. "PopupConsole.wav",
Expand Down
3 changes: 3 additions & 0 deletions C7/Lua/civ3/textures.lua
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ textures.advisors = {
}

textures.screens = {
preferences = {
background = ADVISORS .. "wonders_background.pcx",
},
wonders = {
background = ADVISORS .. "wonders_background.pcx",
},
Expand Down
1 change: 1 addition & 0 deletions C7/PreferencesSettings.cs.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://o03k02xj5kyg
15 changes: 8 additions & 7 deletions C7/UIElements/MainMenu/MainMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ public partial class MainMenu : Node {
Preferences preferences;

GlobalSingleton Global;
AudioManager AudioManager;

public override void _EnterTree() {
GlobalAudio.manager = GetNode<AudioManager>("/root/GlobalAudioManager");

base._EnterTree();
}

public override void _Ready() {
log = LogManager.ForContext<MainMenu>();
Expand All @@ -30,8 +35,6 @@ public override void _Ready() {

try {
DisplayTitleScreen();

AudioManager = GetNode<AudioManager>("/root/GlobalAudioManager");
PlayMusic();
} catch (Exception ex) {
log.Error(ex, "Could not set up the main menu");
Expand Down Expand Up @@ -66,8 +69,6 @@ private void DisplayTitleScreen() {
ButtonContainer.HallOfFame.Pressed += HallOfFame;
ButtonContainer.HallOfFame.Visible = false;
ButtonContainer.Preferences.Pressed += ShowPreferences;
ButtonContainer.AudioPreferences.Pressed += ShowPreferences;
ButtonContainer.AudioPreferences.Visible = false;
ButtonContainer.Credits.Pressed += showCredits;
ButtonContainer.Exit.Pressed += _on_Exit_pressed;

Expand Down Expand Up @@ -170,10 +171,10 @@ private void UseStandaloneModePressed() {
}

private void PlayMusic() {
AudioManager.PlayMusic("menu.main_menu_1");
GlobalAudio.manager.PlayMusic("menu.main_menu_1");
}

private void PlayButtonPressedSound() {
AudioManager.PlayUIAudio("buttons.button_1");
GlobalAudio.manager.PlayUIAudio("buttons.button_1");
}
}
5 changes: 0 additions & 5 deletions C7/UIElements/MainMenu/MenuButtonContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ public partial class MenuButtonContainer : VBoxContainer {
public Civ3MenuButton HallOfFame { get; private set; }
public Civ3MenuButton ToggleGraphics { get; private set; }
public Civ3MenuButton Preferences { get; private set; }
public Civ3MenuButton AudioPreferences { get; private set; }
public Civ3MenuButton Credits { get; private set; }
public Civ3MenuButton Exit { get; private set; }

Expand All @@ -29,7 +28,6 @@ public void CreateButtons() {
HallOfFame = null;
ToggleGraphics = null;
Preferences = null;
AudioPreferences = null;
Credits = null;
Exit = null;

Expand Down Expand Up @@ -57,9 +55,6 @@ public void CreateButtons() {
Preferences = new Civ3MenuButton() { Text = "Preferences" };
AddChild(Preferences);

AudioPreferences = new Civ3MenuButton() { Text = "Audio Preferences" };
AddChild(AudioPreferences);

Credits = new Civ3MenuButton() { Text = "Credits" };
AddChild(Credits);

Expand Down
39 changes: 29 additions & 10 deletions C7/UIElements/Preferences.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using C7.UIElements;
using Godot;

Expand All @@ -12,25 +13,31 @@
[GlobalClass]
public partial class Preferences : Control {
[Export] Civ3Checkbox promptForResearch;

// TODO: Make an audio volume control scene

[Export] Civ3HSlider masterVolume;
[Export] Civ3HSlider musicVolume;
[Export] Civ3HSlider sfxVolume;
[Export] Civ3HSlider uiVolume;
[Export] Civ3HSlider ambienceVolume;
[Export] Label masterVolumeLabel;
[Export] Label musicVolumeLabel;
[Export] Label sfxVolumeLabel;
[Export] Label uiVolumeLabel;
[Export] Label ambienceVolumeLabel;
[Export] Control masterVolumeRow;
[Export] Control musicVolumeRow;
[Export] Control sfxVolumeRow;
[Export] Control uiVolumeRow;
[Export] Control ambienceVolumeRow;
[Export] Civ3TextureButton close;
[Export] TextureRect background;

private AudioManager audioManager;
private AudioManager _audioManager;

public override void _Ready() {
audioManager = GetNode<AudioManager>("/root/GlobalAudioManager");
_audioManager = GlobalAudio.manager;

// Match the advisor screens: the background texture is set on the
// TextureRect via textureConfigKey, and the title is drawn with the
Expand All @@ -42,17 +49,28 @@ public override void _Ready() {
PreferencesSettings.SetPromptForResearch(enabled);
};

ConnectVolumeSlider(musicVolumeRow, musicVolume, musicVolumeLabel, AudioManager.MusicBus);
ConnectVolumeSlider(sfxVolumeRow, sfxVolume, sfxVolumeLabel, AudioManager.SfxAudioBus);
ConnectVolumeSlider(uiVolumeRow, uiVolume, uiVolumeLabel, AudioManager.UIAudioBus);
ConnectVolumeSlider(ambienceVolumeRow, ambienceVolume, ambienceVolumeLabel, AudioManager.AmbienceAudioBus);
ConnectVolumeSlider(masterVolumeRow, masterVolume, masterVolumeLabel, AudioManager.MasterBus,
() => { }); // music is always playing (through master)

ConnectVolumeSlider(musicVolumeRow, musicVolume, musicVolumeLabel, AudioManager.MusicBus,
() => { }); // music is always playing

ConnectVolumeSlider(sfxVolumeRow, sfxVolume, sfxVolumeLabel, AudioManager.SfxAudioBus,
() => _audioManager.PlaySfxAudio("extra.warrior.victory"));

ConnectVolumeSlider(uiVolumeRow, uiVolume, uiVolumeLabel, AudioManager.UIAudioBus,
() => _audioManager.PlayUIAudio("buttons.button_1"));

ConnectVolumeSlider(ambienceVolumeRow, ambienceVolume, ambienceVolumeLabel, AudioManager.AmbienceAudioBus,
() => _audioManager.PlayAmbienceAudio("ambience.oriole"));

TextureLoader.SetButtonTextures(close, "ui.exit");
close.Pressed += HidePreferences;
}

private void ConnectVolumeSlider(Control row, Civ3HSlider slider, Label valueLabel, string bus) {
int volume = audioManager.GetBusVolume(bus);
private void ConnectVolumeSlider(Control row, Civ3HSlider slider, Label valueLabel, string bus,
Action callback) {
int volume = _audioManager.GetBusVolume(bus);
if (volume < 0) {
row.Visible = false;
return;
Expand All @@ -63,10 +81,11 @@ private void ConnectVolumeSlider(Control row, Civ3HSlider slider, Label valueLab

slider.ValueChanged += value => {
UpdateVolumeLabel(valueLabel, (int)value);
audioManager.SetBusVolumePercent(bus, (int)value);
_audioManager.SetBusVolumePercent(bus, (int)value);
};
slider.DragEnded += changed => {
audioManager.SetBusVolume(bus, (int)slider.Value);
_audioManager.SetBusVolume(bus, (int)slider.Value);
callback?.Invoke();
};
}

Expand Down
Loading
Loading