/*
** Command & Conquer Generals(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 .
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: .cpp /////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project:
//
// File name: .cpp
//
// Created:
//
// Desc:
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
#include
// USER INCLUDES //////////////////////////////////////////////////////////////
#include "GameClient/GameWindowGlobal.h"
#include "GameClient/GameWindowManager.h"
#include "GameClient/GadgetSlider.h"
#include "W3DDevice/GameClient/W3DGadget.h"
#include "W3DDevice/GameClient/W3DDisplay.h"
// DEFINES ////////////////////////////////////////////////////////////////////
// PRIVATE TYPES //////////////////////////////////////////////////////////////
// PRIVATE DATA ///////////////////////////////////////////////////////////////
// PUBLIC DATA ////////////////////////////////////////////////////////////////
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#ifdef _INTERNAL
// for occasional debugging...
//#pragma optimize("", off)
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
#endif
// W3DGadgetHorizontalSliderDraw ==============================================
/** Draw colored horizontal slider using standard graphics */
//=============================================================================
void W3DGadgetHorizontalSliderDraw( GameWindow *window, WinInstanceData *instData )
{
Color backBorder, backColor;
ICoord2D origin, size, start, end;
// get screen position and size
window->winGetScreenPosition( &origin.x, &origin.y );
window->winGetSize( &size.x, &size.y );
// get the right colors
if( BitTest( window->winGetStatus(), WIN_STATUS_ENABLED ) == FALSE )
{
backBorder = GadgetSliderGetDisabledBorderColor( window );
backColor = GadgetSliderGetDisabledColor( window );
} // end if, disabled
else if( BitTest( instData->getState(), WIN_STATE_HILITED ) )
{
backBorder = GadgetSliderGetHiliteBorderColor( window );
backColor = GadgetSliderGetHiliteColor( window );
} // end else if, hilited
else
{
backBorder = GadgetSliderGetEnabledBorderColor( window );
backColor = GadgetSliderGetEnabledColor( window );
} // end else, enabled
// draw background border and rect over whole control
if( backBorder != WIN_COLOR_UNDEFINED )
{
start.x = origin.x;
start.y = origin.y;
end.x = start.x + size.x;
end.y = start.y + size.y;
TheWindowManager->winOpenRect( backBorder, WIN_DRAW_LINE_WIDTH,
start.x, start.y, end.x, end.y );
} // end if
if( backColor != WIN_COLOR_UNDEFINED )
{
start.x = origin.x + 1;
start.y = origin.y + 1;
end.x = start.x + size.x - 2;
end.y = start.y + size.y - 2;
TheWindowManager->winFillRect( backColor, WIN_DRAW_LINE_WIDTH,
start.x, start.y, end.x, end.y );
} // end if
} // end W3DGadgetHorizontalSliderDraw
// W3DGadgetHorizontalSliderImageDraw =========================================
/** Draw horizontal slider with user supplied images */
//=============================================================================
void W3DGadgetHorizontalSliderImageDraw( GameWindow *window,
WinInstanceData *instData )
{
const Image *fillSquare, *blankSquare, *highlightSquare;
ICoord2D origin, size, start, end, highlightOffset;
// get screen position and size
window->winGetScreenPosition( &origin.x, &origin.y );
window->winGetSize( &size.x, &size.y );
highlightSquare = GadgetSliderGetHiliteImageLeft( window );
blankSquare = GadgetSliderGetDisabledImageRight( window );
fillSquare = GadgetSliderGetDisabledImageLeft( window );
SliderData *s = (SliderData *)window->winGetUserData();
Real xMulti = INT_TO_REAL(TheDisplay->getWidth()) / 800;
// figure out how many boxes we draw for this slider
Int numBoxes = 0;
Int numSelectedBoxes = 0;
Int numHighlightBoxes = 0;
Int boxWidth = fillSquare->getImageWidth()* xMulti;
Int boxPadding = 2;
start.x = origin.x;
end.x = start.x + boxWidth;
Real selectedPercent = (s->position - s->minVal)/INT_TO_REAL((s->maxVal - s->minVal));
Int maxSelectedX = origin.x + REAL_TO_INT(selectedPercent * size.x);
while(end.x < origin.x + size.x )
{
if (start.x <= maxSelectedX && end.x < origin.x + size.x && s->position != s->minVal)
++numSelectedBoxes;
start.x = end.x + boxPadding;
end.x = start.x + boxWidth;
++numBoxes;
}
numHighlightBoxes = numBoxes + 1;
Int distanceCovered = end.x - origin.x - boxWidth;
highlightOffset.x = -(boxWidth + boxPadding)/2;
highlightOffset.y = boxWidth/3;
Int blankness = size.x - distanceCovered;
origin.x += blankness/2;
Int i;
if( BitTest( instData->getState(), WIN_STATE_HILITED ) )
{
ICoord2D backgroundStart, backgroundEnd;
backgroundStart.y = origin.y + highlightOffset.y;
backgroundEnd.y = backgroundStart.y + boxWidth + boxPadding;
for (i=0; iwinDrawImage( highlightSquare,
backgroundStart.x, backgroundStart.y,
backgroundEnd.x, backgroundEnd.y );
}
}
start.y = origin.y;
end.y = start.y + boxWidth;
for (i=0; iwinDrawImage( fillSquare,
start.x, start.y,
end.x, end.y );
}
for (i=numSelectedBoxes; iwinDrawImage( blankSquare,
start.x, start.y,
end.x, end.y );
}
}
// W3DGadgetHorizontalSliderImageDraw =========================================
/** Draw horizontal slider with user supplied images */
//=============================================================================
void W3DGadgetHorizontalSliderImageDrawB( GameWindow *window,
WinInstanceData *instData )
{
const Image *fillSquare, *blankSquare, *highlightSquare;//, *progressArrow;
ICoord2D origin, size, start, end;
Int xOffset, yOffset;
// get screen position and size
window->winGetScreenPosition( &origin.x, &origin.y );
window->winGetSize( &size.x, &size.y );
SliderData *s = (SliderData *)window->winGetUserData();
Real xMulti = INT_TO_REAL(TheDisplay->getWidth()) / 800;
Real yMulti = INT_TO_REAL(TheDisplay->getHeight())/ 600;
// get image offset
xOffset = instData->m_imageOffset.x;
yOffset = instData->m_imageOffset.y;
UnicodeString tooltip, tmp;
tooltip.format(L"mult:%g/%g, img offset:%d,%d", xMulti, yMulti, xOffset, yOffset);
tmp.format(L"\norigin: %d,%d size:%d,%d", origin.x, origin.y, size.x, size.y);
tooltip.concat(tmp);
tmp.format(L"\ns= %d <--> %d, numTicks=%g, pos = %d", s->minVal, s->maxVal, s->numTicks, s->position);
tooltip.concat(tmp);
if( BitTest( instData->getState(), WIN_STATE_HILITED ) )
{
highlightSquare = GadgetSliderGetHiliteImageLeft( window );
ICoord2D backgroundStart, backgroundEnd;
backgroundStart.x = origin.x - (highlightSquare->getImageWidth() * xMulti)/2;
backgroundStart.y = origin.y + (highlightSquare->getImageHeight() *yMulti)/3;
backgroundEnd.y = backgroundStart.y + highlightSquare->getImageHeight()* yMulti;
backgroundEnd.x = backgroundStart.x + highlightSquare->getImageWidth() * xMulti;
tmp.format(L"\nHighlighted: (%d,%d) -> (%d,%d), step %d/%g, full %d/%d", backgroundStart.x, backgroundStart.y,
backgroundEnd.x, backgroundEnd.y, highlightSquare->getImageWidth(), highlightSquare->getImageWidth() * xMulti,
origin.x, size.x);
tooltip.concat(tmp);
while(backgroundStart.x < origin.x + size.x)
{
TheWindowManager->winDrawImage( highlightSquare,
backgroundStart.x, backgroundStart.y,
backgroundEnd.x, backgroundEnd.y );
backgroundStart.x = backgroundEnd.x;
backgroundEnd.x = backgroundStart.x + highlightSquare->getImageWidth() * xMulti;
}
tmp.format(L"\n bsX = %d, beX = %d (%d < %d+%d or %d?)", backgroundStart.x, backgroundEnd.x,
backgroundStart.x, origin.x, size.x, origin.x + size.x);
tooltip.concat(tmp);
}
fillSquare = GadgetSliderGetDisabledImageLeft( window );
start.x = origin.x;
start.y = origin.y;
end.y = start.y + fillSquare->getImageHeight() * yMulti;
end.x = start.x + fillSquare->getImageWidth()* xMulti;
tmp.format(L"\ntop: start=%d,%d, end=%d,%d", start.x, start.y, end.x, end.y);
tooltip.concat(tmp);
while(start.x <= origin.x + (s->numTicks * (s->position - s->minVal)) && end.x < origin.x + size.x && s->position != s->minVal)
{
TheWindowManager->winDrawImage( fillSquare,
start.x, start.y,
end.x, end.y );
start.x = end.x + 2;
end.x = start.x + fillSquare->getImageWidth()* xMulti;
}
blankSquare = GadgetSliderGetDisabledImageRight( window );
end.x = start.x + blankSquare->getImageWidth()* xMulti;
while(end.x < origin.x + size.x )
{
TheWindowManager->winDrawImage( blankSquare,
start.x, start.y,
end.x, end.y );
start.x = end.x + 2;
end.x = start.x + blankSquare->getImageWidth()* xMulti;
}
instData->setTooltipText(tooltip);
// if( BitTest( instData->getState(), WIN_STATE_HILITED ) )
// {
// progressArrow = GadgetSliderGetHiliteImageRight( window );
// if(!progressArrow)
// return;
// Int transPos = (s->numTicks * (s->position - s->minVal)) - progressArrow->getImageWidth() /2;
// start.x = origin.x + transPos;
// start.y = origin.y + fillSquare->getImageHeight()/3*2;
// end.y = start.y + progressArrow->getImageHeight();
// end.x = start.x + progressArrow->getImageWidth();
// TheWindowManager->winDrawImage( progressArrow,
// start.x, start.y,
// end.x, end.y );
// }
}
// W3DGadgetHorizontalSliderImageDraw =========================================
/** Draw horizontal slider with user supplied images */
//=============================================================================
void W3DGadgetHorizontalSliderImageDrawA( GameWindow *window,
WinInstanceData *instData )
{
const Image *leftImageLeft, *rightImageLeft, *centerImageLeft, *smallCenterImageLeft;
const Image *leftImageRight, *rightImageRight, *centerImageRight, *smallCenterImageRight;
ICoord2D origin, size, start, end;
Int xOffset, yOffset;
Int i;
// get screen position and size
window->winGetScreenPosition( &origin.x, &origin.y );
window->winGetSize( &size.x, &size.y );
SliderData *s = (SliderData *)window->winGetUserData();
Int transPos = (s->numTicks * (s->position - s->minVal)) + HORIZONTAL_SLIDER_THUMB_WIDTH/2;
IRegion2D clipLeft, clipRight;
// get image offset
xOffset = instData->m_imageOffset.x;
yOffset = instData->m_imageOffset.y;
// get the right images
if( BitTest( window->winGetStatus(), WIN_STATUS_ENABLED ) == FALSE )
{
leftImageRight = leftImageLeft = GadgetSliderGetDisabledImageLeft( window );
rightImageRight = rightImageLeft = GadgetSliderGetDisabledImageRight( window );
// centerImageRight = centerImageLeft = GadgetSliderGetDisabledImageCenter( window );
// smallCenterImageRight = smallCenterImageLeft = GadgetSliderGetDisabledImageSmallCenter( window );
} // end if, disabled
else //if( BitTest( instData->getState(), WIN_STATE_HILITED ) )
{
leftImageLeft = GadgetSliderGetHiliteImageLeft( window );
rightImageLeft = GadgetSliderGetHiliteImageRight( window );
centerImageLeft = GadgetSliderGetHiliteImageCenter( window );
smallCenterImageLeft = GadgetSliderGetHiliteImageSmallCenter( window );
leftImageRight = GadgetSliderGetEnabledImageLeft( window );
rightImageRight = GadgetSliderGetEnabledImageRight( window );
centerImageRight = GadgetSliderGetEnabledImageCenter( window );
smallCenterImageRight = GadgetSliderGetEnabledImageSmallCenter( window );
} // end else, enabled
// sanity, we need to have these images to make it look right
if( leftImageLeft == NULL || rightImageLeft == NULL ||
centerImageLeft == NULL || smallCenterImageLeft == NULL ||
leftImageRight == NULL || rightImageRight == NULL ||
centerImageRight == NULL || smallCenterImageRight == NULL )
return;
// get image sizes for the ends
ICoord2D leftSize, rightSize;
leftSize.x = leftImageLeft->getImageWidth();
leftSize.y = leftImageLeft->getImageHeight();
rightSize.x = rightImageLeft->getImageWidth();
rightSize.y = rightImageLeft->getImageHeight();
// get two key points used in the end drawing
ICoord2D leftEnd, rightStart;
leftEnd.x = origin.x + leftSize.x + xOffset;
leftEnd.y = origin.y + size.y + yOffset;
rightStart.x = origin.x + size.x - rightSize.x + xOffset;
rightStart.y = origin.y + size.y - leftSize.y + yOffset;
// draw the center repeating bar
Int centerWidth, pieces;
// get width we have to draw our repeating center in
centerWidth = rightStart.x - leftEnd.x;
// how many whole repeating pieces will fit in that width
pieces = centerWidth / centerImageLeft->getImageWidth();
// draw the pieces
start.x = leftEnd.x;
start.y = origin.y + size.y - leftSize.y + yOffset;
end.y =origin.y + size.y + yOffset;
clipLeft.lo.x = origin.x;
clipLeft.lo.y = rightStart.y;
clipLeft.hi.y = leftEnd.y;
clipLeft.hi.x = origin.x + transPos;
clipRight.lo.x = origin.x + transPos;
clipRight.lo.y = rightStart.y;
clipRight.hi.y = leftEnd.y;
clipRight.hi.x = origin.x + size.x;
for( i = 0; i < pieces; i++ )
{
end.x = start.x + centerImageLeft->getImageWidth();
TheDisplay->setClipRegion(&clipLeft);
TheWindowManager->winDrawImage( centerImageLeft,
start.x, start.y,
end.x, end.y );
TheDisplay->setClipRegion(&clipRight);
TheWindowManager->winDrawImage( centerImageRight,
start.x, start.y,
end.x, end.y );
start.x += centerImageLeft->getImageWidth();
} // end for i
//
// how many small repeating pieces will fit in the gap from where the
// center repeating bar stopped and the right image, draw them
// and overlapping underneath where the right end will go
//
centerWidth = rightStart.x - start.x;
pieces = centerWidth / smallCenterImageLeft->getImageWidth() + 1;
end.y = leftEnd.y;//start.y + smallCenterImageLeft->getImageHeight();
for( i = 0; i < pieces; i++ )
{
end.x = start.x + smallCenterImageLeft->getImageWidth();
TheDisplay->setClipRegion(&clipLeft);
TheWindowManager->winDrawImage( smallCenterImageLeft,
start.x, start.y,
end.x, end.y );
TheDisplay->setClipRegion(&clipRight);
TheWindowManager->winDrawImage( smallCenterImageRight,
start.x, start.y,
end.x, end.y );
start.x += smallCenterImageLeft->getImageWidth();
} // end for i
// draw left end
start.x = origin.x + xOffset;
start.y = rightStart.y;
end = leftEnd;
TheDisplay->setClipRegion(&clipLeft);
TheWindowManager->winDrawImage(leftImageLeft, start.x, start.y, end.x, end.y);
TheDisplay->setClipRegion(&clipRight);
TheWindowManager->winDrawImage(leftImageRight, start.x, start.y, end.x, end.y);
// draw right end
start = rightStart;
end.x = start.x + rightSize.x;
end.y = leftEnd.y;
TheDisplay->setClipRegion(&clipLeft);
TheWindowManager->winDrawImage(rightImageLeft, start.x, start.y, end.x, end.y);
TheDisplay->setClipRegion(&clipRight);
TheWindowManager->winDrawImage(rightImageRight, start.x, start.y, end.x, end.y);
TheDisplay->enableClipping(FALSE);
} // end W3DGadgetHorizontalSliderImageDraw