@@ -4,7 +4,6 @@
#include "NewChat.h"
#include "ZConfiguration.h"
#include "Hitboxes.h"
#include "Draw.h"
#include "ZRule.h"
#include "ZRuleSkillmap.h"
#include "VoiceChat.h"
@@ -16,6 +15,7 @@
#include "MeshManager.h"
#include "hsv.h"
#include "dxerr.h"
#include "defer.h"

#define DXERR(func) DXErr(func, __func__, #func)

@@ -49,8 +49,6 @@ void RGMain::OnCreateDevice()
m_Chat.Construct("Arial", 16);
m_Chat.Get().SetBackgroundColor(ZGetConfiguration()->GetChatBackgroundColor());

g_Draw.OnCreateDevice();

#ifdef VOICECHAT
m_VoiceChat.OnCreateDevice();
#endif
@@ -69,14 +67,14 @@ void RGMain::OnDrawGameInterface(MDrawContext* pDC)
m_HitboxManager.Draw();

#ifdef VOICECHAT
m_VoiceChat.Draw();
m_VoiceChat.OnDraw(pDC);
#endif

if (NewChatEnabled)
GetChat().OnDraw(pDC);

if (ZGetGame()->IsReplay())
g_ReplayControl.Draw();
g_ReplayControl.OnDraw(pDC);
}

bool RGMain::OnGameInput()
@@ -282,34 +280,35 @@ bool RGMain::OnEvent(MEvent *pEvent)
return ret;
}

void RGMain::OnReset()
{
g_Draw.OnReset();
}
void RGMain::OnReset() {}
void RGMain::OnDrawLobby(MDrawContext* pDC) {}

void RGMain::OnInitInterface(ZIDLResource &IDLResource)
struct CustomReplayFrame : MWidget
{
}
using MWidget::MWidget;

void OnDraw(MDrawContext* pDC) override
{
GetRGMain().DrawReplayInfo(pDC, this);
}
};

void RGMain::OnDrawLobby()
void RGMain::OnInitInterface(ZIDLResource &IDLResource)
{
// Create a new widget and attach it as a child to the ReplayGroup widget
// in order to have our own custom draw code run in its OnDraw callback.
auto ReplayWidget = IDLResource.FindWidget("ReplayGroup");
auto Widget = new CustomReplayFrame{ "CustomReplayFrame", ReplayWidget };
// m_Rect controls the area that is drawn to in OnDraw so we need to set it properly.
// This is roughly the right part of the replay window.
Widget->m_Rect = MRECT{ 310, 50, 290, 245 };
}

void RGMain::OnReplaySelected()
void RGMain::OnReplaySelected(MListBox* ReplayFileListWidget)
{
SelectedReplayInfo.PlayerInfos.clear();

ZIDLResource* pResource = ZApplication::GetGameInterface()->GetIDLResource();

auto ReplayWidget = pResource->FindWidget("Replay");

if (!ReplayWidget->IsVisible())
return;

auto ReplayFileList = (MListBox *)pResource->FindWidget("Replay_FileList");

auto SelectedReplay = ReplayFileList->GetSelItem();

auto SelectedReplay = ReplayFileListWidget->GetSelItem();
if (!SelectedReplay)
return;

@@ -414,25 +413,11 @@ void RGMain::OnReplaySelected()
}
}

