Skip to content

Commit

Permalink
Added a voice activity indicator to HUD
Browse files Browse the repository at this point in the history
  • Loading branch information
QuestionableM committed Mar 15, 2024
1 parent 9145f33 commit 85b242f
Show file tree
Hide file tree
Showing 20 changed files with 1,454 additions and 14 deletions.
3 changes: 3 additions & 0 deletions Code/DllGlobals.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "DllGlobals.hpp"

HMODULE DllGlobals::SelfModule = nullptr;
9 changes: 9 additions & 0 deletions Code/DllGlobals.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "win_include.hpp"

class DllGlobals
{
public:
static HMODULE SelfModule;
};
14 changes: 12 additions & 2 deletions Code/PlayerVoiceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "SmSdk/CharacterManager.hpp"
#include "SmSdk/PlayerManager.hpp"
#include "SmSdk/AudioManager.hpp"
#include "SmSdk/MyPlayer.hpp"

#include "Utils/Console.hpp"

Expand Down Expand Up @@ -53,10 +54,19 @@ void PlayerVoiceManager::Update()
PlayerVoiceManager::RemoveDeadVoices();
}

bool is_player_local(Player* pl)
{
MyPlayer* v_player = MyPlayer::GetInstance();
if (!v_player || !v_player->player) return false;

return v_player->player->steam_id == pl->steam_id;
}

