NS/main/source/ui/FadingImageLabel.cpp

607 lines
16 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: FadingImageLabel.cpp $
// $Date: 2002/09/09 19:46:34 $
//
//-------------------------------------------------------------------------------
// $Log: FadingImageLabel.cpp,v $
// Revision 1.16 2002/09/09 19:46:34 Flayra
// - Changes to try to make this draw properly in software
//
// Revision 1.15 2002/08/31 18:04:32 Flayra
// - Work at VALVe
//
// Revision 1.14 2002/07/23 16:52:59 Flayra
// - Added support for multiple sprite frames (for pie nodes and max sprite problem), added document headers
//
//===============================================================================
#include "ui/FadingImageLabel.h"
#include "ui/UIUtil.h"
#include "util/STLUtil.h"
#include <assert.h>
#include "cl_dll/hud.h"
#include "cl_dll/cl_util.h"
#include "common/const.h"
#include "common/com_model.h"
#include "engine/studio.h"
#include "common/entity_state.h"
#include "common/cl_entity.h"
#include "common/dlight.h"
#include "common/triangleapi.h"
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <math.h>
#include "cl_dll/studio_util.h"
#include "cl_dll/r_studioint.h"
#include "cl_dll/StudioModelRenderer.h"
#include "cl_dll/GameStudioModelRenderer.h"
extern engine_studio_api_t IEngineStudio;
const char* kFrameIndicator = "-frame";
//FadingImageLabel::FadingImageLabel(const char* inImageName, int inX, int inY)/*, int inWidth, int inHeight)*/ : CImageLabel(inImageName, inX, inY, 64, 32), mTextImage("Default text")
//{
// this->Init();
//}
FadingImageLabel::FadingImageLabel(int inX, int inY)/*, int inWidth, int inHeight)*/ : /*Panel(inX, inY, 64, 32),*/ mTextImage("Default text")
{
this->Init();
this->mImageMode = false;
}
FadingImageLabel::~FadingImageLabel()
{
}
void FadingImageLabel::DoPaint()
{
//const float thePercentToChopOffXEdge = .1f;
//const float thePercentToChopOffYEdge = 0.0f;
int theX, theY;
this->getPos(theX, theY);
//if(!IEngineStudio.IsHardware())
//{
// theX += ScreenWidth/2;
// theY += ScreenHeight/2;
//}
int theWidth, theHeight;
this->getSize(theWidth, theHeight);
//ASSERT(this->mVisibleWidth <= theWidth);
//ASSERT(this->mVisibleHeight <= theHeight);
if((this->mVisibleWidth <= theWidth) && (this->mVisibleHeight <= theHeight))
{
int r, g, b, a;
this->getBgColor(r, g, b, a);
float theGammaSlope = gHUD.GetGammaSlope();
r = r/theGammaSlope;
g = g/theGammaSlope;
b = b/theGammaSlope;
// Don't take gamma slope into account for alpha
a = 255 - a;
////int theXBorder = thePercentToChopOffXEdge*ScreenWidth;
////int theYBorder = thePercentToChopOffYEdge*ScreenHeight;
int theXBorder = (theWidth - this->mVisibleWidth)/2;
int theYBorder = (theHeight - this->mVisibleHeight)/2;
//vguiSimpleBox(theXBorder, theYBorder, theWidth - theXBorder*2 + theXBorder, theHeight - theYBorder*2 + theYBorder, r, g, b, a);
if(!this->mImageMode)
{
//FillRGBA(theXBorder, theYBorder, theWidth - theXBorder*2, theHeight - theYBorder*2, r, g, b, a);
//int theSprite = SPR_Load("sprites/marinenode.spr");
//DrawScaledHUDSprite(theSprite, kRenderTransAdd, 1, theX, theY, theWidth, theHeight, 0);
gEngfuncs.pTriAPI->RenderMode(kRenderTransAlpha);
gEngfuncs.pTriAPI->CullFace(TRI_NONE);
//gEngfuncs.pTriAPI->Brightness(1);
theX = theXBorder;
theY = theYBorder;
theWidth = theWidth - theXBorder*2;
theHeight = theHeight - theYBorder*2;
// 0 = selectable, valid
// 1 = selectable, valid, current
// 2 = selectable, invalid
// 3 = selectable, invalid, current
int theFrame = 0;
if(this->GetEnabled() && this->GetDrawHighlighted())
{
theFrame = 1;
}
else if(!this->GetEnabled())
{
theFrame = this->GetFadeState() ? 3 : 2;
}
//char theFrameNumber[64];
//sprintf(theFrameNumber, "Frame %d", theFrame);
//this->mTextImage.setText(theFrameNumber);
if(!this->mSprite)
{
this->mSprite = SPR_Load(this->mImageName.c_str());
this->mSpriteWidth = SPR_Width(this->mSprite, this->mSpriteFrame);
this->mSpriteHeight = SPR_Height(this->mSprite, this->mSpriteFrame);
ASSERT(this->mSprite > 0);
}
if(this->mSprite && gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)gEngfuncs.GetSpritePointer(this->mSprite), theFrame))
{
gEngfuncs.pTriAPI->Begin(TRI_TRIANGLE_STRIP);
vec3_t theVertex;
gEngfuncs.pTriAPI->TexCoord2f(0, 1);
theVertex.x = theX;
theVertex.y = theY + theHeight;
theVertex.z = 0;
//gEngfuncs.pTriAPI->Color4ub(255, 255, 255, a);
gEngfuncs.pTriAPI->Vertex3fv((float*)&theVertex);
gEngfuncs.pTriAPI->TexCoord2f(0, 0);
theVertex.x = theX;
theVertex.y = theY;
//gEngfuncs.pTriAPI->Color4ub(255, 255, 255, a);
gEngfuncs.pTriAPI->Vertex3fv((float*)&theVertex);
gEngfuncs.pTriAPI->TexCoord2f(1, 1);
theVertex.x = theX + theWidth;
theVertex.y = theY + theHeight;
//gEngfuncs.pTriAPI->Color4ub(255, 255, 255, a);
gEngfuncs.pTriAPI->Vertex3fv((float*)&theVertex);
gEngfuncs.pTriAPI->TexCoord2f(1, 0);
theVertex.x = theX + theWidth;
theVertex.y = theY;
//gEngfuncs.pTriAPI->Color4ub(255, 255, 255, a);
gEngfuncs.pTriAPI->Vertex3fv((float*)&theVertex);
gEngfuncs.pTriAPI->End();
}
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
}
else
{
SPR_Set(this->mSprite, a, a, a);
int theSpriteWidth = SPR_Width(this->mSprite, this->mSpriteFrame);
int theSpriteHeight = SPR_Height(this->mSprite, this->mSpriteFrame);
//SPR_DrawAdditive(theFrame, (theWidth - theSpriteWidth)/2, (theHeight - theSpriteHeight)/2, NULL);
SPR_DrawHoles(this->mSpriteFrame, (theWidth - theSpriteWidth)/2, (theHeight - theSpriteHeight)/2, NULL);
}
}
}
void FadingImageLabel::FadedIn()
{
Panel::setVisible(true);
}
void FadingImageLabel::FadedOut()
{
Panel::setVisible(false);
}
//vgui::Color FadingImageLabel::GetColor() const
//{
// return vgui::Color(255, 255, 255, this->GetValveAlpha());
//}
void FadingImageLabel::getBgColor(int& r, int& g, int& b, int& a)
{
Panel::getBgColor(r, g, b, a);
a = this->GetValveAlpha();
}
void FadingImageLabel::getBgColor(Color& outColor)
{
Panel::getBgColor(outColor);
int r, g, b, a;
outColor.getColor(r, g, b, a);
a = this->GetValveAlpha();
outColor.setColor(r, g, b, a);
}
void FadingImageLabel::getContentSize(int& wide, int& tall)
{
if(!this->mImageMode)
{
this->getTextSize(wide, tall);
}
else
{
wide = this->mSpriteWidth;
tall = this->mSpriteHeight;
}
}
bool FadingImageLabel::GetDrawHighlighted() const
{
return false;
}
bool FadingImageLabel::GetEnabled() const
{
return true;
}
bool FadingImageLabel::GetFadeState() const
{
return this->mFadeToVisibiltyState;
}
void FadingImageLabel::getTextSize(int& wide,int& tall)
{
int theTextWidth, theTextHeight;
this->mTextImage.getTextSize(theTextWidth, theTextHeight);
wide = theTextWidth;
tall = theTextHeight;
if(this->mSpriteWidth > theTextWidth)
{
theTextWidth = this->mSpriteWidth;
}
if(this->mSpriteHeight > theTextHeight)
{
theTextHeight = this->mSpriteHeight;
}
}
int FadingImageLabel::GetValveAlpha() const
{
return this->mValveAlpha;
}
void FadingImageLabel::GetVisibleSize(int& outWidth, int& outHeight)
{
outWidth = this->mVisibleWidth;
outHeight = this->mVisibleHeight;
}
void FadingImageLabel::Init()
{
// default time to fade in or out
this->mBaseFadeTime = .3f;
this->mTimeToFade = this->mBaseFadeTime;
this->mTimeVisChanged = -1;
this->mTimeScalar = 0.0f;
this->mMaxAlpha = 1.0f;
this->mVisibleWidth = 0;
this->mVisibleHeight = 0;
// this needs to be set to our visibility
this->mFadeToVisibiltyState = false;
this->mAlwaysDrawText = false;
// Valve keeps alpha backwards
this->mValveAlpha = (this->isVisible() ? 0 : 255);
this->mImageMode = false;
this->mSprite = 0;
this->mSpriteWidth = this->mSpriteHeight = 0;
this->mSpriteFrame = 0;
}
void FadingImageLabel::paint()
{
// Calculate current translucency
float theAlphaToUse = (this->mFadeToVisibiltyState ? this->mTimeScalar : 1.0f - this->mTimeScalar);
// Bias in accelerated fashion for dramatic effect (maps to sin(0-pi/2) so it fades fast then slows down)
theAlphaToUse = sin(theAlphaToUse*3.141519/2.0f);
// For some reason Valve thinks alpha of 255 is transparent
this->mValveAlpha = 255 - (int)(255.0f*theAlphaToUse);
//int r, g, b, a;
//theColor.getColor(r, g, b, a);
//this->setFgColor(r, g, b, a);
// Set translucency
//if(this->m_pTGA)
//{
// //this->m_pTGA->setColor(this->GetColor());
// vgui::Color theColor;
// this->getBgColor(theColor);
// //this->setBgColor(theColor);
// this->m_pTGA->setColor(theColor);
//
// //int r, g, b, a;
// //theColor.getColor(r, g, b, a);
// //this->setFgColor(r, g, b, a);
//}
//else
//{
// ASSERT(false);
//}
// Figure out whether we're in image mode or not
this->DoPaint();
// Draw text on top when faded in (check < 2 in case rounding makes it negative)
if((this->mValveAlpha < 2 || this->mAlwaysDrawText) && (!this->mImageMode))
{
// Fade text out as well
Color theColor;
this->mTextImage.getColor(theColor);
int r, g, b, a;
theColor.getColor(r, g, b, a);
//theColor.setColor(r, g, b, this->mValveAlpha);
//this->mTextImage.setColor(theColor);
//this->mTextImage.doPaint(this);
int theX, theY;
this->getPos(theX, theY);
int theWidth, theHeight;
this->getSize(theWidth, theHeight);
const AvHFont& theFont = gHUD.GetSmallFont();
float theTextX = (theWidth - theFont.GetStringWidth(mText.c_str())) / 2;
float theTextY = (theHeight - theFont.GetStringHeight()) / 2;
theFont.DrawString(theTextX, theTextY, mText.c_str(), r, g, b);
}
}
void FadingImageLabel::paintBackground()
{
// Do nothing, we don't draw in our bg color anymore, we only draw in FillRGBA
}
// Called
void FadingImageLabel::RecalculateTextPosition()
{
int theLabelWidth, theLabelHeight;
this->getSize(theLabelWidth, theLabelHeight);
int theTextWidth, theTextHeight;
this->mTextImage.getTextSize(theTextWidth, theTextHeight);
// Center text in middle of label
if((theTextWidth <= theLabelWidth) && (theTextHeight <= theLabelHeight))
{
this->mTextImage.setPos(theLabelWidth/2 - theTextWidth/2, theLabelHeight/2 - theTextHeight/2);
}
// If it can't be centered on image, align with upper left corner
else
{
this->mTextImage.setPos(0, 0);
}
// Center image now
//int theImageWidth = this->getImageWide();
//int theImageHeight = this->getImageTall();
//int theImageX = theLabelWidth/2 - theImageWidth/2;
//int theImageY = theLabelHeight/2 - theImageHeight/2;
//this->m_pTGA->setPos(theImageX, theImageY);
}
void FadingImageLabel::SetAlwaysDrawText(bool inState)
{
this->mAlwaysDrawText = inState;
}
void FadingImageLabel::SetBaseFadeTime(float inSeconds)
{
this->mBaseFadeTime = inSeconds;
}
void FadingImageLabel::SetFadeState(bool inNewState)
{
// if new state is different
if(this->mFadeToVisibiltyState != inNewState)
{
// set fade to state
this->mFadeToVisibiltyState = inNewState;
float theCurrentTime = ::gHUD.m_flTime;
// set new fade to time in case a change was specified during a change
this->mTimeToFade = min(this->mBaseFadeTime, (theCurrentTime - this->mTimeVisChanged));
this->mMaxAlpha = min(1.0f, (theCurrentTime - this->mTimeVisChanged)/this->mBaseFadeTime);
// remember time that it was set
this->mTimeVisChanged = theCurrentTime;
// if new state is visible, set vgui::Panel::setVisible(true)
if(!this->isVisible() && inNewState)
{
this->FadedIn();
}
}
}
void FadingImageLabel::setFont(Scheme::SchemeFont inSchemeFont)
{
this->mTextImage.setFont(inSchemeFont);
}
void FadingImageLabel::setFont(Font* inFont)
{
ASSERT(inFont != NULL);
this->mTextImage.setFont(inFont);
// Sanity check
Font* theFont = this->mTextImage.getFont();
}
void FadingImageLabel::setPos(int x,int y)
{
// Don't set size smaller than we need for out text though!
Panel::setPos(x, y);
this->RecalculateTextPosition();
}
void FadingImageLabel::setSize(int wide,int tall)
{
//int theTextWidth, theTextHeight;
//this->mTextImage.getTextSize(theTextWidth, theTextHeight);
//int theNewWidth = max(wide, theTextWidth);
//int theNewHeight = max(tall, theTextHeight);
//CImageLabel::setSize(theNewWidth, theNewHeight);
Panel::setSize(wide, tall);
this->RecalculateTextPosition();
}
void FadingImageLabel::SetSizeKeepCenter(int inWidth, int inHeight)
{
int theX, theY;
this->getPos(theX, theY);
int theOldWidth, theOldHeight;
this->getSize(theOldWidth, theOldHeight);
// Calculate center of label
int theCenterX = theX + theOldWidth/2;
int theCenterY = theY + theOldHeight/2;
int theXDiff = (theOldWidth - inWidth)/2;
int theYDiff = (theOldHeight - inHeight)/2;
this->setSize(inWidth, inHeight);
this->setPos(theX + theXDiff, theY + theYDiff);
// Did it work?
int theNewX, theNewY;
this->getPos(theNewX, theNewY);
int theNewCenterX = theNewX + inWidth/2;
int theNewCenterY = theNewY + inHeight/2;
// Does the new center equal the old center?
ASSERT(abs(theNewCenterX - theCenterX) <= 1);
ASSERT(abs(theNewCenterY - theCenterY) <= 1);
}
void FadingImageLabel::SetSpriteName(const string& inSpriteName)
{
this->mImageName = inSpriteName;
}
void FadingImageLabel::setText(const char* inText)
{
//if(this->mSprite == 0)
//{
if(*inText == '!')
{
this->mImageMode = true;
this->mTextImage.setText("");
this->mText = "";
// If image name has '-frame' in it, then we draw a frame out of the sprite
string theImageName = string(inText + 1);
size_t theIndex = theImageName.find(kFrameIndicator);
if(theIndex != std::string::npos)
{
// Parse out frame number
string theFrameString = theImageName.substr(theIndex + strlen(kFrameIndicator));
this->mSpriteFrame = MakeIntFromString(theFrameString);
// Set theImageName
theImageName = theImageName.substr(0, theIndex);
}
this->SetSpriteName(theImageName);
}
else
{
this->mTextImage.setText(inText);
this->mText = inText;
this->RecalculateTextPosition();
}
//}
}
void FadingImageLabel::setVisible(bool inVisibility)
{
Panel::setVisible(inVisibility);
this->mValveAlpha = (this->isVisible() ? 0 : 255);
}
void FadingImageLabel::SetVisibleSize(int inVisWidth, int inVisHeight)
{
int theWidth, theHeight;
this->getSize(theWidth, theHeight);
this->mVisibleWidth = min(inVisWidth, theWidth);
this->mVisibleHeight = min(inVisHeight, theHeight);
}
void FadingImageLabel::setVisibleWithoutFading(bool inNewState)
{
this->mFadeToVisibiltyState = inNewState;
this->mTimeToFade = 0.0f;
Panel::setVisible(inNewState);
// TODO: Call FadedIn or FadedOut?
}
void FadingImageLabel::Update(float theCurrentTime)
{
bool theIsVisible = this->isVisible();
// if fade-to state different than our current state
//if((theIsVisible != this->mFadeToVisibiltyState) && (this->mTimeVisChanged != -1))
if(this->mTimeVisChanged != -1)
{
// set current alpha scalar depending on time since fade invoked
this->mTimeScalar = min((theCurrentTime - this->mTimeVisChanged)/this->mTimeToFade, 1);
// if fade-to time has passed and we were fading out, set vgui::Panel::setVisible(false);
if(!this->mFadeToVisibiltyState && this->mTimeScalar >= 1.0f)
{
if(theIsVisible)
{
this->FadedOut();
}
}
}
}
void FadingImageLabel::VidInit(void)
{
// Can we unload the sprite?
this->mSprite = 0;
this->mSpriteWidth = this->mSpriteHeight = 0;
}