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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 74 additions & 4 deletions Client/core/CChat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ CChat::CChat(CGUI* pManager, const CVector2D& vecPosition)
m_bVisible = false;
m_bInputBlocked = false;
m_bInputVisible = false;
m_bInputPreview = false;
m_pFont = m_pManager->GetClearFont();
m_pDXFont = NULL;
SetDxFont(g_pCore->GetGraphics()->GetFont());
Expand Down Expand Up @@ -146,13 +147,35 @@ void CChat::LoadCVars()
CVARS_GET("chat_position_horizontal", (unsigned int&)m_ePositionHorizontal);
CVARS_GET("chat_position_vertical", (unsigned int&)m_ePositionVertical);
CVARS_GET("chat_text_alignment", (unsigned int&)m_eTextAlign);

if (m_bInputPreview)
SetInputText(m_strInputText.c_str());
}

//
// Draw
//
void CChat::Draw(bool bUseCacheTexture, bool bAllowOutline)
void CChat::Draw(bool bUseCacheTexture, bool bAllowOutline, const CRect2D* pClipRect)
{
auto SetScissor = [](bool bEnabled, const CRect2D* pRect)
{
IDirect3DDevice9* pDevice = g_pCore->GetGraphics()->GetDevice();
if (bEnabled)
{
RECT rect;
rect.left = static_cast<LONG>(std::max(0.0f, pRect->fX1));
rect.top = static_cast<LONG>(std::max(0.0f, pRect->fY1));
rect.right = static_cast<LONG>(std::max(0.0f, pRect->fX2));
rect.bottom = static_cast<LONG>(std::max(0.0f, pRect->fY2));
pDevice->SetScissorRect(&rect);
pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
}
else
{
pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
}
};

// Are we visible and is input blocked?
if (!m_bVisible && m_bInputBlocked)
return;
Expand All @@ -166,8 +189,15 @@ void CChat::Draw(bool bUseCacheTexture, bool bAllowOutline)
}

bool bUsingOutline = m_bTextBlackOutline && bAllowOutline && bUseCacheTexture;

if (pClipRect)
SetScissor(true, pClipRect);

DrawInputLine(bUsingOutline);

if (pClipRect)
SetScissor(false, nullptr);

if (m_bInputVisible)
{
// ChrML: Hack so chatbox input always works. It might get unfocused..
Expand All @@ -181,10 +211,18 @@ void CChat::Draw(bool bUseCacheTexture, bool bAllowOutline)
if (!m_bVisible)
return;

// Get drawList for the chat box text
// Get drawList for the chat box text. The background box is rendered inside GetDrawList, so it must be scissored as well, otherwise it would cover the
// settings window and the text drawn by the other clipped draw calls
SDrawList drawList;

if (pClipRect)
SetScissor(true, pClipRect);

GetDrawList(drawList, bUsingOutline);

if (pClipRect)
SetScissor(false, nullptr);

// Calc some size info
CVector2D chatTopLeft(drawList.renderBounds.fX1, drawList.renderBounds.fY1);
CVector2D chatBotRight(drawList.renderBounds.fX2, drawList.renderBounds.fY2);
Expand All @@ -194,7 +232,14 @@ void CChat::Draw(bool bUseCacheTexture, bool bAllowOutline)
// If we are not using a cache texture, just render the text directly to the screen
if (!bUseCacheTexture)
{
if (pClipRect)
SetScissor(true, pClipRect);

DrawDrawList(drawList, chatTopLeft);

if (pClipRect)
SetScissor(false, nullptr);

return;
}

Expand Down Expand Up @@ -234,7 +279,15 @@ void CChat::Draw(bool bUseCacheTexture, bool bAllowOutline)
if (!m_pCacheTexture)
{
drawList.bOutline = false; // Outline too slow without cache texture

if (pClipRect)
SetScissor(true, pClipRect);

DrawDrawList(drawList, chatTopLeft);

if (pClipRect)
SetScissor(false, nullptr);

return;
}

Expand All @@ -255,9 +308,13 @@ void CChat::Draw(bool bUseCacheTexture, bool bAllowOutline)
}