void RGMain::DrawReplayInfo() const
void RGMain::DrawReplayInfo(MDrawContext* pDC, MWidget* Widget) const
{
extern MFontR2 *g_pDefFont;

ZIDLResource* pResource = ZApplication::GetGameInterface()->GetIDLResource();

auto ReplayWidget = pResource->FindWidget("Replay");
if (!ReplayWidget->IsVisible())
return;
v2 Offset{ 0, 0 };

auto ReplayFileList = (MListBox *)pResource->FindWidget("Replay_FileList");
if (!ReplayFileList->GetSelItem())
return;

auto ReplayGroupWidget = pResource->FindWidget("ReplayGroup");
auto Offset = ReplayGroupWidget->GetPosition();

Offset.x += 310;
Offset.y += 50;
pDC->SetColor(ARGB(255, 255, 255, 255));

auto Print = [&](const char *Format, ...)
{
@@ -444,7 +429,7 @@ void RGMain::DrawReplayInfo() const
int ret = _vsnprintf_s(buf, sizeof(buf) - 1, Format, args);
va_end(args);

g_pDefFont->m_Font.DrawTextA(Offset.x, Offset.y, buf);
pDC->Text(Offset.x, Offset.y, buf);

Offset.y += 12;
};
@@ -468,8 +453,8 @@ void RGMain::DrawReplayInfo() const
return;

auto Bitmap = it->second;
((MBitmapR2 *)Bitmap->GetSourceBitmap())->Draw(Offset.x, Offset.y, 260, 30,
Bitmap->GetX(), Bitmap->GetY(), Bitmap->GetWidth(), Bitmap->GetHeight(), 0xFFFFFFFF);
pDC->SetBitmap(Bitmap);
pDC->Draw(Offset.x, Offset.y, 260, 30);

Offset.y += 30;
}();
@@ -510,11 +495,6 @@ void RGMain::DrawReplayInfo() const
}
}

void RGMain::OnRender()
{
DrawReplayInfo();
}

