| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : wwui *
- * *
- * $Archive:: /Commando/Code/wwui/textmarqueectrl.cpp $*
- * *
- * Author:: Patrick Smith *
- * *
- * $Modtime:: 12/17/01 3:32p $*
- * *
- * $Revision:: 3 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "textmarqueectrl.h"
- #include "stylemgr.h"
- #include "dialogmgr.h"
- //////////////////////////////////////////////////////////////////////
- //
- // TextMarqueeCtrlClass
- //
- //////////////////////////////////////////////////////////////////////
- TextMarqueeCtrlClass::TextMarqueeCtrlClass (void) :
- ScrollPos (0),
- PixelHeight (0),
- ScrollRate (2.0F)
- {
- //
- // Configure the renderers
- //
- StyleMgrClass::Assign_Font (&TextRenderers[0], StyleMgrClass::FONT_CREDITS);
- StyleMgrClass::Assign_Font (&TextRenderers[1], StyleMgrClass::FONT_CREDITS_BOLD);
- StyleMgrClass::Configure_Renderer (&ControlRenderer);
- TextRenderers[0].Set_Texture_Size_Hint (256);
- TextRenderers[1].Set_Texture_Size_Hint (256);
- return ;
- }
- //////////////////////////////////////////////////////////////////////
- //
- // ~TextMarqueeCtrlClass
- //
- //////////////////////////////////////////////////////////////////////
- TextMarqueeCtrlClass::~TextMarqueeCtrlClass (void)
- {
- return ;
- }
- //////////////////////////////////////////////////////////////////////
- //
- // Create_Control_Renderer
- //
- //////////////////////////////////////////////////////////////////////
- void
- TextMarqueeCtrlClass::Create_Control_Renderer (void)
- {
- Render2DClass &renderer = ControlRenderer;
- //
- // Configure this renderer
- //
- renderer.Reset ();
- renderer.Enable_Texturing (false);
- //
- // Determine which color to draw the outline in
- //
- int color = StyleMgrClass::Get_Line_Color ();
- int bkcolor = StyleMgrClass::Get_Bk_Color ();
- if (IsEnabled == false) {
- color = StyleMgrClass::Get_Disabled_Line_Color ();
- bkcolor = StyleMgrClass::Get_Disabled_Bk_Color ();
- }
- if (Style & WS_BORDER) {
-
- //
- // Draw the control's outline
- //
- renderer.Add_Outline (Rect, 1.0F, color);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////
- //
- // Create_Text_Renderer
- //
- //////////////////////////////////////////////////////////////////////
- void
- TextMarqueeCtrlClass::Create_Text_Renderer (void)
- {
- TextRenderers[0].Reset ();
- TextRenderers[1].Reset ();
- TextRenderers[0].Set_Clipping_Rect (ClientRect);
- TextRenderers[1].Set_Clipping_Rect (ClientRect);
- TextRenderers[0].Set_Wrapping_Width (0);
- TextRenderers[1].Set_Wrapping_Width (0);
- int row_count = CreditLines.Count ();
- if (row_count <= 0) {
- return ;
- }
- //
- // Calculate where to start rendering text
- //
- int ctrl_height = ClientRect.Height ();
- float start_height = (ScrollPos - ctrl_height);
- float curr_height = 0;
- for (int curr_row = 0; curr_row < CreditLines.Count (); curr_row ++) {
- if ((curr_height + CreditLines[curr_row].Height) >= start_height) {
- break;
- }
- curr_height += CreditLines[curr_row].Height;
- }
- //
- // Configure our starting text rectangle
- //
- RectClass text_rect = ClientRect;
- text_rect.Top += curr_height - (ScrollPos - ctrl_height);
- //
- // Now, render the visible lines of text...
- //
- for ( int index = curr_row;
- (index < CreditLines.Count ()) && (text_rect.Top < ClientRect.Bottom);
- index ++)
- {
- CREDIT_LINE &line = CreditLines[index];
- //
- // Use the formatting parameters for this line...
- //
- Render2DSentenceClass *renderer = &TextRenderers[line.FontIndex];
- int color = line.Color;
- int shadow_color = StyleMgrClass::Get_Text_Shadow_Color ();
- //
- // Render this line of text centered
- //
- StyleMgrClass::Render_Text (line.Text, renderer, color, shadow_color,
- text_rect, true, false, StyleMgrClass::CENTER_JUSTIFY, false);
-
- //
- // Move down to the next row...
- //
- text_rect.Top = int(text_rect.Top + line.Height);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Render
- //
- ////////////////////////////////////////////////////////////////
- void
- TextMarqueeCtrlClass::Render (void)
- {
- //
- // Recreate the renderers (if necessary)
- //
- if (IsDirty) {
- Create_Control_Renderer ();
- Create_Text_Renderer ();
- }
- //
- // Render the image...
- //
- ControlRenderer.Render ();
- TextRenderers[0].Render ();
- TextRenderers[1].Render ();
- DialogControlClass::Render ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Update_Client_Rect
- //
- ////////////////////////////////////////////////////////////////
- void
- TextMarqueeCtrlClass::Update_Client_Rect (void)
- {
- //
- // Set the client area
- //
- ClientRect = Rect;
- ClientRect.Inflate (Vector2 (-5.0F * StyleMgrClass::Get_X_Scale (), -3.75F * StyleMgrClass::Get_Y_Scale ()));
- ClientRect.Left = int(ClientRect.Left);
- ClientRect.Top = int(ClientRect.Top);
- ClientRect.Right = int(ClientRect.Right);
- ClientRect.Bottom = int(ClientRect.Bottom);
- Set_Dirty ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Set_Text
- //
- ////////////////////////////////////////////////////////////////
- void
- TextMarqueeCtrlClass::Set_Text (const WCHAR *title)
- {
- DialogControlClass::Set_Text (title);
- ScrollPos = 0.0F;
- //
- // Rebuild the data structures necessary for us to
- // render formatted text
- //
- Build_Credit_Lines ();
- //
- // Count up the total height of all lines
- //
- for (int index = 0; index < CreditLines.Count (); index ++) {
- PixelHeight += TextRenderers[CreditLines[index].FontIndex].Peek_Font ()->Get_Char_Height ();
- }
- //
- // Add two blank pages
- //
- PixelHeight += ClientRect.Height () * 2;
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Build_Credit_Lines
- //
- ////////////////////////////////////////////////////////////////
- void
- TextMarqueeCtrlClass::Build_Credit_Lines (void)
- {
- CreditLines.Delete_All ();
- if (Title.Get_Length () == 0) {
- return;
- }
- //
- // Handy macro
- //
- #define COPY_LINE(dest, src_start, src_end) \
- if (src_end == NULL) { \
- dest = src_start; \
- } else { \
- uint32 bytes = ((uint32)src_end - (uint32)src_start); \
- uint32 len = bytes / sizeof (WCHAR); \
- ::memcpy (dest.Get_Buffer (len + 1), src_start, bytes); \
- dest.Peek_Buffer ()[len] = 0; \
- }
- int default_color = StyleMgrClass::Get_Text_Color ();
- CREDIT_LINE default_line (L"", 0, default_color);
- //
- // Build an array of formatted text lines
- //
- const WCHAR *text = Title;
- while (text != NULL) {
-
- //
- // Scan this line for formatting information
- //
- CREDIT_LINE line (default_line);
- text = Read_Line (text, line);
- //
- // Determine which renderer to use...
- //
- Render2DSentenceClass *renderer = &TextRenderers[line.FontIndex];
- renderer->Set_Wrapping_Width (ClientRect.Width ());
- //
- // Loop over all the lines of text and check for wrapping...
- //
- const WCHAR *line_start = renderer->Find_Row_Start (line.Text, 0);
- while (line_start != NULL) {
- //
- // Lookup the start of the next line...
- //
- const WCHAR *line_end = renderer->Find_Row_Start (line_start, 1);
-
- //
- // Copy this line of text into the control
- //
- WideStringClass text;
- COPY_LINE (text, line_start, line_end);
- //
- // Add this line to our list
- //
- CREDIT_LINE new_line (line);
- new_line.Text = text;
- new_line.Height = TextRenderers[new_line.FontIndex].Peek_Font ()->Get_Char_Height ();
- CreditLines.Add (new_line);
- //
- // Advance to the next line...
- //
- line_start = line_end;
- }
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Read_Tag
- //
- ////////////////////////////////////////////////////////////////
- int
- TextMarqueeCtrlClass::Read_Tag (const WCHAR *text, CREDIT_LINE &line)
- {
- int retval = -1;
- const WCHAR *TAG_BOLD = L"bold";
- const WCHAR *TAG_COLOR = L"color=";
- if (text[0] == L'<') {
- for (int index = 1; text[index] != 0; index ++) {
-
- //
- // Is this the 'end-tag' bracket?
- //
- if (text[index] == L'>') {
- //
- // What type of specifier did we find?
- //
- if (::_wcsnicmp (text+1, TAG_BOLD, ::wcslen (TAG_BOLD)) == 0) {
-
- //
- // We found the bold specifier
- //
- line.FontIndex = 1;
- retval = index;
- } else if (::_wcsnicmp (text+1, TAG_COLOR, ::wcslen (TAG_COLOR)) == 0) {
-
- //
- // We found the color specifier
- //
- int tag_len = ::wcslen (TAG_COLOR)+1;
- text += tag_len;
- //
- // Copy the params to their own temp string
- //
- WideStringClass temp_buffer (index + 1, true);
- // ::lstrcpynW (temp_buffer.Peek_Buffer (), text, (index + 1) - tag_len);
-
- int length = ((index + 1) - tag_len);
- WCHAR* tempPtr = temp_buffer.Peek_Buffer();
- wcsncpy(tempPtr, text, length);
- tempPtr[length - 1] = 0;
- int color[3] = { 0 };
- //
- // Parse the params for the colors
- //
- WCHAR *buffer = temp_buffer.Peek_Buffer ();
- for (int color_index = 0; color_index < 3; color_index ++) {
- WCHAR *comma_str = ::wcschr (buffer, L',');
- if (comma_str != NULL) {
- comma_str[0] = 0;
- color[color_index] = ::_wtoi (buffer);
- buffer = &comma_str[1];
- } else {
- color[color_index] = ::_wtoi (buffer);
- break;
- }
- }
- //
- // Store the color
- //
- line.Color = RGB_TO_INT32 ((uint8)color[0], (uint8)color[1], (uint8)color[2]);
- retval = index;
- }
- break;
- }
- }
- }
- return retval;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Read_Line
- //
- ////////////////////////////////////////////////////////////////
- const WCHAR *
- TextMarqueeCtrlClass::Read_Line (const WCHAR *text, CREDIT_LINE &line)
- {
- const WCHAR *text_start = text;
- //
- // Set some defaults
- //
- line.FontIndex = 0;
- line.Color = StyleMgrClass::Get_Text_Color ();
- //
- // Loop over all the text in the control
- //
- bool keep_going = true;
- do
- {
- WCHAR ch = *text;
- //
- // Check to see if this character ends the
- //
- if (ch == L'\n' || ch == 0) {
- int len = text - text_start;
- // ::lstrcpynW (line.Text.Get_Buffer (len + 1), text_start, len + 1);
- WCHAR* buffer = line.Text.Get_Buffer(len + 1);
- wcsncpy(buffer, text_start, len + 1);
- buffer[len] = 0;
-
- keep_going = false;
- } else if (ch == L'<') {
-
- //
- // Did we find a tag?
- //
- int new_index = Read_Tag (text, line);
- if (new_index != -1) {
- text = &text[new_index];
- text_start = text + 1;
- }
- }
- //
- // Move to the next character
- //
- if (ch != 0) {
- text ++;
- }
- } while (keep_going);
- return text[0] != 0 ? text : 0;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Frame_Update
- //
- ////////////////////////////////////////////////////////////////
- void
- TextMarqueeCtrlClass::On_Frame_Update (void)
- {
- float char_height = TextRenderers[0].Peek_Font ()->Get_Char_Height ();
- //
- // Determine how many pixels to scroll
- //
- float time = DialogMgrClass::Get_Frame_Time () / 1000.0F;
- float pixels_scrolled = time * ScrollRate * char_height;
-
- //
- // Update the scroll position
- //
- float old_pos = ScrollPos;
- ScrollPos += pixels_scrolled;
- if (ScrollPos >= PixelHeight) {
- ScrollPos = 0;
- }
- //
- // Update the view
- //
- if (int(old_pos) != int(ScrollPos)) {
- Set_Dirty ();
- }
- return ;
- }
|