diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/vgui2/vgui_controls/AnimationController.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/vgui2/vgui_controls/AnimationController.cpp')
| -rw-r--r-- | mp/src/vgui2/vgui_controls/AnimationController.cpp | 3300 |
1 files changed, 1650 insertions, 1650 deletions
diff --git a/mp/src/vgui2/vgui_controls/AnimationController.cpp b/mp/src/vgui2/vgui_controls/AnimationController.cpp index a618231c..76a35250 100644 --- a/mp/src/vgui2/vgui_controls/AnimationController.cpp +++ b/mp/src/vgui2/vgui_controls/AnimationController.cpp @@ -1,1651 +1,1651 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-#pragma warning( disable : 4244 ) // conversion from 'double' to 'float', possible loss of data
-
-#include <vgui/IScheme.h>
-#include <vgui/ISurface.h>
-#include <vgui/ISystem.h>
-#include <vgui/IVGui.h>
-#include <KeyValues.h>
-#include <vgui_controls/AnimationController.h>
-#include "filesystem.h"
-#include "filesystem_helpers.h"
-
-#include <stdio.h>
-#include <math.h>
-#include "mempool.h"
-#include "utldict.h"
-#include "mathlib/mathlib.h"
-#include "characterset.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include <tier0/dbg.h>
-// for SRC
-#include <vstdlib/random.h>
-#include <tier0/memdbgon.h>
-
-using namespace vgui;
-
-static CUtlSymbolTable g_ScriptSymbols(0, 128, true);
-
-// singleton accessor for animation controller for use by the vgui controls
-namespace vgui
-{
-AnimationController *GetAnimationController()
-{
- static AnimationController *s_pAnimationController = new AnimationController(NULL);
- return s_pAnimationController;
-}
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructor
-//-----------------------------------------------------------------------------
-AnimationController::AnimationController(Panel *parent) : BaseClass(parent, NULL)
-{
- m_hSizePanel = 0;
- m_nScreenBounds[ 0 ] = m_nScreenBounds[ 1 ] = -1;
- m_nScreenBounds[ 2 ] = m_nScreenBounds[ 3 ] = -1;
-
- m_bAutoReloadScript = false;
-
- // always invisible
- SetVisible(false);
-
- SetProportional(true);
-
- // get the names of common types
- m_sPosition = g_ScriptSymbols.AddString("position");
- m_sSize = g_ScriptSymbols.AddString("size");
- m_sFgColor = g_ScriptSymbols.AddString("fgcolor");
- m_sBgColor = g_ScriptSymbols.AddString("bgcolor");
-
- m_sXPos = g_ScriptSymbols.AddString("xpos");
- m_sYPos = g_ScriptSymbols.AddString("ypos");
- m_sWide = g_ScriptSymbols.AddString("wide");
- m_sTall = g_ScriptSymbols.AddString("tall");
-
- m_flCurrentTime = 0.0f;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Destructor
-//-----------------------------------------------------------------------------
-AnimationController::~AnimationController()
-{
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Sets which script file to use
-//-----------------------------------------------------------------------------
-bool AnimationController::SetScriptFile( VPANEL sizingPanel, const char *fileName, bool wipeAll /*=false*/ )
-{
- m_hSizePanel = sizingPanel;
-
- if ( wipeAll )
- {
- // clear the current script
- m_Sequences.RemoveAll();
- m_ScriptFileNames.RemoveAll();
-
- CancelAllAnimations();
- }
-
- // Store off this filename for reloading later on (if we don't have it already)
- UtlSymId_t sFilename = g_ScriptSymbols.AddString( fileName );
- if ( m_ScriptFileNames.Find( sFilename ) == m_ScriptFileNames.InvalidIndex() )
- {
- m_ScriptFileNames.AddToTail( sFilename );
- }
-
- UpdateScreenSize();
-
- // load the new script file
- return LoadScriptFile( fileName );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: reloads the currently set script file
-//-----------------------------------------------------------------------------
-void AnimationController::ReloadScriptFile()
-{
- // Clear all current sequences
- m_Sequences.RemoveAll();
-
- UpdateScreenSize();
-
- // Reload each file we've loaded
- for ( int i = 0; i < m_ScriptFileNames.Count(); i++ )
- {
- const char *lpszFilename = g_ScriptSymbols.String( m_ScriptFileNames[i] );
- if ( strlen( lpszFilename ) > 0)
- {
- if ( LoadScriptFile( lpszFilename ) == false )
- {
- Assert( 0 );
- }
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: loads a script file from disk
-//-----------------------------------------------------------------------------
-bool AnimationController::LoadScriptFile(const char *fileName)
-{
- FileHandle_t f = g_pFullFileSystem->Open(fileName, "rt");
- if (!f)
- {
- Warning("Couldn't find script file %s\n", fileName);
- return false;
- }
-
- // read the whole thing into memory
- int size = g_pFullFileSystem->Size(f);
- // read into temporary memory block
- int nBufSize = size+1;
- if ( IsXbox() )
- {
- nBufSize = AlignValue( nBufSize, 512 );
- }
- char *pMem = (char *)malloc(nBufSize);
- int bytesRead = g_pFullFileSystem->ReadEx(pMem, nBufSize, size, f);
- Assert(bytesRead <= size);
- pMem[bytesRead] = 0;
- g_pFullFileSystem->Close(f);
- // parse
- bool success = ParseScriptFile(pMem, bytesRead);
- free(pMem);
- return success;
-}
-
-AnimationController::RelativeAlignmentLookup AnimationController::g_AlignmentLookup[] =
-{
- { AnimationController::a_northwest , "northwest" },
- { AnimationController::a_north , "north" },
- { AnimationController::a_northeast , "northeast" },
- { AnimationController::a_west , "west" },
- { AnimationController::a_center , "center" },
- { AnimationController::a_east , "east" },
- { AnimationController::a_southwest , "southwest" },
- { AnimationController::a_south , "south" },
- { AnimationController::a_southeast , "southeast" },
-
- { AnimationController::a_northwest , "nw" },
- { AnimationController::a_north , "n" },
- { AnimationController::a_northeast , "ne" },
- { AnimationController::a_west , "w" },
- { AnimationController::a_center , "c" },
- { AnimationController::a_east , "e" },
- { AnimationController::a_southwest , "sw" },
- { AnimationController::a_south , "s" },
- { AnimationController::a_southeast , "se" },
-};
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-AnimationController::RelativeAlignment AnimationController::LookupAlignment( char const *token )
-{
- int c = ARRAYSIZE( g_AlignmentLookup );
-
- for ( int i = 0; i < c; i++ )
- {
- if ( !Q_stricmp( token, g_AlignmentLookup[ i ].name ) )
- {
- return g_AlignmentLookup[ i ].align;
- }
- }
-
- return AnimationController::a_northwest;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Parse position including right edge and center adjustment out of a
-// token. This is relative to the screen
-//-----------------------------------------------------------------------------
-void AnimationController::SetupPosition( AnimCmdAnimate_t& cmd, float *output, char const *psz, int screendimension )
-{
- bool r = false, c = false;
- int pos;
- if ( psz[0] == '(' )
- {
- psz++;
-
- if ( Q_strstr( psz, ")" ) )
- {
- char sz[ 256 ];
- Q_strncpy( sz, psz, sizeof( sz ) );
-
- char *colon = Q_strstr( sz, ":" );
- if ( colon )
- {
- *colon = 0;
-
- RelativeAlignment ra = LookupAlignment( sz );
-
- colon++;
-
- char *panelName = colon;
- char *panelEnd = Q_strstr( panelName, ")" );
- if ( panelEnd )
- {
- *panelEnd = 0;
-
- if ( Q_strlen( panelName ) > 0 )
- {
- //
- cmd.align.relativePosition = true;
- cmd.align.alignPanel = g_ScriptSymbols.AddString(panelName);
- cmd.align.alignment = ra;
- }
- }
- }
-
- psz = Q_strstr( psz, ")" ) + 1;
- }
- }
- else if (psz[0] == 'r' || psz[0] == 'R')
- {
- r = true;
- psz++;
- }
- else if (psz[0] == 'c' || psz[0] == 'C')
- {
- c = true;
- psz++;
- }
-
- // get the number
- pos = atoi(psz);
-
- // scale the values
- if (IsProportional())
- {
- pos = vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), pos );
- }
-
- // adjust the positions
- if (r)
- {
- pos = screendimension - pos;
- }
- if (c)
- {
- pos = (screendimension / 2) + pos;
- }
-
- // set the value
- *output = static_cast<float>( pos );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: parses a script into sequences
-//-----------------------------------------------------------------------------
-bool AnimationController::ParseScriptFile(char *pMem, int length)
-{
- // get the scheme (for looking up color names)
- IScheme *scheme = vgui::scheme()->GetIScheme(GetScheme());
-
- // get our screen size (for left/right/center alignment)
- int screenWide = m_nScreenBounds[ 2 ];
- int screenTall = m_nScreenBounds[ 3 ];
-
- // start by getting the first token
- char token[512];
- pMem = ParseFile(pMem, token, NULL);
- while (token[0])
- {
- bool bAccepted = true;
-
- // should be 'event'
- if (stricmp(token, "event"))
- {
- Warning("Couldn't parse script file: expected 'event', found '%s'\n", token);
- return false;
- }
-
- // get the event name
- pMem = ParseFile(pMem, token, NULL);
- if (strlen(token) < 1)
- {
- Warning("Couldn't parse script file: expected <event name>, found nothing\n");
- return false;
- }
-
- int seqIndex;
- UtlSymId_t nameIndex = g_ScriptSymbols.AddString(token);
-
- // Create a new sequence
- seqIndex = m_Sequences.AddToTail();
- AnimSequence_t &seq = m_Sequences[seqIndex];
- seq.name = nameIndex;
- seq.duration = 0.0f;
-
- // get the open brace or a conditional
- pMem = ParseFile(pMem, token, NULL);
- if ( Q_stristr( token, "[$" ) )
- {
- bAccepted = EvaluateConditional( token );
-
- // now get the open brace
- pMem = ParseFile(pMem, token, NULL);
- }
-
- if (stricmp(token, "{"))
- {
- Warning("Couldn't parse script sequence '%s': expected '{', found '%s'\n", g_ScriptSymbols.String(seq.name), token);
- return false;
- }
-
- // walk the commands
- while (token && token[0])
- {
- // get the command type
- pMem = ParseFile(pMem, token, NULL);
-
- // skip out when we hit the end of the sequence
- if (token[0] == '}')
- break;
-
- // create a new command
- int cmdIndex = seq.cmdList.AddToTail();
- AnimCommand_t &animCmd = seq.cmdList[cmdIndex];
- memset(&animCmd, 0, sizeof(animCmd));
- if (!stricmp(token, "animate"))
- {
- animCmd.commandType = CMD_ANIMATE;
- // parse out the animation commands
- AnimCmdAnimate_t &cmdAnimate = animCmd.cmdData.animate;
- // panel to manipulate
- pMem = ParseFile(pMem, token, NULL);
- cmdAnimate.panel = g_ScriptSymbols.AddString(token);
- // variable to change
- pMem = ParseFile(pMem, token, NULL);
- cmdAnimate.variable = g_ScriptSymbols.AddString(token);
- // target value
- pMem = ParseFile(pMem, token, NULL);
- if (cmdAnimate.variable == m_sPosition)
- {
- // Get first token
- SetupPosition( cmdAnimate, &cmdAnimate.target.a, token, screenWide );
-
- // Get second token from "token"
- char token2[32];
- char *psz = ParseFile(token, token2, NULL);
- psz = ParseFile(psz, token2, NULL);
- psz = token2;
-
- // Position Y goes into ".b"
- SetupPosition( cmdAnimate, &cmdAnimate.target.b, psz, screenTall );
- }
- else if ( cmdAnimate.variable == m_sXPos )
- {
- // XPos and YPos both use target ".a"
- SetupPosition( cmdAnimate, &cmdAnimate.target.a, token, screenWide );
- }
- else if ( cmdAnimate.variable == m_sYPos )
- {
- // XPos and YPos both use target ".a"
- SetupPosition( cmdAnimate, &cmdAnimate.target.a, token, screenTall );
- }
- else
- {
- // parse the floating point values right out
- if (0 == sscanf(token, "%f %f %f %f", &cmdAnimate.target.a, &cmdAnimate.target.b, &cmdAnimate.target.c, &cmdAnimate.target.d))
- {
- //=============================================================================
- // HPE_BEGIN:
- // [pfreese] Improved handling colors not defined in scheme
- //=============================================================================
-
- // could be referencing a value in the scheme file, lookup
- Color default_invisible_black(0, 0, 0, 0);
- Color col = scheme->GetColor(token, default_invisible_black);
-
- // we don't have a way of seeing if the color is not declared in the scheme, so we use this
- // silly method of trying again with a different default to see if we get the fallback again
- if (col == default_invisible_black)
- {
- Color error_pink(255, 0, 255, 255); // make it extremely obvious if a scheme lookup fails
- col = scheme->GetColor(token, error_pink);
-
- // commented out for Soldier/Demo release...(getting spammed in console)
- // we'll try to figure this out after the update is out
-// if (col == error_pink)
-// {
-// Warning("Missing color in scheme: %s\n", token);
-// }
- }
-
- //=============================================================================
- // HPE_END
- //=============================================================================
-
- cmdAnimate.target.a = col[0];
- cmdAnimate.target.b = col[1];
- cmdAnimate.target.c = col[2];
- cmdAnimate.target.d = col[3];
- }
- }
-
- // fix up scale
- if (cmdAnimate.variable == m_sSize)
- {
- if (IsProportional())
- {
- cmdAnimate.target.a = static_cast<float>( vgui::scheme()->GetProportionalScaledValueEx(GetScheme(), cmdAnimate.target.a) );
- cmdAnimate.target.b = static_cast<float>( vgui::scheme()->GetProportionalScaledValueEx(GetScheme(), cmdAnimate.target.b) );
- }
- }
- else if (cmdAnimate.variable == m_sWide ||
- cmdAnimate.variable == m_sTall )
- {
- if (IsProportional())
- {
- // Wide and tall both use.a
- cmdAnimate.target.a = static_cast<float>( vgui::scheme()->GetProportionalScaledValueEx(GetScheme(), cmdAnimate.target.a) );
- }
- }
-
- // interpolation function
- pMem = ParseFile(pMem, token, NULL);
- if (!stricmp(token, "Accel"))
- {
- cmdAnimate.interpolationFunction = INTERPOLATOR_ACCEL;
- }
- else if (!stricmp(token, "Deaccel"))
- {
- cmdAnimate.interpolationFunction = INTERPOLATOR_DEACCEL;
- }
- else if ( !stricmp(token, "Spline"))
- {
- cmdAnimate.interpolationFunction = INTERPOLATOR_SIMPLESPLINE;
- }
- else if (!stricmp(token,"Pulse"))
- {
- cmdAnimate.interpolationFunction = INTERPOLATOR_PULSE;
- // frequencey
- pMem = ParseFile(pMem, token, NULL);
- cmdAnimate.interpolationParameter = (float)atof(token);
- }
- else if ( !stricmp( token, "Flicker"))
- {
- cmdAnimate.interpolationFunction = INTERPOLATOR_FLICKER;
- // noiseamount
- pMem = ParseFile(pMem, token, NULL);
- cmdAnimate.interpolationParameter = (float)atof(token);
- }
- else if (!stricmp(token, "Bounce"))
- {
- cmdAnimate.interpolationFunction = INTERPOLATOR_BOUNCE;
- }
- else
- {
- cmdAnimate.interpolationFunction = INTERPOLATOR_LINEAR;
- }
- // start time
- pMem = ParseFile(pMem, token, NULL);
- cmdAnimate.startTime = (float)atof(token);
- // duration
- pMem = ParseFile(pMem, token, NULL);
- cmdAnimate.duration = (float)atof(token);
- // check max duration
- if (cmdAnimate.startTime + cmdAnimate.duration > seq.duration)
- {
- seq.duration = cmdAnimate.startTime + cmdAnimate.duration;
- }
- }
- else if (!stricmp(token, "runevent"))
- {
- animCmd.commandType = CMD_RUNEVENT;
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token);
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.timeDelay = (float)atof(token);
- }
- else if (!stricmp(token, "stopevent"))
- {
- animCmd.commandType = CMD_STOPEVENT;
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token);
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.timeDelay = (float)atof(token);
- }
- else if (!stricmp(token, "StopPanelAnimations"))
- {
- animCmd.commandType = CMD_STOPPANELANIMATIONS;
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token);
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.timeDelay = (float)atof(token);
- }
- else if (!stricmp(token, "stopanimation"))
- {
- animCmd.commandType = CMD_STOPANIMATION;
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token);
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token);
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.timeDelay = (float)atof(token);
- }
- else if ( !stricmp( token, "SetFont" ))
- {
- animCmd.commandType = CMD_SETFONT;
- // Panel name
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token);
- // Font parameter
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token);
- // Font name from scheme
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.variable2 = g_ScriptSymbols.AddString(token);
-
- // Set time
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.timeDelay = (float)atof(token);
- }
- else if ( !stricmp( token, "SetTexture" ))
- {
- animCmd.commandType = CMD_SETTEXTURE;
- // Panel name
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token);
- // Texture Id
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token);
- // material name
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.variable2 = g_ScriptSymbols.AddString(token);
-
- // Set time
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.timeDelay = (float)atof(token);
- }
- else if ( !stricmp( token, "SetString" ))
- {
- animCmd.commandType = CMD_SETSTRING;
- // Panel name
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token);
- // String variable name
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token);
- // String value to set
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.variable2 = g_ScriptSymbols.AddString(token);
-
- // Set time
- pMem = ParseFile(pMem, token, NULL);
- animCmd.cmdData.runEvent.timeDelay = (float)atof(token);
- }
- else
- {
- Warning("Couldn't parse script sequence '%s': expected <anim command>, found '%s'\n", g_ScriptSymbols.String(seq.name), token);
- return false;
- }
-
- // Look ahead one token for a conditional
- char *peek = ParseFile(pMem, token, NULL);
- if ( Q_stristr( token, "[$" ) )
- {
- if ( !EvaluateConditional( token ) )
- {
- seq.cmdList.Remove( cmdIndex );
- }
- pMem = peek;
- }
- }
-
- if ( bAccepted )
- {
- // Attempt to find a collision in the sequences, replacing the old one if found
- int seqIterator;
- for ( seqIterator = 0; seqIterator < m_Sequences.Count()-1; seqIterator++ )
- {
- if ( m_Sequences[seqIterator].name == nameIndex )
- {
- // Get rid of it, we're overriding it
- m_Sequences.Remove( seqIndex );
- break;
- }
- }
- }
- else
- {
- // Dump the entire sequence
- m_Sequences.Remove( seqIndex );
- }
-
- // get the next token, if any
- pMem = ParseFile(pMem, token, NULL);
- }
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: checks all posted animation events, firing if time
-//-----------------------------------------------------------------------------
-void AnimationController::UpdatePostedMessages(bool bRunToCompletion)
-{
- CUtlVector<RanEvent_t> eventsRanThisFrame;
-
- // check all posted messages
- for (int i = 0; i < m_PostedMessages.Count(); i++)
- {
- PostedMessage_t &msgRef = m_PostedMessages[i];
- if (m_flCurrentTime < msgRef.startTime && !bRunToCompletion)
- continue;
-
- // take a copy of th message
- PostedMessage_t msg = msgRef;
-
- // remove the event
- // do this before handling the message because the message queue may be messed with
- m_PostedMessages.Remove(i);
- // reset the count, start the whole queue again
- i = -1;
-
- // handle the event
- switch (msg.commandType)
- {
- case CMD_RUNEVENT:
- {
- RanEvent_t curEvent;
- curEvent.event = msg.event;
- curEvent.pParent = msg.parent.Get();
-
- // run the event, but only if we haven't already run it this frame, for this parent
- if (!eventsRanThisFrame.HasElement(curEvent))
- {
- eventsRanThisFrame.AddToTail(curEvent);
- RunCmd_RunEvent(msg);
- }
- }
- break;
- case CMD_STOPEVENT:
- RunCmd_StopEvent(msg);
- break;
- case CMD_STOPPANELANIMATIONS:
- RunCmd_StopPanelAnimations(msg);
- break;
- case CMD_STOPANIMATION:
- RunCmd_StopAnimation(msg);
- break;
- case CMD_SETFONT:
- RunCmd_SetFont(msg);
- break;
- case CMD_SETTEXTURE:
- RunCmd_SetTexture(msg);
- break;
- case CMD_SETSTRING:
- RunCmd_SetString( msg );
- break;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: runs the current animations
-//-----------------------------------------------------------------------------
-void AnimationController::UpdateActiveAnimations(bool bRunToCompletion)
-{
- // iterate all the currently active animations
- for (int i = 0; i < m_ActiveAnimations.Count(); i++)
- {
- ActiveAnimation_t &anim = m_ActiveAnimations[i];
-
- // see if the anim is ready to start
- if (m_flCurrentTime < anim.startTime && !bRunToCompletion)
- continue;
-
- if (!anim.panel.Get())
- {
- // panel is gone, remove the animation
- m_ActiveAnimations.Remove(i);
- --i;
- continue;
- }
-
- if (!anim.started && !bRunToCompletion)
- {
- // start the animation from the current value
- anim.startValue = GetValue(anim, anim.panel, anim.variable);
- anim.started = true;
-
- // Msg( "Starting animation of %s => %.2f (seq: %s) (%s)\n", g_ScriptSymbols.String(anim.variable), anim.endValue.a, g_ScriptSymbols.String(anim.seqName), anim.panel->GetName());
- }
-
- // get the interpolated value
- Value_t val;
- if (m_flCurrentTime >= anim.endTime || bRunToCompletion)
- {
- // animation is done, use the last value
- val = anim.endValue;
- }
- else
- {
- // get the interpolated value
- val = GetInterpolatedValue(anim.interpolator, anim.interpolatorParam, m_flCurrentTime, anim.startTime, anim.endTime, anim.startValue, anim.endValue);
- }
-
- // apply the new value to the panel
- SetValue(anim, anim.panel, anim.variable, val);
-
- // Msg( "Animate value: %s => %.2f for panel '%s'\n", g_ScriptSymbols.String(anim.variable), val.a, anim.panel->GetName());
-
- // see if we can remove the animation
- if (m_flCurrentTime >= anim.endTime || bRunToCompletion)
- {
- m_ActiveAnimations.Remove(i);
- --i;
- }
- }
-}
-
-bool AnimationController::UpdateScreenSize()
-{
- // get our screen size (for left/right/center alignment)
- int screenWide, screenTall;
- int sx = 0, sy = 0;
- if ( m_hSizePanel != 0 )
- {
- ipanel()->GetSize( m_hSizePanel, screenWide, screenTall );
- ipanel()->GetPos( m_hSizePanel, sx, sy );
- }
- else
- {
- surface()->GetScreenSize(screenWide, screenTall);
- }
-
- bool changed = m_nScreenBounds[ 0 ] != sx ||
- m_nScreenBounds[ 1 ] != sy ||
- m_nScreenBounds[ 2 ] != screenWide ||
- m_nScreenBounds[ 3 ] != screenTall;
-
- m_nScreenBounds[ 0 ] = sx;
- m_nScreenBounds[ 1 ] = sy;
- m_nScreenBounds[ 2 ] = screenWide;
- m_nScreenBounds[ 3 ] = screenTall;
-
- return changed;
-}
-//-----------------------------------------------------------------------------
-// Purpose: runs a frame of animation
-//-----------------------------------------------------------------------------
-void AnimationController::UpdateAnimations( float currentTime )
-{
- m_flCurrentTime = currentTime;
-
- if ( UpdateScreenSize() && m_ScriptFileNames.Count() )
- {
- RunAllAnimationsToCompletion();
- ReloadScriptFile();
- }
-
- UpdatePostedMessages(false);
- UpdateActiveAnimations(false);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: plays all animations to completion instantly
-//-----------------------------------------------------------------------------
-void AnimationController::RunAllAnimationsToCompletion()
-{
- // Msg( "AnimationController::RunAllAnimationsToCompletion()\n" );
- UpdatePostedMessages(true);
- UpdateActiveAnimations(true);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Stops all current animations
-//-----------------------------------------------------------------------------
-void AnimationController::CancelAllAnimations()
-{
- // Msg( "AnimationController::CancelAllAnimations()\n" );
-
- m_ActiveAnimations.RemoveAll();
- m_PostedMessages.RemoveAll();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: produces an interpolated value
-//-----------------------------------------------------------------------------
-AnimationController::Value_t AnimationController::GetInterpolatedValue(int interpolator, float interpolatorParam, float currentTime, float startTime, float endTime, Value_t &startValue, Value_t &endValue)
-{
- // calculate how far we are into the animation
- float pos = (currentTime - startTime) / (endTime - startTime);
-
- // adjust the percentage through by the interpolation function
- switch (interpolator)
- {
- case INTERPOLATOR_ACCEL:
- pos *= pos;
- break;
- case INTERPOLATOR_DEACCEL:
- pos = sqrtf(pos);
- break;
- case INTERPOLATOR_SIMPLESPLINE:
- pos = SimpleSpline( pos );
- break;
- case INTERPOLATOR_PULSE:
- // Make sure we end at 1.0, so use cosine
- pos = 0.5f + 0.5f * ( cos( pos * 2.0f * M_PI * interpolatorParam ) );
- break;
- case INTERPOLATOR_FLICKER:
- if ( RandomFloat( 0.0f, 1.0f ) < interpolatorParam )
- {
- pos = 1.0f;
- }
- else
- {
- pos = 0.0f;
- }
- break;
- case INTERPOLATOR_BOUNCE:
- {
- // fall from startValue to endValue, bouncing a few times and settling out at endValue
- const float hit1 = 0.33f;
- const float hit2 = 0.67f;
- const float hit3 = 1.0f;
-
- if ( pos < hit1 )
- {
- pos = 1.0f - sin( M_PI * pos / hit1 );
- }
- else if ( pos < hit2 )
- {
- pos = 0.5f + 0.5f * ( 1.0f - sin( M_PI * ( pos - hit1 ) / ( hit2 - hit1 ) ) );
- }
- else
- {
- pos = 0.8f + 0.2f * ( 1.0f - sin( M_PI * ( pos - hit2 ) / ( hit3 - hit2 ) ) );
- }
- break;
- }
- case INTERPOLATOR_LINEAR:
- default:
- break;
- }
-
- // calculate the value
- Value_t val;
- val.a = ((endValue.a - startValue.a) * pos) + startValue.a;
- val.b = ((endValue.b - startValue.b) * pos) + startValue.b;
- val.c = ((endValue.c - startValue.c) * pos) + startValue.c;
- val.d = ((endValue.d - startValue.d) * pos) + startValue.d;
- return val;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: sets that the script file should be reloaded each time a script is ran
-// used for development
-//-----------------------------------------------------------------------------
-void AnimationController::SetAutoReloadScript(bool state)
-{
- m_bAutoReloadScript = state;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: starts an animation sequence script
-//-----------------------------------------------------------------------------
-bool AnimationController::StartAnimationSequence(const char *sequenceName)
-{
- // We support calling an animation on elements that are not the calling
- // panel's children. Use the base parent to start the search.
-
- return StartAnimationSequence( GetParent(), sequenceName );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: starts an animation sequence script
-//-----------------------------------------------------------------------------
-bool AnimationController::StartAnimationSequence(Panel *pWithinParent, const char *sequenceName)
-{
- Assert( pWithinParent );
-
- if (m_bAutoReloadScript)
- {
- // Reload the script files
- ReloadScriptFile();
- }
-
- // lookup the symbol for the name
- UtlSymId_t seqName = g_ScriptSymbols.Find(sequenceName);
- if (seqName == UTL_INVAL_SYMBOL)
- return false;
-
- // Msg("Starting animation sequence %s\n", sequenceName);
-
- // remove the existing command from the queue
- RemoveQueuedAnimationCommands(seqName, pWithinParent);
-
- // look through for the sequence
- int i;
- for (i = 0; i < m_Sequences.Count(); i++)
- {
- if (m_Sequences[i].name == seqName)
- break;
- }
- if (i >= m_Sequences.Count())
- return false;
-
- // execute the sequence
- for (int cmdIndex = 0; cmdIndex < m_Sequences[i].cmdList.Count(); cmdIndex++)
- {
- ExecAnimationCommand(seqName, m_Sequences[i].cmdList[cmdIndex], pWithinParent);
- }
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Runs a custom command from code, not from a script file
-//-----------------------------------------------------------------------------
-void AnimationController::RunAnimationCommand(vgui::Panel *panel, const char *variable, float targetValue, float startDelaySeconds, float duration, Interpolators_e interpolator, float animParameter /* = 0 */ )
-{
- // clear any previous animations of this variable
- UtlSymId_t var = g_ScriptSymbols.AddString(variable);
- RemoveQueuedAnimationByType(panel, var, UTL_INVAL_SYMBOL);
-
- // build a new animation
- AnimCmdAnimate_t animateCmd;
- memset(&animateCmd, 0, sizeof(animateCmd));
- animateCmd.panel = 0;
- animateCmd.variable = var;
- animateCmd.target.a = targetValue;
- animateCmd.interpolationFunction = interpolator;
- animateCmd.interpolationParameter = animParameter;
- animateCmd.startTime = startDelaySeconds;
- animateCmd.duration = duration;
-
- // start immediately
- StartCmd_Animate(panel, 0, animateCmd);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Runs a custom command from code, not from a script file
-//-----------------------------------------------------------------------------
-void AnimationController::RunAnimationCommand(vgui::Panel *panel, const char *variable, Color targetValue, float startDelaySeconds, float duration, Interpolators_e interpolator, float animParameter /* = 0 */ )
-{
- // clear any previous animations of this variable
- UtlSymId_t var = g_ScriptSymbols.AddString(variable);
- RemoveQueuedAnimationByType(panel, var, UTL_INVAL_SYMBOL);
-
- // build a new animation
- AnimCmdAnimate_t animateCmd;
- memset(&animateCmd, 0, sizeof(animateCmd));
- animateCmd.panel = 0;
- animateCmd.variable = var;
- animateCmd.target.a = targetValue[0];
- animateCmd.target.b = targetValue[1];
- animateCmd.target.c = targetValue[2];
- animateCmd.target.d = targetValue[3];
- animateCmd.interpolationFunction = interpolator;
- animateCmd.interpolationParameter = animParameter;
- animateCmd.startTime = startDelaySeconds;
- animateCmd.duration = duration;
-
- // start immediately
- StartCmd_Animate(panel, 0, animateCmd);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: gets the length of an animation sequence, in seconds
-//-----------------------------------------------------------------------------
-float AnimationController::GetAnimationSequenceLength(const char *sequenceName)
-{
- // lookup the symbol for the name
- UtlSymId_t seqName = g_ScriptSymbols.Find(sequenceName);
- if (seqName == UTL_INVAL_SYMBOL)
- return 0.0f;
-
- // look through for the sequence
- int i;
- for (i = 0; i < m_Sequences.Count(); i++)
- {
- if (m_Sequences[i].name == seqName)
- break;
- }
- if (i >= m_Sequences.Count())
- return 0.0f;
-
- // sequence found
- return m_Sequences[i].duration;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: removes an existing set of commands from the queue
-//-----------------------------------------------------------------------------
-void AnimationController::RemoveQueuedAnimationCommands(UtlSymId_t seqName, Panel *pWithinParent)
-{
- // Msg("Removing queued anims for sequence %s\n", g_ScriptSymbols.String(seqName));
-
- // remove messages posted by this sequence
- // if pWithinParent is specified, remove only messages under that parent
- {for (int i = 0; i < m_PostedMessages.Count(); i++)
- {
- if ( ( m_PostedMessages[i].seqName == seqName ) &&
- ( !pWithinParent || ( m_PostedMessages[i].parent == pWithinParent ) ) )
- {
- m_PostedMessages.Remove(i);
- --i;
- }
- }}
-
- // remove all animations
- // if pWithinParent is specified, remove only animations under that parent
- for (int i = 0; i < m_ActiveAnimations.Count(); i++)
- {
- if ( m_ActiveAnimations[i].seqName != seqName )
- continue;
-
- // panel this anim is on, m_ActiveAnimations[i].panel
- if ( pWithinParent )
- {
- Panel *animPanel = m_ActiveAnimations[i].panel;
-
- if ( !animPanel )
- continue;
-
- Panel *foundPanel = pWithinParent->FindChildByName(animPanel->GetName(),true);
-
- if ( foundPanel != animPanel )
- continue;
- }
-
- m_ActiveAnimations.Remove(i);
- --i;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: removes the specified queued animation
-//-----------------------------------------------------------------------------
-void AnimationController::RemoveQueuedAnimationByType(vgui::Panel *panel, UtlSymId_t variable, UtlSymId_t sequenceToIgnore)
-{
- for (int i = 0; i < m_ActiveAnimations.Count(); i++)
- {
- if (m_ActiveAnimations[i].panel == panel && m_ActiveAnimations[i].variable == variable && m_ActiveAnimations[i].seqName != sequenceToIgnore)
- {
- // Msg("Removing queued anim %s::%s::%s\n", g_ScriptSymbols.String(m_ActiveAnimations[i].seqName), panel->GetName(), g_ScriptSymbols.String(variable));
- m_ActiveAnimations.Remove(i);
- break;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: runs a single line of the script
-//-----------------------------------------------------------------------------
-void AnimationController::ExecAnimationCommand(UtlSymId_t seqName, AnimCommand_t &animCommand, Panel *pWithinParent)
-{
- if (animCommand.commandType == CMD_ANIMATE)
- {
- StartCmd_Animate(seqName, animCommand.cmdData.animate, pWithinParent);
- }
- else
- {
- // post the command to happen at the specified time
- PostedMessage_t &msg = m_PostedMessages[m_PostedMessages.AddToTail()];
- msg.seqName = seqName;
- msg.commandType = animCommand.commandType;
- msg.event = animCommand.cmdData.runEvent.event;
- msg.variable = animCommand.cmdData.runEvent.variable;
- msg.variable2 = animCommand.cmdData.runEvent.variable2;
- msg.startTime = m_flCurrentTime + animCommand.cmdData.runEvent.timeDelay;
- msg.parent = pWithinParent;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: starts a variable animation
-//-----------------------------------------------------------------------------
-void AnimationController::StartCmd_Animate(UtlSymId_t seqName, AnimCmdAnimate_t &cmd, Panel *pWithinParent)
-{
- Assert( pWithinParent );
- if ( !pWithinParent )
- return;
-
- // make sure the child exists
- Panel *panel = pWithinParent->FindChildByName(g_ScriptSymbols.String(cmd.panel),true);
- if ( !panel )
- {
- // Check the parent
- Panel *parent = GetParent();
- if ( !Q_stricmp( parent->GetName(), g_ScriptSymbols.String(cmd.panel) ) )
- {
- panel = parent;
- }
- }
- if (!panel)
- return;
-
- StartCmd_Animate(panel, seqName, cmd);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Starts an animation command for the specified panel
-//-----------------------------------------------------------------------------
-void AnimationController::StartCmd_Animate(Panel *panel, UtlSymId_t seqName, AnimCmdAnimate_t &cmd)
-{
- // build a command to add to the animation queue
- ActiveAnimation_t &anim = m_ActiveAnimations[m_ActiveAnimations.AddToTail()];
- anim.panel = panel;
- anim.seqName = seqName;
- anim.variable = cmd.variable;
- anim.interpolator = cmd.interpolationFunction;
- anim.interpolatorParam = cmd.interpolationParameter;
- // timings
- anim.startTime = m_flCurrentTime + cmd.startTime;
- anim.endTime = anim.startTime + cmd.duration;
- // values
- anim.started = false;
- anim.endValue = cmd.target;
-
- anim.align = cmd.align;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: a posted message to run another event
-//-----------------------------------------------------------------------------
-void AnimationController::RunCmd_RunEvent(PostedMessage_t &msg)
-{
- StartAnimationSequence(msg.parent.Get(), g_ScriptSymbols.String(msg.event));
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: a posted message to stop another event
-//-----------------------------------------------------------------------------
-void AnimationController::RunCmd_StopEvent(PostedMessage_t &msg)
-{
- RemoveQueuedAnimationCommands(msg.event, msg.parent);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: a posted message to stop all animations relevant to a specified panel
-//-----------------------------------------------------------------------------
-void AnimationController::RunCmd_StopPanelAnimations(PostedMessage_t &msg)
-{
- Panel *panel = FindSiblingByName(g_ScriptSymbols.String(msg.event));
- Assert(panel != NULL);
- if (!panel)
- return;
-
- // loop through all the active animations cancelling any that
- // are operating on said panel, except for the event specified
- for (int i = 0; i < m_ActiveAnimations.Count(); i++)
- {
- if (m_ActiveAnimations[i].panel == panel && m_ActiveAnimations[i].seqName != msg.seqName)
- {
- m_ActiveAnimations.Remove(i);
- --i;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: a posted message to stop animations of a specific type
-//-----------------------------------------------------------------------------
-void AnimationController::RunCmd_StopAnimation(PostedMessage_t &msg)
-{
- Panel *panel = FindSiblingByName(g_ScriptSymbols.String(msg.event));
- Assert(panel != NULL);
- if (!panel)
- return;
-
- RemoveQueuedAnimationByType(panel, msg.variable, msg.seqName);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void AnimationController::RunCmd_SetFont( PostedMessage_t &msg )
-{
- Panel *parent = msg.parent.Get();
-
- if ( !parent )
- {
- parent = GetParent();
- }
-
- Panel *panel = parent->FindChildByName(g_ScriptSymbols.String(msg.event), true);
- Assert(panel != NULL);
- if (!panel)
- return;
-
- KeyValues *inputData = new KeyValues(g_ScriptSymbols.String(msg.variable));
- inputData->SetString(g_ScriptSymbols.String(msg.variable), g_ScriptSymbols.String(msg.variable2));
- if (!panel->SetInfo(inputData))
- {
- // Assert(!("Unhandlable var in AnimationController::SetValue())"));
- }
- inputData->deleteThis();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void AnimationController::RunCmd_SetTexture( PostedMessage_t &msg )
-{
- Panel *panel = FindSiblingByName(g_ScriptSymbols.String(msg.event));
- Assert(panel != NULL);
- if (!panel)
- return;
-
- KeyValues *inputData = new KeyValues(g_ScriptSymbols.String(msg.variable));
- inputData->SetString(g_ScriptSymbols.String(msg.variable), g_ScriptSymbols.String(msg.variable2));
- if (!panel->SetInfo(inputData))
- {
- // Assert(!("Unhandlable var in AnimationController::SetValue())"));
- }
- inputData->deleteThis();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void AnimationController::RunCmd_SetString( PostedMessage_t &msg )
-{
- Panel *panel = FindSiblingByName(g_ScriptSymbols.String(msg.event));
- Assert(panel != NULL);
- if (!panel)
- return;
-
- KeyValues *inputData = new KeyValues(g_ScriptSymbols.String(msg.variable));
- inputData->SetString(g_ScriptSymbols.String(msg.variable), g_ScriptSymbols.String(msg.variable2));
- if (!panel->SetInfo(inputData))
- {
- // Assert(!("Unhandlable var in AnimationController::SetValue())"));
- }
- inputData->deleteThis();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-int AnimationController::GetRelativeOffset( AnimAlign_t& align, bool xcoord )
-{
- if ( !align.relativePosition )
- return 0;
-
- Panel *panel = GetParent()->FindChildByName(g_ScriptSymbols.String(align.alignPanel), true);
- if ( !panel )
- return 0;
-
- int x, y, w, h;
- panel->GetBounds( x, y, w, h );
-
- int offset =0;
- switch ( align.alignment )
- {
- default:
- case a_northwest:
- offset = xcoord ? x : y;
- break;
- case a_north:
- offset = xcoord ? ( x + w ) / 2 : y;
- break;
- case a_northeast:
- offset = xcoord ? ( x + w ) : y;
- break;
- case a_west:
- offset = xcoord ? x : ( y + h ) / 2;
- break;
- case a_center:
- offset = xcoord ? ( x + w ) / 2 : ( y + h ) / 2;
- break;
- case a_east:
- offset = xcoord ? ( x + w ) : ( y + h ) / 2;
- break;
- case a_southwest:
- offset = xcoord ? x : ( y + h );
- break;
- case a_south:
- offset = xcoord ? ( x + w ) / 2 : ( y + h );
- break;
- case a_southeast:
- offset = xcoord ? ( x + w ) : ( y + h );
- break;
- }
-
- return offset;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Gets the specified value from a panel
-//-----------------------------------------------------------------------------
-AnimationController::Value_t AnimationController::GetValue(ActiveAnimation_t& anim, Panel *panel, UtlSymId_t var)
-{
- Value_t val = { 0, 0, 0, 0 };
- if (var == m_sPosition)
- {
- int x, y;
- panel->GetPos(x, y);
- val.a = (float)(x - GetRelativeOffset( anim.align, true ) );
- val.b = (float)(y - GetRelativeOffset( anim.align, false ) );
- }
- else if (var == m_sSize)
- {
- int w, t;
- panel->GetSize(w, t);
- val.a = (float)w;
- val.b = (float)t;
- }
- else if (var == m_sFgColor)
- {
- Color col = panel->GetFgColor();
- val.a = col[0];
- val.b = col[1];
- val.c = col[2];
- val.d = col[3];
- }
- else if (var == m_sBgColor)
- {
- Color col = panel->GetBgColor();
- val.a = col[0];
- val.b = col[1];
- val.c = col[2];
- val.d = col[3];
- }
- else if ( var == m_sXPos )
- {
- int x, y;
- panel->GetPos(x, y);
- val.a = (float)( x - GetRelativeOffset( anim.align, true ) );
- }
- else if ( var == m_sYPos )
- {
- int x, y;
- panel->GetPos(x, y);
- val.a = (float)( y - GetRelativeOffset( anim.align, false ) );
- }
- else if ( var == m_sWide )
- {
- int w, h;
- panel->GetSize(w, h);
- val.a = (float)w;
- }
- else if ( var == m_sTall )
- {
- int w, h;
- panel->GetSize(w, h);
- val.a = (float)h;
- }
- else
- {
- KeyValues *outputData = new KeyValues(g_ScriptSymbols.String(var));
- if (panel->RequestInfo(outputData))
- {
- // find the var and lookup it's type
- KeyValues *kv = outputData->FindKey(g_ScriptSymbols.String(var));
- if (kv && kv->GetDataType() == KeyValues::TYPE_FLOAT)
- {
- val.a = kv->GetFloat();
- val.b = 0.0f;
- val.c = 0.0f;
- val.d = 0.0f;
- }
- else if (kv && kv->GetDataType() == KeyValues::TYPE_COLOR)
- {
- Color col = kv->GetColor();
- val.a = col[0];
- val.b = col[1];
- val.c = col[2];
- val.d = col[3];
- }
- }
- else
- {
- // Assert(!("Unhandlable var in AnimationController::GetValue())"));
- }
- outputData->deleteThis();
- }
- return val;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Sets a value in a panel
-//-----------------------------------------------------------------------------
-void AnimationController::SetValue(ActiveAnimation_t& anim, Panel *panel, UtlSymId_t var, Value_t &value)
-{
- if (var == m_sPosition)
- {
- int x = (int)value.a + GetRelativeOffset( anim.align, true );
- int y = (int)value.b + GetRelativeOffset( anim.align, false );
- panel->SetPos(x, y);
- }
- else if (var == m_sSize)
- {
- panel->SetSize((int)value.a, (int)value.b);
- }
- else if (var == m_sFgColor)
- {
- Color col = panel->GetFgColor();
- col[0] = (unsigned char)value.a;
- col[1] = (unsigned char)value.b;
- col[2] = (unsigned char)value.c;
- col[3] = (unsigned char)value.d;
- panel->SetFgColor(col);
- }
- else if (var == m_sBgColor)
- {
- Color col = panel->GetBgColor();
- col[0] = (unsigned char)value.a;
- col[1] = (unsigned char)value.b;
- col[2] = (unsigned char)value.c;
- col[3] = (unsigned char)value.d;
- panel->SetBgColor(col);
- }
- else if (var == m_sXPos)
- {
- int newx = (int)value.a + GetRelativeOffset( anim.align, true );
- int x, y;
- panel->GetPos( x, y );
- x = newx;
- panel->SetPos(x, y);
- }
- else if (var == m_sYPos)
- {
- int newy = (int)value.a + GetRelativeOffset( anim.align, false );
- int x, y;
- panel->GetPos( x, y );
- y = newy;
- panel->SetPos(x, y);
- }
- else if (var == m_sWide)
- {
- int neww = (int)value.a;
- int w, h;
- panel->GetSize( w, h );
- w = neww;
- panel->SetSize(w, h);
- }
- else if (var == m_sTall)
- {
- int newh = (int)value.a;
- int w, h;
- panel->GetSize( w, h );
- h = newh;
- panel->SetSize(w, h);
- }
- else
- {
- KeyValues *inputData = new KeyValues(g_ScriptSymbols.String(var));
- // set the custom value
- if (value.b == 0.0f && value.c == 0.0f && value.d == 0.0f)
- {
- // only the first value is non-zero, so probably just a float value
- inputData->SetFloat(g_ScriptSymbols.String(var), value.a);
- }
- else
- {
- // multivalue, set the color
- Color col((unsigned char)value.a, (unsigned char)value.b, (unsigned char)value.c, (unsigned char)value.d);
- inputData->SetColor(g_ScriptSymbols.String(var), col);
- }
- if (!panel->SetInfo(inputData))
- {
- // Assert(!("Unhandlable var in AnimationController::SetValue())"));
- }
- inputData->deleteThis();
- }
-}
-// Hooks between panels and animation controller system
-
-class CPanelAnimationDictionary
-{
-public:
- CPanelAnimationDictionary() : m_PanelAnimationMapPool( 32 )
- {
- }
-
- ~CPanelAnimationDictionary()
- {
- m_PanelAnimationMapPool.Clear();
- }
-
- PanelAnimationMap *FindOrAddPanelAnimationMap( char const *className );
- PanelAnimationMap *FindPanelAnimationMap( char const *className );
- void PanelAnimationDumpVars( char const *className );
-private:
-
- struct PanelAnimationMapDictionaryEntry
- {
- PanelAnimationMap *map;
- };
-
- char const *StripNamespace( char const *className );
- void PanelAnimationDumpMap( PanelAnimationMap *map, bool recursive );
-
- CClassMemoryPool< PanelAnimationMap > m_PanelAnimationMapPool;
- CUtlDict< PanelAnimationMapDictionaryEntry, int > m_AnimationMaps;
-};
-
-
-char const *CPanelAnimationDictionary::StripNamespace( char const *className )
-{
- if ( !Q_strnicmp( className, "vgui::", 6 ) )
- {
- return className + 6;
- }
- return className;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Find but don't add mapping
-//-----------------------------------------------------------------------------
-PanelAnimationMap *CPanelAnimationDictionary::FindPanelAnimationMap( char const *className )
-{
- int lookup = m_AnimationMaps.Find( StripNamespace( className ) );
- if ( lookup != m_AnimationMaps.InvalidIndex() )
- {
- return m_AnimationMaps[ lookup ].map;
- }
- return NULL;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-PanelAnimationMap *CPanelAnimationDictionary::FindOrAddPanelAnimationMap( char const *className )
-{
- PanelAnimationMap *map = FindPanelAnimationMap( className );
- if ( map )
- return map;
-
- Panel::InitPropertyConverters();
-
- PanelAnimationMapDictionaryEntry entry;
- entry.map = (PanelAnimationMap *)m_PanelAnimationMapPool.Alloc();
- m_AnimationMaps.Insert( StripNamespace( className ), entry );
- return entry.map;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CPanelAnimationDictionary::PanelAnimationDumpMap( PanelAnimationMap *map, bool recursive )
-{
- if ( map->pfnClassName )
- {
- Msg( "%s\n", (*map->pfnClassName)() );
- }
- int c = map->entries.Count();
- for ( int i = 0; i < c; i++ )
- {
- PanelAnimationMapEntry *e = &map->entries[ i ];
- Msg( " %s %s\n", e->type(), e->name() );
- }
-
- if ( recursive && map->baseMap )
- {
- PanelAnimationDumpMap( map->baseMap, recursive );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CPanelAnimationDictionary::PanelAnimationDumpVars( char const *className )
-{
- if ( className == NULL )
- {
- for ( int i = 0; i < (int)m_AnimationMaps.Count(); i++ )
- {
- PanelAnimationDumpMap( m_AnimationMaps[ i ].map, false );
- }
- }
- else
- {
- PanelAnimationMap *map = FindPanelAnimationMap( className );
- if ( map )
- {
- PanelAnimationDumpMap( map, true );
- }
- else
- {
- Msg( "No such Panel Animation class %s\n", className );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: singleton accessor
-//-----------------------------------------------------------------------------
-CPanelAnimationDictionary& GetPanelAnimationDictionary()
-{
- static CPanelAnimationDictionary dictionary;
- return dictionary;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-PanelAnimationMap *FindOrAddPanelAnimationMap( char const *className )
-{
- return GetPanelAnimationDictionary().FindOrAddPanelAnimationMap( className );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Find but don't add mapping
-//-----------------------------------------------------------------------------
-PanelAnimationMap *FindPanelAnimationMap( char const *className )
-{
- return GetPanelAnimationDictionary().FindPanelAnimationMap( className );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void PanelAnimationDumpVars( char const *className )
-{
- GetPanelAnimationDictionary().PanelAnimationDumpVars( className );
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// +#pragma warning( disable : 4244 ) // conversion from 'double' to 'float', possible loss of data + +#include <vgui/IScheme.h> +#include <vgui/ISurface.h> +#include <vgui/ISystem.h> +#include <vgui/IVGui.h> +#include <KeyValues.h> +#include <vgui_controls/AnimationController.h> +#include "filesystem.h" +#include "filesystem_helpers.h" + +#include <stdio.h> +#include <math.h> +#include "mempool.h" +#include "utldict.h" +#include "mathlib/mathlib.h" +#include "characterset.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/dbg.h> +// for SRC +#include <vstdlib/random.h> +#include <tier0/memdbgon.h> + +using namespace vgui; + +static CUtlSymbolTable g_ScriptSymbols(0, 128, true); + +// singleton accessor for animation controller for use by the vgui controls +namespace vgui +{ +AnimationController *GetAnimationController() +{ + static AnimationController *s_pAnimationController = new AnimationController(NULL); + return s_pAnimationController; +} +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +AnimationController::AnimationController(Panel *parent) : BaseClass(parent, NULL) +{ + m_hSizePanel = 0; + m_nScreenBounds[ 0 ] = m_nScreenBounds[ 1 ] = -1; + m_nScreenBounds[ 2 ] = m_nScreenBounds[ 3 ] = -1; + + m_bAutoReloadScript = false; + + // always invisible + SetVisible(false); + + SetProportional(true); + + // get the names of common types + m_sPosition = g_ScriptSymbols.AddString("position"); + m_sSize = g_ScriptSymbols.AddString("size"); + m_sFgColor = g_ScriptSymbols.AddString("fgcolor"); + m_sBgColor = g_ScriptSymbols.AddString("bgcolor"); + + m_sXPos = g_ScriptSymbols.AddString("xpos"); + m_sYPos = g_ScriptSymbols.AddString("ypos"); + m_sWide = g_ScriptSymbols.AddString("wide"); + m_sTall = g_ScriptSymbols.AddString("tall"); + + m_flCurrentTime = 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +AnimationController::~AnimationController() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Sets which script file to use +//----------------------------------------------------------------------------- +bool AnimationController::SetScriptFile( VPANEL sizingPanel, const char *fileName, bool wipeAll /*=false*/ ) +{ + m_hSizePanel = sizingPanel; + + if ( wipeAll ) + { + // clear the current script + m_Sequences.RemoveAll(); + m_ScriptFileNames.RemoveAll(); + + CancelAllAnimations(); + } + + // Store off this filename for reloading later on (if we don't have it already) + UtlSymId_t sFilename = g_ScriptSymbols.AddString( fileName ); + if ( m_ScriptFileNames.Find( sFilename ) == m_ScriptFileNames.InvalidIndex() ) + { + m_ScriptFileNames.AddToTail( sFilename ); + } + + UpdateScreenSize(); + + // load the new script file + return LoadScriptFile( fileName ); +} + +//----------------------------------------------------------------------------- +// Purpose: reloads the currently set script file +//----------------------------------------------------------------------------- +void AnimationController::ReloadScriptFile() +{ + // Clear all current sequences + m_Sequences.RemoveAll(); + + UpdateScreenSize(); + + // Reload each file we've loaded + for ( int i = 0; i < m_ScriptFileNames.Count(); i++ ) + { + const char *lpszFilename = g_ScriptSymbols.String( m_ScriptFileNames[i] ); + if ( strlen( lpszFilename ) > 0) + { + if ( LoadScriptFile( lpszFilename ) == false ) + { + Assert( 0 ); + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: loads a script file from disk +//----------------------------------------------------------------------------- +bool AnimationController::LoadScriptFile(const char *fileName) +{ + FileHandle_t f = g_pFullFileSystem->Open(fileName, "rt"); + if (!f) + { + Warning("Couldn't find script file %s\n", fileName); + return false; + } + + // read the whole thing into memory + int size = g_pFullFileSystem->Size(f); + // read into temporary memory block + int nBufSize = size+1; + if ( IsXbox() ) + { + nBufSize = AlignValue( nBufSize, 512 ); + } + char *pMem = (char *)malloc(nBufSize); + int bytesRead = g_pFullFileSystem->ReadEx(pMem, nBufSize, size, f); + Assert(bytesRead <= size); + pMem[bytesRead] = 0; + g_pFullFileSystem->Close(f); + // parse + bool success = ParseScriptFile(pMem, bytesRead); + free(pMem); + return success; +} + +AnimationController::RelativeAlignmentLookup AnimationController::g_AlignmentLookup[] = +{ + { AnimationController::a_northwest , "northwest" }, + { AnimationController::a_north , "north" }, + { AnimationController::a_northeast , "northeast" }, + { AnimationController::a_west , "west" }, + { AnimationController::a_center , "center" }, + { AnimationController::a_east , "east" }, + { AnimationController::a_southwest , "southwest" }, + { AnimationController::a_south , "south" }, + { AnimationController::a_southeast , "southeast" }, + + { AnimationController::a_northwest , "nw" }, + { AnimationController::a_north , "n" }, + { AnimationController::a_northeast , "ne" }, + { AnimationController::a_west , "w" }, + { AnimationController::a_center , "c" }, + { AnimationController::a_east , "e" }, + { AnimationController::a_southwest , "sw" }, + { AnimationController::a_south , "s" }, + { AnimationController::a_southeast , "se" }, +}; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +AnimationController::RelativeAlignment AnimationController::LookupAlignment( char const *token ) +{ + int c = ARRAYSIZE( g_AlignmentLookup ); + + for ( int i = 0; i < c; i++ ) + { + if ( !Q_stricmp( token, g_AlignmentLookup[ i ].name ) ) + { + return g_AlignmentLookup[ i ].align; + } + } + + return AnimationController::a_northwest; +} + +//----------------------------------------------------------------------------- +// Purpose: Parse position including right edge and center adjustment out of a +// token. This is relative to the screen +//----------------------------------------------------------------------------- +void AnimationController::SetupPosition( AnimCmdAnimate_t& cmd, float *output, char const *psz, int screendimension ) +{ + bool r = false, c = false; + int pos; + if ( psz[0] == '(' ) + { + psz++; + + if ( Q_strstr( psz, ")" ) ) + { + char sz[ 256 ]; + Q_strncpy( sz, psz, sizeof( sz ) ); + + char *colon = Q_strstr( sz, ":" ); + if ( colon ) + { + *colon = 0; + + RelativeAlignment ra = LookupAlignment( sz ); + + colon++; + + char *panelName = colon; + char *panelEnd = Q_strstr( panelName, ")" ); + if ( panelEnd ) + { + *panelEnd = 0; + + if ( Q_strlen( panelName ) > 0 ) + { + // + cmd.align.relativePosition = true; + cmd.align.alignPanel = g_ScriptSymbols.AddString(panelName); + cmd.align.alignment = ra; + } + } + } + + psz = Q_strstr( psz, ")" ) + 1; + } + } + else if (psz[0] == 'r' || psz[0] == 'R') + { + r = true; + psz++; + } + else if (psz[0] == 'c' || psz[0] == 'C') + { + c = true; + psz++; + } + + // get the number + pos = atoi(psz); + + // scale the values + if (IsProportional()) + { + pos = vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), pos ); + } + + // adjust the positions + if (r) + { + pos = screendimension - pos; + } + if (c) + { + pos = (screendimension / 2) + pos; + } + + // set the value + *output = static_cast<float>( pos ); +} + + +//----------------------------------------------------------------------------- +// Purpose: parses a script into sequences +//----------------------------------------------------------------------------- +bool AnimationController::ParseScriptFile(char *pMem, int length) +{ + // get the scheme (for looking up color names) + IScheme *scheme = vgui::scheme()->GetIScheme(GetScheme()); + + // get our screen size (for left/right/center alignment) + int screenWide = m_nScreenBounds[ 2 ]; + int screenTall = m_nScreenBounds[ 3 ]; + + // start by getting the first token + char token[512]; + pMem = ParseFile(pMem, token, NULL); + while (token[0]) + { + bool bAccepted = true; + + // should be 'event' + if (stricmp(token, "event")) + { + Warning("Couldn't parse script file: expected 'event', found '%s'\n", token); + return false; + } + + // get the event name + pMem = ParseFile(pMem, token, NULL); + if (strlen(token) < 1) + { + Warning("Couldn't parse script file: expected <event name>, found nothing\n"); + return false; + } + + int seqIndex; + UtlSymId_t nameIndex = g_ScriptSymbols.AddString(token); + + // Create a new sequence + seqIndex = m_Sequences.AddToTail(); + AnimSequence_t &seq = m_Sequences[seqIndex]; + seq.name = nameIndex; + seq.duration = 0.0f; + + // get the open brace or a conditional + pMem = ParseFile(pMem, token, NULL); + if ( Q_stristr( token, "[$" ) ) + { + bAccepted = EvaluateConditional( token ); + + // now get the open brace + pMem = ParseFile(pMem, token, NULL); + } + + if (stricmp(token, "{")) + { + Warning("Couldn't parse script sequence '%s': expected '{', found '%s'\n", g_ScriptSymbols.String(seq.name), token); + return false; + } + + // walk the commands + while (token && token[0]) + { + // get the command type + pMem = ParseFile(pMem, token, NULL); + + // skip out when we hit the end of the sequence + if (token[0] == '}') + break; + + // create a new command + int cmdIndex = seq.cmdList.AddToTail(); + AnimCommand_t &animCmd = seq.cmdList[cmdIndex]; + memset(&animCmd, 0, sizeof(animCmd)); + if (!stricmp(token, "animate")) + { + animCmd.commandType = CMD_ANIMATE; + // parse out the animation commands + AnimCmdAnimate_t &cmdAnimate = animCmd.cmdData.animate; + // panel to manipulate + pMem = ParseFile(pMem, token, NULL); + cmdAnimate.panel = g_ScriptSymbols.AddString(token); + // variable to change + pMem = ParseFile(pMem, token, NULL); + cmdAnimate.variable = g_ScriptSymbols.AddString(token); + // target value + pMem = ParseFile(pMem, token, NULL); + if (cmdAnimate.variable == m_sPosition) + { + // Get first token + SetupPosition( cmdAnimate, &cmdAnimate.target.a, token, screenWide ); + + // Get second token from "token" + char token2[32]; + char *psz = ParseFile(token, token2, NULL); + psz = ParseFile(psz, token2, NULL); + psz = token2; + + // Position Y goes into ".b" + SetupPosition( cmdAnimate, &cmdAnimate.target.b, psz, screenTall ); + } + else if ( cmdAnimate.variable == m_sXPos ) + { + // XPos and YPos both use target ".a" + SetupPosition( cmdAnimate, &cmdAnimate.target.a, token, screenWide ); + } + else if ( cmdAnimate.variable == m_sYPos ) + { + // XPos and YPos both use target ".a" + SetupPosition( cmdAnimate, &cmdAnimate.target.a, token, screenTall ); + } + else + { + // parse the floating point values right out + if (0 == sscanf(token, "%f %f %f %f", &cmdAnimate.target.a, &cmdAnimate.target.b, &cmdAnimate.target.c, &cmdAnimate.target.d)) + { + //============================================================================= + // HPE_BEGIN: + // [pfreese] Improved handling colors not defined in scheme + //============================================================================= + + // could be referencing a value in the scheme file, lookup + Color default_invisible_black(0, 0, 0, 0); + Color col = scheme->GetColor(token, default_invisible_black); + + // we don't have a way of seeing if the color is not declared in the scheme, so we use this + // silly method of trying again with a different default to see if we get the fallback again + if (col == default_invisible_black) + { + Color error_pink(255, 0, 255, 255); // make it extremely obvious if a scheme lookup fails + col = scheme->GetColor(token, error_pink); + + // commented out for Soldier/Demo release...(getting spammed in console) + // we'll try to figure this out after the update is out +// if (col == error_pink) +// { +// Warning("Missing color in scheme: %s\n", token); +// } + } + + //============================================================================= + // HPE_END + //============================================================================= + + cmdAnimate.target.a = col[0]; + cmdAnimate.target.b = col[1]; + cmdAnimate.target.c = col[2]; + cmdAnimate.target.d = col[3]; + } + } + + // fix up scale + if (cmdAnimate.variable == m_sSize) + { + if (IsProportional()) + { + cmdAnimate.target.a = static_cast<float>( vgui::scheme()->GetProportionalScaledValueEx(GetScheme(), cmdAnimate.target.a) ); + cmdAnimate.target.b = static_cast<float>( vgui::scheme()->GetProportionalScaledValueEx(GetScheme(), cmdAnimate.target.b) ); + } + } + else if (cmdAnimate.variable == m_sWide || + cmdAnimate.variable == m_sTall ) + { + if (IsProportional()) + { + // Wide and tall both use.a + cmdAnimate.target.a = static_cast<float>( vgui::scheme()->GetProportionalScaledValueEx(GetScheme(), cmdAnimate.target.a) ); + } + } + + // interpolation function + pMem = ParseFile(pMem, token, NULL); + if (!stricmp(token, "Accel")) + { + cmdAnimate.interpolationFunction = INTERPOLATOR_ACCEL; + } + else if (!stricmp(token, "Deaccel")) + { + cmdAnimate.interpolationFunction = INTERPOLATOR_DEACCEL; + } + else if ( !stricmp(token, "Spline")) + { + cmdAnimate.interpolationFunction = INTERPOLATOR_SIMPLESPLINE; + } + else if (!stricmp(token,"Pulse")) + { + cmdAnimate.interpolationFunction = INTERPOLATOR_PULSE; + // frequencey + pMem = ParseFile(pMem, token, NULL); + cmdAnimate.interpolationParameter = (float)atof(token); + } + else if ( !stricmp( token, "Flicker")) + { + cmdAnimate.interpolationFunction = INTERPOLATOR_FLICKER; + // noiseamount + pMem = ParseFile(pMem, token, NULL); + cmdAnimate.interpolationParameter = (float)atof(token); + } + else if (!stricmp(token, "Bounce")) + { + cmdAnimate.interpolationFunction = INTERPOLATOR_BOUNCE; + } + else + { + cmdAnimate.interpolationFunction = INTERPOLATOR_LINEAR; + } + // start time + pMem = ParseFile(pMem, token, NULL); + cmdAnimate.startTime = (float)atof(token); + // duration + pMem = ParseFile(pMem, token, NULL); + cmdAnimate.duration = (float)atof(token); + // check max duration + if (cmdAnimate.startTime + cmdAnimate.duration > seq.duration) + { + seq.duration = cmdAnimate.startTime + cmdAnimate.duration; + } + } + else if (!stricmp(token, "runevent")) + { + animCmd.commandType = CMD_RUNEVENT; + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + } + else if (!stricmp(token, "stopevent")) + { + animCmd.commandType = CMD_STOPEVENT; + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + } + else if (!stricmp(token, "StopPanelAnimations")) + { + animCmd.commandType = CMD_STOPPANELANIMATIONS; + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + } + else if (!stricmp(token, "stopanimation")) + { + animCmd.commandType = CMD_STOPANIMATION; + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + } + else if ( !stricmp( token, "SetFont" )) + { + animCmd.commandType = CMD_SETFONT; + // Panel name + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token); + // Font parameter + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token); + // Font name from scheme + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable2 = g_ScriptSymbols.AddString(token); + + // Set time + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + } + else if ( !stricmp( token, "SetTexture" )) + { + animCmd.commandType = CMD_SETTEXTURE; + // Panel name + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token); + // Texture Id + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token); + // material name + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable2 = g_ScriptSymbols.AddString(token); + + // Set time + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + } + else if ( !stricmp( token, "SetString" )) + { + animCmd.commandType = CMD_SETSTRING; + // Panel name + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token); + // String variable name + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token); + // String value to set + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable2 = g_ScriptSymbols.AddString(token); + + // Set time + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + } + else + { + Warning("Couldn't parse script sequence '%s': expected <anim command>, found '%s'\n", g_ScriptSymbols.String(seq.name), token); + return false; + } + + // Look ahead one token for a conditional + char *peek = ParseFile(pMem, token, NULL); + if ( Q_stristr( token, "[$" ) ) + { + if ( !EvaluateConditional( token ) ) + { + seq.cmdList.Remove( cmdIndex ); + } + pMem = peek; + } + } + + if ( bAccepted ) + { + // Attempt to find a collision in the sequences, replacing the old one if found + int seqIterator; + for ( seqIterator = 0; seqIterator < m_Sequences.Count()-1; seqIterator++ ) + { + if ( m_Sequences[seqIterator].name == nameIndex ) + { + // Get rid of it, we're overriding it + m_Sequences.Remove( seqIndex ); + break; + } + } + } + else + { + // Dump the entire sequence + m_Sequences.Remove( seqIndex ); + } + + // get the next token, if any + pMem = ParseFile(pMem, token, NULL); + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: checks all posted animation events, firing if time +//----------------------------------------------------------------------------- +void AnimationController::UpdatePostedMessages(bool bRunToCompletion) +{ + CUtlVector<RanEvent_t> eventsRanThisFrame; + + // check all posted messages + for (int i = 0; i < m_PostedMessages.Count(); i++) + { + PostedMessage_t &msgRef = m_PostedMessages[i]; + if (m_flCurrentTime < msgRef.startTime && !bRunToCompletion) + continue; + + // take a copy of th message + PostedMessage_t msg = msgRef; + + // remove the event + // do this before handling the message because the message queue may be messed with + m_PostedMessages.Remove(i); + // reset the count, start the whole queue again + i = -1; + + // handle the event + switch (msg.commandType) + { + case CMD_RUNEVENT: + { + RanEvent_t curEvent; + curEvent.event = msg.event; + curEvent.pParent = msg.parent.Get(); + + // run the event, but only if we haven't already run it this frame, for this parent + if (!eventsRanThisFrame.HasElement(curEvent)) + { + eventsRanThisFrame.AddToTail(curEvent); + RunCmd_RunEvent(msg); + } + } + break; + case CMD_STOPEVENT: + RunCmd_StopEvent(msg); + break; + case CMD_STOPPANELANIMATIONS: + RunCmd_StopPanelAnimations(msg); + break; + case CMD_STOPANIMATION: + RunCmd_StopAnimation(msg); + break; + case CMD_SETFONT: + RunCmd_SetFont(msg); + break; + case CMD_SETTEXTURE: + RunCmd_SetTexture(msg); + break; + case CMD_SETSTRING: + RunCmd_SetString( msg ); + break; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: runs the current animations +//----------------------------------------------------------------------------- +void AnimationController::UpdateActiveAnimations(bool bRunToCompletion) +{ + // iterate all the currently active animations + for (int i = 0; i < m_ActiveAnimations.Count(); i++) + { + ActiveAnimation_t &anim = m_ActiveAnimations[i]; + + // see if the anim is ready to start + if (m_flCurrentTime < anim.startTime && !bRunToCompletion) + continue; + + if (!anim.panel.Get()) + { + // panel is gone, remove the animation + m_ActiveAnimations.Remove(i); + --i; + continue; + } + + if (!anim.started && !bRunToCompletion) + { + // start the animation from the current value + anim.startValue = GetValue(anim, anim.panel, anim.variable); + anim.started = true; + + // Msg( "Starting animation of %s => %.2f (seq: %s) (%s)\n", g_ScriptSymbols.String(anim.variable), anim.endValue.a, g_ScriptSymbols.String(anim.seqName), anim.panel->GetName()); + } + + // get the interpolated value + Value_t val; + if (m_flCurrentTime >= anim.endTime || bRunToCompletion) + { + // animation is done, use the last value + val = anim.endValue; + } + else + { + // get the interpolated value + val = GetInterpolatedValue(anim.interpolator, anim.interpolatorParam, m_flCurrentTime, anim.startTime, anim.endTime, anim.startValue, anim.endValue); + } + + // apply the new value to the panel + SetValue(anim, anim.panel, anim.variable, val); + + // Msg( "Animate value: %s => %.2f for panel '%s'\n", g_ScriptSymbols.String(anim.variable), val.a, anim.panel->GetName()); + + // see if we can remove the animation + if (m_flCurrentTime >= anim.endTime || bRunToCompletion) + { + m_ActiveAnimations.Remove(i); + --i; + } + } +} + +bool AnimationController::UpdateScreenSize() +{ + // get our screen size (for left/right/center alignment) + int screenWide, screenTall; + int sx = 0, sy = 0; + if ( m_hSizePanel != 0 ) + { + ipanel()->GetSize( m_hSizePanel, screenWide, screenTall ); + ipanel()->GetPos( m_hSizePanel, sx, sy ); + } + else + { + surface()->GetScreenSize(screenWide, screenTall); + } + + bool changed = m_nScreenBounds[ 0 ] != sx || + m_nScreenBounds[ 1 ] != sy || + m_nScreenBounds[ 2 ] != screenWide || + m_nScreenBounds[ 3 ] != screenTall; + + m_nScreenBounds[ 0 ] = sx; + m_nScreenBounds[ 1 ] = sy; + m_nScreenBounds[ 2 ] = screenWide; + m_nScreenBounds[ 3 ] = screenTall; + + return changed; +} +//----------------------------------------------------------------------------- +// Purpose: runs a frame of animation +//----------------------------------------------------------------------------- +void AnimationController::UpdateAnimations( float currentTime ) +{ + m_flCurrentTime = currentTime; + + if ( UpdateScreenSize() && m_ScriptFileNames.Count() ) + { + RunAllAnimationsToCompletion(); + ReloadScriptFile(); + } + + UpdatePostedMessages(false); + UpdateActiveAnimations(false); +} + +//----------------------------------------------------------------------------- +// Purpose: plays all animations to completion instantly +//----------------------------------------------------------------------------- +void AnimationController::RunAllAnimationsToCompletion() +{ + // Msg( "AnimationController::RunAllAnimationsToCompletion()\n" ); + UpdatePostedMessages(true); + UpdateActiveAnimations(true); +} + +//----------------------------------------------------------------------------- +// Purpose: Stops all current animations +//----------------------------------------------------------------------------- +void AnimationController::CancelAllAnimations() +{ + // Msg( "AnimationController::CancelAllAnimations()\n" ); + + m_ActiveAnimations.RemoveAll(); + m_PostedMessages.RemoveAll(); +} + +//----------------------------------------------------------------------------- +// Purpose: produces an interpolated value +//----------------------------------------------------------------------------- +AnimationController::Value_t AnimationController::GetInterpolatedValue(int interpolator, float interpolatorParam, float currentTime, float startTime, float endTime, Value_t &startValue, Value_t &endValue) +{ + // calculate how far we are into the animation + float pos = (currentTime - startTime) / (endTime - startTime); + + // adjust the percentage through by the interpolation function + switch (interpolator) + { + case INTERPOLATOR_ACCEL: + pos *= pos; + break; + case INTERPOLATOR_DEACCEL: + pos = sqrtf(pos); + break; + case INTERPOLATOR_SIMPLESPLINE: + pos = SimpleSpline( pos ); + break; + case INTERPOLATOR_PULSE: + // Make sure we end at 1.0, so use cosine + pos = 0.5f + 0.5f * ( cos( pos * 2.0f * M_PI * interpolatorParam ) ); + break; + case INTERPOLATOR_FLICKER: + if ( RandomFloat( 0.0f, 1.0f ) < interpolatorParam ) + { + pos = 1.0f; + } + else + { + pos = 0.0f; + } + break; + case INTERPOLATOR_BOUNCE: + { + // fall from startValue to endValue, bouncing a few times and settling out at endValue + const float hit1 = 0.33f; + const float hit2 = 0.67f; + const float hit3 = 1.0f; + + if ( pos < hit1 ) + { + pos = 1.0f - sin( M_PI * pos / hit1 ); + } + else if ( pos < hit2 ) + { + pos = 0.5f + 0.5f * ( 1.0f - sin( M_PI * ( pos - hit1 ) / ( hit2 - hit1 ) ) ); + } + else + { + pos = 0.8f + 0.2f * ( 1.0f - sin( M_PI * ( pos - hit2 ) / ( hit3 - hit2 ) ) ); + } + break; + } + case INTERPOLATOR_LINEAR: + default: + break; + } + + // calculate the value + Value_t val; + val.a = ((endValue.a - startValue.a) * pos) + startValue.a; + val.b = ((endValue.b - startValue.b) * pos) + startValue.b; + val.c = ((endValue.c - startValue.c) * pos) + startValue.c; + val.d = ((endValue.d - startValue.d) * pos) + startValue.d; + return val; +} + +//----------------------------------------------------------------------------- +// Purpose: sets that the script file should be reloaded each time a script is ran +// used for development +//----------------------------------------------------------------------------- +void AnimationController::SetAutoReloadScript(bool state) +{ + m_bAutoReloadScript = state; +} + +//----------------------------------------------------------------------------- +// Purpose: starts an animation sequence script +//----------------------------------------------------------------------------- +bool AnimationController::StartAnimationSequence(const char *sequenceName) +{ + // We support calling an animation on elements that are not the calling + // panel's children. Use the base parent to start the search. + + return StartAnimationSequence( GetParent(), sequenceName ); +} + +//----------------------------------------------------------------------------- +// Purpose: starts an animation sequence script +//----------------------------------------------------------------------------- +bool AnimationController::StartAnimationSequence(Panel *pWithinParent, const char *sequenceName) +{ + Assert( pWithinParent ); + + if (m_bAutoReloadScript) + { + // Reload the script files + ReloadScriptFile(); + } + + // lookup the symbol for the name + UtlSymId_t seqName = g_ScriptSymbols.Find(sequenceName); + if (seqName == UTL_INVAL_SYMBOL) + return false; + + // Msg("Starting animation sequence %s\n", sequenceName); + + // remove the existing command from the queue + RemoveQueuedAnimationCommands(seqName, pWithinParent); + + // look through for the sequence + int i; + for (i = 0; i < m_Sequences.Count(); i++) + { + if (m_Sequences[i].name == seqName) + break; + } + if (i >= m_Sequences.Count()) + return false; + + // execute the sequence + for (int cmdIndex = 0; cmdIndex < m_Sequences[i].cmdList.Count(); cmdIndex++) + { + ExecAnimationCommand(seqName, m_Sequences[i].cmdList[cmdIndex], pWithinParent); + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Runs a custom command from code, not from a script file +//----------------------------------------------------------------------------- +void AnimationController::RunAnimationCommand(vgui::Panel *panel, const char *variable, float targetValue, float startDelaySeconds, float duration, Interpolators_e interpolator, float animParameter /* = 0 */ ) +{ + // clear any previous animations of this variable + UtlSymId_t var = g_ScriptSymbols.AddString(variable); + RemoveQueuedAnimationByType(panel, var, UTL_INVAL_SYMBOL); + + // build a new animation + AnimCmdAnimate_t animateCmd; + memset(&animateCmd, 0, sizeof(animateCmd)); + animateCmd.panel = 0; + animateCmd.variable = var; + animateCmd.target.a = targetValue; + animateCmd.interpolationFunction = interpolator; + animateCmd.interpolationParameter = animParameter; + animateCmd.startTime = startDelaySeconds; + animateCmd.duration = duration; + + // start immediately + StartCmd_Animate(panel, 0, animateCmd); +} + +//----------------------------------------------------------------------------- +// Purpose: Runs a custom command from code, not from a script file +//----------------------------------------------------------------------------- +void AnimationController::RunAnimationCommand(vgui::Panel *panel, const char *variable, Color targetValue, float startDelaySeconds, float duration, Interpolators_e interpolator, float animParameter /* = 0 */ ) +{ + // clear any previous animations of this variable + UtlSymId_t var = g_ScriptSymbols.AddString(variable); + RemoveQueuedAnimationByType(panel, var, UTL_INVAL_SYMBOL); + + // build a new animation + AnimCmdAnimate_t animateCmd; + memset(&animateCmd, 0, sizeof(animateCmd)); + animateCmd.panel = 0; + animateCmd.variable = var; + animateCmd.target.a = targetValue[0]; + animateCmd.target.b = targetValue[1]; + animateCmd.target.c = targetValue[2]; + animateCmd.target.d = targetValue[3]; + animateCmd.interpolationFunction = interpolator; + animateCmd.interpolationParameter = animParameter; + animateCmd.startTime = startDelaySeconds; + animateCmd.duration = duration; + + // start immediately + StartCmd_Animate(panel, 0, animateCmd); +} + +//----------------------------------------------------------------------------- +// Purpose: gets the length of an animation sequence, in seconds +//----------------------------------------------------------------------------- +float AnimationController::GetAnimationSequenceLength(const char *sequenceName) +{ + // lookup the symbol for the name + UtlSymId_t seqName = g_ScriptSymbols.Find(sequenceName); + if (seqName == UTL_INVAL_SYMBOL) + return 0.0f; + + // look through for the sequence + int i; + for (i = 0; i < m_Sequences.Count(); i++) + { + if (m_Sequences[i].name == seqName) + break; + } + if (i >= m_Sequences.Count()) + return 0.0f; + + // sequence found + return m_Sequences[i].duration; +} + +//----------------------------------------------------------------------------- +// Purpose: removes an existing set of commands from the queue +//----------------------------------------------------------------------------- +void AnimationController::RemoveQueuedAnimationCommands(UtlSymId_t seqName, Panel *pWithinParent) +{ + // Msg("Removing queued anims for sequence %s\n", g_ScriptSymbols.String(seqName)); + + // remove messages posted by this sequence + // if pWithinParent is specified, remove only messages under that parent + {for (int i = 0; i < m_PostedMessages.Count(); i++) + { + if ( ( m_PostedMessages[i].seqName == seqName ) && + ( !pWithinParent || ( m_PostedMessages[i].parent == pWithinParent ) ) ) + { + m_PostedMessages.Remove(i); + --i; + } + }} + + // remove all animations + // if pWithinParent is specified, remove only animations under that parent + for (int i = 0; i < m_ActiveAnimations.Count(); i++) + { + if ( m_ActiveAnimations[i].seqName != seqName ) + continue; + + // panel this anim is on, m_ActiveAnimations[i].panel + if ( pWithinParent ) + { + Panel *animPanel = m_ActiveAnimations[i].panel; + + if ( !animPanel ) + continue; + + Panel *foundPanel = pWithinParent->FindChildByName(animPanel->GetName(),true); + + if ( foundPanel != animPanel ) + continue; + } + + m_ActiveAnimations.Remove(i); + --i; + } +} + +//----------------------------------------------------------------------------- +// Purpose: removes the specified queued animation +//----------------------------------------------------------------------------- +void AnimationController::RemoveQueuedAnimationByType(vgui::Panel *panel, UtlSymId_t variable, UtlSymId_t sequenceToIgnore) +{ + for (int i = 0; i < m_ActiveAnimations.Count(); i++) + { + if (m_ActiveAnimations[i].panel == panel && m_ActiveAnimations[i].variable == variable && m_ActiveAnimations[i].seqName != sequenceToIgnore) + { + // Msg("Removing queued anim %s::%s::%s\n", g_ScriptSymbols.String(m_ActiveAnimations[i].seqName), panel->GetName(), g_ScriptSymbols.String(variable)); + m_ActiveAnimations.Remove(i); + break; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: runs a single line of the script +//----------------------------------------------------------------------------- +void AnimationController::ExecAnimationCommand(UtlSymId_t seqName, AnimCommand_t &animCommand, Panel *pWithinParent) +{ + if (animCommand.commandType == CMD_ANIMATE) + { + StartCmd_Animate(seqName, animCommand.cmdData.animate, pWithinParent); + } + else + { + // post the command to happen at the specified time + PostedMessage_t &msg = m_PostedMessages[m_PostedMessages.AddToTail()]; + msg.seqName = seqName; + msg.commandType = animCommand.commandType; + msg.event = animCommand.cmdData.runEvent.event; + msg.variable = animCommand.cmdData.runEvent.variable; + msg.variable2 = animCommand.cmdData.runEvent.variable2; + msg.startTime = m_flCurrentTime + animCommand.cmdData.runEvent.timeDelay; + msg.parent = pWithinParent; + } +} + +//----------------------------------------------------------------------------- +// Purpose: starts a variable animation +//----------------------------------------------------------------------------- +void AnimationController::StartCmd_Animate(UtlSymId_t seqName, AnimCmdAnimate_t &cmd, Panel *pWithinParent) +{ + Assert( pWithinParent ); + if ( !pWithinParent ) + return; + + // make sure the child exists + Panel *panel = pWithinParent->FindChildByName(g_ScriptSymbols.String(cmd.panel),true); + if ( !panel ) + { + // Check the parent + Panel *parent = GetParent(); + if ( !Q_stricmp( parent->GetName(), g_ScriptSymbols.String(cmd.panel) ) ) + { + panel = parent; + } + } + if (!panel) + return; + + StartCmd_Animate(panel, seqName, cmd); +} + +//----------------------------------------------------------------------------- +// Purpose: Starts an animation command for the specified panel +//----------------------------------------------------------------------------- +void AnimationController::StartCmd_Animate(Panel *panel, UtlSymId_t seqName, AnimCmdAnimate_t &cmd) +{ + // build a command to add to the animation queue + ActiveAnimation_t &anim = m_ActiveAnimations[m_ActiveAnimations.AddToTail()]; + anim.panel = panel; + anim.seqName = seqName; + anim.variable = cmd.variable; + anim.interpolator = cmd.interpolationFunction; + anim.interpolatorParam = cmd.interpolationParameter; + // timings + anim.startTime = m_flCurrentTime + cmd.startTime; + anim.endTime = anim.startTime + cmd.duration; + // values + anim.started = false; + anim.endValue = cmd.target; + + anim.align = cmd.align; +} + +//----------------------------------------------------------------------------- +// Purpose: a posted message to run another event +//----------------------------------------------------------------------------- +void AnimationController::RunCmd_RunEvent(PostedMessage_t &msg) +{ + StartAnimationSequence(msg.parent.Get(), g_ScriptSymbols.String(msg.event)); +} + +//----------------------------------------------------------------------------- +// Purpose: a posted message to stop another event +//----------------------------------------------------------------------------- +void AnimationController::RunCmd_StopEvent(PostedMessage_t &msg) +{ + RemoveQueuedAnimationCommands(msg.event, msg.parent); +} + +//----------------------------------------------------------------------------- +// Purpose: a posted message to stop all animations relevant to a specified panel +//----------------------------------------------------------------------------- +void AnimationController::RunCmd_StopPanelAnimations(PostedMessage_t &msg) +{ + Panel *panel = FindSiblingByName(g_ScriptSymbols.String(msg.event)); + Assert(panel != NULL); + if (!panel) + return; + + // loop through all the active animations cancelling any that + // are operating on said panel, except for the event specified + for (int i = 0; i < m_ActiveAnimations.Count(); i++) + { + if (m_ActiveAnimations[i].panel == panel && m_ActiveAnimations[i].seqName != msg.seqName) + { + m_ActiveAnimations.Remove(i); + --i; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: a posted message to stop animations of a specific type +//----------------------------------------------------------------------------- +void AnimationController::RunCmd_StopAnimation(PostedMessage_t &msg) +{ + Panel *panel = FindSiblingByName(g_ScriptSymbols.String(msg.event)); + Assert(panel != NULL); + if (!panel) + return; + + RemoveQueuedAnimationByType(panel, msg.variable, msg.seqName); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void AnimationController::RunCmd_SetFont( PostedMessage_t &msg ) +{ + Panel *parent = msg.parent.Get(); + + if ( !parent ) + { + parent = GetParent(); + } + + Panel *panel = parent->FindChildByName(g_ScriptSymbols.String(msg.event), true); + Assert(panel != NULL); + if (!panel) + return; + + KeyValues *inputData = new KeyValues(g_ScriptSymbols.String(msg.variable)); + inputData->SetString(g_ScriptSymbols.String(msg.variable), g_ScriptSymbols.String(msg.variable2)); + if (!panel->SetInfo(inputData)) + { + // Assert(!("Unhandlable var in AnimationController::SetValue())")); + } + inputData->deleteThis(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void AnimationController::RunCmd_SetTexture( PostedMessage_t &msg ) +{ + Panel *panel = FindSiblingByName(g_ScriptSymbols.String(msg.event)); + Assert(panel != NULL); + if (!panel) + return; + + KeyValues *inputData = new KeyValues(g_ScriptSymbols.String(msg.variable)); + inputData->SetString(g_ScriptSymbols.String(msg.variable), g_ScriptSymbols.String(msg.variable2)); + if (!panel->SetInfo(inputData)) + { + // Assert(!("Unhandlable var in AnimationController::SetValue())")); + } + inputData->deleteThis(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void AnimationController::RunCmd_SetString( PostedMessage_t &msg ) +{ + Panel *panel = FindSiblingByName(g_ScriptSymbols.String(msg.event)); + Assert(panel != NULL); + if (!panel) + return; + + KeyValues *inputData = new KeyValues(g_ScriptSymbols.String(msg.variable)); + inputData->SetString(g_ScriptSymbols.String(msg.variable), g_ScriptSymbols.String(msg.variable2)); + if (!panel->SetInfo(inputData)) + { + // Assert(!("Unhandlable var in AnimationController::SetValue())")); + } + inputData->deleteThis(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int AnimationController::GetRelativeOffset( AnimAlign_t& align, bool xcoord ) +{ + if ( !align.relativePosition ) + return 0; + + Panel *panel = GetParent()->FindChildByName(g_ScriptSymbols.String(align.alignPanel), true); + if ( !panel ) + return 0; + + int x, y, w, h; + panel->GetBounds( x, y, w, h ); + + int offset =0; + switch ( align.alignment ) + { + default: + case a_northwest: + offset = xcoord ? x : y; + break; + case a_north: + offset = xcoord ? ( x + w ) / 2 : y; + break; + case a_northeast: + offset = xcoord ? ( x + w ) : y; + break; + case a_west: + offset = xcoord ? x : ( y + h ) / 2; + break; + case a_center: + offset = xcoord ? ( x + w ) / 2 : ( y + h ) / 2; + break; + case a_east: + offset = xcoord ? ( x + w ) : ( y + h ) / 2; + break; + case a_southwest: + offset = xcoord ? x : ( y + h ); + break; + case a_south: + offset = xcoord ? ( x + w ) / 2 : ( y + h ); + break; + case a_southeast: + offset = xcoord ? ( x + w ) : ( y + h ); + break; + } + + return offset; +} + +//----------------------------------------------------------------------------- +// Purpose: Gets the specified value from a panel +//----------------------------------------------------------------------------- +AnimationController::Value_t AnimationController::GetValue(ActiveAnimation_t& anim, Panel *panel, UtlSymId_t var) +{ + Value_t val = { 0, 0, 0, 0 }; + if (var == m_sPosition) + { + int x, y; + panel->GetPos(x, y); + val.a = (float)(x - GetRelativeOffset( anim.align, true ) ); + val.b = (float)(y - GetRelativeOffset( anim.align, false ) ); + } + else if (var == m_sSize) + { + int w, t; + panel->GetSize(w, t); + val.a = (float)w; + val.b = (float)t; + } + else if (var == m_sFgColor) + { + Color col = panel->GetFgColor(); + val.a = col[0]; + val.b = col[1]; + val.c = col[2]; + val.d = col[3]; + } + else if (var == m_sBgColor) + { + Color col = panel->GetBgColor(); + val.a = col[0]; + val.b = col[1]; + val.c = col[2]; + val.d = col[3]; + } + else if ( var == m_sXPos ) + { + int x, y; + panel->GetPos(x, y); + val.a = (float)( x - GetRelativeOffset( anim.align, true ) ); + } + else if ( var == m_sYPos ) + { + int x, y; + panel->GetPos(x, y); + val.a = (float)( y - GetRelativeOffset( anim.align, false ) ); + } + else if ( var == m_sWide ) + { + int w, h; + panel->GetSize(w, h); + val.a = (float)w; + } + else if ( var == m_sTall ) + { + int w, h; + panel->GetSize(w, h); + val.a = (float)h; + } + else + { + KeyValues *outputData = new KeyValues(g_ScriptSymbols.String(var)); + if (panel->RequestInfo(outputData)) + { + // find the var and lookup it's type + KeyValues *kv = outputData->FindKey(g_ScriptSymbols.String(var)); + if (kv && kv->GetDataType() == KeyValues::TYPE_FLOAT) + { + val.a = kv->GetFloat(); + val.b = 0.0f; + val.c = 0.0f; + val.d = 0.0f; + } + else if (kv && kv->GetDataType() == KeyValues::TYPE_COLOR) + { + Color col = kv->GetColor(); + val.a = col[0]; + val.b = col[1]; + val.c = col[2]; + val.d = col[3]; + } + } + else + { + // Assert(!("Unhandlable var in AnimationController::GetValue())")); + } + outputData->deleteThis(); + } + return val; +} + +//----------------------------------------------------------------------------- +// Purpose: Sets a value in a panel +//----------------------------------------------------------------------------- +void AnimationController::SetValue(ActiveAnimation_t& anim, Panel *panel, UtlSymId_t var, Value_t &value) +{ + if (var == m_sPosition) + { + int x = (int)value.a + GetRelativeOffset( anim.align, true ); + int y = (int)value.b + GetRelativeOffset( anim.align, false ); + panel->SetPos(x, y); + } + else if (var == m_sSize) + { + panel->SetSize((int)value.a, (int)value.b); + } + else if (var == m_sFgColor) + { + Color col = panel->GetFgColor(); + col[0] = (unsigned char)value.a; + col[1] = (unsigned char)value.b; + col[2] = (unsigned char)value.c; + col[3] = (unsigned char)value.d; + panel->SetFgColor(col); + } + else if (var == m_sBgColor) + { + Color col = panel->GetBgColor(); + col[0] = (unsigned char)value.a; + col[1] = (unsigned char)value.b; + col[2] = (unsigned char)value.c; + col[3] = (unsigned char)value.d; + panel->SetBgColor(col); + } + else if (var == m_sXPos) + { + int newx = (int)value.a + GetRelativeOffset( anim.align, true ); + int x, y; + panel->GetPos( x, y ); + x = newx; + panel->SetPos(x, y); + } + else if (var == m_sYPos) + { + int newy = (int)value.a + GetRelativeOffset( anim.align, false ); + int x, y; + panel->GetPos( x, y ); + y = newy; + panel->SetPos(x, y); + } + else if (var == m_sWide) + { + int neww = (int)value.a; + int w, h; + panel->GetSize( w, h ); + w = neww; + panel->SetSize(w, h); + } + else if (var == m_sTall) + { + int newh = (int)value.a; + int w, h; + panel->GetSize( w, h ); + h = newh; + panel->SetSize(w, h); + } + else + { + KeyValues *inputData = new KeyValues(g_ScriptSymbols.String(var)); + // set the custom value + if (value.b == 0.0f && value.c == 0.0f && value.d == 0.0f) + { + // only the first value is non-zero, so probably just a float value + inputData->SetFloat(g_ScriptSymbols.String(var), value.a); + } + else + { + // multivalue, set the color + Color col((unsigned char)value.a, (unsigned char)value.b, (unsigned char)value.c, (unsigned char)value.d); + inputData->SetColor(g_ScriptSymbols.String(var), col); + } + if (!panel->SetInfo(inputData)) + { + // Assert(!("Unhandlable var in AnimationController::SetValue())")); + } + inputData->deleteThis(); + } +} +// Hooks between panels and animation controller system + +class CPanelAnimationDictionary +{ +public: + CPanelAnimationDictionary() : m_PanelAnimationMapPool( 32 ) + { + } + + ~CPanelAnimationDictionary() + { + m_PanelAnimationMapPool.Clear(); + } + + PanelAnimationMap *FindOrAddPanelAnimationMap( char const *className ); + PanelAnimationMap *FindPanelAnimationMap( char const *className ); + void PanelAnimationDumpVars( char const *className ); +private: + + struct PanelAnimationMapDictionaryEntry + { + PanelAnimationMap *map; + }; + + char const *StripNamespace( char const *className ); + void PanelAnimationDumpMap( PanelAnimationMap *map, bool recursive ); + + CClassMemoryPool< PanelAnimationMap > m_PanelAnimationMapPool; + CUtlDict< PanelAnimationMapDictionaryEntry, int > m_AnimationMaps; +}; + + +char const *CPanelAnimationDictionary::StripNamespace( char const *className ) +{ + if ( !Q_strnicmp( className, "vgui::", 6 ) ) + { + return className + 6; + } + return className; +} + +//----------------------------------------------------------------------------- +// Purpose: Find but don't add mapping +//----------------------------------------------------------------------------- +PanelAnimationMap *CPanelAnimationDictionary::FindPanelAnimationMap( char const *className ) +{ + int lookup = m_AnimationMaps.Find( StripNamespace( className ) ); + if ( lookup != m_AnimationMaps.InvalidIndex() ) + { + return m_AnimationMaps[ lookup ].map; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +PanelAnimationMap *CPanelAnimationDictionary::FindOrAddPanelAnimationMap( char const *className ) +{ + PanelAnimationMap *map = FindPanelAnimationMap( className ); + if ( map ) + return map; + + Panel::InitPropertyConverters(); + + PanelAnimationMapDictionaryEntry entry; + entry.map = (PanelAnimationMap *)m_PanelAnimationMapPool.Alloc(); + m_AnimationMaps.Insert( StripNamespace( className ), entry ); + return entry.map; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPanelAnimationDictionary::PanelAnimationDumpMap( PanelAnimationMap *map, bool recursive ) +{ + if ( map->pfnClassName ) + { + Msg( "%s\n", (*map->pfnClassName)() ); + } + int c = map->entries.Count(); + for ( int i = 0; i < c; i++ ) + { + PanelAnimationMapEntry *e = &map->entries[ i ]; + Msg( " %s %s\n", e->type(), e->name() ); + } + + if ( recursive && map->baseMap ) + { + PanelAnimationDumpMap( map->baseMap, recursive ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPanelAnimationDictionary::PanelAnimationDumpVars( char const *className ) +{ + if ( className == NULL ) + { + for ( int i = 0; i < (int)m_AnimationMaps.Count(); i++ ) + { + PanelAnimationDumpMap( m_AnimationMaps[ i ].map, false ); + } + } + else + { + PanelAnimationMap *map = FindPanelAnimationMap( className ); + if ( map ) + { + PanelAnimationDumpMap( map, true ); + } + else + { + Msg( "No such Panel Animation class %s\n", className ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: singleton accessor +//----------------------------------------------------------------------------- +CPanelAnimationDictionary& GetPanelAnimationDictionary() +{ + static CPanelAnimationDictionary dictionary; + return dictionary; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +PanelAnimationMap *FindOrAddPanelAnimationMap( char const *className ) +{ + return GetPanelAnimationDictionary().FindOrAddPanelAnimationMap( className ); +} + +//----------------------------------------------------------------------------- +// Purpose: Find but don't add mapping +//----------------------------------------------------------------------------- +PanelAnimationMap *FindPanelAnimationMap( char const *className ) +{ + return GetPanelAnimationDictionary().FindPanelAnimationMap( className ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void PanelAnimationDumpVars( char const *className ) +{ + GetPanelAnimationDictionary().PanelAnimationDumpVars( className ); }
\ No newline at end of file |