void PlayerVoiceManager::UpdatePlayerSound(Player* player)
{
//Players without the characters should not be processed
if (player->character_id == -1) return;
if (player->character_id == -1 || is_player_local(player))
return;

AudioManager* v_aud_mgr = AudioManager::GetInstance();
if (!v_aud_mgr) return;
Expand Down Expand Up @@ -99,7 +109,7 @@ void PlayerVoiceManager::UpdatePlayerSound(Player* player)
v_new_voice->m_pChannel->setMode(FMOD_3D);
v_new_voice->m_pChannel->set3DConeSettings(30.0f, 360.0f, 0.01f);
v_new_voice->m_pChannel->set3DMinMaxDistance(0.01f, 10000.0f);
v_new_voice->m_pChannel->setVolume(200.0f);
v_new_voice->m_pChannel->setVolume(300.0f);
v_new_voice->m_pChannel->setReverbProperties(0, 0.0f);
v_new_voice->m_pChannel->setReverbProperties(1, 0.0f);
v_new_voice->m_pChannel->setReverbProperties(2, 0.0f);
Expand Down
79 changes: 79 additions & 0 deletions Code/Utils/TextureLoader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include "TextureLoader.hpp"

#include "DllGlobals.hpp"

const char* TexLoader::TexLoadResultToString(TexLoader::TexLoadResult load_res)
{
switch (load_res)
{
case TexLoadResult_ResourceNotFound: return "Couldn't find the resource!";
case TexLoadResult_ResourceDataNotFound: return "Couldn't find the resource data!";
case TexLoadResult_FailedToGetImageMemory: return "Failed to get image memory!";
case TexLoadResult_FailedToOpenImageMemory: return "Failed to open image memory!";
case TexLoadResult_FailedToLoadImgFromMemory: return "Failed to load image from memory!";
case TexLoadResult_Success: return "Success";
default: return "UNKNOWN";
}
}

std::uint32_t TexLoader::GetBitsPerPixels(MyGUI::PixelFormat fmt)
{
switch (fmt.getValue())
{
case MyGUI::PixelFormat::Enum::R8G8B8A8:
return 32;
case MyGUI::PixelFormat::Enum::R8G8B8:
return 24;
default:
return 0;
}
}

TexLoader::TexLoadResult TexLoader::LoadTextureFromResource(
FIBITMAP** out_fibitmap,
LPCWSTR resource_name,
LPCWSTR resource_type,
FREE_IMAGE_FORMAT fmt,
MyGUI::PixelFormat pix_fmt)
{
HRSRC v_imgRes = FindResource(DllGlobals::SelfModule, resource_name, resource_type);
if (!v_imgRes) return TexLoadResult_ResourceNotFound;

HGLOBAL v_imgResData = LoadResource(DllGlobals::SelfModule, v_imgRes);
if (!v_imgResData) return TexLoadResult_ResourceDataNotFound;

void* v_imgMem = LockResource(v_imgResData);
if (!v_imgMem) return TexLoadResult_FailedToGetImageMemory;

const DWORD v_imgSize = SizeofResource(DllGlobals::SelfModule, v_imgRes);
FIMEMORY* v_fmem = FreeImage_OpenMemory((BYTE*)v_imgMem, v_imgSize);
if (!v_fmem) return TexLoadResult_FailedToOpenImageMemory;

FIBITMAP* v_img_data = FreeImage_LoadFromMemory(fmt, v_fmem, 0);
FreeImage_CloseMemory(v_fmem);
if (!v_img_data) return TexLoadResult_FailedToLoadImgFromMemory;

if (FreeImage_GetBPP(v_img_data) != TexLoader::GetBitsPerPixels(pix_fmt))
{
FIBITMAP* v_old_img_data = v_img_data;
switch (pix_fmt.getValue())
{
case MyGUI::PixelFormat::Enum::R8G8B8A8:
v_img_data = FreeImage_ConvertTo32Bits(v_img_data);
break;
case MyGUI::PixelFormat::Enum::R8G8B8:
v_img_data = FreeImage_ConvertTo24Bits(v_img_data);
break;
default:
break;
}

if (v_img_data == nullptr)
v_img_data = v_old_img_data;
else if (v_img_data != v_old_img_data)
FreeImage_Unload(v_old_img_data);
}

*out_fibitmap = v_img_data;
return TexLoadResult_Success;
}
29 changes: 29 additions & 0 deletions Code/Utils/TextureLoader.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include "win_include.hpp"

#include <freeimage/FreeImage.h>
#include <MyGUI.h>

namespace TexLoader
{
enum TexLoadResult : std::uint8_t
{
TexLoadResult_Success = 0,
TexLoadResult_ResourceNotFound = 1,
TexLoadResult_ResourceDataNotFound = 2,
TexLoadResult_FailedToGetImageMemory = 3,
TexLoadResult_FailedToOpenImageMemory = 4,
TexLoadResult_FailedToLoadImgFromMemory = 5
};

const char* TexLoadResultToString(TexLoadResult load_res);

std::uint32_t GetBitsPerPixels(MyGUI::PixelFormat fmt);
TexLoadResult LoadTextureFromResource(
FIBITMAP** out_fibitmap,
LPCWSTR resource_name,
LPCWSTR resource_type,
FREE_IMAGE_FORMAT fmt,
MyGUI::PixelFormat pix_fmt = MyGUI::PixelFormat::Enum::R8G8B8A8);
}
84 changes: 84 additions & 0 deletions Code/VoiceManager.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
#include "VoiceManager.hpp"

#include "SmSdk/Gui/GuiSystemManager.hpp"
#include "SmSdk/Gui/InGameGuiManager.hpp"
#include "SmSdk/InputManager.hpp"
#include "SmSdk/GameState.hpp"
#include "SmSdk/MyPlayer.hpp"

#include "Utils/TextureLoader.hpp"
#include "Utils/BufferWriter.hpp"
#include "Utils/BufferReader.hpp"
#include "Utils/Console.hpp"
#include "DllGlobals.hpp"

#include "PlayerVoiceManager.hpp"

#include <steam/steam_api.h>
#include <lz4/lz4.h>

#include "../resource.h"



VoiceManager::fClientPacketHandler VoiceManager::o_clientPacketHandler = nullptr;
VoiceManager::fServerPacketHandler VoiceManager::o_serverPacketHandler = nullptr;
Expand Down Expand Up @@ -135,6 +141,7 @@ void VoiceManager::StartVoiceRecording()
if (!sm_isVoiceRecording)
{
sm_isVoiceRecording = true;
VoiceManager::UpdateSpeakerUiIcon();
SteamUser()->StartVoiceRecording();
}
}
Expand All @@ -144,6 +151,7 @@ void VoiceManager::StopVoiceRecording()
if (sm_isVoiceRecording)
{
sm_isVoiceRecording = false;
VoiceManager::UpdateSpeakerUiIcon();
SteamUser()->StopVoiceRecording();
}
}
Expand Down Expand Up @@ -220,4 +228,80 @@ void VoiceManager::UpdateVoiceRecording()
DebugErrorL("Couldn't send the packet to server host");
}
}
}

////////////////UI FUNCTIONS/////////////////

void VoiceManager::CreateSpeakerImage()
{
MyGUI::RenderManager* v_rend_mgr = MyGUI::RenderManager::getInstancePtr();
if (v_rend_mgr->getTexture("SpeakerIcon"))
return;

MyGUI::ITexture* v_new_tex = v_rend_mgr->createTexture("SpeakerIcon");
FIBITMAP* v_fibitmap;

TexLoader::TexLoadResult v_res = TexLoader::LoadTextureFromResource(&v_fibitmap, MAKEINTRESOURCE(IDB_PNG1), L"PNG", FIF_PNG);
if (v_res != TexLoader::TexLoadResult_Success)
{
AttachDebugConsole();
DebugErrorL(TexLoader::TexLoadResultToString(v_res));
return;
}

const int v_img_width = int(FreeImage_GetWidth(v_fibitmap));
const int v_img_height = int(FreeImage_GetHeight(v_fibitmap));
BYTE* v_img_bits = FreeImage_GetBits(v_fibitmap);

v_new_tex->createManual(v_img_width, v_img_height,
MyGUI::TextureUsage::Write | MyGUI::TextureUsage::Static, MyGUI::PixelFormat::R8G8B8A8);
void* v_img_mem = v_new_tex->lock(MyGUI::TextureUsage::Write);
std::memcpy(v_img_mem, v_img_bits, v_img_width * v_img_height * 4);
v_new_tex->unlock();

FreeImage_Unload(v_fibitmap);
}

