mirror of
https://github.com/unknownworlds/NS.git
synced 2024-11-22 20:51:36 +00:00
8552ac617c
git-svn-id: https://unknownworlds.svn.cloudforge.com/ns1@1 67975925-1194-0748-b3d5-c16f83f1a3a1
545 lines
15 KiB
C++
545 lines
15 KiB
C++
//======== (C) Copyright 2002 Charles G. Cleveland All rights reserved. =========
|
|
//
|
|
// The copyright to the contents herein is the property of Charles G. Cleveland.
|
|
// The contents may be used and/or copied only with the written permission of
|
|
// Charles G. Cleveland, or in accordance with the terms and conditions stipulated in
|
|
// the agreement/contract under which the contents have been supplied.
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $Workfile: UIUtil.cpp $
|
|
// $Date: 2002/05/23 04:03:05 $
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
// $Log: UIUtil.cpp,v $
|
|
// Revision 1.8 2002/05/23 04:03:05 Flayra
|
|
// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
|
|
//
|
|
//===============================================================================
|
|
#include "ui/UIUtil.h"
|
|
#include "ui/UITags.h"
|
|
#include "VGUI_Label.h"
|
|
#include "cl_dll/hud.h"
|
|
#include "cl_dll/cl_util.h"
|
|
|
|
void UIDrawVariableBarSpriteHoles(int inSprite, int inX, int inY, float inPercentage, float inGammaSlope, bool inTrueHolesFalseAdditive, float inSecondaryPercentage)
|
|
{
|
|
// Assumes that frame 0 is the empty sprite, frame 1 is full sprite
|
|
const int kEmptyFrame = 0;
|
|
const int kFullFrame = 1;
|
|
|
|
int theSpriteWidth = SPR_Width(inSprite, kFullFrame);
|
|
int theSpriteHeight = SPR_Height(inSprite, kFullFrame);
|
|
|
|
int theColorComponent = 255/inGammaSlope;
|
|
|
|
// Draw empty sprite
|
|
SPR_Set(inSprite, theColorComponent, theColorComponent, theColorComponent);
|
|
if(inTrueHolesFalseAdditive)
|
|
{
|
|
SPR_DrawHoles(kEmptyFrame, inX, inY, NULL);
|
|
}
|
|
else
|
|
{
|
|
SPR_DrawAdditive(kEmptyFrame, inX, inY, NULL);
|
|
}
|
|
|
|
// Draw secondary level if specified, at half brightness
|
|
int theFilledHeight = theSpriteHeight*inPercentage;
|
|
if(inSecondaryPercentage != -1)
|
|
{
|
|
theFilledHeight = theSpriteHeight*inSecondaryPercentage;
|
|
int theSecondaryColorComponent = .5f*theColorComponent;
|
|
|
|
SPR_EnableScissor(inX, inY + (theSpriteHeight - theFilledHeight), theSpriteWidth, theFilledHeight);
|
|
|
|
SPR_Set(inSprite, theSecondaryColorComponent, theSecondaryColorComponent, theSecondaryColorComponent);
|
|
if(inTrueHolesFalseAdditive)
|
|
{
|
|
SPR_DrawHoles(kFullFrame, inX, inY, NULL);
|
|
}
|
|
else
|
|
{
|
|
SPR_DrawAdditive(kFullFrame, inX, inY, NULL);
|
|
}
|
|
|
|
SPR_DisableScissor();
|
|
}
|
|
|
|
theFilledHeight = theSpriteHeight*inPercentage;
|
|
|
|
// Draw partially full sprite
|
|
// Enable scissor so it's not all drawn
|
|
SPR_EnableScissor(inX, inY + (theSpriteHeight - theFilledHeight), theSpriteWidth, theFilledHeight);
|
|
|
|
SPR_Set(inSprite, theColorComponent, theColorComponent, theColorComponent);
|
|
if(inTrueHolesFalseAdditive)
|
|
{
|
|
SPR_DrawHoles(kFullFrame, inX, inY, NULL);
|
|
}
|
|
else
|
|
{
|
|
SPR_DrawAdditive(kFullFrame, inX, inY, NULL);
|
|
}
|
|
|
|
SPR_DisableScissor();
|
|
}
|
|
|
|
void UIGetPosition(const TRDescription& inDesc, float& outXPos, float& outYPos, int& outWidth, int& outHeight)
|
|
{
|
|
outXPos = UIDefaultXPos;
|
|
outYPos = UIDefaultYPos;
|
|
outWidth = UIDefaultWidth;
|
|
outHeight = UIDefaultHeight;
|
|
|
|
// Get normalized xpos if specified. Don't care if they aren't specified, it will just fail and not change the default.
|
|
inDesc.GetTagValue(UITagXPos, outXPos);
|
|
inDesc.GetTagValue(UITagYPos, outYPos);
|
|
inDesc.GetTagValue(UITagWidth, outWidth);
|
|
inDesc.GetTagValue(UITagHeight, outHeight);
|
|
}
|
|
|
|
void UIStringToAlignment(const string& inString, int outAlignment)
|
|
{
|
|
if(inString == "northwest")
|
|
{
|
|
outAlignment = vgui::Label::a_northwest;
|
|
}
|
|
else if(inString == "north")
|
|
{
|
|
outAlignment = vgui::Label::a_north;
|
|
}
|
|
else if(inString == "northeast")
|
|
{
|
|
outAlignment = vgui::Label::a_northeast;
|
|
}
|
|
else if(inString == "west")
|
|
{
|
|
outAlignment = vgui::Label::a_west;
|
|
}
|
|
else if(inString == "center")
|
|
{
|
|
outAlignment = vgui::Label::a_center;
|
|
}
|
|
else if(inString == "east")
|
|
{
|
|
outAlignment = vgui::Label::a_east;
|
|
}
|
|
else if(inString == "southwest")
|
|
{
|
|
outAlignment = vgui::Label::a_southwest;
|
|
}
|
|
else if(inString == "south")
|
|
{
|
|
outAlignment = vgui::Label::a_southeast;
|
|
}
|
|
else
|
|
{
|
|
// Default is centered
|
|
outAlignment = UIDefaultAlignment;
|
|
}
|
|
}
|
|
|
|
void UIStringToColor(const string& inString, vgui::Color& outColor)
|
|
{
|
|
// Set default rgba in case the string is totally bogus (default is opaque white)
|
|
int r = 255;
|
|
int g = 255;
|
|
int b = 255;
|
|
int a = 255;
|
|
int theColor = 0;
|
|
|
|
// Get rgba values from inString
|
|
if(sscanf(inString.c_str(), "%x", &theColor) == 1)
|
|
{
|
|
r = (theColor >> 24) & 0xFF;
|
|
g = (theColor >> 16) & 0xFF;
|
|
b = (theColor >> 8) & 0xFF;
|
|
a = (theColor >> 0) & 0xFF;
|
|
}
|
|
|
|
// Set it to the read in values or the default if we couldn't read it
|
|
outColor.setColor(r, g, b, a);
|
|
}
|
|
|
|
char UIKeyCodeToChar(vgui::KeyCode inKeyCode)
|
|
{
|
|
static char theLookup[57] = {
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
'\\', '*', '-', '+',
|
|
'\n', '.', '[', ']',
|
|
';', '\'', '\\',
|
|
};
|
|
|
|
int theOffset = (int)(inKeyCode);
|
|
ASSERT(theOffset >= 0);
|
|
ASSERT(theOffset < 57);
|
|
|
|
char theReturnChar = theLookup[theOffset];
|
|
return theReturnChar;
|
|
}
|
|
|
|
string UINameToSprite(const string& inName, int inScreenWidth, bool inNoRes)
|
|
{
|
|
string theSpriteName;
|
|
|
|
// Add 640/320 also
|
|
string thePrefix;
|
|
if(!inNoRes)
|
|
{
|
|
thePrefix = "640";
|
|
if(inScreenWidth < 640)
|
|
{
|
|
thePrefix = "320";
|
|
}
|
|
}
|
|
|
|
theSpriteName = "sprites/" + thePrefix;
|
|
theSpriteName += inName;
|
|
theSpriteName += ".spr";
|
|
|
|
return theSpriteName;
|
|
}
|
|
|
|
vgui::Color UIBlendColor(const vgui::Color& inBaseColor, const vgui::Color& inDestColor, float inParametricPercentage)
|
|
{
|
|
ASSERT(inParametricPercentage >= 0.0f);
|
|
ASSERT(inParametricPercentage <= 1.0f);
|
|
|
|
vgui::Color theBaseColor = inBaseColor;
|
|
vgui::Color theDestColor = inDestColor;
|
|
|
|
int theBaseR, theBaseG, theBaseB, theBaseA;
|
|
theBaseColor.getColor(theBaseR, theBaseG, theBaseB, theBaseA);
|
|
|
|
int theDestR, theDestG, theDestB, theDestA;
|
|
theDestColor.getColor(theDestR, theDestG, theDestB, theDestA);
|
|
|
|
int theOutR = theBaseR + (theDestR - theBaseR)*inParametricPercentage;
|
|
int theOutG = theBaseG + (theDestG - theBaseG)*inParametricPercentage;
|
|
int theOutB = theBaseB + (theDestB - theBaseB)*inParametricPercentage;
|
|
int theOutA = theBaseA + (theDestA - theBaseA)*inParametricPercentage;
|
|
|
|
vgui::Color theBlendedColor;
|
|
theBlendedColor.setColor(theOutR, theOutG, theOutB, theOutA);
|
|
|
|
return theBlendedColor;
|
|
}
|
|
|
|
int vguiRound(float inFloat)
|
|
{
|
|
return (int)(inFloat + .5f);
|
|
}
|
|
|
|
int vguiAbs(int inNum)
|
|
{
|
|
return (inNum > -inNum ? inNum : -inNum);
|
|
}
|
|
|
|
void vguiSimpleLine(int x0, int y0, int x1, int y1, int r, int g, int b, int a)
|
|
{
|
|
//public void lineImproved(int x0, int y0, int x1, int y1, Color color)
|
|
//{
|
|
//int pix = color.getRGB();
|
|
int dx = x1 - x0;
|
|
int dy = y1 - y0;
|
|
|
|
//raster.setPixel(pix, x0, y0);
|
|
FillRGBA(x0, y0, 1, 1, r, g, b, a);
|
|
//if (Math.abs(dx) > Math.abs(dy)) { // slope < 1
|
|
if(vguiAbs(dx) > vguiAbs(dy))
|
|
{
|
|
float m = (float) dy / (float) dx; // compute slope
|
|
float b = y0 - m*x0;
|
|
dx = (dx < 0) ? -1 : 1;
|
|
while (x0 != x1)
|
|
{
|
|
x0 += dx;
|
|
//raster.setPixel(pix, x0, Math.round(m*x0 + b));
|
|
FillRGBA(x0, vguiRound(m*x0 + b), 1, 1, r, g, b, a);
|
|
}
|
|
}
|
|
else if (dy != 0)
|
|
{ // slope >= 1
|
|
float m = (float) dx / (float) dy; // compute slope
|
|
float b = x0 - m*y0;
|
|
dy = (dy < 0) ? -1 : 1;
|
|
while (y0 != y1)
|
|
{
|
|
y0 += dy;
|
|
//raster.setPixel(pix, Math.round(m*y0 + b), y0);
|
|
FillRGBA(vguiRound(m*y0 + b), y0, 1, 1, r, g, b, a);
|
|
}
|
|
}
|
|
//}
|
|
}
|
|
|
|
void vguiSimpleBox(int x0, int y0, int x1, int y1, int r, int g, int b, int a)
|
|
{
|
|
// Draw lines around edges of box, don't duplicate corner pixels though, looks weird where additive
|
|
|
|
// Top
|
|
vguiSimpleLine(x0, y0, x1, y0, r, g, b, a);
|
|
|
|
// Left
|
|
vguiSimpleLine(x0, y0+1, x0, y1, r, g, b, a);
|
|
|
|
// Right
|
|
vguiSimpleLine(x1, y0+1, x1, y1, r, g, b, a);
|
|
|
|
// Bottom
|
|
vguiSimpleLine(x0+1, y1, x1, y1, r, g, b, a);
|
|
}
|
|
|
|
//int trunc(float inX)
|
|
//{
|
|
// return 0;
|
|
// //return integer part of x
|
|
//}
|
|
//
|
|
//float frac(float inX)
|
|
//{
|
|
// return 0.0f;
|
|
// //return fractional part of x
|
|
//}
|
|
//
|
|
//float invfrac(inX)
|
|
//{
|
|
// return 0.0f;
|
|
// //return 1 - (fractional part of x)
|
|
//}
|
|
//
|
|
//
|
|
//void vguiWuLine(int x1, int y1, int x2, int y2)
|
|
//{
|
|
//
|
|
// variable declerations:
|
|
// int variables:
|
|
// grad, xd, yd, length,xm,ym
|
|
// xgap, ygap, xend, yend, xf, yf
|
|
// brigheness1, brigheness2
|
|
//
|
|
// integer variables:
|
|
// x, y, ix1, ix2, iy1, iy2
|
|
//
|
|
// byte variables:
|
|
// c1,c2
|
|
//
|
|
// code starts here:
|
|
//
|
|
// Width and Height of the line
|
|
// xd = (x2-x1)
|
|
// yd = (y2-y1)
|
|
//
|
|
//
|
|
// if abs(xd) > abs(yd) then check line gradient
|
|
// horizontal(ish) lines
|
|
//
|
|
//
|
|
// if x1 > x2 then if line is back to front
|
|
// swap x1 and x2 then swap it round
|
|
// swap y1 and y2
|
|
// xd = (x2-x1) and recalc xd & yd
|
|
// yd = (y2-y1)
|
|
// end if
|
|
//
|
|
// grad = yd/xd gradient of the line
|
|
//
|
|
//
|
|
// End Point 1
|
|
// -----------
|
|
//
|
|
// xend = trunc(x1+.5) find nearest integer X-coordinate
|
|
// yend = y1 + grad*(xend-x1) and corresponding Y value
|
|
//
|
|
// xgap = invfrac(x1+.5) distance i
|
|
//
|
|
// ix1 = int(xend) calc screen coordinates
|
|
// iy1 = int(yend)
|
|
//
|
|
// brightness1 = invfrac(yend) * xgap calc the intensity of the other
|
|
// brightness2 = frac(yend) * xgap end point pixel pair.
|
|
//
|
|
// c1 = byte(brightness1 * MaxPixelValue) calc pixel values
|
|
// c2 = byte(brightness2 * MaxPixelValue)
|
|
//
|
|
// DrawPixel(ix1,iy1), c1 draw the pair of pixels
|
|
// DrawPixel(ix1,iy1+1), c2
|
|
//
|
|
// yf = yend+grad calc first Y-intersection for
|
|
// main loop
|
|
//
|
|
// End Point 2
|
|
// -----------
|
|
//
|
|
// xend = trunc(x2+.5) find nearest integer X-coordinate
|
|
// yend = y2 + grad*(xend-x2) and corresponding Y value
|
|
//
|
|
// xgap = invfrac(x2-.5) distance i
|
|
//
|
|
// ix2 = int(xend) calc screen coordinates
|
|
// iy2 = int(yend)
|
|
//
|
|
// brightness1 = invfrac(yend) * xgap calc the intensity of the first
|
|
// brightness2 = frac(yend) * xgap end point pixel pair.
|
|
//
|
|
// c1 = byte(brightness1 * MaxPixelValue) calc pixel values
|
|
// c2 = byte(brightness2 * MaxPixelValue)
|
|
//
|
|
// DrawPixel(ix2,iy2), c1 draw the pair of pixels
|
|
// DrawPixel(ix2,iy2+1), c2
|
|
//
|
|
//
|
|
//
|
|
// MAIN LOOP
|
|
// ---------
|
|
//
|
|
// Loop x from (ix1+1) to (ix2-1) main loop
|
|
//
|
|
// brightness1 = invfrac(yf) calc pixel brightnesses
|
|
// brightness2 = frac(yf)
|
|
//
|
|
// c1 = byte(brightness1 * MaxPixelValue) calc pixel values
|
|
// c2 = byte(brightness2 * MaxPixelValue)
|
|
//
|
|
// DrawPixel(x,int(yf)), c1 draw the pair of pixels
|
|
// DrawPixel(x,int(yf)+1), c2
|
|
//
|
|
// yf = yf + grad update the y-coordinate
|
|
//
|
|
// end of x loop end of loop
|
|
//
|
|
// else
|
|
// vertical(ish) lines
|
|
//
|
|
// handle the vertical(ish) lines in the
|
|
// same way as the horizontal(ish) ones
|
|
// but swap the roles of X and Y
|
|
// end if
|
|
//// end of procedure
|
|
//}
|
|
|
|
|
|
//void vguiDrawLine(int x0, int y0, int x1, int y1, vgui::Color inDrawColor) {
|
|
// int dx, dy, temp;
|
|
//
|
|
// // First clip input points to ICanvas
|
|
// if(x0 < 0) {
|
|
// x0 = 0;
|
|
// }
|
|
// if(x1 < 0) {
|
|
// x1 = 0;
|
|
// }
|
|
// if(x0 >= width) {
|
|
// x0 = width - 1;
|
|
// }
|
|
// if(x1 >= width) {
|
|
// x1 = width - 1;
|
|
// }
|
|
// if(y0 < 0) {
|
|
// y0 = 0;
|
|
// }
|
|
// if(y1 < 0) {
|
|
// y1 = 0;
|
|
// }
|
|
// if(y0 >= height) {
|
|
// y0 = height - 1;
|
|
// }
|
|
// if(y1 >= height) {
|
|
// y1 = height - 1;
|
|
// }
|
|
//
|
|
// dx = x1-x0;
|
|
// dy = y1-y0;
|
|
//
|
|
// if(y0 == y1) { // Special case horizontal lines!
|
|
// if(dx < 0) {
|
|
// dx = -dx; // Change to dx = -dx;
|
|
// x0 = x1;
|
|
// }
|
|
// // Call asm_drawHorizontalLine
|
|
// drawHorizontalLine(x0, y0, dx, inDrawColor);
|
|
// return;
|
|
// }
|
|
//
|
|
// if(x0 == x1) {
|
|
// if(dy < 0) {
|
|
// dy = -dy;
|
|
// y0 = y1;
|
|
// }
|
|
// // Call asm_drawVerticalLine
|
|
// drawVerticalLine(x0, y0, dy, inDrawColor);
|
|
// return;
|
|
// }
|
|
//
|
|
// bufferDest = (unsigned long)(buffer + y0*width + x0);
|
|
// if(fabs(dx) > fabs(dy)) {
|
|
// // We're going to call octant0
|
|
// oldYFract = (float)((float)(y1 - y0)/(float)fabs(x1 - x0));
|
|
// bufferWidth = width;
|
|
// if(oldYFract < 0) {
|
|
// oldYFract = -oldYFract; // Probably not needed cause sign bit shifted out
|
|
// bufferWidth = -width;
|
|
// }
|
|
// oldYFract++;
|
|
// if(x0 < x1) {
|
|
// drawDirection = 1;
|
|
// } else {
|
|
// drawDirection = -1;
|
|
// }
|
|
// if(fabs(dx) != 0) {
|
|
// octant0(fabs(dx));
|
|
// }
|
|
// } else {
|
|
// // We're going to call octant1
|
|
// oldXFract = (float)((float)(x1 - x0)/(float)fabs((y1 - y0)));
|
|
// oldXFract++;
|
|
// drawDirection = 1;
|
|
// if(oldXFract < 0) {
|
|
// oldXFract = -oldXFract;
|
|
// drawDirection = -1;
|
|
// }
|
|
// if(y0 < y1) {
|
|
// bufferWidth = width;
|
|
// } else {
|
|
// bufferWidth = -width;
|
|
// }
|
|
// if(fabs(dy) != 0) {
|
|
// octant1(fabs(dy));
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
//void vguiOctant0(int inBufferDest, int inDeltaX, vgui::Color inDrawColor)
|
|
//{
|
|
// asm_octant0_ PROC NEAR
|
|
// ; Set up destination
|
|
// mov edi,[_bufferDest]
|
|
// mov bl,[_drawColor]
|
|
|
|
|
|
//
|
|
// ; Set up fractional error
|
|
// mov eax,[_oldYFract]
|
|
// shl eax,9
|
|
// xor ax,ax
|
|
// mov [_yFract],eax
|
|
//; xor eax,eax
|
|
// xor edx,edx
|
|
//
|
|
//NOTDONEOCTANT0:
|
|
// mov [edi],bl
|
|
// ;inc edi
|
|
// add edi,[_drawDirection]
|
|
//
|
|
// ; Now just figure out whether we go to the next line or not
|
|
// add edx,[_yFract]
|
|
// jnc DONTADDOCTANT0
|
|
// add edi,[_bufferWidth]
|
|
//DONTADDOCTANT0:
|
|
// sub ecx,1
|
|
// jnz NOTDONEOCTANT0
|
|
// ret
|
|
//}
|