diff --git a/Client/core/CChat.cpp b/Client/core/CChat.cpp index 4182d27946..465f70fcdf 100644 --- a/Client/core/CChat.cpp +++ b/Client/core/CChat.cpp @@ -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()); @@ -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(std::max(0.0f, pRect->fX1)); + rect.top = static_cast(std::max(0.0f, pRect->fY1)); + rect.right = static_cast(std::max(0.0f, pRect->fX2)); + rect.bottom = static_cast(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; @@ -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.. @@ -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); @@ -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; } @@ -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; } @@ -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); } // @@ -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; @@ -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); } @@ -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) @@ -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); diff --git a/Client/core/CChat.h b/Client/core/CChat.h index 1aa79c2a83..7beff1c245 100644 --- a/Client/core/CChat.h +++ b/Client/core/CChat.h @@ -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(); @@ -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(); @@ -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; diff --git a/Client/core/CConsole.cpp b/Client/core/CConsole.cpp index 9350863a9f..9d85ca612a 100644 --- a/Client/core/CConsole.cpp +++ b/Client/core/CConsole.cpp @@ -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) diff --git a/Client/core/CConsole.h b/Client/core/CConsole.h index 4b11422eca..9d6fbd9970 100644 --- a/Client/core/CConsole.h +++ b/Client/core/CConsole.h @@ -52,6 +52,7 @@ class CConsole : public CConsoleInterface void ResetAutoCompleteMatch(); CVector2D GetPosition(); + void GetWindowRect(CRect2D& outRect); void SetPosition(CVector2D& vecPosition); CVector2D GetSize(); diff --git a/Client/core/CGUI.cpp b/Client/core/CGUI.cpp index e007e24fca..2149b74b82 100644 --- a/Client/core/CGUI.cpp +++ b/Client/core/CGUI.cpp @@ -482,13 +482,31 @@ 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); @@ -496,7 +514,9 @@ void CLocalGUI::Draw() UpdateCursor(); // Draw the chat - m_pChat->Draw(true, true); + if (!bChatPreview) + m_pChat->Draw(true, true); + // Draw the debugger m_pDebugView->Draw(true, false); @@ -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 clipRects; + clipRects.emplace_back(0.0f, 0.0f, fScreenWidth, fScreenHeight); + + std::vector 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 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() diff --git a/Client/core/CGUI.h b/Client/core/CGUI.h index 11ab607d95..cfdc3f3495 100644 --- a/Client/core/CGUI.h +++ b/Client/core/CGUI.h @@ -121,13 +121,16 @@ class CLocalGUI : public CSingleton 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; diff --git a/Client/core/CSettings.cpp b/Client/core/CSettings.cpp index d956181d5c..88146924c2 100644 --- a/Client/core/CSettings.cpp +++ b/Client/core/CSettings.cpp @@ -2168,6 +2168,9 @@ void CSettings::Update() m_dwFrameCount++; UpdateCaptureAxis(); + + if (IsChatTabVisible()) + LiveUpdateChatSettings(); } void CSettings::UpdateAudioTab() @@ -3199,6 +3202,7 @@ void CSettings::CreateInterfaceTabGUI() m_pChatHorizontalCombo->AddItem(_("Right"))->SetData((void*)Chat::Position::Horizontal::RIGHT); m_pChatHorizontalCombo->SetReadOnly(true); m_pChatHorizontalCombo->SetSelectedItemByIndex(0); + m_pChatHorizontalCombo->SetSelectionHandler(GUI_CALLBACK(&CSettings::OnChatHorizontalComboChanged, this)); pLabel = reinterpret_cast(pManager->CreateLabel(pTabLayout, strVertical)); pLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + fLineSizeY + fLineGapY)); @@ -3213,6 +3217,7 @@ void CSettings::CreateInterfaceTabGUI() m_pChatVerticalCombo->AddItem(_("Bottom"))->SetData((void*)Chat::Position::Vertical::BOTTOM); m_pChatVerticalCombo->SetReadOnly(true); m_pChatVerticalCombo->SetSelectedItemByIndex(0); + m_pChatVerticalCombo->SetSelectionHandler(GUI_CALLBACK(&CSettings::OnChatVerticalComboChanged, this)); pLabel = reinterpret_cast(pManager->CreateLabel(pTabLayout, strTextAlign)); pLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + fLineSizeY + fLineGapY)); @@ -3226,6 +3231,7 @@ void CSettings::CreateInterfaceTabGUI() m_pChatTextAlignCombo->AddItem(_("Right"))->SetData((void*)Chat::Text::Align::RIGHT); m_pChatTextAlignCombo->SetReadOnly(true); m_pChatTextAlignCombo->SetSelectedItemByIndex(0); + m_pChatTextAlignCombo->SetSelectionHandler(GUI_CALLBACK(&CSettings::OnChatTextAlignComboChanged, this)); pLabel = reinterpret_cast(pManager->CreateLabel(pTabLayout, strXOffset)); pLabel->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + fLineSizeY + fLineGapY)); @@ -3879,6 +3885,18 @@ bool CSettings::IsVisible() return m_pWindow->IsVisible(); } +bool CSettings::IsChatTabVisible() +{ + return IsVisible() && m_pTabs->IsTabSelected(m_pTabInterface); +} + +void CSettings::GetWindowRect(CRect2D& outRect) +{ + 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); +} + void CSettings::SetIsModLoaded(bool bLoaded) { m_bIsModLoaded = bLoaded; @@ -3929,6 +3947,8 @@ bool CSettings::OnCancelButtonClick(CGUIElement* pElement) CVARS_SET("mtavolume", m_fOldMTAVolume); CVARS_SET("voicevolume", m_fOldVoiceVolume); + RestoreChatSettings(); + // restore old audio mute settings CVARS_SET("mute_master_when_minimized", m_bOldMuteMaster); CVARS_SET("mute_radio_when_minimized", m_bOldMuteRadio); @@ -4248,21 +4268,26 @@ void CSettings::LoadData() if (iVar > Chat::Position::Horizontal::RIGHT) iVar = Chat::Position::Horizontal::LEFT; m_pChatHorizontalCombo->SetSelectedItemByIndex(iVar); + m_iChatHorizontalValue = iVar; CVARS_GET("chat_position_vertical", iVar); if (iVar > Chat::Position::Vertical::BOTTOM) iVar = Chat::Position::Vertical::TOP; m_pChatVerticalCombo->SetSelectedItemByIndex(iVar); + m_iChatVerticalValue = iVar; CVARS_GET("chat_text_alignment", iVar); if (iVar > Chat::Text::Align::RIGHT) iVar = Chat::Text::Align::LEFT; m_pChatTextAlignCombo->SetSelectedItemByIndex(iVar); + m_iChatTextAlignValue = iVar; CVARS_GET("chat_position_offset_x", strVar); m_pChatOffsetX->SetText(strVar.c_str()); CVARS_GET("chat_position_offset_y", strVar); m_pChatOffsetY->SetText(strVar.c_str()); + SnapshotChatSettings(); + // Interface CVARS_GET("server_can_flash_window", bVar); m_pFlashWindow->SetSelected(bVar); @@ -4675,47 +4700,7 @@ void CSettings::SaveData() } // Chat - SaveChatColor(Chat::ColorType::BG, "chat_color"); - SaveChatColor(Chat::ColorType::TEXT, "chat_text_color"); - SaveChatColor(Chat::ColorType::INPUT_BG, "chat_input_color"); - SaveChatColor(Chat::ColorType::INPUT_TEXT, "chat_input_text_color"); - for (int iFont = 0; iFont < Chat::ColorType::MAX; iFont++) - { - if (m_pRadioChatFont[iFont]->GetSelected()) - { - CVARS_SET("chat_font", iFont); - break; - } - } - - strVar = m_pChatScaleX->GetText() + " " + m_pChatScaleY->GetText(); - CVARS_SET("chat_scale", strVar); - CVARS_SET("chat_lines", m_pChatLines->GetText()); - CVARS_SET("chat_width", m_pChatWidth->GetText()); - CVARS_SET("chat_css_style_text", m_pChatCssText->GetSelected()); - CVARS_SET("chat_css_style_background", m_pChatCssBackground->GetSelected()); - CVARS_SET("chat_nickcompletion", m_pChatNickCompletion->GetSelected()); - CVARS_SET("chat_text_outline", m_pChatTextBlackOutline->GetSelected()); - CVARS_SET("chat_line_life", GetMilliseconds(m_pChatLineLife)); - CVARS_SET("chat_line_fade_out", GetMilliseconds(m_pChatLineFadeout)); - - CVARS_SET("chat_position_offset_x", m_pChatOffsetX->GetText()); - CVARS_SET("chat_position_offset_y", m_pChatOffsetY->GetText()); - if (CGUIListItem* pSelected = m_pChatHorizontalCombo->GetSelectedItem()) - { - int iSelected = (int)pSelected->GetData(); - CVARS_SET("chat_position_horizontal", iSelected); - } - if (CGUIListItem* pSelected = m_pChatVerticalCombo->GetSelectedItem()) - { - int iSelected = (int)pSelected->GetData(); - CVARS_SET("chat_position_vertical", iSelected); - } - if (CGUIListItem* pSelected = m_pChatTextAlignCombo->GetSelectedItem()) - { - int iSelected = (int)pSelected->GetData(); - CVARS_SET("chat_text_alignment", iSelected); - } + SaveChatSettings(); // Interface CVARS_SET("server_can_flash_window", m_pFlashWindow->GetSelected()); @@ -5014,12 +4999,13 @@ void CSettings::SaveChatColor(eChatColorType eType, const char* szCVar) CColor CSettings::GetChatColorValues(eChatColorType eType) { - // Retrieve the color according to the scrollbar values + // Retrieve the color according to the scrollbar values (rounded, so saving an unchanged + // colour round-trips exactly instead of drifting by one step each time) CColor pColor; - pColor.R = m_pChatRed[eType]->GetScrollPosition() * 255; - pColor.G = m_pChatGreen[eType]->GetScrollPosition() * 255; - pColor.B = m_pChatBlue[eType]->GetScrollPosition() * 255; - pColor.A = m_pChatAlpha[eType]->GetScrollPosition() * 255; + pColor.R = static_cast(m_pChatRed[eType]->GetScrollPosition() * 255.0f + 0.5f); + pColor.G = static_cast(m_pChatGreen[eType]->GetScrollPosition() * 255.0f + 0.5f); + pColor.B = static_cast(m_pChatBlue[eType]->GetScrollPosition() * 255.0f + 0.5f); + pColor.A = static_cast(m_pChatAlpha[eType]->GetScrollPosition() * 255.0f + 0.5f); return pColor; } @@ -5032,6 +5018,185 @@ void CSettings::SetChatColorValues(eChatColorType eType, CColor pColor) m_pChatAlpha[eType]->SetScrollPosition((float)pColor.A / 255.0f); } +void CSettings::SaveChatSettings() +{ + SaveChatColor(Chat::ColorType::BG, "chat_color"); + SaveChatColor(Chat::ColorType::TEXT, "chat_text_color"); + SaveChatColor(Chat::ColorType::INPUT_BG, "chat_input_color"); + SaveChatColor(Chat::ColorType::INPUT_TEXT, "chat_input_text_color"); + + for (int iFont = 0; iFont < Chat::Font::MAX; iFont++) + { + if (m_pRadioChatFont[iFont]->GetSelected()) + { + CVARS_SET("chat_font", iFont); + break; + } + } + + SString strVar = m_pChatScaleX->GetText() + " " + m_pChatScaleY->GetText(); + CVARS_SET("chat_scale", strVar); + + CVARS_SET("chat_lines", m_pChatLines->GetText()); + CVARS_SET("chat_width", m_pChatWidth->GetText()); + CVARS_SET("chat_css_style_text", m_pChatCssText->GetSelected()); + CVARS_SET("chat_css_style_background", m_pChatCssBackground->GetSelected()); + CVARS_SET("chat_nickcompletion", m_pChatNickCompletion->GetSelected()); + CVARS_SET("chat_text_outline", m_pChatTextBlackOutline->GetSelected()); + CVARS_SET("chat_line_life", GetMilliseconds(m_pChatLineLife)); + CVARS_SET("chat_line_fade_out", GetMilliseconds(m_pChatLineFadeout)); + + CVARS_SET("chat_position_offset_x", m_pChatOffsetX->GetText()); + CVARS_SET("chat_position_offset_y", m_pChatOffsetY->GetText()); + + CVARS_SET("chat_position_horizontal", m_iChatHorizontalValue); + CVARS_SET("chat_position_vertical", m_iChatVerticalValue); + CVARS_SET("chat_text_alignment", m_iChatTextAlignValue); +} + +SString CSettings::GetChatSettingsSignature() +{ + SString strSignature; + + for (int iColor = 0; iColor < Chat::ColorType::MAX; iColor++) + { + const CColor color = GetChatColorValues(static_cast(iColor)); + strSignature += SString("%d,%d,%d,%d|", color.R, color.G, color.B, color.A); + } + + for (int iFont = 0; iFont < Chat::Font::MAX; iFont++) + strSignature += m_pRadioChatFont[iFont]->GetSelected() ? "1" : "0"; + + strSignature += "|" + m_pChatLines->GetText(); + strSignature += "|" + m_pChatScaleX->GetText(); + strSignature += "|" + m_pChatScaleY->GetText(); + strSignature += "|" + m_pChatWidth->GetText(); + + strSignature += SString("|%d|%d|%d|%d", m_pChatCssText->GetSelected(), m_pChatCssBackground->GetSelected(), m_pChatNickCompletion->GetSelected(), + m_pChatTextBlackOutline->GetSelected()); + + strSignature += "|" + m_pChatLineLife->GetText(); + strSignature += "|" + m_pChatLineFadeout->GetText(); + strSignature += "|" + m_pChatOffsetX->GetText(); + strSignature += "|" + m_pChatOffsetY->GetText(); + + strSignature += SString("|%d", m_iChatHorizontalValue); + strSignature += SString("|%d", m_iChatVerticalValue); + strSignature += SString("|%d", m_iChatTextAlignValue); + + return strSignature; +} + +bool CSettings::OnChatHorizontalComboChanged(CGUIElement* pElement) +{ + if (CGUIListItem* pSelected = m_pChatHorizontalCombo->GetSelectedItem()) + m_iChatHorizontalValue = static_cast(reinterpret_cast(pSelected->GetData())); + + LiveUpdateChatSettings(); + + return true; +} + +bool CSettings::OnChatVerticalComboChanged(CGUIElement* pElement) +{ + if (CGUIListItem* pSelected = m_pChatVerticalCombo->GetSelectedItem()) + m_iChatVerticalValue = static_cast(reinterpret_cast(pSelected->GetData())); + + LiveUpdateChatSettings(); + + return true; +} + +bool CSettings::OnChatTextAlignComboChanged(CGUIElement* pElement) +{ + if (CGUIListItem* pSelected = m_pChatTextAlignCombo->GetSelectedItem()) + m_iChatTextAlignValue = static_cast(reinterpret_cast(pSelected->GetData())); + + LiveUpdateChatSettings(); + + return true; +} + +void CSettings::LiveUpdateChatSettings() +{ + SString strSignature = GetChatSettingsSignature(); + + if (strSignature != m_strChatSettingsSignature) + { + m_strChatSettingsSignature = strSignature; + SaveChatSettings(); + } +} + +void CSettings::SnapshotChatSettings() +{ + std::string strVar; + + CVARS_GET("chat_color", strVar); + m_strOldChatColor = strVar; + CVARS_GET("chat_text_color", strVar); + m_strOldChatTextColor = strVar; + CVARS_GET("chat_input_color", strVar); + m_strOldChatInputColor = strVar; + CVARS_GET("chat_input_text_color", strVar); + m_strOldChatInputTextColor = strVar; + CVARS_GET("chat_font", strVar); + m_strOldChatFont = strVar; + CVARS_GET("chat_lines", strVar); + m_strOldChatLines = strVar; + CVARS_GET("chat_scale", strVar); + m_strOldChatScale = strVar; + CVARS_GET("chat_width", strVar); + m_strOldChatWidth = strVar; + CVARS_GET("chat_css_style_text", strVar); + m_strOldChatCssStyleText = strVar; + CVARS_GET("chat_css_style_background", strVar); + m_strOldChatCssStyleBackground = strVar; + CVARS_GET("chat_nickcompletion", strVar); + m_strOldChatNickCompletion = strVar; + CVARS_GET("chat_text_outline", strVar); + m_strOldChatTextOutline = strVar; + CVARS_GET("chat_line_life", strVar); + m_strOldChatLineLife = strVar; + CVARS_GET("chat_line_fade_out", strVar); + m_strOldChatLineFadeOut = strVar; + CVARS_GET("chat_position_horizontal", strVar); + m_strOldChatPositionHorizontal = strVar; + CVARS_GET("chat_position_vertical", strVar); + m_strOldChatPositionVertical = strVar; + CVARS_GET("chat_text_alignment", strVar); + m_strOldChatTextAlignment = strVar; + CVARS_GET("chat_position_offset_x", strVar); + m_strOldChatPositionOffsetX = strVar; + CVARS_GET("chat_position_offset_y", strVar); + m_strOldChatPositionOffsetY = strVar; + + m_strChatSettingsSignature.clear(); +} + +void CSettings::RestoreChatSettings() +{ + CVARS_SET("chat_color", m_strOldChatColor); + CVARS_SET("chat_text_color", m_strOldChatTextColor); + CVARS_SET("chat_input_color", m_strOldChatInputColor); + CVARS_SET("chat_input_text_color", m_strOldChatInputTextColor); + CVARS_SET("chat_font", m_strOldChatFont); + CVARS_SET("chat_lines", m_strOldChatLines); + CVARS_SET("chat_scale", m_strOldChatScale); + CVARS_SET("chat_width", m_strOldChatWidth); + CVARS_SET("chat_css_style_text", m_strOldChatCssStyleText); + CVARS_SET("chat_css_style_background", m_strOldChatCssStyleBackground); + CVARS_SET("chat_nickcompletion", m_strOldChatNickCompletion); + CVARS_SET("chat_text_outline", m_strOldChatTextOutline); + CVARS_SET("chat_line_life", m_strOldChatLineLife); + CVARS_SET("chat_line_fade_out", m_strOldChatLineFadeOut); + CVARS_SET("chat_position_horizontal", m_strOldChatPositionHorizontal); + CVARS_SET("chat_position_vertical", m_strOldChatPositionVertical); + CVARS_SET("chat_text_alignment", m_strOldChatTextAlignment); + CVARS_SET("chat_position_offset_x", m_strOldChatPositionOffsetX); + CVARS_SET("chat_position_offset_y", m_strOldChatPositionOffsetY); +} + void CSettings::LoadChatPresets() { CXMLFile* pPresetsFile = CCore::GetSingleton().GetXML()->CreateXML(CalcMTASAPath(CHAT_PRESETS_PATH)); diff --git a/Client/core/CSettings.h b/Client/core/CSettings.h index 864feadb72..2a0de715e1 100644 --- a/Client/core/CSettings.h +++ b/Client/core/CSettings.h @@ -91,6 +91,8 @@ class CSettings void SetVisible(bool bVisible); bool IsVisible(); + bool IsChatTabVisible(); + void GetWindowRect(CRect2D& outRect); void SetIsModLoaded(bool bLoaded); @@ -352,6 +354,33 @@ class CSettings CGUICheckBox* m_pChatTextBlackOutline; CGUIEdit* m_pChatLineLife; CGUIEdit* m_pChatLineFadeout; + + SString m_strOldChatColor; + SString m_strOldChatTextColor; + SString m_strOldChatInputColor; + SString m_strOldChatInputTextColor; + SString m_strOldChatFont; + SString m_strOldChatLines; + SString m_strOldChatScale; + SString m_strOldChatWidth; + SString m_strOldChatCssStyleText; + SString m_strOldChatCssStyleBackground; + SString m_strOldChatNickCompletion; + SString m_strOldChatTextOutline; + SString m_strOldChatLineLife; + SString m_strOldChatLineFadeOut; + SString m_strOldChatPositionHorizontal; + SString m_strOldChatPositionVertical; + SString m_strOldChatTextAlignment; + SString m_strOldChatPositionOffsetX; + SString m_strOldChatPositionOffsetY; + + int m_iChatHorizontalValue = -1; + int m_iChatVerticalValue = -1; + int m_iChatTextAlignValue = -1; + + SString m_strChatSettingsSignature; + CGUICheckBox* m_pFlashWindow; CGUICheckBox* m_pTrayBalloon; @@ -419,6 +448,9 @@ class CSettings bool OnChatGreenChanged(CGUIElement* pElement); bool OnChatBlueChanged(CGUIElement* pElement); bool OnChatAlphaChanged(CGUIElement* pElement); + bool OnChatHorizontalComboChanged(CGUIElement* pElement); + bool OnChatVerticalComboChanged(CGUIElement* pElement); + bool OnChatTextAlignComboChanged(CGUIElement* pElement); bool OnUpdateButtonClick(CGUIElement* pElement); bool OnCachePathShowButtonClick(CGUIElement* pElement); bool OnMouseSensitivityChanged(CGUIElement* pElement); @@ -469,15 +501,20 @@ class CSettings void LoadSkins(); - void LoadChatPresets(); - void CreateChatColorTab(eChatColorType eType, const char* szName, CGUITabPanel* pParent); - void LoadChatColorFromCVar(eChatColorType eType, const char* szCVar); - void LoadChatColorFromString(eChatColorType eType, const std::string& strColor); - void SaveChatColor(eChatColorType eType, const char* szCVar); - CColor GetChatColorValues(eChatColorType eType); - void SetChatColorValues(eChatColorType eType, CColor pColor); - int GetMilliseconds(CGUIEdit* pEdit); - void SetMilliseconds(CGUIEdit* pEdit, int milliseconds); + void LoadChatPresets(); + void CreateChatColorTab(eChatColorType eType, const char* szName, CGUITabPanel* pParent); + void LoadChatColorFromCVar(eChatColorType eType, const char* szCVar); + void LoadChatColorFromString(eChatColorType eType, const std::string& strColor); + void SaveChatColor(eChatColorType eType, const char* szCVar); + CColor GetChatColorValues(eChatColorType eType); + void SetChatColorValues(eChatColorType eType, CColor pColor); + void SaveChatSettings(); + SString GetChatSettingsSignature(); + void LiveUpdateChatSettings(); + void SnapshotChatSettings(); + void RestoreChatSettings(); + int GetMilliseconds(CGUIEdit* pEdit); + void SetMilliseconds(CGUIEdit* pEdit, int milliseconds); void ResetGTAVolume(); void SetRadioVolume(float fVolume);