MyGUI::ImageBox* VoiceManager::GetSpeakerImageBox(MyGUI::Widget* main_panel)
{
MyGUI::Widget* v_widget = main_panel->findWidget("SpeakerIcon");
if (v_widget)
{
if (v_widget->isType<MyGUI::ImageBox>())
return v_widget->castType<MyGUI::ImageBox>();

return nullptr;
}

VoiceManager::CreateSpeakerImage();
MyGUI::ImageBox* v_new_img_box = main_panel->createWidgetReal<MyGUI::ImageBox>(
"ImageBox", MyGUI::FloatCoord(0.0f, 0.0f, 0.0f, 0.0f), MyGUI::Align::Default, "SpeakerIcon")->castType<MyGUI::ImageBox>();

v_new_img_box->setVisible(false);
v_new_img_box->setImageTexture("SpeakerIcon");

return v_new_img_box;
}

void VoiceManager::UpdateSpeakerUiIcon()
{
InGameGuiManager* v_gui_mgr = InGameGuiManager::GetInstance();
if (!v_gui_mgr || !v_gui_mgr->m_pHudGui) return;

MyGUI::ImageBox* v_speaker_icon = VoiceManager::GetSpeakerImageBox(v_gui_mgr->m_pHudGui->m_pMainPanel);
if (!v_speaker_icon) return;

MyGUI::Widget* v_main_panel = v_gui_mgr->m_pHudGui->m_pMainPanel;
const float v_aspect_ratio = float(v_main_panel->getWidth()) / float(v_main_panel->getHeight());
const int v_icon_sz = int(50.0f * v_aspect_ratio);
const int v_icon_spacing = int(20.0f * v_aspect_ratio);

v_speaker_icon->setSize(v_icon_sz, v_icon_sz);

v_speaker_icon->setPosition(MyGUI::IntPoint(
v_main_panel->getWidth() - v_speaker_icon->getWidth() - v_icon_spacing,
(v_main_panel->getHeight() - v_speaker_icon->getHeight()) / 2
));

v_speaker_icon->setVisible(VoiceManager::sm_isVoiceRecording);
}
8 changes: 8 additions & 0 deletions Code/VoiceManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "SmSdk/Network/NetworkServer.hpp"

#include <MyGUI.h>

#include <cstddef>
#include <cstdint>

Expand Down Expand Up @@ -49,6 +51,12 @@ class VoiceManager
static void StopVoiceRecording();
static void UpdateVoiceRecording();

////UI FUNCTIONS

static void CreateSpeakerImage();
static MyGUI::ImageBox* GetSpeakerImageBox(MyGUI::Widget* main_panel);
static void UpdateSpeakerUiIcon();

private:
static bool sm_isVoiceRecording;
};
7 changes: 5 additions & 2 deletions Code/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "Utils/BufferWriter.hpp"
#include "Utils/BufferReader.hpp"
#include "Utils/Console.hpp"
#include "DllGlobals.hpp"

#include "PlayerVoiceManager.hpp"
#include "VoiceManager.hpp"
Expand Down Expand Up @@ -32,8 +33,10 @@ static void h_perframeUpdate(void* a1, float dt, void* a3, void* a4, void* pFram
o_perframeUpdate(a1, dt, a3, a4, pFrameSettings);
}

static void process_attach()
static void process_attach(HMODULE hMod)
{
DllGlobals::SelfModule = hMod;

AttachDebugConsole();

if (MH_Initialize() != MH_OK)
Expand Down Expand Up @@ -74,7 +77,7 @@ BOOL APIENTRY DllMain(
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
process_attach();
process_attach(hModule);
break;
case DLL_PROCESS_DETACH:
process_detach(hModule);
Expand Down
Binary file added Dependencies/FreeImage/DLL/x64/FreeImage.dll
Binary file not shown.
Binary file added Dependencies/FreeImage/DLL/x64/FreeImage.lib
Binary file not shown.
Binary file added Dependencies/FreeImage/DLL/x86/FreeImage.dll
Binary file not shown.
Binary file added Dependencies/FreeImage/DLL/x86/FreeImage.lib
Binary file not shown.
Loading

0 comments on commit 85b242f

Please sign in to comment.