// Draw the cache texture
if (pClipRect)
SetScissor(true, pClipRect);
pGraphics->SetBlendMode(EBlendMode::ADD);
pGraphics->DrawTexture(m_pCacheTexture, chatTopLeft.fX, chatTopLeft.fY);
pGraphics->SetBlendMode(EBlendMode::BLEND);
if (pClipRect)
SetScissor(false, nullptr);
}

//
Expand Down Expand Up @@ -381,7 +438,7 @@ void CChat::DrawInputLine(bool bUsingOutline)
}
}

if (m_bInputVisible)
if (m_bInputVisible || m_bInputPreview)
{
float fLineDifference = CChat::GetFontHeight(m_vecScale.fY);
bool bInputShadow = (m_InputColor.A * m_fInputBackgroundAlpha == 0.f) && !bUsingOutline;
Expand Down Expand Up @@ -479,7 +536,7 @@ void CChat::UpdateSmoothScroll(float* pfPixelScroll, int* piLineScroll)
//
// Also update input background alpha
//
fTarget = (m_bInputVisible) ? 1.0f : 0.0f;
fTarget = (m_bInputVisible || m_bInputPreview) ? 1.0f : 0.0f;
fMaxAmount = fDeltaSeconds * 5.0f; // 0.2 seconds fade time
m_fInputBackgroundAlpha += Clamp(-fMaxAmount, fTarget - m_fInputBackgroundAlpha, fMaxAmount);
}
Expand Down Expand Up @@ -857,6 +914,16 @@ void CChat::SetInputVisible(bool bVisible)
m_bInputVisible = bVisible;
}

void CChat::SetInputPreview(const char* szText)
{
m_bInputPreview = (szText != nullptr);

if (m_bInputPreview)
SetInputText(szText);
else
ClearInput();
}

