Programming/vgui soundscape maker.cpp: Difference between revisions
WadDelz0949 (talk | contribs) m (set g_ShowSoundscapePanel to false) |
WadDelz0949 (talk | contribs) m (added ability to save filename to soundscapes_manifest.txt file) |
||
Line 1: | Line 1: | ||
//========= Created by Waddelz. https://www.youtube.com/@WadDeIz_Real. ============// | //========= Created by Waddelz. https://www.youtube.com/@WadDeIz_Real. ============// | ||
// | // | ||
Line 265: | Line 263: | ||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||
// Purpose: | // Purpose: Called on command | ||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||
void CSoundListPanel::OnCommand(const char* pszCommand) | void CSoundListPanel::OnCommand(const char* pszCommand) | ||
Line 435: | Line 433: | ||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||
// Purpose: | // Purpose: adds a button to the soundscape list | ||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||
void CSoundscapeList::AddButton(const char* name, const char* text, const char* command, vgui::Panel* parent) | void CSoundscapeList::AddButton(const char* name, const char* text, const char* command, vgui::Panel* parent) | ||
Line 828: | Line 826: | ||
//static bool to determin if the soundscape panel should show or not | //static bool to determin if the soundscape panel should show or not | ||
bool g_ShowSoundscapePanel = | bool g_ShowSoundscapePanel = true; | ||
bool g_IsPlayingSoundscape = false; | bool g_IsPlayingSoundscape = false; | ||
Line 2,139: | Line 2,137: | ||
m_pDataList->AddButton(data->GetName(), data->GetName(), CFmtStr("$playlooping%d", LoopingNum), this); | m_pDataList->AddButton(data->GetName(), data->GetName(), CFmtStr("$playlooping%d", LoopingNum), this); | ||
} | } | ||
if (!Q_strcasecmp(name, "playsoundscape")) | if (!Q_strcasecmp(name, "playsoundscape")) | ||
{ | { | ||
Line 2,150: | Line 2,148: | ||
BaseClass::OnCommand(pszCommand); | BaseClass::OnCommand(pszCommand); | ||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: Function to recursivly write keyvalues to keyvalue files. the keyvalues | |||
// class does have a function to do this BUT this function writes every single | |||
// item one after another. this function does that but writes the keys | |||
// first then the subkeys so the order is good. | |||
//----------------------------------------------------------------------------- | |||
void RecursivlyWriteKeyvalues(KeyValues* prev, CUtlBuffer& buffer, int& indent) | |||
{ | |||
//write \t indent | |||
for (int i = 0; i < indent; i++) | |||
buffer.PutChar('\t'); | |||
//write name | |||
buffer.PutChar('"'); | |||
buffer.PutString(prev->GetName()); | |||
buffer.PutString("\"\n"); | |||
//write { | |||
for (int i = 0; i < indent; i++) | |||
buffer.PutChar('\t'); | |||
buffer.PutString("{\n"); | |||
//increment indent | |||
indent++; | |||
//write all the keys first | |||
FOR_EACH_VALUE(prev, value) | |||
{ | |||
for (int i = 0; i < indent; i++) | |||
buffer.PutChar('\t'); | |||
//write name and value | |||
buffer.PutChar('"'); | |||
buffer.PutString(value->GetName()); | |||
buffer.PutString("\"\t"); | |||
buffer.PutChar('"'); | |||
buffer.PutString(value->GetString()); | |||
buffer.PutString("\"\n"); | |||
} | |||
//write all the subkeys now | |||
FOR_EACH_TRUE_SUBKEY(prev, value) | |||
{ | |||
//increment indent | |||
RecursivlyWriteKeyvalues(value, buffer, indent); | |||
if (value->GetNextTrueSubKey()) | |||
buffer.PutChar('\n'); | |||
} | |||
//decrement indent | |||
indent--; | |||
//write ending } | |||
for (int i = 0; i < indent; i++) | |||
buffer.PutChar('\t'); | |||
buffer.PutString("}\n"); | |||
} | } | ||
Line 2,179: | Line 2,239: | ||
while (pCurrent) | while (pCurrent) | ||
{ | { | ||
pCurrent | int indent = 0; | ||
pCurrent = pCurrent-> | RecursivlyWriteKeyvalues(pCurrent, buf, indent); | ||
pCurrent = pCurrent->GetNextTrueSubKey(); | |||
//put a newline | //put a newline | ||
Line 2,186: | Line 2,247: | ||
} | } | ||
g_pFullFileSystem->WriteFile(pszFileName, "MOD", buf); | if (!g_pFullFileSystem->WriteFile(pszFileName, "MOD", buf)) | ||
{ | |||
//play an error sound | |||
vgui::surface()->PlaySound("resource/warning.wav"); | |||
//get the error first | |||
char buf[1028]; | |||
Q_snprintf(buf, sizeof(buf), "Failed to save soundscape to file \"%s\"", pszFileName); | |||
//show an error | |||
vgui::QueryBox* popup = new vgui::QueryBox("Error", buf, this); | |||
popup->SetOKButtonText("Ok"); | |||
popup->SetCancelButtonVisible(false); | |||
popup->AddActionSignalTarget(this); | |||
popup->DoModal(this); | |||
return; | |||
} | |||
} | } | ||
Line 2,208: | Line 2,285: | ||
SetTitle(buf, true); | SetTitle(buf, true); | ||
//create copy of pszFileName | |||
char manifest[1028]; | |||
Q_strncpy(manifest, pszFileName, sizeof(manifest)); | |||
//get last / | |||
char* lastSlash = strrchr(manifest, '\\'); | |||
if (lastSlash == nullptr || *lastSlash == '\0') | |||
return; | |||
//append 'soundscapes_manifest.txt' | |||
lastSlash[1] = '\0'; | |||
strcat(manifest, "soundscapes_manifest.txt"); | |||
//see if we can open manifest file | |||
KeyValues* man_file = new KeyValues("manifest"); | |||
if (!man_file->LoadFromFile(g_pFullFileSystem, manifest)) | |||
{ | |||
//cant open manifest file | |||
man_file->deleteThis(); | |||
return; | |||
} | |||
//get real filename | |||
pszFileName = Q_strrchr(pszFileName, '\\'); | |||
if (!pszFileName || !*pszFileName) | |||
{ | |||
man_file->deleteThis(); | |||
return; | |||
} | |||
pszFileName = pszFileName + 1; | |||
//create name to be added to the manifest file | |||
char add_file[1028]; | |||
Q_snprintf(add_file, sizeof(add_file), "scripts/%s", pszFileName); | |||
//add filename to manifest file if not found | |||
FOR_EACH_VALUE(man_file, value) | |||
{ | |||
if (!Q_strcmp(value->GetString(), add_file)) | |||
{ | |||
man_file->deleteThis(); | |||
return; | |||
} | |||
} | |||
//add to manifest file | |||
KeyValues* kv = new KeyValues("file"); | |||
kv->SetString(nullptr, add_file); | |||
man_file->AddSubKey(kv); | |||
//write to file | |||
man_file->SaveToFile(g_pFullFileSystem, manifest); | |||
man_file->deleteThis(); | |||
return; | return; | ||
} | } | ||
Line 2,619: | Line 2,752: | ||
SoundscapeMaker.SetVisible(g_ShowSoundscapePanel); | SoundscapeMaker.SetVisible(g_ShowSoundscapePanel); | ||
} | } | ||
Revision as of 19:53, 10 May 2025
//========= Created by Waddelz. https://www.youtube.com/@WadDeIz_Real. ============// // // Purpose: a vgui panel that allows you to create and test soundscapes in game // // $NoKeywords: $ // //=================================================================================//
- include "cbase.h"
- include "c_soundscape.h"
- include "vgui_soundscape_maker.h"
- include <vgui_controls/Frame.h>
- include <vgui_controls/Button.h>
- include <vgui_controls/Divider.h>
- include <vgui_controls/FileOpenDialog.h>
- include <vgui_controls/QueryBox.h>
- include <vgui_controls/Label.h>
- include <vgui_controls/ScrollBar.h>
- include <vgui_controls/Button.h>
- include <vgui_controls/TextEntry.h>
- include <vgui_controls/ComboBox.h>
- include <vgui_controls/CheckButton.h>
- include <vgui_controls/Menu.h>
- include <vgui_controls/MenuItem.h>
- include <engine/IEngineSound.h>
- include <vgui/IVGui.h>
- include <vgui/IInput.h>
- include <vgui/ISurface.h>
- include <filesystem.h>
- include <fmtstr.h>
//selected text mode enum class SoundscapeMode { Mode_Random, Mode_Soundscape, Mode_Looping, };
//dsp effects static const char* g_DspEffects[] = { "Normal (off)", "Generic", "Metal Small", "Metal Medium", "Metal Large", "Tunnel Small", "Tunnel Medium", "Tunnel Large", "Chamber Small", "Chamber Medium", "Chamber Large", "Bright Small", "Bright Medium", "Bright Large", "Water 1", "Water 2", "Water 3", "Concrete Small", "Concrete Medium", "Concrete Large", "Big 1", "Big 2", "Big 3", "Cavern Small", "Cavern Medium", "Cavern Large", "Weirdo 1", "Weirdo 2", "Weirdo 3", };
//sound levels static const char* g_SoundLevels[] = { "SNDLVL_50dB", "SNDLVL_55dB", "SNDLVL_IDLE", "SNDLVL_TALKING", "SNDLVL_60dB", "SNDLVL_65dB", "SNDLVL_STATIC", "SNDLVL_70dB", "SNDLVL_NORM", "SNDLVL_75dB", "SNDLVL_80dB", "SNDLVL_85dB", "SNDLVL_90dB", "SNDLVL_95dB", "SNDLVL_100dB", "SNDLVL_105dB", "SNDLVL_120dB", "SNDLVL_130dB", "SNDLVL_GUNFIRE", "SNDLVL_140dB", "SNDLVL_150dB" };
//holds all the sound names static CUtlVector<char*> g_SoundDirectories;
//----------------------------------------------------------------------------- // Purpose: Sort function for utl vector //----------------------------------------------------------------------------- static int VectorSortFunc(char* const* p1, char* const* p2) { return Q_stricmp(*p1, *p2); }
//----------------------------------------------------------------------------- // Purpose: Gets all the sound names and stores them into g_SoundDirectories //----------------------------------------------------------------------------- static void GetSoundNames() { //first off clear the sound array first for (int i = 0; i < g_SoundDirectories.Count(); i++) free(g_SoundDirectories[i]);
g_SoundDirectories.RemoveAll();
//directories to search CUtlVector<char*> directoriesToSearch; directoriesToSearch.AddToTail(strdup("sound"));
//loop until all directories have been processed while (directoriesToSearch.Count() > 0) { //take the last added directory (depth-first search) char* currentDir = directoriesToSearch[directoriesToSearch.Count() - 1]; directoriesToSearch.Remove(directoriesToSearch.Count() - 1);
//create a wildcard path to search all files and subdirs char searchPath[MAX_PATH]; Q_snprintf(searchPath, sizeof(searchPath), "%s/*", currentDir);
FileFindHandle_t findHandle; const char* filename = g_pFullFileSystem->FindFirst(searchPath, &findHandle);
while (filename) { //ignore special directories if (Q_strcmp(filename, ".") != 0 && Q_strcmp(filename, "..") != 0) { char fullPath[MAX_PATH]; Q_snprintf(fullPath, sizeof(fullPath), "%s/%s", currentDir, filename);
//if it's a directory, add it to the list for later processing if (g_pFullFileSystem->FindIsDirectory(findHandle)) { directoriesToSearch.AddToTail(strdup(fullPath)); } else { //check file extension and print if it's .wav or .mp3 const char* ext = V_GetFileExtension(filename); if (ext && (!Q_stricmp(ext, "wav") || !Q_stricmp(ext, "mp3"))) { g_SoundDirectories.AddToTail(strdup(fullPath + 6)); } } }
// Move to next file filename = g_pFullFileSystem->FindNext(findHandle); }
//free the memory g_pFullFileSystem->FindClose(findHandle); free(currentDir); }
// g_SoundDirectories.Sort(VectorSortFunc); }
//sounds list panel
- define SOUND_LIST_PANEL_WIDTH 325
- define SOUND_LIST_PANEL_HEIGHT 155
- define SOUND_LIST_PLAY_COMMAND "PlaySound"
- define SOUND_LIST_STOP_COMMAND "StopSound"
- define SOUND_LIST_INSERT_COMMAND "Insert"
- define SOUND_LIST_RELOAD_COMMAND "Reload"
class CSoundListPanel : public vgui::Frame { public: DECLARE_CLASS(CSoundListPanel, vgui::Frame);
CSoundListPanel(vgui::VPANEL parent, const char* name);
//initalizes sound combo box void InitalizeSounds();
//other void OnCommand(const char* pszCommand); void OnClose();
private: vgui::ComboBox* m_SoundsList; vgui::Button* m_PlayButton; vgui::Button* m_StopSoundButton; vgui::Button* m_InsertButton; vgui::Button* m_ReloadSounds;
//current sound guid int m_iSongGuid = -1; };
//----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CSoundListPanel::CSoundListPanel(vgui::VPANEL parent, const char* name) : BaseClass(nullptr, name) { SetParent(parent);
SetKeyBoardInputEnabled(true); SetMouseInputEnabled(true);
SetProportional(false); SetTitleBarVisible(true); SetMinimizeButtonVisible(false); SetMaximizeButtonVisible(false); SetCloseButtonVisible(true); SetSizeable(false); SetMoveable(true); SetVisible(false);
//set the size and pos int ScreenWide, ScreenTall; vgui::surface()->GetScreenSize(ScreenWide, ScreenTall);
SetTitle("Sounds List", true); SetSize(SOUND_LIST_PANEL_WIDTH, SOUND_LIST_PANEL_HEIGHT); SetPos((ScreenWide - SOUND_LIST_PANEL_WIDTH) / 2, (ScreenTall - SOUND_LIST_PANEL_HEIGHT) / 2);
SetScheme(vgui::scheme()->LoadSchemeFromFile("resource/SourceScheme.res", "SourceScheme"));
//create combo box m_SoundsList = new vgui::ComboBox(this, "SoundsList", 20, true); m_SoundsList->SetBounds(5, 25, SOUND_LIST_PANEL_WIDTH - 15, 20);
//create play button m_PlayButton = new vgui::Button(this, "PlayButton", "Play Sound", this); m_PlayButton ->SetBounds(5, 50, SOUND_LIST_PANEL_WIDTH - 15, 20); m_PlayButton->SetCommand(SOUND_LIST_PLAY_COMMAND);
//create stop sound button m_StopSoundButton = new vgui::Button(this, "StopSound", "Stop Sound", this); m_StopSoundButton ->SetBounds(5, 75, SOUND_LIST_PANEL_WIDTH - 15, 20); m_StopSoundButton->SetCommand(SOUND_LIST_STOP_COMMAND);
//create sound insert button m_InsertButton = new vgui::Button(this, "InsertSound", "Insert Sound", this); m_InsertButton ->SetBounds(5, 100, SOUND_LIST_PANEL_WIDTH - 15, 20); m_InsertButton->SetCommand(SOUND_LIST_INSERT_COMMAND);
//create reload sounds button m_ReloadSounds = new vgui::Button(this, "ReloadSounds", "Reload Sounds", this); m_ReloadSounds ->SetBounds(5, 125, SOUND_LIST_PANEL_WIDTH - 15, 20); m_ReloadSounds->SetCommand(SOUND_LIST_RELOAD_COMMAND); }
//----------------------------------------------------------------------------- // Purpose: Called on command //----------------------------------------------------------------------------- void CSoundListPanel::OnCommand(const char* pszCommand) { if (!Q_strcmp(pszCommand, SOUND_LIST_PLAY_COMMAND)) { //get the sound char buf[512]; m_SoundsList->GetText(buf, sizeof(buf));
//stop the sound if (enginesound->IsSoundStillPlaying(m_iSongGuid)) { enginesound->StopSoundByGuid(m_iSongGuid); m_iSongGuid = -1; }
//precache and play the sound if (!enginesound->IsSoundPrecached(buf)) enginesound->PrecacheSound(buf);
enginesound->EmitAmbientSound(buf, 1, 100); m_iSongGuid = enginesound->GetGuidForLastSoundEmitted(); return; } else if (!Q_strcmp(pszCommand, SOUND_LIST_STOP_COMMAND)) { //stop the sound if (m_iSongGuid != -1 && enginesound->IsSoundStillPlaying(m_iSongGuid)) { enginesound->StopSoundByGuid(m_iSongGuid); m_iSongGuid = -1; }
return; } else if (!Q_strcmp(pszCommand, SOUND_LIST_INSERT_COMMAND)) { //make not visible SetVisible(false);
//stop the sound if (enginesound->IsSoundStillPlaying(m_iSongGuid)) { enginesound->StopSoundByGuid(m_iSongGuid); m_iSongGuid = -1; }
//get the sound char buf[512]; m_SoundsList->GetText(buf, sizeof(buf));
//set the sound text g_SoundscapeMaker->SetSoundText(buf); return; } else if (!Q_strcmp(pszCommand, SOUND_LIST_RELOAD_COMMAND)) { //clear everything for the combo box and reload it m_SoundsList->RemoveAll();
InitalizeSounds(); return; }
BaseClass::OnCommand(pszCommand); }
//----------------------------------------------------------------------------- // Purpose: Called on panel close //----------------------------------------------------------------------------- void CSoundListPanel::OnClose() { OnCommand(SOUND_LIST_STOP_COMMAND); BaseClass::OnClose(); }
//----------------------------------------------------------------------------- // Purpose: Initalizes the sounds list //----------------------------------------------------------------------------- void CSoundListPanel::InitalizeSounds() { //get the sound array GetSoundNames();
//add all the sounds for (int i = 0; i < g_SoundDirectories.Size(); i++) m_SoundsList->AddItem(g_SoundDirectories[i], nullptr);
m_SoundsList->ActivateItem(0); }
//static sound list instance static CSoundListPanel* g_SoundPanel = nullptr; static bool g_SoundPanelInitalized = false;
//soundscape list
- define ADD_SOUNDSCAPE_COMMAND "AddSoundscape"
//soundscape list class
class CSoundscapeList : public vgui::Divider
{
public:
DECLARE_CLASS_SIMPLE(CSoundscapeList, vgui::Divider);
//constructor CSoundscapeList(vgui::Panel* parent, const char* name, const char* text, int text_x_pos, int max, int width, int height);
//menu item stuff virtual void AddButton(const char* name, const char* text, const char* command, vgui::Panel* parent); virtual void Clear();
//other virtual void OnMouseWheeled(int delta); virtual void OnMouseReleased(vgui::MouseCode code);
virtual void OnCommand(const char* pszCommand); virtual void ApplySchemeSettings(vgui::IScheme* scheme);
//message funcs MESSAGE_FUNC_INT(ScrollBarMoved, "ScrollBarSliderMoved", position);
protected: friend class CSoundscapeMaker;
//keyvalue list. KeyValues* m_Keyvalues;
//says "Soundscapes List" vgui::Label* m_pLabel; vgui::ScrollBar* m_pSideSlider;
//menu button stuff CUtlVector<vgui::Button*> m_MenuButtons; int m_iCurrentY; int m_iMax; int m_AmtAdded; };
//----------------------------------------------------------------------------- // Purpose: Constructor for soundscape list panel //----------------------------------------------------------------------------- CSoundscapeList::CSoundscapeList(vgui::Panel* parent, const char* name, const char* text, int text_x_pos, int max, int width, int height) : BaseClass(parent, name) { //create the text m_pLabel = new vgui::Label(this, "ListsText", text); m_pLabel->SetVisible(true); m_pLabel->SetBounds(text_x_pos, 2, 150, 20);
//create the side slider m_pSideSlider = new vgui::ScrollBar(this, "ListsSlider", true); m_pSideSlider->SetBounds(width - 20, 0, 20, height - 2); m_pSideSlider->SetValue(0); m_pSideSlider->SetEnabled(false); m_pSideSlider->SetRange(0, 0); m_pSideSlider->SetButtonPressedScrollValue(1); m_pSideSlider->SetRangeWindow(0); m_pSideSlider->AddActionSignalTarget(this);
m_iCurrentY = 22; m_iMax = max; m_Keyvalues = nullptr; }
//----------------------------------------------------------------------------- // Purpose: adds a button to the soundscape list //----------------------------------------------------------------------------- void CSoundscapeList::AddButton(const char* name, const char* text, const char* command, vgui::Panel* parent) { //create a new button vgui::Button* button = new vgui::Button(this, name, text, parent, command); button->SetBounds(5, m_iCurrentY, GetWide() - 30, 20);
//increment current y m_iCurrentY = m_iCurrentY + 22;
//add button to array m_MenuButtons.AddToTail(button);
//if the count is more then m_iMax then set slider value if (m_MenuButtons.Count() > m_iMax) { int max = m_MenuButtons.Count() - m_iMax;
m_pSideSlider->SetRange(0, max); m_pSideSlider->SetRangeWindow(1); m_pSideSlider->SetEnabled(true); }
m_AmtAdded++;
//check to see if we need to scroll down if (m_MenuButtons.Count() >= m_iMax) OnMouseWheeled(-1); }
//----------------------------------------------------------------------------- // Purpose: Clears everything for this list //----------------------------------------------------------------------------- void CSoundscapeList::Clear() { //reset the slider m_pSideSlider->SetValue(0); m_pSideSlider->SetEnabled(false); m_pSideSlider->SetRange(0, 0); m_pSideSlider->SetButtonPressedScrollValue(1); m_pSideSlider->SetRangeWindow(0);
//delete and clear the buttons for (int i = 0; i < m_MenuButtons.Count(); i++) m_MenuButtons[i]->DeletePanel();
m_MenuButtons.RemoveAll();
//reset current y m_iCurrentY = 22;
m_AmtAdded = 0; }
//----------------------------------------------------------------------------- // Purpose: Clears everything for this list //----------------------------------------------------------------------------- void CSoundscapeList::OnMouseWheeled(int delta) { //check for scroll down if (delta == -1) m_pSideSlider->SetValue(m_pSideSlider->GetValue() + 1);
//check for scroll up else if (delta == 1) m_pSideSlider->SetValue(m_pSideSlider->GetValue() - 1); }
//----------------------------------------------------------------------------- // Purpose: Called when a mouse code is released //----------------------------------------------------------------------------- void CSoundscapeList::OnMouseReleased(vgui::MouseCode code) { if (code != vgui::MouseCode::MOUSE_RIGHT) return;
//get cursor pos int x, y; vgui::surface()->SurfaceGetCursorPos(x, y);
//create menu vgui::Menu* menu = new vgui::Menu(this, "Menu"); menu->AddMenuItem("AddSoundscape", "Add Soundscape", ADD_SOUNDSCAPE_COMMAND, this); menu->SetBounds(x, y, 200, 50); menu->SetVisible(true); }
//----------------------------------------------------------------------------- // Purpose: Called on command //----------------------------------------------------------------------------- void CSoundscapeList::OnCommand(const char* pszCommand) { if (!Q_strcmp(pszCommand, ADD_SOUNDSCAPE_COMMAND)) { const char* name = CFmtStr("New Soundscape %d", m_AmtAdded); AddButton(name, name, name, GetParent());
//add to keyvalues file KeyValues* kv = new KeyValues(name); KeyValues* tmp = m_Keyvalues; KeyValues* tmp2 = tmp;
//get last subkey while (tmp != nullptr) { tmp2 = tmp; tmp = tmp->GetNextTrueSubKey(); }
//add to last subkey tmp2->SetNextKey(kv);
GetParent()->OnCommand(name); return; }
BaseClass::OnCommand(pszCommand); }
//----------------------------------------------------------------------------- // Purpose: Called on command //----------------------------------------------------------------------------- void CSoundscapeList::ApplySchemeSettings(vgui::IScheme* scheme) { BaseClass::ApplySchemeSettings(scheme); SetBgColor(Color(100, 100, 100, 200)); }
//----------------------------------------------------------------------------- // Purpose: Called on scroll bar moved //----------------------------------------------------------------------------- void CSoundscapeList::ScrollBarMoved(int delta) { int position = m_pSideSlider->GetValue();
//move everything down (if needed) for (int i = 0; i < m_MenuButtons.Count(); i++) { //make not visible if i < position if (i < position) { m_MenuButtons[i]->SetVisible(false); continue; }
m_MenuButtons[i]->SetPos(5, 22 * ((i - position) + 1)); m_MenuButtons[i]->SetVisible(true); } }
//soundscape data list
- define NEW_PLAYLOOPING_COMMAND "NewLooping"
- define NEW_SOUNDSCAPE_COMMAND "NewSoundscape"
- define NEW_RANDOM_COMMAND "NewRandom"
class CSoundscapeDataList : public CSoundscapeList
{
public:
DECLARE_CLASS_SIMPLE(CSoundscapeDataList, CSoundscapeList);
CSoundscapeDataList(vgui::Panel* parent, const char* name, const char* text, int text_x_pos, int max, int width, int height) : CSoundscapeList(parent, name, text, text_x_pos, max, width, height) {}
//override right click functionality virtual void OnMouseReleased(vgui::MouseCode code);
void OnCommand(const char* pszCommand);
private: friend class CSoundscapeMaker; };
//-----------------------------------------------------------------------------
// Purpose: Called when a mouse code is released
//-----------------------------------------------------------------------------
void CSoundscapeDataList::OnMouseReleased(vgui::MouseCode code)
{
//if no soundscape is selected or mouse code != right then return
if (code != vgui::MouseCode::MOUSE_RIGHT || !m_Keyvalues)
return;
//get cursor pos int x, y; vgui::surface()->SurfaceGetCursorPos(x, y);
//create menu vgui::Menu* menu = new vgui::Menu(this, "Menu"); menu->AddMenuItem("AddLooping", "Add Looping Sound", NEW_PLAYLOOPING_COMMAND, this); menu->AddMenuItem("AddSoundscape", "Add Soundscape", NEW_SOUNDSCAPE_COMMAND, this); menu->AddMenuItem("AddSoundscape", "Add Random Sounds", NEW_RANDOM_COMMAND, this); menu->SetBounds(x, y, 200, 50); menu->SetVisible(true); }
//-----------------------------------------------------------------------------
// Purpose: Called on command
//-----------------------------------------------------------------------------
void CSoundscapeDataList::OnCommand(const char* pszCommand)
{
if (!Q_strcmp(pszCommand, NEW_PLAYLOOPING_COMMAND))
{
int LoopingNum = 0;
FOR_EACH_TRUE_SUBKEY(m_Keyvalues, data)
{
//store data name
const char* name = data->GetName();
//increment variables based on name if (!Q_strcasecmp(name, "playlooping")) LoopingNum++; }
//add the keyvalue to both this and the keyvalues AddButton("playlooping", "playlooping", CFmtStr("$playlooping%d", LoopingNum + 1), GetParent());
//add the keyvalues KeyValues* kv = new KeyValues("playlooping"); kv->SetFloat("volume", 1); kv->SetInt("pitch", 100);
m_Keyvalues->AddSubKey(kv);
GetParent()->OnCommand(CFmtStr("$playlooping%d", LoopingNum + 1));
return; } else if (!Q_strcmp(pszCommand, NEW_SOUNDSCAPE_COMMAND)) { int SoundscapeNum = 0; FOR_EACH_TRUE_SUBKEY(m_Keyvalues, data) { //store data name const char* name = data->GetName();
//increment variables based on name if (!Q_strcasecmp(name, "playsoundscape")) SoundscapeNum++; }
AddButton("playsoundscape", "playsoundscape", CFmtStr("$playsoundscape%d", SoundscapeNum + 1), GetParent());
//add the keyvalues KeyValues* kv = new KeyValues("playsoundscape"); kv->SetFloat("volume", 1);
//add the keyvalue to both this and the keyvalues m_Keyvalues->AddSubKey(kv);
GetParent()->OnCommand(CFmtStr("$playsoundscape%d", SoundscapeNum + 1));
return; } else if (!Q_strcmp(pszCommand, NEW_RANDOM_COMMAND)) { int RandomNum = 0; FOR_EACH_TRUE_SUBKEY(m_Keyvalues, data) { //store data name const char* name = data->GetName();
//increment variables based on name if (!Q_strcasecmp(name, "playrandom")) RandomNum++; }
AddButton("playrandom", "playrandom", CFmtStr("$playrandom%d", RandomNum + 1), GetParent());
//add the keyvalues KeyValues* kv = new KeyValues("playrandom"); kv->SetString("volume", "0.5,0.8"); kv->SetInt("pitch", 100); kv->SetString("time", "10,20");
//make rndwave subkey KeyValues* rndwave = new KeyValues("rndwave"); kv->AddSubKey(rndwave);
//add the keyvalue to both this and the keyvalues m_Keyvalues->AddSubKey(kv);
//make the parent show the new item GetParent()->OnCommand(CFmtStr("$playrandom%d", RandomNum + 1));
return; }
BaseClass::OnCommand(pszCommand); }
//soundscape rndwave data list
- define NEW_RNDWAVE_WAVE_COMMAND "NewRNDWave"
class CSoundscapeRndwaveList : public CSoundscapeList
{
public:
DECLARE_CLASS_SIMPLE(CSoundscapeDataList, CSoundscapeList);
CSoundscapeRndwaveList(vgui::Panel* parent, const char* name, const char* text, int text_x_pos, int max, int width, int height) : CSoundscapeList(parent, name, text, text_x_pos, max, width, height) {}
//override right click functionality virtual void OnMouseReleased(vgui::MouseCode code);
void OnCommand(const char* pszCommand);
private: friend class CSoundscapeMaker; };
//-----------------------------------------------------------------------------
// Purpose: Called when a mouse code is released
//-----------------------------------------------------------------------------
void CSoundscapeRndwaveList::OnMouseReleased(vgui::MouseCode code)
{
//if no soundscape is selected or mouse code != right then return
if (code != vgui::MouseCode::MOUSE_RIGHT || !m_Keyvalues)
return;
//get cursor pos int x, y; vgui::surface()->SurfaceGetCursorPos(x, y);
//create menu vgui::Menu* menu = new vgui::Menu(this, "Menu"); menu->AddMenuItem("AddRandom", "Add Random Wave", NEW_RNDWAVE_WAVE_COMMAND, this); menu->SetBounds(x, y, 200, 50); menu->SetVisible(true); }
//-----------------------------------------------------------------------------
// Purpose: Called on command
//-----------------------------------------------------------------------------
void CSoundscapeRndwaveList::OnCommand(const char* pszCommand)
{
if (!Q_strcmp(pszCommand, NEW_RNDWAVE_WAVE_COMMAND))
{
//get number of keyvalues
int num = 0;
FOR_EACH_VALUE(m_Keyvalues, kv) num++;
//add keyvalues and button AddButton("Rndwave", "", CFmtStr("$rndwave%d", num + 1), GetParent());
KeyValues* add = new KeyValues("wave"); add->SetString(nullptr, ""); m_Keyvalues->AddSubKey(add);
//forward command to parent GetParent()->OnCommand(CFmtStr("$rndwave%d", num + 1));
return; }
BaseClass::OnCommand(pszCommand); }
//soundscape panel
- define SOUNDSCAPE_PANEL_WIDTH 760
- define SOUNDSCAPE_PANEL_HEIGHT 600
- define NEW_BUTTON_COMMAND "NewSoundscape"
- define SAVE_BUTTON_COMMAND "SaveSoundscape"
- define LOAD_BUTTON_COMMAND "LoadSoundscape"
- define RESET_BUTTON_COMMAND "ResetSoundscapes"
- define SOUNDS_LIST_BUTTON_COMMAND "ShowSoundsList"
- define PLAY_SOUNDSCAPE_COMMAND "PlaySoundscape"
- define RESET_SOUNDSCAPE_BUTTON_COMMAND "ResetSoundscape"
- define DELETE_CURRENT_ITEM_COMMAND "DeleteItem"
//static bool to determin if the soundscape panel should show or not bool g_ShowSoundscapePanel = true; bool g_IsPlayingSoundscape = false;
//soundscape maker panel class CSoundscapeMaker : public vgui::Frame, CAutoGameSystem { public: DECLARE_CLASS_SIMPLE(CSoundscapeMaker, vgui::Frame)
CSoundscapeMaker(vgui::VPANEL parent);
//tick functions void OnTick();
//other functions void OnClose(); void OnCommand(const char* pszCommand);
void PlaySelectedSoundscape(); void LoadFile(KeyValues* file);
void OnKeyCodePressed(vgui::KeyCode code);
void SetSoundText(const char* text);
//to play the soundscape on map spawn void LevelInitPostEntity();
//message pointer funcs MESSAGE_FUNC_CHARPTR(OnFileSelected, "FileSelected", fullpath); MESSAGE_FUNC_PARAMS(OnTextChanged, "TextChanged", data);
~CSoundscapeMaker();
private: //the soundscape keyvalues file KeyValues* m_KeyValues = nullptr;
private: void CreateEverything();
private: //lists all the soundscapes CSoundscapeList* m_SoundscapesList; CSoundscapeDataList* m_pDataList; CSoundscapeRndwaveList* m_pSoundList;
//buttons vgui::Button* m_ButtonNew = nullptr; vgui::Button* m_ButtonSave = nullptr; vgui::Button* m_ButtonLoad = nullptr;
//file load and save dialogs vgui::FileOpenDialog* m_FileSave = nullptr; vgui::FileOpenDialog* m_FileLoad = nullptr; bool m_bWasFileLoad = false;
//text entry for name vgui::TextEntry* m_TextEntryName;
//combo box for dsp effects vgui::ComboBox* m_DspEffects; vgui::ComboBox* m_SoundLevels;
//sound data text entry vgui::TextEntry* m_TimeTextEntry; vgui::TextEntry* m_VolumeTextEntry; vgui::TextEntry* m_PitchTextEntry; vgui::TextEntry* m_PositionTextEntry; vgui::TextEntry* m_SoundNameTextEntry;
//play sound button vgui::Button* m_SoundNamePlay;
//play/reset soundscape buttons vgui::CheckButton* m_PlaySoundscapeButton; vgui::Button* m_ResetSoundscapeButton; vgui::Button* m_DeleteCurrentButton;
//current selected soundscape vgui::Button* m_pCurrentSelected = nullptr; KeyValues* m_kvCurrSelected = nullptr; KeyValues* m_kvCurrSound = nullptr; KeyValues* m_kvCurrRndwave = nullptr;
int m_iCurrRndWave = 0;
//currently in non randomwave thing SoundscapeMode m_iSoundscapeMode = SoundscapeMode::Mode_Random;
//temporary added soundscapes CUtlVector<KeyValues*> m_TmpAddedSoundscapes; };
//----------------------------------------------------------------------------- // Purpose: Constructor for soundscape maker panel //----------------------------------------------------------------------------- CSoundscapeMaker::CSoundscapeMaker(vgui::VPANEL parent) : BaseClass(nullptr, "SoundscapeMaker") { //set variables m_pCurrentSelected = nullptr;
SetParent(parent);
SetKeyBoardInputEnabled(true); SetMouseInputEnabled(true);
SetProportional(false); SetTitleBarVisible(true); SetMinimizeButtonVisible(false); SetMaximizeButtonVisible(false); SetCloseButtonVisible(true); SetSizeable(false); SetMoveable(true); SetVisible(g_ShowSoundscapePanel);
int ScreenWide, ScreenTall; vgui::surface()->GetScreenSize(ScreenWide, ScreenTall);
SetTitle("Soundscape Maker (New File)", true); SetSize(SOUNDSCAPE_PANEL_WIDTH, SOUNDSCAPE_PANEL_HEIGHT); SetPos((ScreenWide - SOUNDSCAPE_PANEL_WIDTH) / 2, (ScreenTall - SOUNDSCAPE_PANEL_HEIGHT) / 2);
SetScheme(vgui::scheme()->LoadSchemeFromFile("resource/SourceScheme.res", "SourceScheme"));
//add a tick signal for every 50 ms vgui::ivgui()->AddTickSignal(GetVPanel(), 50);
CreateEverything(); }
//----------------------------------------------------------------------------- // Purpose: Called every tick for the soundscape maker //----------------------------------------------------------------------------- void CSoundscapeMaker::CreateEverything() { //create the divider that will be the outline for the inside of the panel vgui::Divider* PanelOutline = new vgui::Divider(this, "InsideOutline"); PanelOutline->SetEnabled(false); PanelOutline->SetBounds(5, 25, SOUNDSCAPE_PANEL_WIDTH - 10, SOUNDSCAPE_PANEL_HEIGHT - 30);
//create the buttons m_ButtonNew = new vgui::Button(this, "NewButton", "New Soundscape File"); m_ButtonNew->SetVisible(true); m_ButtonNew->SetBounds(325, 566, 165, 25); m_ButtonNew->SetCommand(NEW_BUTTON_COMMAND); m_ButtonNew->SetDepressedSound("ui/buttonclickrelease.wav");
m_ButtonSave = new vgui::Button(this, "SaveButton", "Save Soundscapes"); m_ButtonSave->SetVisible(true); m_ButtonSave->SetBounds(495, 566, 125, 25); m_ButtonSave->SetCommand(SAVE_BUTTON_COMMAND); m_ButtonSave->SetDepressedSound("ui/buttonclickrelease.wav");
m_ButtonLoad = new vgui::Button(this, "LoadButton", "Load Soundscapes"); m_ButtonLoad->SetVisible(true); m_ButtonLoad->SetBounds(625, 566, 125, 25); m_ButtonLoad->SetCommand(LOAD_BUTTON_COMMAND); m_ButtonLoad->SetDepressedSound("ui/buttonclickrelease.wav");
//create the soundscapes menu m_SoundscapesList = new CSoundscapeList(this, "SoundscapesList", "Soundscapes:", 90, 22, 300, 550); m_SoundscapesList->SetBounds(15, 35, 300, 550); m_SoundscapesList->SetVisible(true);
//create data list m_pDataList = new CSoundscapeDataList(this, "SoudscapeDataList", "Soundscape Data:", 35, 10, 200, 280); m_pDataList->SetBounds(327, 275, 200, 280); m_pDataList->SetVisible(true);
//create sound list m_pSoundList = new CSoundscapeRndwaveList(this, "SoudscapeDataList", "Random Sounds:", 40, 10, 200, 280); m_pSoundList->SetBounds(542, 275, 200, 280); m_pSoundList->SetVisible(true);
//name text entry m_TextEntryName = new vgui::TextEntry(this, "NameTextEntry"); m_TextEntryName->SetEnabled(false); m_TextEntryName->SetBounds(325, 40, 295, 20); m_TextEntryName->SetMaximumCharCount(50);
//dsp effects combo box m_DspEffects = new vgui::ComboBox(this, "DspEffects", sizeof(g_DspEffects) / sizeof(g_DspEffects[0]), false); m_DspEffects->SetEnabled(false); m_DspEffects->SetBounds(325, 65, 295, 20); m_DspEffects->SetText(""); m_DspEffects->AddActionSignalTarget(this);
for (int i = 0; i < sizeof(g_DspEffects) / sizeof(g_DspEffects[i]); i++) m_DspEffects->AddItem(g_DspEffects[i], nullptr);
//time text entry m_TimeTextEntry = new vgui::TextEntry(this, "TimeTextEntry"); m_TimeTextEntry->SetBounds(325, 90, 295, 20); m_TimeTextEntry->SetEnabled(false); m_TimeTextEntry->SetVisible(true);
//volume text entry m_VolumeTextEntry = new vgui::TextEntry(this, "VolumeTextEntry"); m_VolumeTextEntry->SetBounds(325, 115, 295, 20); m_VolumeTextEntry->SetEnabled(false); m_VolumeTextEntry->SetVisible(true);
//pitch text entry m_PitchTextEntry = new vgui::TextEntry(this, "PitchTextEntry"); m_PitchTextEntry->SetBounds(325, 140, 295, 20); m_PitchTextEntry->SetEnabled(false); m_PitchTextEntry->SetVisible(true);
//position text entry m_PositionTextEntry = new vgui::TextEntry(this, "PositionTextEntry"); m_PositionTextEntry->SetBounds(325, 165, 295, 20); m_PositionTextEntry->SetEnabled(false); m_PositionTextEntry->SetVisible(true);
//sound levels m_SoundLevels = new vgui::ComboBox(this, "SoundLevels", sizeof(g_SoundLevels) / sizeof(g_SoundLevels[0]), false); m_SoundLevels->SetEnabled(false); m_SoundLevels->SetBounds(325, 190, 295, 20); m_SoundLevels->SetText(""); m_SoundLevels->AddActionSignalTarget(this);
for (int i = 0; i < sizeof(g_SoundLevels) / sizeof(g_SoundLevels[i]); i++) m_SoundLevels->AddItem(g_SoundLevels[i], nullptr);
//sound name m_SoundNameTextEntry = new vgui::TextEntry(this, "SoundName"); m_SoundNameTextEntry->SetBounds(325, 215, 215, 20); m_SoundNameTextEntry->SetEnabled(false); m_SoundNameTextEntry->SetVisible(true);
//play sound button m_SoundNamePlay = new vgui::Button(this, "SoundPlayButton", "Sounds List"); m_SoundNamePlay->SetBounds(545, 215, 75, 20); m_SoundNamePlay->SetCommand(SOUNDS_LIST_BUTTON_COMMAND); m_SoundNamePlay->SetEnabled(false);
//starts the soundscape m_PlaySoundscapeButton = new vgui::CheckButton(this, "PlaySoundscape", "Play Soundscape"); m_PlaySoundscapeButton->SetBounds(330, 243, 125, 20); m_PlaySoundscapeButton->SetCommand(PLAY_SOUNDSCAPE_COMMAND); m_PlaySoundscapeButton->SetEnabled(false); m_PlaySoundscapeButton->SetSelected(false);
//reset soundscape button m_ResetSoundscapeButton = new vgui::Button(this, "ResetSoundscape", "Restart Soundscape"); m_ResetSoundscapeButton->SetBounds(465, 243, 125, 20); m_ResetSoundscapeButton->SetCommand(RESET_SOUNDSCAPE_BUTTON_COMMAND); m_ResetSoundscapeButton->SetEnabled(false);
//delete this item m_DeleteCurrentButton = new vgui::Button(this, "DeleteItem", "Delete Current Item"); m_DeleteCurrentButton->SetBounds(595, 243, 135, 20); m_DeleteCurrentButton->SetCommand(DELETE_CURRENT_ITEM_COMMAND); m_DeleteCurrentButton->SetEnabled(false);
//create the soundscape name text vgui::Label* NameLabel = new vgui::Label(this, "NameLabel", "Soundscape Name"); NameLabel->SetBounds(635, 40, 125, 20);
//create the soundscape dsp text vgui::Label* DspLabel = new vgui::Label(this, "DspLabel", "Soundscape Dsp"); DspLabel->SetBounds(635, 65, 125, 20);
//create the soundscape time text vgui::Label* TimeLabel = new vgui::Label(this, "TimeLabel", "Sound Time"); TimeLabel->SetBounds(635, 90, 125, 20);
//create the soundscape volumn text vgui::Label* VolumeLabel = new vgui::Label(this, "VolumeLabel", "Sound Volume"); VolumeLabel->SetBounds(635, 115, 125, 20);
//create the soundscape pitch text vgui::Label* PitchLabel = new vgui::Label(this, "PitchLabel", "Sound Pitch"); PitchLabel->SetBounds(635, 140, 125, 20);
//create the soundscape position text vgui::Label* PositionLabel = new vgui::Label(this, "PositionLabel", "Sound Position"); PositionLabel->SetBounds(635, 165, 125, 20);
//create the soundscape sound level text vgui::Label* SoundLevelLabel = new vgui::Label(this, "SoundLevelLabel", "Sound Level"); SoundLevelLabel ->SetBounds(635, 190, 125, 20);
//create the soundscape sound name text vgui::Label* SoundName = new vgui::Label(this, "SoundName", "Sound Name"); SoundName->SetBounds(635, 215, 125, 20);
//create the soundscape keyvalues and load it m_KeyValues = new KeyValues("Empty Soundscape");
LoadFile(m_KeyValues); }
//----------------------------------------------------------------------------- // Purpose: Called every tick for the soundscape maker //----------------------------------------------------------------------------- void CSoundscapeMaker::OnTick() { //set the visibility static bool bPrevVisible = g_ShowSoundscapePanel; if (g_ShowSoundscapePanel != bPrevVisible) SetVisible(g_ShowSoundscapePanel);
//set the old visibility bPrevVisible = g_ShowSoundscapePanel; }
//----------------------------------------------------------------------------- // Purpose: Called when the close button is pressed //----------------------------------------------------------------------------- void CSoundscapeMaker::OnClose() { //hide the sound panel g_SoundPanel->OnClose();
g_ShowSoundscapePanel = false; }
//----------------------------------------------------------------------------- // Purpose: Play the selected soundscape //----------------------------------------------------------------------------- void CSoundscapeMaker::PlaySelectedSoundscape() { g_IsPlayingSoundscape = false;
//remove all the temporary soundscapes from the soundscape system for (int i = 0; i < m_TmpAddedSoundscapes.Count(); i++) { for (int j = 0; j < g_SoundscapeSystem.m_soundscapes.Count(); j++) { if (g_SoundscapeSystem.m_soundscapes[j] == m_TmpAddedSoundscapes[i]) { g_SoundscapeSystem.m_soundscapes.Remove(j); break; } } }
m_TmpAddedSoundscapes.RemoveAll();
//if m_kvCurrSelected then add all the "playsoundscape" soundscape keyvalues //into the g_SoundscapeSystem.m_soundscapes array if (m_kvCurrSelected) { CUtlVector<const char*> SoundscapeNames; FOR_EACH_TRUE_SUBKEY(m_kvCurrSelected, subkey) { //look for playsoundscape file if (!Q_strcasecmp(subkey->GetName(), "playsoundscape")) { const char* name = subkey->GetString("name", nullptr); if (!name || !name[0] || SoundscapeNames.Find(name) != SoundscapeNames.InvalidIndex()) continue;
SoundscapeNames.AddToTail(name); } }
//now look for each keyvalue for (int i = 0; i < SoundscapeNames.Count(); i++) { for (KeyValues* subkey = m_KeyValues; subkey != nullptr; subkey = subkey->GetNextTrueSubKey()) { //look for playsoundscape file if (!Q_strcmp(subkey->GetName(), SoundscapeNames[i])) { //add it to the soundscape system m_TmpAddedSoundscapes.AddToTail(subkey); g_SoundscapeSystem.m_soundscapes.AddToTail(subkey); } } } }
//stop all sounds enginesound->StopAllSounds(true);
//stop the current soundscape and start a new soundscape g_SoundscapeSystem.StartNewSoundscape(nullptr); g_SoundscapeSystem.StartNewSoundscape(m_kvCurrSelected);
g_IsPlayingSoundscape = true; }
//----------------------------------------------------------------------------- // Purpose: Called when a button or something else gets pressed //----------------------------------------------------------------------------- void CSoundscapeMaker::OnCommand(const char* pszCommand) {
//check for close command first if (!Q_strcmp(pszCommand, "Close")) { BaseClass::OnCommand(pszCommand); return; }
//check for the save button command else if (!Q_strcmp(pszCommand, SAVE_BUTTON_COMMAND)) { //initalize the file save dialog if (!m_FileSave) { //get the current game directory char buf[512]; filesystem->RelativePathToFullPath("scripts", "MOD", buf, sizeof(buf));
//create the save dialog m_FileSave = new vgui::FileOpenDialog(this, "Save Soundscape File", false); m_FileSave->AddFilter("*.txt", "Soundscape Text File", true); m_FileSave->AddFilter("*.*", "All Files (*.*)", false); m_FileSave->SetStartDirectory(buf); m_FileSave->AddActionSignalTarget(this); }
//show the dialog m_FileSave->DoModal(false); m_FileSave->Activate();
//file wasnt loadad m_bWasFileLoad = false;
return; }
//check for load button command else if (!Q_strcmp(pszCommand, LOAD_BUTTON_COMMAND)) { //initalize the file save dialog if (!m_FileLoad) { //get the current game directory char buf[512]; filesystem->RelativePathToFullPath("scripts", "MOD", buf, sizeof(buf));
//create the load dialog m_FileLoad = new vgui::FileOpenDialog(this, "Load Soundscape File", true); m_FileLoad->AddFilter("*.txt", "Soundscape Text File", true); m_FileLoad->AddFilter("*.*", "All Files (*.*)", false); m_FileLoad->SetStartDirectory(buf); m_FileLoad->AddActionSignalTarget(this); }
//show the file load dialog m_FileLoad->DoModal(false); m_FileLoad->Activate();
//file was loadad m_bWasFileLoad = true;
return; }
//check for new soundscape else if (!Q_strcmp(pszCommand, NEW_BUTTON_COMMAND)) { //make sure you want to create a new soundscape file vgui::QueryBox* popup = new vgui::QueryBox("New File?", "Are you sure you want to create a new soundscape file?", this); popup->SetOKCommand(new KeyValues("Command", "command", RESET_BUTTON_COMMAND)); popup->SetCancelButtonVisible(false); popup->AddActionSignalTarget(this); popup->DoModal(this);
return; }
//check for reset soundscape else if (!Q_strcmp(pszCommand, RESET_BUTTON_COMMAND)) { m_kvCurrSelected = nullptr;
//stop all soundscapes before deleting the old soundscapes if (g_IsPlayingSoundscape) PlaySelectedSoundscape();
m_KeyValues->deleteThis(); m_KeyValues = new KeyValues("Empty Soundscape");
LoadFile(m_KeyValues); return; }
//check for play sound else if (!Q_strcmp(pszCommand, SOUNDS_LIST_BUTTON_COMMAND)) { //initalize the sounds if (!g_SoundPanelInitalized) { g_SoundPanelInitalized = true; g_SoundPanel->InitalizeSounds(); }
g_SoundPanel->SetVisible(true); g_SoundPanel->MoveToFront(); g_SoundPanel->RequestFocus(); return; }
//check for play soundscape else if (!Q_strcmp(pszCommand, PLAY_SOUNDSCAPE_COMMAND)) { if (m_PlaySoundscapeButton->IsSelected()) { //enable the reset soundscape button m_ResetSoundscapeButton->SetEnabled(true);
//play the soundscape PlaySelectedSoundscape(); } else { //disable the reset soundscape button m_ResetSoundscapeButton->SetEnabled(false);
g_IsPlayingSoundscape = false;
//stop all sounds and soundscapes enginesound->StopAllSounds(true); g_SoundscapeSystem.StartNewSoundscape(nullptr); }
return; }
//check for play soundscape else if (!Q_strcmp(pszCommand, RESET_SOUNDSCAPE_BUTTON_COMMAND)) { PlaySelectedSoundscape(); return; }
//check for delete item
else if (!Q_strcmp(pszCommand, DELETE_CURRENT_ITEM_COMMAND))
{
//check for current rndwave
if (m_kvCurrRndwave && m_SoundNameTextEntry->IsEnabled())
{
if (!m_kvCurrRndwave || m_iCurrRndWave <= 0)
return;
//get the keyvalues by the index int curr = 0; KeyValues* prev = nullptr;
FOR_EACH_VALUE(m_kvCurrRndwave, keyvalues) { if (++curr == m_iCurrRndWave) { //delete if (prev) prev->SetNextKey(keyvalues->GetNextValue()); else { m_kvCurrRndwave->m_pSub = keyvalues->GetNextValue(); m_iCurrRndWave = -1; }
curr = curr - 1;
keyvalues->SetNextKey(nullptr); keyvalues->deleteThis(); break; }
prev = keyvalues; }
//reset everything m_SoundNameTextEntry->SetText(""); m_SoundNameTextEntry->SetEnabled(false); m_SoundNamePlay->SetEnabled(false);
//store vector auto& vec = m_pSoundList->m_MenuButtons;
//remove it delete vec[curr]; vec.Remove(curr);
//move everything down m_pSoundList->m_iCurrentY = m_pSoundList->m_iCurrentY - 22; m_pSoundList->m_Keyvalues = m_kvCurrRndwave;
if (vec.Count() >= m_pSoundList->m_iMax) { m_pSoundList->OnMouseWheeled(1);
int min, max; m_pSoundList->m_pSideSlider->GetRange(min, max); m_pSoundList->m_pSideSlider->SetRange(0, max - 1); }
for (int i = curr; i < vec.Count(); i++) { //move everything down int x, y = 0; vec[i]->GetPos(x, y); vec[i]->SetPos(x, y - 22); }
//reset every command int WaveAmount = 0; for (int i = 0; i < vec.Count(); i++) { //store data name const char* name = vec[i]->GetCommand()->GetString("command");
//increment variables based on name if (Q_stristr(name, "$rndwave") == name) { WaveAmount++; vec[i]->SetCommand(CFmtStr("$rndwave%d", WaveAmount)); } }
//bounds check if (vec.Count() <= 0) return;
//select next item if (m_iCurrRndWave <= vec.Count()) OnCommand(CFmtStr("$rndwave%d", curr + 1)); else OnCommand(CFmtStr("$rndwave%d", curr)); } else if (m_kvCurrSound) { if (!m_kvCurrSelected) return;
//find keyvalue with same pointer and get the index int tmpindex = 0; int index = -1;
KeyValues* prev = nullptr; FOR_EACH_TRUE_SUBKEY(m_kvCurrSelected, keyvalues) { if (m_kvCurrSound == keyvalues) { //remove it if (prev) prev->SetNextKey(keyvalues->GetNextTrueSubKey()); else m_kvCurrSelected->m_pSub = keyvalues->GetNextTrueSubKey();
keyvalues->SetNextKey(nullptr); keyvalues->deleteThis();
//get index index = tmpindex; break; }
prev = keyvalues;
//increment tmpindex++; }
//error if (index == -1) return;
//store vector auto& vec = m_pDataList->m_MenuButtons;
//remove it delete vec[index]; vec.Remove(index);
//move everything down m_pDataList->m_iCurrentY = m_pDataList->m_iCurrentY - 22; m_pDataList->m_Keyvalues = m_kvCurrSelected;
for (int i = index; i < vec.Count(); i++) { //move everything down int x, y = 0; vec[i]->GetPos(x, y); vec[i]->SetPos(x, y - 22); }
if (vec.Count() >= m_pDataList->m_iMax) { m_pDataList->OnMouseWheeled(1);
int min, max; m_pDataList->m_pSideSlider->GetRange(min, max); m_pDataList->m_pSideSlider->SetRange(0, max - 1); }
//reset the names of each button int RandomNum = 0; int LoopingNum = 0; int SoundscapeNum = 0;
for (int i = 0; i < vec.Count(); i++) { //store data name const char* name = vec[i]->GetCommand()->GetString("command");
//increment variables based on name if (Q_stristr(name, "$playrandom") == name) { RandomNum++; vec[i]->SetCommand(CFmtStr("$playrandom%d", RandomNum)); }
if (Q_stristr(name, "$playlooping") == name) { LoopingNum++; vec[i]->SetCommand(CFmtStr("$playlooping%d", LoopingNum)); }
if (Q_stristr(name, "$playsoundscape") == name) { SoundscapeNum++; vec[i]->SetCommand(CFmtStr("$playsoundscape%d", SoundscapeNum)); } }
//reset everything m_SoundLevels->SetText(""); m_SoundNameTextEntry->SetText(""); m_TimeTextEntry->SetText(""); m_PitchTextEntry->SetText(""); m_PositionTextEntry->SetText(""); m_VolumeTextEntry->SetText("");
m_SoundLevels->SetEnabled(false); m_SoundNameTextEntry->SetEnabled(false); m_TimeTextEntry->SetEnabled(false); m_PitchTextEntry->SetEnabled(false); m_PositionTextEntry->SetEnabled(false); m_VolumeTextEntry->SetEnabled(false); m_SoundNamePlay->SetEnabled(false);
m_pSoundList->Clear();
m_kvCurrSound = nullptr; m_pSoundList->m_Keyvalues = nullptr; } else if (m_kvCurrSelected) { if (m_KeyValues == m_kvCurrSelected) { //play an error sound vgui::surface()->PlaySound("resource/warning.wav");
//show an error vgui::QueryBox* popup = new vgui::QueryBox("Error", "Can not delete base soundscape!", this); popup->SetOKButtonText("Ok"); popup->SetCancelButtonVisible(false); popup->AddActionSignalTarget(this); popup->DoModal(this);
return; }
//find keyvalue with same pointer and get the index int tmpindex = 0; int index = -1;
KeyValues* prev = nullptr; for (KeyValues* keyvalues = m_KeyValues; keyvalues != nullptr; keyvalues = keyvalues->GetNextTrueSubKey()) { if (m_kvCurrSelected == keyvalues) { //remove it if (!prev) break;
prev->SetNextKey(keyvalues->GetNextTrueSubKey()); keyvalues->SetNextKey(nullptr); keyvalues->deleteThis();
//get index index = tmpindex; break; }
prev = keyvalues;
//increment tmpindex++; }
//error if (index == -1) return;
//store vector auto& vec = m_SoundscapesList->m_MenuButtons;
//remove it delete vec[index]; vec.Remove(index);
//move everything down m_SoundscapesList->m_iCurrentY = m_SoundscapesList->m_iCurrentY - 22;
for (int i = index; i < vec.Count(); i++) { //move everything down int x, y = 0; vec[i]->GetPos(x, y); vec[i]->SetPos(x, y - 22); }
if (vec.Count() >= m_SoundscapesList->m_iMax) { m_SoundscapesList->OnMouseWheeled(1);
int min, max; m_SoundscapesList->m_pSideSlider->GetRange(min, max); m_SoundscapesList->m_pSideSlider->SetRange(0, max - 1); }
//reset everything m_DspEffects->SetText(""); m_SoundLevels->SetText(""); m_TextEntryName->SetText(""); m_SoundNameTextEntry->SetText(""); m_TimeTextEntry->SetText(""); m_PitchTextEntry->SetText(""); m_PositionTextEntry->SetText(""); m_VolumeTextEntry->SetText("");
m_DspEffects->SetEnabled(false); m_SoundLevels->SetEnabled(false); m_TextEntryName->SetEnabled(false); m_SoundNameTextEntry->SetEnabled(false); m_TimeTextEntry->SetEnabled(false); m_PitchTextEntry->SetEnabled(false); m_PositionTextEntry->SetEnabled(false); m_VolumeTextEntry->SetEnabled(false); m_SoundNamePlay->SetEnabled(false);
m_pDataList->Clear(); m_pSoundList->Clear();
m_kvCurrSound = nullptr; m_pDataList->m_Keyvalues = nullptr;
//go to next soundscape if (!prev) return;
if (prev->GetNextTrueSubKey()) OnCommand(prev->GetNextTrueSubKey()->GetName()); else OnCommand(prev->GetName()); }
return; }
//check for "playrandom", "playsoundscape" or "playlooping" if (Q_stristr(pszCommand, "$playrandom") == pszCommand) { //get the selected number char* str_number = (char*)(pszCommand + 11); int number = atoi(str_number); if (number != 0) { //clear the m_pSoundList m_pSoundList->Clear(); m_pSoundList->m_Keyvalues = nullptr;
//store variables KeyValues* data = nullptr; int curr = 0;
//get subkey FOR_EACH_TRUE_SUBKEY(m_kvCurrSelected, sounds) { if (Q_strcasecmp(sounds->GetName(), "playrandom")) continue;
if (++curr == number) { data = sounds; break; } }
//no data if (!data) return;
m_kvCurrSound = data; m_kvCurrRndwave = nullptr;
//set the random times m_TimeTextEntry->SetText(data->GetString("time", "10,20")); m_VolumeTextEntry->SetText(data->GetString("volume", "0.5,0.8")); m_PitchTextEntry->SetText(data->GetString("pitch", "100")); m_PositionTextEntry->SetText(data->GetString("position", "")); m_SoundNameTextEntry->SetText("");
//get snd level index int index = 8; //8 = SNDLVL_NORM const char* name = data->GetString("soundlevel", nullptr);
//check for the name if (name) {
//loop through the sound levels to find the right one for (int i = 0; i < sizeof(g_SoundLevels) / sizeof(g_SoundLevels[i]); i++) { if (!Q_strcmp(name, g_SoundLevels[i])) { index = i; break; } } }
//select the index m_SoundLevels->ActivateItem(index);
//enable the text entries m_TimeTextEntry->SetEnabled(true); m_VolumeTextEntry->SetEnabled(true); m_PitchTextEntry->SetEnabled(true); m_PositionTextEntry->SetEnabled(true); m_SoundLevels->SetEnabled(true); m_SoundNameTextEntry->SetEnabled(false); m_SoundNamePlay->SetEnabled(false);
g_SoundPanel->OnCommand(SOUND_LIST_STOP_COMMAND); g_SoundPanel->SetVisible(false);
//check for randomwave subkey if ((data = data->FindKey("rndwave")) == nullptr) return;
m_kvCurrRndwave = data; m_pSoundList->m_Keyvalues = data;
//add all the data int i = 0; FOR_EACH_VALUE(data, sound) { const char* name = sound->GetName();
m_pSoundList->AddButton(name, sound->GetString(), CFmtStr("$rndwave%d", ++i), this); }
m_iSoundscapeMode = SoundscapeMode::Mode_Random; return; } } else if (Q_stristr(pszCommand, "$playlooping") == pszCommand) { //get the selected number char* str_number = (char*)(pszCommand + 12); int number = atoi(str_number); if (number != 0) { //clear the m_pSoundList m_pSoundList->Clear(); m_pSoundList->m_Keyvalues = nullptr;
//store variables KeyValues* data = nullptr; int curr = 0;
//get subkey FOR_EACH_TRUE_SUBKEY(m_kvCurrSelected, sounds) { if (Q_strcasecmp(sounds->GetName(), "playlooping")) continue;
if (++curr == number) { data = sounds; break; } }
//no data if (!data) return;
m_kvCurrSound = data; m_kvCurrRndwave = nullptr;
//set the random times m_TimeTextEntry->SetText(""); m_VolumeTextEntry->SetText(data->GetString("volume", "1")); m_PitchTextEntry->SetText(data->GetString("pitch", "100")); m_PositionTextEntry->SetText(data->GetString("position", "")); m_SoundNameTextEntry->SetText(data->GetString("wave", ""));
//get snd level index int index = 8; //8 = SNDLVL_NORM const char* name = data->GetString("soundlevel", nullptr);
//check for the name if (name) {
//loop through the sound levels to find the right one for (int i = 0; i < sizeof(g_SoundLevels) / sizeof(g_SoundLevels[i]); i++) { if (!Q_strcmp(name, g_SoundLevels[i])) { index = i; break; } } }
//select the index m_SoundLevels->ActivateItem(index);
//enable the text entries m_TimeTextEntry->SetEnabled(false); m_VolumeTextEntry->SetEnabled(true); m_PitchTextEntry->SetEnabled(true); m_PositionTextEntry->SetEnabled(true); m_SoundLevels->SetEnabled(true); m_SoundNameTextEntry->SetEnabled(true); m_SoundNamePlay->SetEnabled(true); g_SoundPanel->SetVisible(false);
m_iSoundscapeMode = SoundscapeMode::Mode_Looping; return; } } else if (Q_stristr(pszCommand, "$playsoundscape") == pszCommand) { //get the selected number char* str_number = (char*)(pszCommand + 15); int number = atoi(str_number); if (number != 0) { //clear the m_pSoundList m_pSoundList->Clear(); m_pSoundList->m_Keyvalues = nullptr;
//store variables KeyValues* data = nullptr; int curr = 0;
//get subkey FOR_EACH_TRUE_SUBKEY(m_kvCurrSelected, sounds) { if (Q_strcasecmp(sounds->GetName(), "playsoundscape")) continue;
if (++curr == number) { data = sounds; break; } }
//no data if (!data) return;
m_kvCurrSound = data; m_kvCurrRndwave = nullptr;
//set the random times m_TimeTextEntry->SetText(""); m_VolumeTextEntry->SetText(data->GetString("volume", "1")); m_PositionTextEntry->SetText(data->GetString("positionoverride", "")); m_SoundNameTextEntry->SetText(data->GetString("name", "")); m_PitchTextEntry->SetText("");
//get snd level index int index = 8; //8 = SNDLVL_NORM const char* name = data->GetString("soundlevel", nullptr);
//check for the name if (name) {
//loop through the sound levels to find the right one for (int i = 0; i < sizeof(g_SoundLevels) / sizeof(g_SoundLevels[i]); i++) { if (!Q_strcmp(name, g_SoundLevels[i])) { index = i; break; } } }
//select the index m_SoundLevels->ActivateItem(index);
//enable the text entries m_TimeTextEntry->SetEnabled(true); m_VolumeTextEntry->SetEnabled(true); m_PitchTextEntry->SetEnabled(false); m_PositionTextEntry->SetEnabled(true); m_SoundLevels->SetEnabled(true); m_SoundNameTextEntry->SetEnabled(true); m_TimeTextEntry->SetEnabled(false); m_SoundNamePlay->SetEnabled(false);
g_SoundPanel->OnCommand(SOUND_LIST_STOP_COMMAND); g_SoundPanel->SetVisible(false);
m_iSoundscapeMode = SoundscapeMode::Mode_Soundscape; return; } } else if (Q_stristr(pszCommand, "$rndwave") == pszCommand) { if (!m_kvCurrRndwave) return;
//get the selected number char* str_number = (char*)(pszCommand + 8); m_iCurrRndWave = atoi(str_number); if (m_iCurrRndWave != 0) { int i = 0;
//get value KeyValues* curr = nullptr; FOR_EACH_VALUE(m_kvCurrRndwave, wave) { if (++i == m_iCurrRndWave) { curr = wave; break; } }
//if no curr then throw an error if (!curr) { //play an error sound vgui::surface()->PlaySound("resource/warning.wav");
//show error char buf[1028]; Q_snprintf(buf, sizeof(buf), "Failed to get rndwave '%d' for subkey \"%s\"\nfor current soundscape file!", i, m_kvCurrSelected->GetName());
//show an error vgui::QueryBox* popup = new vgui::QueryBox("Error", buf, this); popup->SetOKButtonText("Ok"); popup->SetCancelButtonVisible(false); popup->AddActionSignalTarget(this); popup->DoModal(this); return; }
m_SoundNameTextEntry->SetEnabled(true); m_SoundNameTextEntry->SetText(curr->GetString());
m_SoundNamePlay->SetEnabled(true);
m_iSoundscapeMode = SoundscapeMode::Mode_Random; return; } }
//look for button with the same name as the command { //store vars CUtlVector<vgui::Button*>& array = m_SoundscapesList->m_MenuButtons;
//check for name for (int i = 0; i < m_SoundscapesList->m_MenuButtons.Size(); i++) { //check button name if (!Q_strcmp(array[i]->GetCommand()->GetString("command"), pszCommand)) { //found it m_pCurrentSelected = array[i]; break; } }
//find selected keyvalue
//set needed stuff if (m_pCurrentSelected) { m_DeleteCurrentButton->SetEnabled(false);
//reset the selected kv m_kvCurrSelected = nullptr;
//find selected keyvalues
for (KeyValues* kv = m_KeyValues; kv != nullptr; kv = kv->GetNextTrueSubKey()) { if (!Q_strcmp(kv->GetName(), pszCommand)) { m_kvCurrSelected = kv; break; } }
//set m_kvCurrSound = nullptr; m_kvCurrRndwave = nullptr;
m_TimeTextEntry->SetEnabled(false); m_TimeTextEntry->SetText("");
m_VolumeTextEntry->SetEnabled(false); m_VolumeTextEntry->SetText("");
m_PitchTextEntry->SetEnabled(false); m_PitchTextEntry->SetText("");
m_PositionTextEntry->SetEnabled(false); m_PositionTextEntry->SetText("");
m_SoundLevels->SetEnabled(false); m_SoundLevels->SetText("");
m_SoundNameTextEntry->SetEnabled(false); m_SoundNameTextEntry->SetText("");
m_SoundNamePlay->SetEnabled(false);
if (g_SoundPanel) { g_SoundPanel->OnCommand(SOUND_LIST_STOP_COMMAND); g_SoundPanel->SetVisible(false); }
//check for current keyvalues. should never bee nullptr but could be if (!m_kvCurrSelected) { //play an error sound vgui::surface()->PlaySound("resource/warning.wav");
//show error char buf[1028]; Q_snprintf(buf, sizeof(buf), "Failed to find KeyValue subkey \"%s\"\nfor current soundscape file!", pszCommand);
//show an error vgui::QueryBox* popup = new vgui::QueryBox("Error", buf, this); popup->SetOKButtonText("Ok"); popup->SetCancelButtonVisible(false); popup->AddActionSignalTarget(this); popup->DoModal(this);
//reset vars m_pCurrentSelected = nullptr;
m_TextEntryName->SetEnabled(false); m_TextEntryName->SetText("");
m_DspEffects->SetEnabled(false); m_DspEffects->SetText(""); return; }
if (g_IsPlayingSoundscape) PlaySelectedSoundscape();
m_DeleteCurrentButton->SetEnabled(true);
//set current soundscape name m_TextEntryName->SetText(pszCommand); m_TextEntryName->SetEnabled(true); m_pDataList->m_Keyvalues = m_kvCurrSelected;
//set dsp effect int dsp = Clamp<int>(m_kvCurrSelected->GetInt("dsp"), 0, 29);
m_PlaySoundscapeButton->SetEnabled(true);
m_DspEffects->SetEnabled(true); m_DspEffects->ActivateItem(dsp);
//clear these m_pDataList->Clear(); m_pSoundList->Clear(); m_pSoundList->m_Keyvalues = nullptr;
//set variables int RandomNum = 0; int LoopingNum = 0; int SoundscapeNum = 0;
FOR_EACH_TRUE_SUBKEY(m_kvCurrSelected, data) { //store data name const char* name = data->GetName();
//increment variables based on name if (!Q_strcasecmp(name, "playrandom")) { RandomNum++; m_pDataList->AddButton(data->GetName(), data->GetName(), CFmtStr("$playrandom%d", RandomNum), this); }
if (!Q_strcasecmp(name, "playlooping")) { LoopingNum++; m_pDataList->AddButton(data->GetName(), data->GetName(), CFmtStr("$playlooping%d", LoopingNum), this); }
if (!Q_strcasecmp(name, "playsoundscape")) { SoundscapeNum++; m_pDataList->AddButton(data->GetName(), data->GetName(), CFmtStr("$playsoundscape%d", SoundscapeNum), this); } } } }
BaseClass::OnCommand(pszCommand); }
//----------------------------------------------------------------------------- // Purpose: Function to recursivly write keyvalues to keyvalue files. the keyvalues // class does have a function to do this BUT this function writes every single // item one after another. this function does that but writes the keys // first then the subkeys so the order is good. //----------------------------------------------------------------------------- void RecursivlyWriteKeyvalues(KeyValues* prev, CUtlBuffer& buffer, int& indent) { //write \t indent for (int i = 0; i < indent; i++) buffer.PutChar('\t');
//write name buffer.PutChar('"'); buffer.PutString(prev->GetName()); buffer.PutString("\"\n");
//write { for (int i = 0; i < indent; i++) buffer.PutChar('\t');
buffer.PutString("{\n");
//increment indent indent++;
//write all the keys first FOR_EACH_VALUE(prev, value) { for (int i = 0; i < indent; i++) buffer.PutChar('\t');
//write name and value buffer.PutChar('"'); buffer.PutString(value->GetName()); buffer.PutString("\"\t");
buffer.PutChar('"'); buffer.PutString(value->GetString()); buffer.PutString("\"\n"); }
//write all the subkeys now FOR_EACH_TRUE_SUBKEY(prev, value) { //increment indent RecursivlyWriteKeyvalues(value, buffer, indent);
if (value->GetNextTrueSubKey()) buffer.PutChar('\n'); }
//decrement indent indent--;
//write ending } for (int i = 0; i < indent; i++) buffer.PutChar('\t');
buffer.PutString("}\n"); }
//----------------------------------------------------------------------------- // Purpose: Called when a file gets opened/closed //----------------------------------------------------------------------------- void CSoundscapeMaker::OnFileSelected(const char* pszFileName) { //check for null or empty string if (!pszFileName || pszFileName[0] == '\0') return;
//check for file save if (!m_bWasFileLoad) { //save the file if (m_KeyValues) { //write everything into a buffer CUtlBuffer buf(0, 0, CUtlBuffer::TEXT_BUFFER); buf.PutString("//------------------------------------------------------------------------------------\n"); buf.PutString("//\n"); buf.PutString("// Auto-generated soundscape file created with modbases soundscape tool'\n"); buf.PutString("//\n"); buf.PutString("//------------------------------------------------------------------------------------\n");
//now write the keyvalues KeyValues* pCurrent = m_KeyValues; while (pCurrent) { int indent = 0; RecursivlyWriteKeyvalues(pCurrent, buf, indent); pCurrent = pCurrent->GetNextTrueSubKey();
//put a newline buf.PutChar('\n'); }
if (!g_pFullFileSystem->WriteFile(pszFileName, "MOD", buf)) { //play an error sound vgui::surface()->PlaySound("resource/warning.wav");
//get the error first char buf[1028]; Q_snprintf(buf, sizeof(buf), "Failed to save soundscape to file \"%s\"", pszFileName);
//show an error vgui::QueryBox* popup = new vgui::QueryBox("Error", buf, this); popup->SetOKButtonText("Ok"); popup->SetCancelButtonVisible(false); popup->AddActionSignalTarget(this); popup->DoModal(this); return; } }
//store vars
const char* last = pszFileName;
const char* tmp = nullptr;
//get the last / while ((last = Q_strstr(last, "\\")) != nullptr) tmp = ++last; //move past the backslash
//check tmp if (!tmp || !*tmp) tmp = pszFileName;
//set new title char buf[1028]; Q_snprintf(buf, sizeof(buf), "Soundscape Maker (%s)", tmp);
SetTitle(buf, true);
//create copy of pszFileName char manifest[1028]; Q_strncpy(manifest, pszFileName, sizeof(manifest));
//get last / char* lastSlash = strrchr(manifest, '\\'); if (lastSlash == nullptr || *lastSlash == '\0') return;
//append 'soundscapes_manifest.txt' lastSlash[1] = '\0'; strcat(manifest, "soundscapes_manifest.txt");
//see if we can open manifest file KeyValues* man_file = new KeyValues("manifest"); if (!man_file->LoadFromFile(g_pFullFileSystem, manifest)) { //cant open manifest file man_file->deleteThis(); return; }
//get real filename pszFileName = Q_strrchr(pszFileName, '\\'); if (!pszFileName || !*pszFileName) { man_file->deleteThis(); return; }
pszFileName = pszFileName + 1;
//create name to be added to the manifest file char add_file[1028]; Q_snprintf(add_file, sizeof(add_file), "scripts/%s", pszFileName);
//add filename to manifest file if not found FOR_EACH_VALUE(man_file, value) { if (!Q_strcmp(value->GetString(), add_file)) { man_file->deleteThis(); return; } }
//add to manifest file
KeyValues* kv = new KeyValues("file");
kv->SetString(nullptr, add_file);
man_file->AddSubKey(kv);
//write to file man_file->SaveToFile(g_pFullFileSystem, manifest);
man_file->deleteThis(); return; }
//try and load the keyvalues file first KeyValues* temp = new KeyValues("SoundscapeFile"); if (!temp->LoadFromFile(filesystem, pszFileName)) { //play an error sound vgui::surface()->PlaySound("resource/warning.wav");
//get the error first char buf[1028]; Q_snprintf(buf, sizeof(buf), "Failed to open keyvalues file \"%s\"", pszFileName);
//show an error vgui::QueryBox* popup = new vgui::QueryBox("Error", buf, this); popup->SetOKButtonText("Ok"); popup->SetCancelButtonVisible(false); popup->AddActionSignalTarget(this); popup->DoModal(this);
temp->deleteThis(); return; }
//set the new title { //store vars const char* last = pszFileName; const char* tmp = nullptr;
//get the last / while ((last = Q_strstr(last, "\\")) != nullptr) tmp = ++last; //move past the backslash
//check tmp if (!tmp || !*tmp) tmp = pszFileName;
//create the new new title char buf[1028]; Q_snprintf(buf, sizeof(buf), "Soundscape Maker (%s)", tmp);
SetTitle(buf, true); }
//stop all soundscapes before deleting the old soundscapes m_kvCurrSelected = nullptr;
if (g_IsPlayingSoundscape) PlaySelectedSoundscape();
//delete and set the old keyvalues if (m_KeyValues) m_KeyValues->deleteThis();
m_KeyValues = temp;
//load the file LoadFile(m_KeyValues); }
//----------------------------------------------------------------------------- // Purpose: Called when a text thing changes //----------------------------------------------------------------------------- void CSoundscapeMaker::OnTextChanged(KeyValues* keyvalues) { //check for these things if (!m_pCurrentSelected || !m_kvCurrSelected) return;
//check to see if the current focus is the text text entry if (m_TextEntryName->HasFocus()) { //get text char buf[50]; m_TextEntryName->GetText(buf, sizeof(buf));
//set current text and keyvalue name m_kvCurrSelected->SetName(buf); m_pCurrentSelected->SetText(buf); m_pCurrentSelected->SetCommand(buf); return; }
//set dsp m_kvCurrSelected->SetInt("dsp", Clamp<int>(m_DspEffects->GetActiveItem(), 0, 28));
//if the m_kvCurrSound is nullptr then dont do the rest of the stuff if (!m_kvCurrSound) return;
//set the curr sound and stuff if (m_TimeTextEntry->HasFocus()) { //get text char buf[38]; m_TimeTextEntry->GetText(buf, sizeof(buf));
m_kvCurrSound->SetString("time", buf); return; } else if (m_VolumeTextEntry->HasFocus()) { //get text char buf[38]; m_VolumeTextEntry->GetText(buf, sizeof(buf));
m_kvCurrSound->SetString("volume", buf); return; } else if (m_PitchTextEntry->HasFocus()) { //dont add to soundscaep if (m_iSoundscapeMode == SoundscapeMode::Mode_Soundscape) return;
//get text char buf[38]; m_PitchTextEntry->GetText(buf, sizeof(buf));
m_kvCurrSound->SetString("pitch", buf); return; } else if (m_PositionTextEntry->HasFocus()) { //get text char buf[38]; m_PositionTextEntry->GetText(buf, sizeof(buf));
//if the string is empty then remove the position instead if (!buf[0]) { if (m_iSoundscapeMode == SoundscapeMode::Mode_Soundscape) m_kvCurrSound->RemoveSubKey(m_kvCurrSound->FindKey("positionoverride")); else m_kvCurrSound->RemoveSubKey(m_kvCurrSound->FindKey("position")); } else { if (m_iSoundscapeMode == SoundscapeMode::Mode_Soundscape) m_kvCurrSound->SetString("positionoverride", buf); else m_kvCurrSound->SetString("position", buf);
}
return; }
//get the sound level amount int sndlevel = Clamp<int>(m_SoundLevels->GetActiveItem(), 0, 20); m_kvCurrSound->SetString("soundlevel", g_SoundLevels[sndlevel]);
//set soundscape name/wave if (m_SoundNameTextEntry->HasFocus()) { //get text char buf[512]; m_SoundNameTextEntry->GetText(buf, sizeof(buf));
if (m_iSoundscapeMode == SoundscapeMode::Mode_Looping) m_kvCurrSound->SetString("wave", buf); else if (m_iSoundscapeMode == SoundscapeMode::Mode_Soundscape) m_kvCurrSound->SetString("name", buf); else if (m_iSoundscapeMode == SoundscapeMode::Mode_Random && m_kvCurrRndwave) { //get value int i = 0;
FOR_EACH_VALUE(m_kvCurrRndwave, wave) { if (++i == m_iCurrRndWave) { wave->SetStringValue(buf);
//set text on the sounds panel vgui::Button* button = m_pSoundList->m_MenuButtons[i - 1]; if (button) button->SetText(buf);
break; } } }
return; } }
//----------------------------------------------------------------------------- // Purpose: Destructor for soundscape maker panel //----------------------------------------------------------------------------- void CSoundscapeMaker::LoadFile(KeyValues* file) { //clear all the text's m_TextEntryName->SetEnabled(false); m_TextEntryName->SetText("");
m_DspEffects->SetEnabled(false); m_DspEffects->SetText("");
m_TimeTextEntry->SetEnabled(false); m_TimeTextEntry->SetText("");
m_VolumeTextEntry->SetEnabled(false); m_VolumeTextEntry->SetText("");
m_PitchTextEntry->SetEnabled(false); m_PitchTextEntry->SetText("");
m_PositionTextEntry->SetEnabled(false); m_PositionTextEntry->SetText("");
m_SoundNameTextEntry->SetEnabled(false); m_SoundNameTextEntry->SetText("");
m_SoundNamePlay->SetEnabled(false);
if (g_SoundPanel) { g_SoundPanel->OnCommand(SOUND_LIST_STOP_COMMAND); g_SoundPanel->SetVisible(false); }
m_PlaySoundscapeButton->SetEnabled(false); m_PlaySoundscapeButton->SetSelected(false);
m_ResetSoundscapeButton->SetEnabled(false); m_DeleteCurrentButton->SetEnabled(false);
//clear current file m_pCurrentSelected = nullptr; m_kvCurrSelected = nullptr; m_kvCurrSound = nullptr; m_kvCurrRndwave = nullptr;
//clear the menu items m_SoundscapesList->Clear(); m_pSoundList->Clear(); m_pDataList->Clear();
m_SoundscapesList->m_Keyvalues = file; m_pDataList->m_Keyvalues = nullptr; m_pSoundList->m_Keyvalues = nullptr;
g_IsPlayingSoundscape = false;
//temp soundscapes list CUtlVector<const char*> Added;
//add all the menu items for (KeyValues* soundscape = file; soundscape != nullptr; soundscape = soundscape->GetNextTrueSubKey()) { //add the menu buttons const char* name = soundscape->GetName();
//check for the soundscape first if (Added.Find(name) != Added.InvalidIndex()) { ConWarning("CSoundscapePanel: Failed to add repeated soundscape '%s'\n", name); continue; }
Added.AddToTail(name); m_SoundscapesList->AddButton(name, name, name, this); }
// OnCommand(file->GetName()); }
//----------------------------------------------------------------------------- // Purpose: Sets the sounds text //----------------------------------------------------------------------------- void CSoundscapeMaker::SetSoundText(const char* text) { m_SoundNameTextEntry->SetText(text);
//set soundscape name/wave if (m_iSoundscapeMode != SoundscapeMode::Mode_Random) { m_kvCurrSound->SetString("wave", text); } else { //get value int i = 0;
FOR_EACH_VALUE(m_kvCurrRndwave, wave) { if (++i == m_iCurrRndWave) { wave->SetStringValue(text);
//set text on the sounds panel vgui::Button* button = m_pSoundList->m_MenuButtons[i - 1]; if (button) button->SetText(text);
break; } } }
return; }
//----------------------------------------------------------------------------- // Purpose: Called when a keyboard key is pressed //----------------------------------------------------------------------------- void CSoundscapeMaker::OnKeyCodePressed(vgui::KeyCode code) { //check for ctrl o or ctrl s if (vgui::input()->IsKeyDown(vgui::KeyCode::KEY_LCONTROL)) { if (code == vgui::KeyCode::KEY_O) OnCommand(LOAD_BUTTON_COMMAND); else if (code == vgui::KeyCode::KEY_S) OnCommand(SAVE_BUTTON_COMMAND); else if (code == vgui::KeyCode::KEY_N) OnCommand(NEW_BUTTON_COMMAND);
return; }
//get key bound to this const char* key = engine->Key_LookupBinding("modbase_soundscape_panel"); if (!key) return;
//convert the key to a keyboard code const char* keystring = KeyCodeToString(code);
//remove the KEY_ if found if (Q_strstr(keystring, "KEY_") == keystring) keystring = keystring + 4;
//check both strings if (!Q_strcasecmp(key, keystring)) OnClose(); }
//----------------------------------------------------------------------------- // Purpose: Starts the soundscape on map spawn //----------------------------------------------------------------------------- void CSoundscapeMaker::LevelInitPostEntity() { if (g_IsPlayingSoundscape) PlaySelectedSoundscape(); }
//----------------------------------------------------------------------------- // Purpose: Destructor for soundscape maker panel //----------------------------------------------------------------------------- CSoundscapeMaker::~CSoundscapeMaker() { //delete the keyvalue files if needed if (m_KeyValues) m_KeyValues->deleteThis(); }
//interface class class CSoundscapeMakerInterface : public ISoundscapeMaker { public: void Create(vgui::VPANEL parent) { m_Panel = new CSoundscapeMaker(parent); g_SoundPanel = new CSoundListPanel(parent, "SoundListPanel"); }
void SetVisible(bool bVisible) { if (m_Panel) m_Panel->SetVisible(bVisible); }
void Destroy() { if (m_Panel) m_Panel->DeletePanel();
if (g_SoundPanel) g_SoundPanel->DeletePanel();
m_Panel = nullptr; g_SoundPanel = nullptr; }
void SetSoundText(const char* text) { m_Panel->SetSoundText(text); m_Panel->RequestFocus(); m_Panel->MoveToFront(); } private: CSoundscapeMaker* m_Panel; };
CSoundscapeMakerInterface SoundscapeMaker; ISoundscapeMaker* g_SoundscapeMaker = &SoundscapeMaker;
//----------------------------------------------------------------------------- // Purpose: Command to toggle the soundscape panel //----------------------------------------------------------------------------- CON_COMMAND(modbase_soundscape_panel, "Toggles the modebase soundscape panel") { g_ShowSoundscapePanel = !g_ShowSoundscapePanel; SoundscapeMaker.SetVisible(g_ShowSoundscapePanel); }