| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 |
- /*
- ** Command & Conquer Generals Zero Hour(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) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: W3DGameWindow.cpp ////////////////////////////////////////////////////
- //-----------------------------------------------------------------------------
- //
- // Westwood Studios Pacific.
- //
- // Confidential Information
- // Copyright (C) 2001 - All Rights Reserved
- //
- //-----------------------------------------------------------------------------
- //
- // Project: RTS3
- //
- // File name: W3DGameWindow.cpp
- //
- // Created: Colin Day, June 2001
- //
- // Desc: W3D implementation of a game window
- //
- //-----------------------------------------------------------------------------
- ///////////////////////////////////////////////////////////////////////////////
- // SYSTEM INCLUDES ////////////////////////////////////////////////////////////
- #include <stdlib.h>
- // USER INCLUDES //////////////////////////////////////////////////////////////
- #include "GameClient/Gadget.h"
- #include "GameClient/GameWindowGlobal.h"
- #include "W3DDevice/GameClient/W3DGameWindow.h"
- #include "W3DDevice/GameClient/W3DGameWindowManager.h"
- #include "W3DDevice/GameClient/W3DDisplay.h"
- // DEFINES ////////////////////////////////////////////////////////////////////
- enum
- {
- BORDER_CORNER_SIZE = 15,
- BORDER_LINE_SIZE = 20,
- };
- // PRIVATE TYPES //////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- // PRIVATE DATA ///////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- static Bool bordersInit = FALSE;
- static const Image *borderPieces[NUM_BORDER_PIECES] = { 0 };
- // PUBLIC DATA ////////////////////////////////////////////////////////////////
- // PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- // PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- // initBorders ================================================================
- //=============================================================================
- static void initBorders( void )
- {
- borderPieces[ BORDER_CORNER_UL ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderCornerUL" ) );
- borderPieces[ BORDER_CORNER_UR ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderCornerUR" ) );
- borderPieces[ BORDER_CORNER_LL ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderCornerLL" ) );
- borderPieces[ BORDER_CORNER_LR ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderCornerLR" ) );
- borderPieces[ BORDER_VERTICAL_LEFT ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderLeft" ) );
- borderPieces[ BORDER_VERTICAL_LEFT_SHORT ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderLeftShort" ) );
- borderPieces[ BORDER_HORIZONTAL_TOP ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderTop" ) );
- borderPieces[ BORDER_HORIZONTAL_TOP_SHORT ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderTopShort" ) );
- borderPieces[ BORDER_VERTICAL_RIGHT ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderRight" ) );
- borderPieces[ BORDER_VERTICAL_RIGHT_SHORT ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderRightShort" ) );
- borderPieces[ BORDER_HORIZONTAL_BOTTOM ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderBottom" ) );
- borderPieces[ BORDER_HORIZONTAL_BOTTOM_SHORT ] =
- TheMappedImageCollection->findImageByName( AsciiString( "BorderBottomShort" ) );
- bordersInit = TRUE;
- }
- // W3DGameWindow::blitBorderRect ==============================================
- //=============================================================================
- void W3DGameWindow::blitBorderRect( Int x, Int y, Int width, Int height )
- {
- Int Offset = 15;
- Int OffsetLower = 5;
- // init image loc if needed
- if( bordersInit == FALSE )
- initBorders();
- // save original x, y
- Int originalX = x;
- Int originalY = y;
- Int maxX = x + width;
- Int maxY = y + height;
- Int x2, y2; // used for simultaneous drawing of line pairs
- Int size = 20;
- Int halfSize = size / 2;
- // Draw Horizontal Lines
- // All border pieces are based on a 10 pixel offset from the centerline
- y = originalY - Offset;
- y2 = maxY - OffsetLower;
- x2 = maxX - (OffsetLower + BORDER_LINE_SIZE);
- for( x=(originalX + OffsetLower); x <= x2; x += BORDER_LINE_SIZE )
- {
- TheDisplay->drawImage( borderPieces[ BORDER_HORIZONTAL_TOP ],
- x, y, x + size, y + size );
- TheDisplay->drawImage( borderPieces[ BORDER_HORIZONTAL_BOTTOM ],
- x, y2, x + size, y2 + size );
- }
- x2 = maxX - 5;//BORDER_CORNER_SIZE;
- // x == place to draw remainder if any
- if( (x2 - x) >= (BORDER_LINE_SIZE / 2) )
- {
-
- //Blit Half piece
- TheDisplay->drawImage( borderPieces[ BORDER_HORIZONTAL_TOP_SHORT ],
- x, y, x + halfSize, y + size );
- TheDisplay->drawImage( borderPieces[ BORDER_HORIZONTAL_BOTTOM_SHORT ],
- x, y2, x + halfSize, y2 + size );
- x += (BORDER_LINE_SIZE / 2);
- }
- // x2 - x ... must now be less than a half piece
- // check for equals and if not blit an adjusted half piece border pieces have
- // a two pixel repeat so we will blit one pixel over if necessary to line up
- // the art, but we'll cover-up the overlap with the corners
- if( x < x2 )
- {
- x -= ((BORDER_LINE_SIZE / 2) - (((x2 - x) + 1) & ~1));
- //Blit Half piece
- TheDisplay->drawImage( borderPieces[ BORDER_HORIZONTAL_TOP_SHORT ],
- x, y, x + halfSize, y + size );
- TheDisplay->drawImage( borderPieces[ BORDER_HORIZONTAL_BOTTOM_SHORT ],
- x, y2, x + halfSize, y2 + size );
- }
- // Draw Vertical Lines
- // All border pieces are based on a 10 pixel offset from the centerline
- x = originalX - Offset;
- x2 = maxX - OffsetLower;
- y2 = maxY - (OffsetLower + BORDER_LINE_SIZE);
- for( y=(originalY + OffsetLower); y <= y2; y += BORDER_LINE_SIZE )
- {
- TheDisplay->drawImage( borderPieces[ BORDER_VERTICAL_LEFT ],
- x, y, x + size, y + size );
- TheDisplay->drawImage( borderPieces[ BORDER_VERTICAL_RIGHT ],
- x2, y, x2 + size, y + size );
- }
- y2 = maxY - OffsetLower;//BORDER_CORNER_SIZE;
- // y == place to draw remainder if any
- if( (y2 - y) >= (BORDER_LINE_SIZE / 2) )
- {
- //Blit Half piece
- TheDisplay->drawImage( borderPieces[ BORDER_VERTICAL_LEFT_SHORT ],
- x, y, x + size, y + halfSize );
- TheDisplay->drawImage( borderPieces[ BORDER_VERTICAL_RIGHT_SHORT ],
- x2, y, x2 + size, y + halfSize );
- y += (BORDER_LINE_SIZE / 2);
- }
- // y2 - y ... must now be less than a half piece
- // check for equals and if not blit an adjusted half piece border pieces have
- // a two pixel repeat so we will blit one pixel over if necessary to line up
- // the art, but we'll cover-up the overlap with the corners
- if( y < y2 )
- {
- y -= ((BORDER_LINE_SIZE / 2) - (((y2 - y) + 1) & ~1));
- //Blit Half piece
- TheDisplay->drawImage( borderPieces[ BORDER_VERTICAL_LEFT_SHORT ],
- x, y, x + size, y + halfSize );
- TheDisplay->drawImage( borderPieces[ BORDER_VERTICAL_RIGHT_SHORT ],
- x2, y, x2 + size, y + halfSize );
- }
- // Draw Corners
- x = originalX - BORDER_CORNER_SIZE ;
- y = originalY - BORDER_CORNER_SIZE;
- TheDisplay->drawImage( borderPieces[ BORDER_CORNER_UL ],
- x, y, x + size, y + size );
- x = maxX - 5;//BORDER_CORNER_SIZE;
- y = originalY - BORDER_CORNER_SIZE;
- TheDisplay->drawImage( borderPieces[ BORDER_CORNER_UR ],
- x, y, x + size, y + size );
- x = originalX - BORDER_CORNER_SIZE;
- y = maxY - 5;//BORDER_CORNER_SIZE;
- TheDisplay->drawImage( borderPieces[ BORDER_CORNER_LL ],
- x, y, x + size, y + size );
- x = maxX - 5;//BORDER_CORNER_SIZE;
- y = maxY - 5;//BORDER_CORNER_SIZE;
- TheDisplay->drawImage( borderPieces[ BORDER_CORNER_LR ],
- x, y, x + size, y + size );
- } // end blitBorderRect
- ///////////////////////////////////////////////////////////////////////////////
- // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- // W3DGameWindow::W3DGameWindow ===============================================
- //=============================================================================
- W3DGameWindow::W3DGameWindow( void )
- {
- // override the default draw with our own default draw function for W3D
- winSetDrawFunc( TheWindowManager->getDefaultDraw() );
- m_textPos.x = m_textPos.y = 0;
- m_currTextColor = WIN_COLOR_UNDEFINED;
- m_needPolyDraw = FALSE;
- m_newTextPos = FALSE;
- } // end W3DGameWindow
- // W3DGameWindow::~W3DGameWindow ==============================================
- //=============================================================================
- W3DGameWindow::~W3DGameWindow( void )
- {
- } // end ~W3DGameWindow
- // W3DGameWinDefaultDraw ======================================================
- /** The default redraw callback. Draws the background using either
- * the drawData or the background color unless the background color
- * is set to -1 indicating that default drawing is turned off. */
- //=============================================================================
- void W3DGameWinDefaultDraw( GameWindow *window, WinInstanceData *instData )
- {
- Real borderWidth = 1.0f;
- ICoord2D origin;
- ICoord2D size;
- W3DGameWindow *w3dWindow = (W3DGameWindow *)window;
- /** @todo NOTE that we're making a W3DGameWindow cast here, it seems
- logical because we are in a W3D draw function so it's reasonable to assume
- that we have a W3DGameWindow. However, we may want to revisit this
- type of casting in the future, we have the same problems with the
- ObjectModules where we cast object modules for their individual methods.
- Also note that the other W3D implementations of GUI controls are making
- a similar cast for their device implementation functions */
- // get the window position in the screen coordinates
- w3dWindow->winGetScreenPosition( &origin.x, &origin.y );
- // get size of window
- w3dWindow->winGetSize( &size.x, &size.y );
- // image drawing vs color drawing
- if( BitTest( window->winGetStatus(), WIN_STATUS_IMAGE ) )
- {
- const Image *image;
- // get image
- if( BitTest( window->winGetStatus(), WIN_STATUS_ENABLED ) == FALSE )
- image = window->winGetDisabledImage( 0 );
- else if( BitTest( instData->getState(), WIN_STATE_HILITED ) )
- image = window->winGetHiliteImage( 0 );
- else
- image = window->winGetEnabledImage( 0 );
- if( image )
- {
- ICoord2D start, end;
- start.x = origin.x + instData->m_imageOffset.x;
- start.y = origin.y + instData->m_imageOffset.y;
- end.x = start.x + size.x;
- end.y = start.y + size.y;
- TheWindowManager->winDrawImage( image, start.x, start.y, end.x, end.y );
- } // end if
- } // end if
- else
- {
- Color color, borderColor;
- // get colors
- if( BitTest( window->winGetStatus(), WIN_STATUS_ENABLED ) == FALSE )
- {
- color = window->winGetDisabledColor( 0 );
- borderColor = window->winGetDisabledBorderColor( 0 );
- } // end if
- else if( BitTest( instData->getState(), WIN_STATE_HILITED ) )
- {
- color = window->winGetHiliteColor( 0 );
- borderColor = window->winGetHiliteBorderColor( 0 );
- } // end else if
- else
- {
- color = window->winGetEnabledColor( 0 );
- borderColor = window->winGetEnabledBorderColor( 0 );
- } // end else
- //
- // draw the border at the edges
- //
- if( borderColor != WIN_COLOR_UNDEFINED )
- TheWindowManager->winOpenRect( borderColor, borderWidth,
- origin.x, origin.y,
- origin.x + size.x, origin.y + size.y );
- // draw filled background
- if( color != WIN_COLOR_UNDEFINED )
- TheWindowManager->winFillRect( color, borderWidth,
- origin.x + borderWidth,
- origin.y + borderWidth,
- origin.x + size.x - borderWidth,
- origin.y + size.y - borderWidth );
- } // end else
- // if we have a video buffer, draw the video buffer
- if ( instData->m_videoBuffer )
- {
- ICoord2D pos, size;
- window->winGetScreenPosition( &pos.x, &pos.y );
- window->winGetSize( &size.x, &size.y );
- TheDisplay->drawVideoBuffer( instData->m_videoBuffer, pos.x, pos.y, pos.x + size.x, pos.y + size.y );
- }
- } // end W3DGameWinDefaultDraw
- // W3DGameWindow::winDrawBorder ===============================================
- //=============================================================================
- void W3DGameWindow::winDrawBorder( void )
- {
- Bool found = FALSE;
- Int originalX, originalY;
- Int x, y;
- Int width;
- Int i, bits;
- /** @todo this WinDrawBorder is the old Nox function for drawing the borders
- * on various windows and controls. We should derive classes of game
- * windows for the different GUI controls and move the specific pieces of
- * code that apply for those gadgets to those classes */
- // based on window class pass different regions to real draw
- winGetScreenPosition( &originalX, &originalY );
- for( i = 0; (i < (sizeof(UnsignedInt) * 8)) && (found == FALSE); i++ )
- {
- bits = (1 << i);
- if( m_instData.getStyle() & bits )
- {
- switch( m_instData.getStyle() & bits )
- {
- case GWS_CHECK_BOX:
- found = TRUE;
- break;
- case GWS_ENTRY_FIELD:
- {
- // EntryData *e = (EntryData *)m_userData;
- width = m_size.x;
- x = originalX;
- y = originalY;
- // Calculate space for Label
- if( m_instData.getTextLength() )
- {
- Int textWidth = 0;
- TheWindowManager->winGetTextSize( m_instData.getFont(),
- m_instData.getText(),
- &textWidth, NULL, 0 );
- width -= textWidth + 6;
- x += textWidth + 6;
- }
- /*
- // Colin: The very notion of entry width makes no sense to me since
- // we already have a gadget width, and the max characters for
- // an entry box so I am removing this.
- // Adjust entry box if an entryWidth is provided
- if( (e->entryWidth > 0) && (width > e->entryWidth) )
- {
- width = e->entryWidth;
- x = originalX + (m_size.x - e->entryWidth);
- }
- */
- blitBorderRect( x, y, width, m_size.y );
- found = TRUE;
- break;
- }
- // Sliders may need a bar for the button
- // it is assumed that the smaller size component (width, height)
- // is the axis of the slider
- case GWS_VERT_SLIDER:
- case GWS_HORZ_SLIDER:
- // blitBorderLine( originalX, originalY, window->size.x, window->size.y );
- found = TRUE;
- break;
- case GWS_SCROLL_LISTBOX:
- {
- ListboxData *list = (ListboxData *)m_userData;
- Int sliderAdjustment = 0;
- Int labelAdjustment = 0;
- if( list->scrollBar )
- {
- GameWindow *child = list->slider->winGetChild();
- ICoord2D size;
- child->winGetSize( &size.x, &size.y );
- sliderAdjustment = size.y;
- } // end if
- if( m_instData.getTextLength() )
- labelAdjustment = 4;
- blitBorderRect( (originalX - 3),
- (originalY - (3 + labelAdjustment)),
- (m_size.x + 3 - sliderAdjustment),
- (m_size.y + 6) );
- found = TRUE;
- break;
- }
- case GWS_RADIO_BUTTON:
- case GWS_STATIC_TEXT:
- case GWS_PROGRESS_BAR:
- case GWS_PUSH_BUTTON:
- case GWS_USER_WINDOW:
- case GWS_TAB_CONTROL:
- blitBorderRect( originalX, originalY, m_size.x, m_size.y );
- found = TRUE;
- break;
- } // end switch
- } // end if
- } // end for i
- } // end WinDrawBorder
- // W3DGameWindow::winSetFont ==================================================
- /** Set the font for a widow */
- //=============================================================================
- void W3DGameWindow::winSetFont( GameFont *font )
- {
- // extending functionality
- GameWindow::winSetFont( font );
- // assign font to text renderer
- m_textRenderer.Set_Font( static_cast<FontCharsClass *>(font->fontData) );
- // this is a visual change
- m_needPolyDraw = TRUE;
- } // end WinSetFont
- // W3DGameWindow::winSetText ==================================================
- /** Set the text for window */
- //=============================================================================
- Int W3DGameWindow::winSetText( UnicodeString newText )
- {
- // extending functionality
- GameWindow::winSetText( newText );
- // rebuild the sentence in our text renderer
- m_textRenderer.Build_Sentence( m_instData.getText().str(),NULL, NULL );
- // this is a visual change
- m_needPolyDraw = TRUE;
- return WIN_ERR_OK;
-
- } // end WinSetText
- // W3DGameWindow::winSetPosition ==============================================
- /** Set window position */
- //=============================================================================
- Int W3DGameWindow::winSetPosition( Int x, Int y )
- {
- ICoord2D prevPos;
- // get previous position
- prevPos.x = m_region.lo.x;
- prevPos.y = m_region.lo.y;
- // extending functionality
- GameWindow::winSetPosition( x, y );
- // update any text position change
- m_textPos.x += m_region.lo.x - prevPos.x;
- m_textPos.y += m_region.lo.y - prevPos.y;
- m_newTextPos = TRUE;
- return WIN_ERR_OK;
- } // end WinSetPosition
- // W3DGameWindow::getTextSize =================================================
- /** Get the size of the text in our inst data */
- //=============================================================================
- void W3DGameWindow::getTextSize( Int *width, Int *height )
- {
- Vector2 extents = m_textRenderer.Get_Text_Extents( m_instData.getText().str() );
- if( width )
- *width = extents.X;
- if( height )
- *height = extents.Y;
- } // end getTextSize
- // W3DGameWindow::getTextLoc ==================================================
- // Set our text rendering location */
- //=============================================================================
- void W3DGameWindow::setTextLoc( Int x, Int y )
- {
- if( m_textPos.x != x )
- {
- m_textPos.x = x;
- m_newTextPos = TRUE;
- }
- if( m_textPos.y != y )
- {
- m_textPos.y = y;
- m_newTextPos = TRUE;
- } // end if
- } // end setTextLoc
- // W3DGameWindow::drawText ====================================================
- /** Draw the text in our 2d sentence renderer */
- //=============================================================================
- void W3DGameWindow::drawText( Color color )
- {
- Bool needDraw = FALSE;
- // if new text pos we need to redraw
- if( m_newTextPos )
- {
- m_newTextPos = FALSE;
- needDraw = TRUE;
- } // end if
- // if color switch, set new color
- if( m_currTextColor != color )
- {
- m_currTextColor = color;
- needDraw = TRUE;
- } // end if
- // draw the quads if needed
- if( needDraw || m_needPolyDraw )
- {
- UnsignedInt outline = TheWindowManager->winMakeColor( 0, 0, 0, 255 );
-
- m_textRenderer.Reset_Polys();
- m_textRenderer.Set_Location( Vector2( m_textPos.x + 1, m_textPos.y + 1 ) );
- m_textRenderer.Draw_Sentence( outline );
- m_textRenderer.Set_Location( Vector2( m_textPos.x, m_textPos.y ) );
- m_textRenderer.Draw_Sentence( m_currTextColor );
- m_needPolyDraw = FALSE;
- } // end if
- // do the render
- m_textRenderer.Render();
- } // end drawText
|