void CChat::SetNumLines(unsigned int uiNumLines)
{
if (uiNumLines <= CHAT_MAX_LINES)
Expand Down Expand Up @@ -1318,6 +1385,9 @@ void CChatInputLine::Draw(CVector2D& position, unsigned char alpha, bool shadow,

if (g_pChat->m_InputTextColor.A > 0 && m_Sections.size() > 0)
{
for (auto& section : m_Sections)
section.SetColor(g_pChat->m_InputTextColor);

m_Sections[0].Draw(CVector2D(position.fX + m_Prefix.GetWidth(), position.fY), g_pChat->m_InputTextColor.A, shadow, outline, renderBounds);

float lineDifference = CChat::GetFontHeight(g_pChat->m_vecScale.fY);
Expand Down
5 changes: 4 additions & 1 deletion Client/core/CChat.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class CChat
CChat(CGUI* pManager, const CVector2D& vecPosition);
virtual ~CChat();

virtual void Draw(bool bUseCacheTexture, bool bAllowOutline);
virtual void Draw(bool bUseCacheTexture, bool bAllowOutline, const CRect2D* pClipRect = nullptr);
virtual void Output(const char* szText, bool bColorCoded = true);
void Clear();
void ClearInput();
Expand All @@ -173,6 +173,8 @@ class CChat
bool IsInputVisible() const { return !m_bInputBlocked && m_bInputVisible; }
void SetInputVisible(bool bVisible);

void SetInputPreview(const char* szText);

bool CanTakeInput() { return !CLocalGUI::GetSingleton().GetConsole()->IsVisible() && IsInputVisible(); };

void ResetHistoryChanges();
Expand Down Expand Up @@ -270,6 +272,7 @@ class CChat
bool m_bVisible;
bool m_bInputBlocked;
bool m_bInputVisible;
bool m_bInputPreview;
int m_iScrollingBack; // Non zero if currently scrolling back
float m_fCssStyleOverrideAlpha; // For fading out 'CssStyle' effect. (When entering text or scrolling back)
float m_fBackgroundAlpha;
Expand Down
14 changes: 14 additions & 0 deletions Client/core/CConsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,20 @@ CVector2D CConsole::GetPosition()
return CVector2D();
}

void CConsole::GetWindowRect(CRect2D& outRect)
{
if (m_pWindow)
{
CVector2D vecPosition = m_pWindow->GetPosition(false);
CVector2D vecSize = m_pWindow->GetSize(false);
outRect = CRect2D(vecPosition.fX, vecPosition.fY, vecPosition.fX + vecSize.fX, vecPosition.fY + vecSize.fY);
}
else
{
outRect = CRect2D();
}
}

void CConsole::SetPosition(CVector2D& vecPosition)
{
if (m_pWindow)
Expand Down
1 change: 1 addition & 0 deletions Client/core/CConsole.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class CConsole : public CConsoleInterface
void ResetAutoCompleteMatch();

CVector2D GetPosition();
void GetWindowRect(CRect2D& outRect);
void SetPosition(CVector2D& vecPosition);

CVector2D GetSize();
Expand Down
110 changes: 104 additions & 6 deletions Client/core/CGUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,21 +482,41 @@ void CLocalGUI::Draw()
// Update mainmenu stuff
m_pMainMenu->Update();

// If we're ingame, make sure the chatbox is drawn
bool bChatVisible =
(systemState == SystemState::GS_PLAYING_GAME && m_pMainMenu->GetIsIngame() && m_bChatboxVisible && !CCore::GetSingleton().IsOfflineMod());
if (m_pChat->IsVisible() != bChatVisible)
m_pChat->SetVisible(bChatVisible, !bChatVisible);
// If we're ingame, make sure the chatbox is drawn. Also show it as a preview while the chatbox settings are open (Interface tab), so its appearance can be
// adjusted without having to join a server.
bool bIsIngame = systemState == SystemState::GS_PLAYING_GAME && m_pMainMenu->GetIsIngame() && !CCore::GetSingleton().IsOfflineMod();
bool bChatPreview = m_pMainMenu->GetSettingsWindow()->IsChatTabVisible();
bool bChatVisible = (bIsIngame && m_bChatboxVisible) || bChatPreview;

bool bChatInputBlocked = !bChatVisible || bChatPreview;

if (m_pChat->IsVisible() != bChatVisible || m_pChat->IsInputBlocked() != bChatInputBlocked)
m_pChat->SetVisible(bChatVisible, bChatInputBlocked);

if (bChatPreview && !m_bChatInputPreviewActive)
{
m_pChat->SetInputPreview("Your message here...");
m_bChatInputPreviewActive = true;
}
else if (!bChatPreview && m_bChatInputPreviewActive)
{
m_pChat->SetInputPreview(nullptr);
m_bChatInputPreviewActive = false;
}

bool bDebugVisible =
(systemState == SystemState::GS_PLAYING_GAME && m_pMainMenu->GetIsIngame() && m_pDebugViewVisible && !CCore::GetSingleton().IsOfflineMod());

if (m_pDebugView->IsVisible() != bDebugVisible)
m_pDebugView->SetVisible(bDebugVisible, true);

// Make sure the cursor is displayed only when needed
UpdateCursor();

// Draw the chat
m_pChat->Draw(true, true);
if (!bChatPreview)
m_pChat->Draw(true, true);

// Draw the debugger
m_pDebugView->Draw(true, false);

Expand All @@ -516,6 +536,84 @@ void CLocalGUI::Draw()
bDelayedFrame = true;
}
}

if (bChatPreview)
{
const CVector2D resolution = pGUI ? pGUI->GetResolution() : CVector2D(0.0f, 0.0f);
const float fScreenWidth = resolution.fX;
const float fScreenHeight = resolution.fY;

std::vector<CRect2D> clipRects;
clipRects.emplace_back(0.0f, 0.0f, fScreenWidth, fScreenHeight);

std::vector<CRect2D> cutoutRects;
m_pMainMenu->GetSettingsWindow()->GetWindowRect(cutoutRects.emplace_back());
if (CConsole* console = GetConsole(); console->IsVisible())
console->GetWindowRect(cutoutRects.emplace_back());

for (const CRect2D& cutout : cutoutRects)
{
std::vector<CRect2D> splitRects;

for (const CRect2D& rect : clipRects)
{
const CRect2D parts[] = {
{rect.fX1, rect.fY1, rect.fX2, std::min(rect.fY2, cutout.fY1)},
{rect.fX1, std::max(rect.fY1, cutout.fY2), rect.fX2, rect.fY2},
{rect.fX1, std::max(rect.fY1, cutout.fY1), std::min(rect.fX2, cutout.fX1), std::min(rect.fY2, cutout.fY2)},
{std::max(rect.fX1, cutout.fX2), std::max(rect.fY1, cutout.fY1), rect.fX2, std::min(rect.fY2, cutout.fY2)},
};

for (const CRect2D& part : parts)
{
if (part.fX2 > part.fX1 && part.fY2 > part.fY1)
splitRects.push_back(part);
}
}

clipRects = std::move(splitRects);
}

if (!clipRects.empty())
{
for (const CRect2D& clipRect : clipRects)
m_pChat->Draw(true, true, &clipRect);
}
else
m_pChat->Draw(true, true);
}

if (bChatPreview && !bIsIngame)
{
const unsigned int uiRevision = CCore::GetSingleton().GetCVars()->GetRevision();

if (!m_bChatPreviewActive || uiRevision != m_uiChatPreviewRevision)
{
m_uiChatPreviewRevision = uiRevision;
m_pChat->Clear();

m_pChat->Output("Multi Theft Auto: What more could you want? Multi Theft Auto provides the best online Grand Theft Auto experience there is.");

m_pChat->Output(
"Multi Theft Auto: If you've played Grand Theft Auto online in the past, you'll know that the accuracy of the reproduction of other player's "
"actions often leaves a lot to be desired. This is a hard thing to get perfect, but Multi Theft Auto has the best GTA synchronization out "
"there "
"and it's getting better all the time! Want to shoot someone's limbs one by one? MTA makes that possible!");

m_pChat->Output(
"Multi Theft Auto: Online games are all about their community, and Multi Theft Auto has a great community! We've got a great forum where you "
"can "
"get support for any problems you have playing MTA, get help with scripting problems or just hang out and chat. We also run a special site for "
"downloading game modes and maps that members of the community have created.");

m_bChatPreviewActive = true;
}
}
else if (!bChatPreview && m_bChatPreviewActive)
{
m_pChat->Clear();
m_bChatPreviewActive = false;
}
}

void CLocalGUI::Invalidate()
Expand Down
17 changes: 10 additions & 7 deletions Client/core/CGUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,16 @@ class CLocalGUI : public CSingleton<CLocalGUI>

CGUILabel* m_pLabelVersionTag;

bool m_bForceCursorVisible;
bool m_bChatboxVisible;
bool m_bChatboxInputBlocked;
bool m_pDebugViewVisible;
bool m_bGUIHasInput;
int m_uiActiveCompositionSize;
POINT m_StoredMousePosition;
bool m_bForceCursorVisible;
bool m_bChatboxVisible;
bool m_bChatPreviewActive = false;
bool m_bChatInputPreviewActive = false;
unsigned int m_uiChatPreviewRevision = 0;
bool m_bChatboxInputBlocked;
bool m_pDebugViewVisible;
bool m_bGUIHasInput;
int m_uiActiveCompositionSize;
POINT m_StoredMousePosition;

int m_LastSettingsRevision; // the revision number the last time we saw the skin change
SString m_LastSkinName;
Expand Down
Loading
Loading