std::pair<bool, uint32_t> RGMain::GetPlayerSwordColor(const MUID& UID)
{
auto it = SwordColors.find(UID);
@@ -59,15 +59,14 @@ class RGMain
bool OnEvent(MEvent *pEvent);
void OnReset();
void OnInitInterface(ZIDLResource &IDLResource);
void OnReplaySelected();
void OnReplaySelected(MListBox* ReplayFileListWidget);
void OnCreateDevice();
void OnAppCreate();
#ifdef VOICECHAT
auto MutePlayer(const MUID& UID) { return m_VoiceChat.MutePlayer(UID); }
#endif

void OnDrawLobby();
void OnRender();
void OnDrawLobby(MDrawContext* pDC);
void OnDrawGame();
void OnDrawGameInterface(MDrawContext* pDC);
void OnGameCreate();
@@ -103,11 +102,11 @@ class RGMain
const Chat& GetChat() const { return m_Chat.Get(); }
bool IsNewChatEnabled() const { return NewChatEnabled; }

void DrawReplayInfo(MDrawContext* pDC, MWidget* Widget) const;

private:
friend void LoadRGCommands(ZChatCmdManager& CmdManager);

void DrawReplayInfo() const;

double Time = 0;
double LastTime = 0;

@@ -1,60 +1,76 @@
#include "stdafx.h"
#include "ReplayControl.h"
#include "RGMain.h"
#include "Draw.h"
#include "NewChat.h"

ReplayControl g_ReplayControl;

void ReplayControl::Draw()
static void DrawBorder(MDrawContext* pDC, v2 p1, v2 p2)
{
v2 vs[] = {
{ float(p1.x), float(p1.y) },
{ float(p2.x), float(p1.y) },
{ float(p2.x), float(p2.y) },
{ float(p1.x), float(p2.y) },
};

for (size_t i = 0; i < std::size(vs); i++)
{
auto a = vs[i];
auto b = vs[(i + 1) % std::size(vs)];
pDC->Line(a.x, a.y, b.x, b.y);
}
}

void ReplayControl::OnDraw(MDrawContext* pDC)
{
if (!ZGetGame()->IsReplay())
return;

if (!GetRGMain().GetChat().IsInputEnabled())
return;

D3DXVECTOR2 v1, v2;
v1.x = RELWIDTH(1920.f / 2 - 220);
v1.y = RELHEIGHT(830);
v2.x = RELWIDTH(1920.f / 2 + 220);
v2.y = RELHEIGHT(870);
pDC->SetColor(CHAT_DEFAULT_INTERFACE_COLOR);

v2 p1, p2;
p1.x = RELWIDTH(1920.f / 2 - 220);
p1.y = RELHEIGHT(830);
p2.x = RELWIDTH(1920.f / 2 + 220);
p2.y = RELHEIGHT(870);

g_Draw.Border(v1, v2);
DrawBorder(pDC, p1, p2);

v1.x = RELWIDTH(1920.f / 2 - 170);
v1.y = RELHEIGHT(850);
v2.x = RELWIDTH(1920.f / 2 + 170);
v2.y = RELHEIGHT(850);
p1.x = RELWIDTH(1920.f / 2 - 170);
p1.y = RELHEIGHT(850);
p2.x = RELWIDTH(1920.f / 2 + 170);
p2.y = RELHEIGHT(850);

g_Draw.Line(v1, v2);
pDC->Line(p1.x, p1.y, p2.x, p2.y);

float ReplayTime = ZGetGame()->GetReplayTime();
float ReplayLength = ZGetGame()->GetReplayLength();

float Index = ReplayTime / ReplayLength;

v1.x = RELWIDTH(1920.f / 2 - 170 + Index * 340 - 5);
v1.y = RELHEIGHT(835);
v2.x = RELWIDTH(1920.f / 2 - 170 + Index * 340 + 5);
v2.y = RELHEIGHT(865);
p1.x = RELWIDTH(1920.f / 2 - 170 + Index * 340 - 5);
p1.y = RELHEIGHT(835);
p2.x = RELWIDTH(1920.f / 2 - 170 + Index * 340 + 5);
p2.y = RELHEIGHT(865);

g_Draw.Quad(v1, v2);
pDC->FillRectangle(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);

char buf[64];

sprintf_safe(buf, "%02d:%02d", int(ReplayTime / 60), int(fmod(ReplayTime, 60)));

extern MFontR2 *g_pDefFont;
g_pDefFont->m_Font.DrawTextA(RELWIDTH(1920.f / 2 - 215), RELHEIGHT(835), buf);
pDC->Text(RELWIDTH(1920.f / 2 - 215), RELHEIGHT(835), buf);

sprintf_safe(buf, "%02d:%02d", int(ReplayLength / 60), int(fmod(ReplayLength, 60)));

extern MFontR2 *g_pDefFont;
g_pDefFont->m_Font.DrawTextA(RELWIDTH(1920.f / 2 + 185), RELHEIGHT(835), buf);
pDC->Text(RELWIDTH(1920.f / 2 + 185), RELHEIGHT(835), buf);
}

bool CursorInRange(const POINT &Cursor, int x1, int y1, int x2, int y2){
static bool CursorInRange(const POINT &Cursor, int x1, int y1, int x2, int y2){
return Cursor.x > x1 && Cursor.x < x2 && Cursor.y > y1 && Cursor.y < y2;
}

@@ -4,7 +4,7 @@
class ReplayControl
{
public:
void Draw();
void OnDraw(MDrawContext* pDC);
bool OnEvent(MEvent *pEvent);
private:
};
@@ -1,7 +1,6 @@
#include "stdafx.h"
#include "VoiceChat.h"
#include "RGMain.h"
#include "Draw.h"

#ifdef VOICECHAT

@@ -396,35 +395,37 @@ int VoiceChat::PlayCallback(const void *inputBuffer, void *outputBuffer,

void VoiceChat::OnCreateDevice()
{
SpeakerTexture = RBaseTexturePtr{ RCreateBaseTexture("Interface/default/SpeakerIcon.png") };
if (!SpeakerTexture)
auto Success = SpeakerBitmap.Create("SpeakerIcon", RGetDevice(), "Interface/default/SpeakerIcon.png");
if (!Success)
MLog("Failed to create speaker icon texture\n");
}

void VoiceChat::Draw()
void VoiceChat::OnDraw(MDrawContext* pDC)
{
int i = 0;

auto DrawStuff = [&](ZCharacter* Player)
{
D3DXVECTOR2 TopLeft(RELWIDTH(1920 - 400), RELHEIGHT(1080 / 2 + i * 100));
D3DXVECTOR2 Extents(RELWIDTH(300), RELHEIGHT(50));
v2 TopLeft{ float(RELWIDTH(1920 - 400)), float(RELHEIGHT(1080 / 2 + i * 100)) };
v2 Extents{ float(RELWIDTH(300)), float(RELHEIGHT(50)) };

auto color = Player->GetTeamID() == MMT_BLUE ? 0xC000A5C3 : 0xC0FF0000;

g_Draw.Quad(TopLeft, TopLeft + Extents, color);
pDC->SetColor(color);
pDC->FillRectangle(TopLeft.x, TopLeft.y, Extents.x, Extents.y);

D3DXVECTOR2 TextOffset(RELWIDTH(50), RELHEIGHT(10));
v2 TextOffset{ float(RELWIDTH(50)), float(RELHEIGHT(10)) };

auto v = TopLeft + TextOffset;

g_Draw.Text(Player->GetUserName(), v.x, v.y);
pDC->SetColor(ARGB(255, 255, 255, 255));
pDC->Text(v.x, v.y, Player->GetUserName());

D3DXVECTOR2 SpeakerIconOrigin = TopLeft + D3DXVECTOR2(RELWIDTH(10), RELHEIGHT(10));
D3DXVECTOR2 SpeakerIconExtents(RELWIDTH(30), RELHEIGHT(30));
auto SpeakerIconOrigin = TopLeft + v2{ float(RELWIDTH(10)), float(RELHEIGHT(10)) };
v2 SpeakerIconExtents{ float(RELWIDTH(30)), float(RELHEIGHT(30)) };

g_Draw.TexturedQuad(SpeakerIconOrigin, SpeakerIconOrigin + SpeakerIconExtents,
SpeakerTexture.get()->GetTexture());
pDC->SetBitmap(&SpeakerBitmap);
pDC->Draw(SpeakerIconOrigin.x, SpeakerIconOrigin.y, SpeakerIconExtents.x, SpeakerIconExtents.y);

i++;
};
@@ -32,7 +32,7 @@ class VoiceChat

bool MutePlayer(const MUID& UID);

void Draw();
void OnDraw(MDrawContext* pDC);

static constexpr int SampleRate = 48000;
static constexpr int FrameSize = static_cast<int>(SampleRate * 0.06); // 60 ms
@@ -110,6 +110,6 @@ class VoiceChat
std::unordered_map<ZCharacter*, MicStuff> MicStreams;
std::unordered_set<MUID> MutedPlayers;

RBaseTexturePtr SpeakerTexture;
MBitmapR2 SpeakerBitmap;
};
#endif
@@ -2374,7 +2374,7 @@ void ZGameInterface::OnDraw(MDrawContext *pDC)
{
OnDrawStateLobbyNStage(pDC);
if(GetState() == GUNZ_LOBBY)
GetRGMain().OnDrawLobby();
GetRGMain().OnDrawLobby(pDC);
}
break;
case GUNZ_CHARSELECTION:
@@ -4200,7 +4200,7 @@ static void HideShopOrEquipmentDialog(bool Shop)
ZPostStageState(ZGetGameClient()->GetPlayerUID(), ZGetGameClient()->GetStageUID(), MOSS_NONREADY);

// Hide the shop or equipment widget.
MWidget* pWidget = GetZIDLResource()->FindWidget(Shop ? "Shop" : "Equipment");
MWidget* pWidget = ZGetIDLResource()->FindWidget(Shop ? "Shop" : "Equipment");
if (pWidget)
pWidget->Show(false);

@@ -375,6 +375,6 @@ class ZGameInterface : public ZInterface {

void ZChangeGameState(GunzState state);

inline ZIDLResource* GetZIDLResource() {
inline ZIDLResource* ZGetIDLResource() {
return ZGetGameInterface()->GetIDLResource();
}
@@ -2039,7 +2039,7 @@ MListener* ZGetReplayFileListBoxListener( void)
if (pFindWidget != NULL)
pFindWidget->Enable(true);

GetRGMain().OnReplaySelected();
GetRGMain().OnReplaySelected(static_cast<MListBox*>(pWidget));

return true;
}
@@ -417,8 +417,6 @@ RRESULT OnRender(void *pParam)
#endif
}

GetRGMain().OnRender();

MEndProfile(mainOnRender);

return R_OK;