//======== (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 #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 #include #include #include #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 = Safe_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 = Safe_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; }