//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// // // Purpose: // // $NoKeywords: $ // // Author: samisalreadytaken // //=============================================================================// #include "cbase.h" #include "tier1/utlcommon.h" #include "inputsystem/iinputsystem.h" #include "iinput.h" #include #include #include #include #include #include #include #include "matsys_controls/matsyscontrols.h" #include "VGuiMatSurface/IMatSystemSurface.h" #include #include #include #include #include #include #include #include #include #include //#include #if VGUI_TGA_IMAGE_PANEL #include "bitmap/tgaloader.h" #endif #if !defined(NO_STEAM) #include "steam/steam_api.h" #include "vgui_avatarimage.h" #endif #include "view.h" #include "hudelement.h" //#include "iclientmode.h" // g_pClientMode->GetViewport() #include "vscript_vgui.h" #include "vscript_vgui.nut" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" //============================================================================= // // Exposing a new panel class (e.g. vgui::FileOpenDialog): // // 1. Create C++ bindings using 'CLASS_HELPER_INTERFACE( FileOpenDialog, Frame ){};' // 2. Define script bindings using '#define DEFINE_VGUI_SCRIPTFUNC_FileOpenDialog()' // 3. Create 'class CScript_FileOpenDialog : FileOpenDialog' with vgui message callbacks and overrides if needed // 4. Create script helper using 'BEGIN_VGUI_HELPER( FileOpenDialog )', 'END_VGUI_HELPER()'. This determines the script class name. // 5. Register script bindings with 'BEGIN_SCRIPTDESC_VGUI( FileOpenDialog )', 'END_SCRIPTDESC()' // 6. Add new condition in CScriptVGUI::CreatePanel() // // // // CScript_FileOpenDialog_Helper // ^^ // IScript_FileOpenDialog << CScript_FileOpenDialog // ^^ ^^ // IScript_Frame FileOpenDialog // ^^ ^^ // IScript_Panel Frame // ^^ ^^ // CScriptVGUIObject Panel // //============================================================================= // When enabled, script panels will be parented to custom root panels. // When disabled, script panels will be parented to engine root panels, and allow Z values for script panels to be interplaced amongst non-script panels. // Changing this is not backwards compatible, as existing top level script panel depth would then change relative to non-script panels. #define SCRIPT_ENGINE_ROOT_PANELS 1 // NOTE: causes rendering issues #define ALLOW_SCRIPT_HUD_VIEWPORT_ROOT_PANEL 0 #define ALLOW_SCRIPT_GAMEUI_ROOT_PANEL 0 // On level transitions Restore is called up to 4 times in a row (due to .hl? client state files), each time // trying to restore script panels from pre and post transitions, failing every time because script panels are // destroyed on level shutdown but after client state files are written. // // Script variables are also reset between each OnRestore callback, causing duplicate panels if user scripts create panels // by checking restored script variables. // // The workaround hack is to queue OnRestore callbacks with a think function. // // This code is left here for testing. #define SCRIPT_VGUI_SAVERESTORE 0 #define SCRIPT_VGUI_SIGNAL_INTERFACE 0 #ifdef _DEBUG #define DebugMsg(...) ConColorMsg( Color(196, 196, 156, 255), __VA_ARGS__ ) #define DebugWarning(...) Warning( __VA_ARGS__ ) #define DebugDevMsg(...) DevMsg( __VA_ARGS__ ) #define DBG_PARAM(...) __VA_ARGS__ #else #define DebugMsg(...) (void)(0) #define DebugWarning(...) (void)(0) #define DebugDevMsg(...) (void)(0) #define DBG_PARAM(...) #endif template< typename T > class CCopyableUtlVectorConservative : public CUtlVectorConservative< T > { typedef CUtlVectorConservative< T > BaseClass; public: explicit CCopyableUtlVectorConservative( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {} explicit CCopyableUtlVectorConservative( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} CCopyableUtlVectorConservative( CCopyableUtlVectorConservative const& vec ) { this->CopyArray( vec.Base(), vec.Count() ); } }; using namespace vgui; class IScriptVGUIObject; struct FontData_t; // Aliases contain only one font definition unless 'yres' was defined typedef CCopyableUtlVectorConservative< FontData_t > fontalias_t; typedef CUtlDict< fontalias_t > CFontDict; CFontDict g_ScriptFonts( k_eDictCompareTypeCaseSensitive ); CUtlVector< int > g_ScriptTextureIDs; CUtlLinkedList< IScriptVGUIObject*, unsigned short > g_ScriptPanels; // Boundary is not checked in Surface, keep count manually to sanitise user input. static int g_nFontCount = 0; static inline HFont IntToFontHandle( int i ) { if ( i < 0 || i > g_nFontCount ) return INVALID_FONT; return static_cast< unsigned int >(i); } // vscript does not support unsigned int, // but the representation of the handle does not matter, // and these handles are CUtlVector indices static inline int HandleToInt( unsigned int i ) { return static_cast< int >(i); } struct FontData_t { HFont font; char *name; int tall; int weight; int blur; int scanlines; int flags; //int range_min; //int range_max; int yres_min; int yres_max; bool proportional; }; static const char *GetFixedFontName( const char *name, bool proportional ) { static char fontName[64]; V_snprintf( fontName, sizeof(fontName), "%s-%s", name, proportional ? "p" : "no" ); return fontName; } CON_COMMAND( vgui_spew_fonts_script, "" ) { char fontName[64]; FOR_EACH_DICT_FAST( g_ScriptFonts, i ) { const FontData_t &data = g_ScriptFonts[i].Head(); const char *name = surface()->GetFontName( data.font ); const char *alias = g_ScriptFonts.GetElementName(i); // Strip off the appendix "-p" / "-no" V_StrLeft( alias, V_strlen(alias) - (data.proportional ? 2 : 3), fontName, sizeof(fontName) ); Msg( " %2d: HFont:0x%8.8lx, %s, %s, font:%s, tall:%d(%d) {%d}\n", i, data.font, fontName, alias, name ? name : "??", surface()->GetFontTall( data.font ), surface()->GetFontTallRequested( data.font ), g_ScriptFonts[i].Count() ); } } bool LoadFont( const FontData_t &font DBG_PARAM(, const char *fontAlias) ) { if ( font.yres_min ) { int nScreenWide, nScreenTall; surface()->GetScreenSize( nScreenWide, nScreenTall ); if ( nScreenTall < font.yres_min ) return false; if ( font.yres_max && nScreenTall > font.yres_max ) return false; } int tall = font.tall; int blur = font.blur; int scanlines = font.scanlines; if ( font.proportional && !font.yres_min ) { tall = scheme()->GetProportionalScaledValue( tall ); blur = scheme()->GetProportionalScaledValue( blur ); scanlines = scheme()->GetProportionalScaledValue( scanlines ); } bool bSuccess = surface()->SetFontGlyphSet( font.font, font.name, tall, font.weight, blur, scanlines, font.flags ); NOTE_UNUSED( bSuccess ); if ( bSuccess ) { if ( font.yres_min ) DebugMsg( "Load font [%li]%s [%d %d]\n", font.font, fontAlias, font.yres_min, font.yres_max ); else DebugMsg( "Load font [%li]%s\n", font.font, fontAlias ); } else { DebugWarning( "Failed to load font [%li]%s\n", font.font, fontAlias ); } return true; } void ReloadScriptFontGlyphs() { // Invalidate cached values if ( g_pScriptVM ) g_pScriptVM->Run( "ISurface.__OnScreenSizeChanged()" ); FOR_EACH_DICT_FAST( g_ScriptFonts, i ) { const fontalias_t &alias = g_ScriptFonts[i]; for ( int j = 0; j < alias.Count(); ++j ) { if ( LoadFont( alias.Element(j) DBG_PARAM(, g_ScriptFonts.GetElementName(i)) ) ) break; } } } static inline void InitRootPanel( Panel *p, VGuiPanel_t parent, const char *name ) { int w, h; surface()->GetScreenSize( w, h ); p->Init( 0, 0, w, h ); p->SetName( name ); p->SetVisible( true ); p->SetPaintEnabled( false ); p->SetPaintBackgroundEnabled( false ); p->SetPaintBorderEnabled( false ); p->SetPostChildPaintEnabled( false ); p->SetParent( enginevgui->GetPanel( parent ) ); } class CScriptRootPanel : public Panel { public: CScriptRootPanel() { InitRootPanel( this, PANEL_ROOT, "VScriptRoot" ); } void OnTick() { if ( m_nLastFrame == gpGlobals->framecount ) return; ReloadScriptFontGlyphs(); ivgui()->RemoveTickSignal( GetVPanel() ); } // Used as a callback to font invalidation. // Ideally script fonts would be loaded along with others in engine. // In that case CScriptRootPanel would be removed, and // g_pScriptRootPanel would be CScriptRootDLLPanel inside #if SCRIPT_ENGINE_ROOT_PANELS void OnScreenSizeChanged( int w, int t ) { // Reload fonts in the next vgui frame ivgui()->AddTickSignal( GetVPanel() ); m_nLastFrame = gpGlobals->framecount; // Invalidate cached values if ( g_pScriptVM ) g_pScriptVM->Run( "ISurface.__OnScreenSizeChanged()" ); Panel::OnScreenSizeChanged( w, t ); } private: int m_nLastFrame; }; CScriptRootPanel *g_pScriptRootPanel = NULL; #if SCRIPT_ENGINE_ROOT_PANELS class CScriptRootDLLPanel : public Panel { public: CScriptRootDLLPanel( VGuiPanel_t parent, const char *name ) { InitRootPanel( this, parent, name ); } }; CScriptRootDLLPanel *g_pScriptClientDLLPanel = NULL; #if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL CScriptRootDLLPanel *g_pScriptGameUIDLLPanel = NULL; #endif #endif void VGUI_DestroyScriptRootPanels() { if ( g_pScriptRootPanel ) { delete g_pScriptRootPanel; g_pScriptRootPanel = NULL; } #if SCRIPT_ENGINE_ROOT_PANELS if ( g_pScriptClientDLLPanel ) { delete g_pScriptClientDLLPanel; g_pScriptClientDLLPanel = NULL; } #if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL if ( g_pScriptGameUIDLLPanel ) { delete g_pScriptGameUIDLLPanel; g_pScriptGameUIDLLPanel = NULL; } #endif #endif } VPANEL VGUI_GetScriptRootPanel( VGuiPanel_t type ) { #if !SCRIPT_ENGINE_ROOT_PANELS if ( !g_pScriptRootPanel ) g_pScriptRootPanel = new CScriptRootPanel(); return enginevgui->GetPanel( type ); #else switch ( type ) { case PANEL_ROOT: { if ( !g_pScriptRootPanel ) g_pScriptRootPanel = new CScriptRootPanel(); return g_pScriptRootPanel->GetVPanel(); } case PANEL_CLIENTDLL: { if ( !g_pScriptClientDLLPanel ) g_pScriptClientDLLPanel = new CScriptRootDLLPanel( PANEL_CLIENTDLL, "VScriptClient" ); return g_pScriptClientDLLPanel->GetVPanel(); } #if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL case PANEL_GAMEUIDLL: { if ( !g_pScriptGameUIDLLPanel ) g_pScriptGameUIDLLPanel = new CScriptRootDLLPanel( PANEL_GAMEUIDLL, "VScriptGameUI" ); return g_pScriptGameUIDLLPanel->GetVPanel(); } #endif } return NULL; #endif } // // Escapes "vgui/" prepended to the file name in CSchemeManager::GetImage(). // IImage *vgui_GetImage( const char *imageName, bool hardwareFilter ) { char fileName[MAX_PATH]; V_snprintf( fileName, sizeof( fileName ), "../%s", imageName ); return scheme()->GetImage( fileName, hardwareFilter ); } //-------------------------------------------------------------- // //-------------------------------------------------------------- class CScriptSurface { public: void PlaySound( const char* sound ); void SetColor( int r, int g, int b, int a ); void DrawFilledRect( int x0, int y0, int width, int height ); void DrawFilledRectFade( int x0, int y0, int width, int height, int a0, int a1, bool bHorz ); void DrawOutlinedRect( int x0, int y0, int width, int height, int thickness ); void DrawLine( int x0, int y0, int x1, int y1 ); void DrawOutlinedCircle( int x, int y, int radius, int segments ); void SetTextColor( int r, int g, int b, int a ); void SetTextPos( int x, int y ); void SetTextFont( int font ); void DrawText( const char *text, int drawType/* = FONT_DRAW_DEFAULT*/ ); void DrawUnicodeChar( int ch, int drawType/* = FONT_DRAW_DEFAULT*/ ); int GetFont( const char* name, bool proportional, const char* schema ); int GetTextWidth( int font, const char* text ); int GetFontTall( int font ); int GetCharacterWidth( int font, int ch ); void CreateFont( const char *customName, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int yresMin, int yresMax, bool proportional ); bool AddCustomFontFile( const char *fontFileName ); int GetTextureID( char const *filename ); int ValidateTexture( const char *filename, bool hardwareFilter, bool forceReload, bool procedural ); void SetTextureFile( int id, const char *filename, bool hardwareFilter ); int GetTextureWide( int id ); int GetTextureTall( int id ); void SetTexture( int id ); void DrawTexturedRect( int x0, int y0, int width, int height ); void DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 ); // ------------------------------------------------------------ // Utility functions // ------------------------------------------------------------ void DrawTexturedBox( int texture, int x, int y, int wide, int tall, int r, int g, int b, int a ); void DrawColoredText( int font, int x, int y, int r, int g, int b, int a, const char *text ); void DrawColoredTextRect( int font, int x, int y, int w, int h, int r, int g, int b, int a, const char *text ); void DrawTexturedRectRotated( int x, int y, int w, int t, float yaw ); } script_surface; BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptSurface, "ISurface", SCRIPT_SINGLETON ) DEFINE_SCRIPTFUNC( PlaySound, "" ) DEFINE_SCRIPTFUNC( SetColor, "" ) DEFINE_SCRIPTFUNC( DrawFilledRect, "" ) DEFINE_SCRIPTFUNC( DrawFilledRectFade, "" ) DEFINE_SCRIPTFUNC( DrawOutlinedRect, "" ) DEFINE_SCRIPTFUNC( DrawLine, "" ) DEFINE_SCRIPTFUNC( DrawOutlinedCircle, "" ) DEFINE_SCRIPTFUNC( SetTextColor, "" ) DEFINE_SCRIPTFUNC( SetTextPos, "" ) DEFINE_SCRIPTFUNC( SetTextFont, "" ) DEFINE_SCRIPTFUNC( DrawText, "" ) DEFINE_SCRIPTFUNC( DrawUnicodeChar, "" ) DEFINE_SCRIPTFUNC( GetFont, "" ) DEFINE_SCRIPTFUNC( GetTextWidth, "" ) DEFINE_SCRIPTFUNC( GetFontTall, "" ) DEFINE_SCRIPTFUNC( GetCharacterWidth, "" ) DEFINE_SCRIPTFUNC( CreateFont, SCRIPT_HIDE ) DEFINE_SCRIPTFUNC( AddCustomFontFile, "" ) DEFINE_SCRIPTFUNC( GetTextureID, "" ) DEFINE_SCRIPTFUNC( ValidateTexture, "" ) DEFINE_SCRIPTFUNC( SetTextureFile, "" ) DEFINE_SCRIPTFUNC( GetTextureWide, "" ) DEFINE_SCRIPTFUNC( GetTextureTall, "" ) DEFINE_SCRIPTFUNC( SetTexture, "" ) DEFINE_SCRIPTFUNC( DrawTexturedRect, "" ) DEFINE_SCRIPTFUNC( DrawTexturedSubRect, "" ) DEFINE_SCRIPTFUNC( DrawTexturedBox, "" ) DEFINE_SCRIPTFUNC( DrawColoredText, "" ) DEFINE_SCRIPTFUNC( DrawColoredTextRect, "" ) DEFINE_SCRIPTFUNC( DrawTexturedRectRotated, "" ) END_SCRIPTDESC() void CScriptSurface::PlaySound( const char* sound ) { surface()->PlaySound(sound); } void CScriptSurface::SetColor( int r, int g, int b, int a ) { surface()->DrawSetColor( r, g, b, a ); } void CScriptSurface::DrawFilledRect( int x0, int y0, int width, int height ) { surface()->DrawFilledRect( x0, y0, x0 + width, y0 + height ); } void CScriptSurface::DrawFilledRectFade( int x0, int y0, int width, int height, int a0, int a1, bool bHorz ) { surface()->DrawFilledRectFade( x0, y0, x0 + width, y0 + height, a0, a1, bHorz ); } void CScriptSurface::DrawOutlinedRect( int x0, int y0, int width, int height, int thickness ) { int x1 = x0 + width; int y1 = y0 + height - thickness; y0 += thickness; surface()->DrawFilledRect( x0, y0 - thickness, x1, y0 ); // top surface()->DrawFilledRect( x1 - thickness, y0, x1, y1 ); // right surface()->DrawFilledRect( x0, y1, x1, y1 + thickness ); // bottom surface()->DrawFilledRect( x0, y0, x0 + thickness, y1 ); // left } void CScriptSurface::DrawLine( int x0, int y0, int x1, int y1 ) { surface()->DrawLine( x0, y0, x1, y1 ); } #if 0 void CScriptSurface::DrawPolyLine( HSCRIPT ax, HSCRIPT ay, int count ) { if (count < 1) return; if (count > 4096) count = 4096; int *px = (int*)stackalloc( count * sizeof(int) ); int *py = (int*)stackalloc( count * sizeof(int) ); ScriptVariant_t vx, vy; int i = count; while ( i-- ) { g_pScriptVM->GetValue( ax, i, &vx ); g_pScriptVM->GetValue( ay, i, &vy ); px[i] = vx.m_int; py[i] = vy.m_int; } surface()->DrawPolyLine( px, py, count ); } #endif void CScriptSurface::DrawOutlinedCircle( int x, int y, int radius, int segments ) { surface()->DrawOutlinedCircle( x, y, radius, segments ); } void CScriptSurface::SetTextColor( int r, int g, int b, int a ) { surface()->DrawSetTextColor( r, g, b, a ); } void CScriptSurface::SetTextPos( int x, int y ) { surface()->DrawSetTextPos( x, y ); } void CScriptSurface::SetTextFont( int font ) { surface()->DrawSetTextFont( IntToFontHandle(font) ); } void CScriptSurface::DrawText( const char *text, int drawType ) { wchar_t wcs[512]; g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); surface()->DrawPrintText( wcs, wcslen(wcs), (FontDrawType_t)drawType ); } void CScriptSurface::DrawUnicodeChar( int ch, int drawType ) { surface()->DrawUnicodeChar( (wchar_t)ch, (FontDrawType_t)drawType ); } int CScriptSurface::GetFont( const char* name, bool proportional, const char* schema ) { HFont font = INVALID_FONT; if ( !schema || !schema[0] ) { int idx = g_ScriptFonts.Find( GetFixedFontName( name, proportional ) ); if ( idx != g_ScriptFonts.InvalidIndex() ) { font = g_ScriptFonts[idx].Head().font; } } else { HScheme sch = scheme()->GetScheme( schema ); font = scheme()->GetIScheme(sch)->GetFont( name, proportional ); // Update known count if ( font > (unsigned int)g_nFontCount ) g_nFontCount = font; } return HandleToInt( font ); } int CScriptSurface::GetTextWidth( int font, const char* text ) { int w, t; wchar_t wcs[512]; g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); surface()->GetTextSize( IntToFontHandle(font), wcs, w, t ); return w; } int CScriptSurface::GetFontTall( int font ) { return surface()->GetFontTall( IntToFontHandle(font) ); } int CScriptSurface::GetCharacterWidth( int font, int ch ) { return surface()->GetCharacterWidth( IntToFontHandle(font), ch ); } void CScriptSurface::CreateFont( const char *customName, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int yresMin, int yresMax, bool proportional ) { if ( flags & ISurface::FONTFLAG_BITMAP ) { AssertMsg( 0, "Bitmap fonts are not supported!" ); return; } if ( proportional && yresMin ) { AssertMsg( 0, "Resolution cannot be defined on a proportional font!" ); return; } if ( (yresMin < 0 || yresMax < 0) || (!!yresMin != !!yresMax) ) { AssertMsg( 0, "Invalid resolution!" ); return; } const char *fontAlias = GetFixedFontName( customName, proportional ); int idx = g_ScriptFonts.Find( fontAlias ); if ( idx != g_ScriptFonts.InvalidIndex() ) { fontalias_t &alias = g_ScriptFonts[idx]; // TODO: One proportional font to fall back to amongst resolution filtered fonts. #ifdef _DEBUG if ( !yresMin && !yresMax ) { // There must be only one font registered. Assert( alias.Count() == 1 ); HFont font = alias.Head().font; int oldTall = surface()->GetFontTallRequested( font ); int newTall = proportional ? scheme()->GetProportionalScaledValue( tall ) : tall; const char *oldName = surface()->GetFontName( font ); // Font changes will not be applied. Assert( oldTall == newTall ); if ( oldName ) // can be null Assert( !V_stricmp( oldName, windowsFontName ) ); } #endif // if input resolutions match any of the existing fonts, // then this must be a duplicate call. for ( int i = 0; i < alias.Count(); ++i ) { FontData_t &data = alias.Element(i); if ( yresMin == data.yres_min && yresMax == data.yres_max ) return; } DebugMsg( "Create font add '%s' [%d %d]\n", fontAlias, yresMin, yresMax ); FontData_t &newFont = alias.Element( alias.AddToTail() ); newFont.font = alias.Head().font; newFont.name = strdup( windowsFontName ); newFont.tall = tall; newFont.weight = weight; newFont.blur = blur; newFont.scanlines = scanlines; newFont.flags = flags; newFont.yres_min = yresMin; newFont.yres_max = yresMax; newFont.proportional = proportional; LoadFont( newFont DBG_PARAM(, fontAlias) ); } else { HFont font = surface()->CreateFont(); // Sanity check Assert( font > (unsigned int)g_nFontCount && font < INT_MAX ); // Update known count if ( font > (unsigned int)g_nFontCount ) g_nFontCount = font; if ( yresMax && yresMin > yresMax ) { int t = yresMin; yresMin = yresMax; yresMax = t; } if ( yresMin ) DebugMsg( "Create font new '%s' [%d %d]\n", fontAlias, yresMin, yresMax ); else DebugMsg( "Create font new '%s'\n", fontAlias ); fontalias_t &alias = g_ScriptFonts.Element( g_ScriptFonts.Insert( fontAlias ) ); FontData_t &newFont = alias.Element( alias.AddToTail() ); newFont.font = font; newFont.name = strdup( windowsFontName ); newFont.tall = tall; newFont.weight = weight; newFont.blur = blur; newFont.scanlines = scanlines; newFont.flags = flags; newFont.yres_min = yresMin; newFont.yres_max = yresMax; newFont.proportional = proportional; LoadFont( newFont DBG_PARAM(, fontAlias) ); } } bool CScriptSurface::AddCustomFontFile( const char *fontFileName ) { return surface()->AddCustomFontFile( NULL, fontFileName ); } int CScriptSurface::GetTextureID( char const *filename ) { return surface()->DrawGetTextureId( filename ); } // Create texture if it does not already exist int CScriptSurface::ValidateTexture( const char *filename, bool hardwareFilter, bool forceReload, bool procedural ) { int id = surface()->DrawGetTextureId( filename ); if ( id <= 0 ) { id = surface()->CreateNewTextureID( procedural ); g_ScriptTextureIDs.AddToTail( id ); surface()->DrawSetTextureFile( id, filename, hardwareFilter, forceReload ); #ifdef _DEBUG char tex[MAX_PATH]; surface()->DrawGetTextureFile( id, tex, sizeof(tex)-1 ); if ( !V_stricmp( filename, tex ) ) { DebugMsg( "Create texture [%i]%s\n", id, filename ); } else { DebugWarning( "Create texture [%i]%s(%s)\n", id, tex, filename ); } #endif } else if ( forceReload && g_ScriptTextureIDs.HasElement( id ) ) { surface()->DrawSetTextureFile( id, filename, hardwareFilter, forceReload ); } else { surface()->DrawSetTexture( id ); } return id; } // Replace existing texture void CScriptSurface::SetTextureFile( int id, const char *filename, bool hardwareFilter ) { if ( g_ScriptTextureIDs.HasElement(id) ) { Assert( surface()->IsTextureIDValid(id) ); surface()->DrawSetTextureFile( id, filename, hardwareFilter, true ); #ifdef _DEBUG char tex[MAX_PATH]; surface()->DrawGetTextureFile( id, tex, sizeof(tex)-1 ); if ( !V_stricmp( filename, tex ) ) { DebugMsg( "Set texture [%i]%s\n", id, filename ); } else { DebugWarning( "Set texture [%i]%s(%s)\n", id, tex, filename ); } #endif } #ifdef _DEBUG if ( !g_ScriptTextureIDs.HasElement(id) && surface()->IsTextureIDValid(id) ) { DebugWarning( "Tried to set non-script created texture! [%i]%s\n", id, filename ); } if ( !surface()->IsTextureIDValid(id) ) { DebugWarning( "Tried to set invalid texture id! [%i]%s\n", id, filename ); } #endif } #if 0 void CScriptSurface::SetTextureMaterial( int id, HSCRIPT hMaterial ) { IMaterial *pMaterial = (IMaterial*)HScriptToClass< IScriptMaterial >( hMaterial ); if ( !IsValid( pMaterial ) ) return; if ( g_ScriptTextureIDs.HasElement(id) ) { Assert( surface()->IsTextureIDValid(id) ); MatSystemSurface()->DrawSetTextureMaterial( id, pMaterial ); DebugMsg( "Set texture [%i]%s\n", id, pMaterial->GetName() ); } #ifdef _DEBUG if ( !g_ScriptTextureIDs.HasElement(id) && surface()->IsTextureIDValid(id) ) { DebugWarning( "Tried to set non-script created texture! [%i]\n", id ); } if ( !surface()->IsTextureIDValid(id) ) { DebugWarning( "Tried to set invalid texture id! [%i]\n", id ); } #endif } #endif int CScriptSurface::GetTextureWide( int id ) { int w, t; surface()->DrawGetTextureSize( id, w, t ); return w; } int CScriptSurface::GetTextureTall( int id ) { int w, t; surface()->DrawGetTextureSize( id, w, t ); return t; } void CScriptSurface::SetTexture( int id ) { surface()->DrawSetTexture( id ); } void CScriptSurface::DrawTexturedRect( int x0, int y0, int width, int height ) { surface()->DrawTexturedRect( x0, y0, x0 + width, y0 + height ); } void CScriptSurface::DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 ) { surface()->DrawTexturedSubRect( x0, y0, x1, y1, texs0, text0, texs1, text1 ); } void CScriptSurface::DrawTexturedRectRotated( int x, int y, int w, int t, float yaw ) { Vertex_t verts[4]; Vector2D axis[2]; float sy, cy; SinCos( DEG2RAD( -yaw ), &sy, &cy ); axis[0].x = cy; axis[0].y = sy; axis[1].x = -axis[0].y; axis[1].y = axis[0].x; verts[0].m_TexCoord.Init( 0, 0 ); Vector2DMA( Vector2D( x + w * 0.5f, y + t * 0.5f ), w * -0.5f, axis[0], verts[0].m_Position ); Vector2DMA( verts[0].m_Position, t * -0.5f, axis[1], verts[0].m_Position ); verts[1].m_TexCoord.Init( 1, 0 ); Vector2DMA( verts[0].m_Position, w, axis[0], verts[1].m_Position ); verts[2].m_TexCoord.Init( 1, 1 ); Vector2DMA( verts[1].m_Position, t, axis[1], verts[2].m_Position ); verts[3].m_TexCoord.Init( 0, 1 ); Vector2DMA( verts[0].m_Position, t, axis[1], verts[3].m_Position ); surface()->DrawTexturedPolygon( 4, verts ); } void CScriptSurface::DrawTexturedBox( int texture, int x, int y, int wide, int tall, int r, int g, int b, int a ) { surface()->DrawSetColor( r, g, b, a ); surface()->DrawSetTexture( texture ); surface()->DrawTexturedRect( x, y, x + wide, y + tall ); } void CScriptSurface::DrawColoredText( int font, int x, int y, int r, int g, int b, int a, const char *text ) { wchar_t wcs[512]; g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); surface()->DrawSetTextFont( IntToFontHandle(font) ); surface()->DrawSetTextColor( r, g, b, a ); surface()->DrawSetTextPos( x, y ); surface()->DrawPrintText( wcs, wcslen(wcs) ); } void CScriptSurface::DrawColoredTextRect( int font, int x, int y, int w, int h, int r, int g, int b, int a, const char *text ) { MatSystemSurface()->DrawColoredTextRect( IntToFontHandle(font), x, y, w, h, r, g, b, a, text ); } //============================================================== //============================================================== #define __base() this->_base #define BEGIN_SCRIPTDESC_VGUI( panelClass )\ BEGIN_SCRIPTDESC_NAMED( CScript_##panelClass##_Helper, IScriptVGUIObject, #panelClass, "" )\ DEFINE_VGUI_SCRIPTFUNC_##panelClass() // // Script helpers are wrappers that only redirect to VGUI panels (such as CScript_Panel : Panel), // these macros help to simplify definitions. // // // BEGIN_VGUI_HELPER() assumes the VGUI panel class has the prefix 'CScript_' // Use BEGIN_VGUI_HELPER_EX() to manually define VGUI panel class name. // #define BEGIN_VGUI_HELPER( panelClass )\ BEGIN_VGUI_HELPER_EX( panelClass, CScript_##panelClass ) #define BEGIN_VGUI_HELPER_DEFAULT_TEXT( panelClass )\ BEGIN_VGUI_HELPER_DEFAULT_TEXT_EX( panelClass, CScript_##panelClass ) #define BEGIN_VGUI_HELPER_EX( panelClass, baseClass )\ class CScript_##panelClass##_Helper : public IScript_##panelClass< baseClass >\ {\ void Create( const char *panelName ) override\ {\ Assert( !_base && !_vpanel );\ _base = new baseClass( NULL, panelName );\ }\ \ public: #define BEGIN_VGUI_HELPER_DEFAULT_TEXT_EX( panelClass, baseClass )\ class CScript_##panelClass##_Helper : public IScript_##panelClass< baseClass >\ {\ void Create( const char *panelName ) override\ {\ Assert( !_base && !_vpanel );\ _base = new baseClass( NULL, panelName, (const char*)NULL );\ }\ \ public: #define END_VGUI_HELPER()\ }; #define CLASS_HELPER_INTERFACE_ROOT( panelClass )\ template \ class IScript_##panelClass : public CScriptVGUIObject #define CLASS_HELPER_INTERFACE( panelClass, baseClass )\ template \ class IScript_##panelClass : public IScript_##baseClass #ifdef _DEBUG #define DEBUG_DESTRUCTOR( panelClass, baseClass )\ panelClass()\ {\ DebugDestructor( baseClass )\ } #define DebugDestructor( panelClass )\ {\ DebugDevMsg( " ~" #panelClass "() '%s'\n", GetName() );\ } #else #define DEBUG_DESTRUCTOR( panelClass, baseClass ) #define DebugDestructor( panelClass ) #endif #define DECLARE_SCRIPTVGUI_CLASS( baseClass )\ DECLARE_SCRIPTVGUI_CLASS_EX( CScript_##baseClass, baseClass )\ DEBUG_DESTRUCTOR( ~CScript_##baseClass, baseClass ) #define DECLARE_SCRIPTVGUI_CLASS_EX( panelClass, baseClass )\ typedef baseClass BaseClass;\ typedef panelClass ThisClass;\ public:\ void OnDelete()\ {\ DebugMsg( #baseClass "::OnDelete() '%s'\n", GetName() );\ int i;\ IScriptVGUIObject *obj = FindInScriptPanels( GetVPanel(), i );\ if ( obj )\ {\ obj->Destroy( i );\ }\ BaseClass::OnDelete();\ } // // Definitions for 'empty' vgui objects that do not have any script specific implementation - overrides or callbacks. // These are required to shutdown script objects on panel death // (on save restore where panel destructor is called after the VM is restarted while HSCRIPT members are invalid but not nullified, // and on C++ deletion where IScriptVGUIObject::Destroy() is not automatically called). // #define DEFINE_VGUI_CLASS_EMPTY( panelClass )\ class CScript_##panelClass : public panelClass\ {\ DECLARE_SCRIPTVGUI_CLASS( panelClass )\ void Shutdown() {}\ \ public:\ CScript_##panelClass( Panel *parent, const char *name )\ : BaseClass( parent, name )\ {}\ };\ \ BEGIN_VGUI_HELPER( panelClass )\ END_VGUI_HELPER()\ \ BEGIN_SCRIPTDESC_VGUI( panelClass )\ END_SCRIPTDESC() #define DEFINE_VGUI_CLASS_EMPTY_DEFAULT_TEXT( panelClass )\ class CScript_##panelClass : public panelClass\ {\ DECLARE_SCRIPTVGUI_CLASS( panelClass )\ void Shutdown() {}\ \ public:\ CScript_##panelClass( Panel *parent, const char *name, const char *text )\ : BaseClass( parent, name, text )\ {}\ };\ \ BEGIN_VGUI_HELPER_DEFAULT_TEXT( panelClass )\ END_VGUI_HELPER()\ \ BEGIN_SCRIPTDESC_VGUI( panelClass )\ END_SCRIPTDESC() class IScriptVGUIObject { public: virtual ~IScriptVGUIObject() {} #ifdef _DEBUG virtual const char *GetName() = 0; #endif //----------------------------------------------------- // Free the VGUI panel and script instance. //----------------------------------------------------- virtual void Destroy( int ) = 0; //----------------------------------------------------- // Create new panel //----------------------------------------------------- virtual void Create( const char *panelName ) = 0; public: VPANEL GetVPanel() { return _vpanel; } HSCRIPT GetScriptInstance() { return m_hScriptInstance; } protected: VPANEL _vpanel; HSCRIPT m_hScriptInstance; // Called on deletion static void ResolveChildren_r( VPANEL panel DBG_PARAM(, int level) ); public: #if SCRIPT_VGUI_SAVERESTORE IScriptVGUIObject() {} void SetScriptInstance( HSCRIPT h ) { m_hScriptInstance = h; } char m_pszScriptId[16]; #endif #ifdef _DEBUG #if SCRIPT_VGUI_SAVERESTORE const char *GetDebugName() { return m_pszScriptId; } #else const char *GetDebugName() { return ""; } #endif #endif }; BEGIN_SCRIPTDESC_ROOT( IScriptVGUIObject, SCRIPT_HIDE ) END_SCRIPTDESC() #if SCRIPT_VGUI_SAVERESTORE class CScriptVGUIScriptInstanceHelper : public IScriptInstanceHelper { void *BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId ) { DebugMsg( "BindOnRead (0x%p) (%s) (count %d)\n", (uint)hInstance, pszId, g_ScriptPanels.Count() ); FOR_EACH_LL( g_ScriptPanels, i ) { IScriptVGUIObject *pPanel = g_ScriptPanels[i]; // DebugMsg( " cmp (%s)\n", pPanel->m_pszScriptId ); if ( !V_stricmp( pPanel->m_pszScriptId, pszId ) ) { pPanel->SetScriptInstance( hInstance ); DebugMsg( " ret (%s)\n", pPanel->m_pszScriptId ); return pPanel; } } DebugMsg( " ret (null)\n" ); return NULL; } }; static CScriptVGUIScriptInstanceHelper g_ScriptVGUIScriptInstanceHelper; #define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER() DEFINE_SCRIPT_INSTANCE_HELPER( &g_ScriptVGUIScriptInstanceHelper ) #else #define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER() #endif IScriptVGUIObject *ToScriptVGUIObj( HSCRIPT inst ) { return (IScriptVGUIObject *)g_pScriptVM->GetInstanceValue( inst, ::GetScriptDesc( (IScriptVGUIObject *)0 ) ); } template < typename T > inline T* AllocScriptPanel() { return new T; } inline IScriptVGUIObject *FindInScriptPanels( VPANEL panel, int &I ) { for ( int i = g_ScriptPanels.Head(); i != g_ScriptPanels.InvalidIndex(); i = g_ScriptPanels.Next(i) ) { IScriptVGUIObject *obj = g_ScriptPanels[i]; if ( obj->GetVPanel() == panel ) { I = i; return obj; } } return NULL; } void IScriptVGUIObject::ResolveChildren_r( VPANEL panel DBG_PARAM(, int level = 0) ) { #ifdef _DEBUG char indent[32]; int l = level, c = 0; if ( l > 15 ) l = 15; while ( l-- ) { indent[c++] = ' '; indent[c++] = ' '; } indent[c] = 0; if ( level > 15 ) { indent[c-1] = '.'; indent[c-2] = '.'; } #endif CUtlVector< VPANEL > &children = ipanel()->GetChildren( panel ); FOR_EACH_VEC_BACK( children, i ) { VPANEL child = children[i]; int j; IScriptVGUIObject *obj = FindInScriptPanels( child, j ); if ( obj ) { if ( ipanel()->IsAutoDeleteSet(child) ) { DebugMsg( " %sResolveChildren: '%s' (autodelete)\n", indent, obj->GetName() ); if ( g_pScriptVM ) g_pScriptVM->RemoveInstance( obj->m_hScriptInstance ); g_ScriptPanels.Remove( j ); delete obj; ResolveChildren_r( child DBG_PARAM(, level+1) ); } else { DebugMsg( " %sResolveChildren: '%s'\n", indent, obj->GetName() ); // Panel::SetAutoDelete should not be added until // what to do on their parent death is finalised. // // This assert will be hit if a deleted panel has // C++ created and autodelete disabled children who are // also registered to script. Assert(0); } } } } template class CScriptVGUIObject : public IScriptVGUIObject { public: T *_base; CScriptVGUIObject() : _base(0) { _vpanel = 0; m_hScriptInstance = 0; } void Destroy( int i = -1 ) { if ( i != -1 ) { Assert( g_ScriptPanels.IsValidIndex(i) ); Assert( g_ScriptPanels[i] == this ); g_ScriptPanels.Remove( i ); } else { Assert( g_ScriptPanels.Find( this ) != g_ScriptPanels.InvalidIndex() ); g_ScriptPanels.FindAndRemove( this ); } if ( GetVPanel() ) { DebugMsg( " Destroy panel '%s' %s\n", _base->GetName(), GetDebugName() ); _base->Shutdown(); ResolveChildren_r( _vpanel ); _base->MarkForDeletion(); } if ( m_hScriptInstance ) { if ( g_pScriptVM ) g_pScriptVM->RemoveInstance( m_hScriptInstance ); } delete this; } template void CreateFromScript( HSCRIPT parent, const char *panelName, int root ) { Assert( !_vpanel && !m_hScriptInstance && !g_ScriptPanels.IsValidIndex( g_ScriptPanels.Find( this ) ) ); Create( panelName && *panelName ? panelName : NULL ); _vpanel = _base->GetVPanel(); m_hScriptInstance = g_pScriptVM->RegisterInstance< CHelper >( static_cast< CHelper* >( this ) ); #if SCRIPT_VGUI_SAVERESTORE g_pScriptVM->GenerateUniqueKey( "", m_pszScriptId, sizeof(m_pszScriptId) ); g_pScriptVM->SetInstanceUniqeId( m_hScriptInstance, m_pszScriptId ); #endif if ( parent ) { IScriptVGUIObject *obj = ToScriptVGUIObj( parent ); if ( obj ) { // Insert this after the parent to make sure children come after their parents, // and their removal is done inside ResolveChildren_r(), not by individual Destroy() calls from LevelShutdown. unsigned short parentIdx = g_ScriptPanels.Find( obj ); // My parent can't not be in the list. Assert( parentIdx != g_ScriptPanels.InvalidIndex() && g_ScriptPanels.IsInList( parentIdx ) ); g_ScriptPanels.InsertAfter( parentIdx, this ); _base->SetParent( obj->GetVPanel() ); return; } AssertMsg( 0, "invalid parent" ); } g_ScriptPanels.AddToTail( this ); // Script specified root panel - a cheap alternative to registering uneditable panel instances. // Match the values to vscript_vgui.nut. // // This parameter is hidden in script, and is defined by the return value of dummy functions. VPANEL vparent = 0; switch ( root ) { case 0: vparent = VGUI_GetScriptRootPanel( PANEL_ROOT ); break; #if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL case 1: vparent = VGUI_GetScriptRootPanel( PANEL_GAMEUIDLL ); break; #endif case 2: vparent = VGUI_GetScriptRootPanel( PANEL_CLIENTDLL ); break; #if ALLOW_SCRIPT_HUD_VIEWPORT_ROOT_PANEL // Hud viewport case 10: Assert( g_pClientMode && g_pClientMode->GetViewport() ); vparent = g_pClientMode->GetViewport()->GetVPanel(); break; #endif default: UNREACHABLE(); // Invalid parent panel } _base->SetParent( vparent ); } }; //-------------------------------------------------------------- //-------------------------------------------------------------- CLASS_HELPER_INTERFACE_ROOT( Panel ) { public: void Destroy() { CScriptVGUIObject::Destroy(); } void MakeReadyForUse() { __base()->MakeReadyForUse(); } const char *GetName() { return __base()->GetName(); } void AddTickSignal( int i ) { ivgui()->AddTickSignal( this->GetVPanel(), i ); } #if SCRIPT_VGUI_SIGNAL_INTERFACE void AddActionSignalTarget( HSCRIPT messageTarget ) { IScriptVGUIObject *obj = ToScriptVGUIObj( messageTarget ); if ( obj ) { __base()->AddActionSignalTarget( obj->GetVPanel() ); } } #endif //----------------------------------------------------- // Get script created parent //----------------------------------------------------- HSCRIPT GetParent() { VPANEL parent = ipanel()->GetParent( this->GetVPanel() ); if ( !parent ) return NULL; int i; IScriptVGUIObject* obj = FindInScriptPanels( parent, i ); if ( obj ) { // My parent can't be invalid. Assert( ToScriptVGUIObj( obj->GetScriptInstance() ) ); return obj->GetScriptInstance(); } #ifdef _DEBUG // Is my parent one of the root panels? bool bRootParent = false; #if SCRIPT_ENGINE_ROOT_PANELS if ( ( parent == g_pScriptRootPanel->GetVPanel() ) #if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL || ( g_pScriptGameUIDLLPanel && parent == g_pScriptGameUIDLLPanel->GetVPanel() ) #endif || ( g_pScriptClientDLLPanel && parent == g_pScriptClientDLLPanel->GetVPanel() ) ) { bRootParent = true; } else #endif for ( int i = PANEL_ROOT; i <= PANEL_CLIENTDLL_TOOLS; ++i ) { if ( parent == enginevgui->GetPanel( (VGuiPanel_t)i ) ) { bRootParent = true; break; } } #if ALLOW_SCRIPT_HUD_VIEWPORT_ROOT_PANEL if ( g_pClientMode && g_pClientMode->GetViewport() && ( parent == g_pClientMode->GetViewport()->GetVPanel() ) ) bRootParent = true; #endif // My parent wasn't registered. AssertMsg1( bRootParent, "'%s'", ipanel()->GetName(parent) ); #endif return NULL; } //----------------------------------------------------- // Set script created parent //----------------------------------------------------- void SetParent( HSCRIPT parent ) { if ( !parent ) { __base()->SetParent( (VPANEL)NULL ); return; } IScriptVGUIObject *obj = ToScriptVGUIObj( parent ); if ( obj ) { __base()->SetParent( obj->GetVPanel() ); return; } AssertMsg( 0, "invalid parent" ); } void GetChildren( HSCRIPT arr ) { CUtlVector< VPANEL > &children = ipanel()->GetChildren( this->GetVPanel() ); FOR_EACH_VEC( children, i ) { VPANEL child = children[i]; int j; IScriptVGUIObject* obj = FindInScriptPanels( child, j ); if ( obj ) { g_pScriptVM->ArrayAppend( arr, obj->GetScriptInstance() ); } // Beware of dangling pointers if C++ created children are to be registered } } int GetXPos() { int x, y; ipanel()->GetPos( this->GetVPanel(), x, y ); return x; } int GetYPos() { int x, y; ipanel()->GetPos( this->GetVPanel(), x, y ); return y; } void SetPos( int x, int y ) { ipanel()->SetPos( this->GetVPanel(), x, y ); } void SetZPos( int i ) { ipanel()->SetZPos( this->GetVPanel(), i ); } int GetZPos() { return ipanel()->GetZPos( this->GetVPanel() ); } void SetSize( int w, int t ) { ipanel()->SetSize( this->GetVPanel(), w, t ); } void SetWide( int w ) { ipanel()->SetSize( this->GetVPanel(), w, GetTall() ); } int GetWide() { int w, t; ipanel()->GetSize( this->GetVPanel(), w, t ); return w; } void SetTall( int t ) { ipanel()->SetSize( this->GetVPanel(), GetWide(), t ); } int GetTall() { int w, t; ipanel()->GetSize( this->GetVPanel(), w, t ); return t; } int GetAlpha() { return __base()->GetAlpha(); } void SetAlpha( int i ) { __base()->SetAlpha( i ); } void SetVisible( bool i ) { ipanel()->SetVisible( this->GetVPanel(), i ); } bool IsVisible() { return ipanel()->IsVisible( this->GetVPanel() ); } #if BUILD_GROUPS_ENABLED void SetProportional( bool i ) { __base()->SetProportional(i); } #endif #if 0 void LocalToScreen( HSCRIPT out ) { int px, py; ipanel()->GetAbsPos( this->GetVPanel(), px, py ); ScriptVariant_t x, y; g_pScriptVM->GetValue( out, (ScriptVariant_t)0, &x ); g_pScriptVM->GetValue( out, 1, &y ); g_pScriptVM->SetValue( out, (ScriptVariant_t)0, x.m_int + px ); g_pScriptVM->SetValue( out, 1, y.m_int + py ); } void ScreenToLocal( HSCRIPT out ) { int px, py; ipanel()->GetAbsPos( this->GetVPanel(), px, py ); ScriptVariant_t x, y; g_pScriptVM->GetValue( out, (ScriptVariant_t)0, &x ); g_pScriptVM->GetValue( out, 1, &y ); g_pScriptVM->SetValue( out, (ScriptVariant_t)0, x.m_int - px ); g_pScriptVM->SetValue( out, 1, y.m_int - py ); } #endif bool IsWithin( int x, int y ) { return __base()->IsWithin( x, y ); } void SetEnabled( bool i ) { __base()->SetEnabled(i); } bool IsEnabled() { return __base()->IsEnabled(); } void SetPaintEnabled( bool i ) { __base()->SetPaintEnabled(i); } void SetPaintBackgroundEnabled( bool i ) { __base()->SetPaintBackgroundEnabled(i); } void SetPaintBorderEnabled( bool i ) { __base()->SetPaintBorderEnabled(i); } void SetPostChildPaintEnabled( bool i ) { __base()->SetPostChildPaintEnabled(i); } // 0 for normal(opaque), 1 for single texture from Texture1, and 2 for rounded box w/ four corner textures void SetPaintBackgroundType( int i ) { __base()->SetPaintBackgroundType(i); } void SetFgColor( int r, int g, int b, int a ) { __base()->SetFgColor( Color( r, g, b, a ) ); } void SetBgColor( int r, int g, int b, int a ) { __base()->SetBgColor( Color( r, g, b, a ) ); } #if 0 void SetScheme( const char *tag ) { return __base()->SetScheme( tag ); } #endif void SetCursor( int cursor ) { AssertMsg( cursor >= 0 && cursor < dc_last, "invalid cursor" ); // do nothing if ( cursor < 0 || cursor >= dc_last ) return; return __base()->SetCursor( (HCursor)cursor ); } bool IsCursorOver() { return __base()->IsCursorOver(); } bool HasFocus() { return __base()->HasFocus(); } void RequestFocus() { __base()->RequestFocus(); } void MakePopup() { __base()->MakePopup(); } void MoveToFront() { __base()->MoveToFront(); } void SetMouseInputEnabled( bool i ) { __base()->SetMouseInputEnabled(i); } void SetKeyBoardInputEnabled( bool i ) { __base()->SetKeyBoardInputEnabled(i); } // ----------------------- // Drawing utility // ----------------------- //void SetRoundedCorners( int cornerFlags ) //{ // __base()->SetRoundedCorners( cornerFlags & 0xff ); //} void DrawBox( int x, int y, int wide, int tall, int r, int g, int b, int a, bool hollow ) { __base()->DrawBox( x, y, wide, tall, Color(r, g, b, a), 1.0f, hollow ); } void DrawBoxFade( int x, int y, int wide, int tall, int r, int g, int b, int a, int alpha0, int alpha1, bool bHorizontal, bool hollow ) { __base()->DrawBoxFade( x, y, wide, tall, Color(r, g, b, a), 1.0f, alpha0, alpha1, bHorizontal, hollow ); } #if 0 // ----------------------- // drag drop // ----------------------- void SetDragEnabled( bool i ) { __base()->SetDragEnabled(i); } bool IsDragEnabled() { return __base()->IsDragEnabled(); } void SetDropEnabled( bool i ) { __base()->SetDropEnabled( i, 0.0f ); } bool IsDropEnabled() { return __base()->IsDropEnabled(); } void SetShowDragHelper( int i ) { __base()->SetShowDragHelper(i); } int GetDragStartTolerance() { return __base()->GetDragStartTolerance(); } void SetDragStartTolerance( int i ) { __base()->SetDragSTartTolerance(i); } #endif #if 0 void SetTooltip( const char *text ) { __base()->GetTooltip()->SetText( text ); } void SetTooltipDelay( int delay ) { __base()->GetTooltip()->SetTooltipDelay( delay ); } #endif }; #define DEFINE_VGUI_SCRIPTFUNC_Panel()\ DEFINE_VGUI_SCRIPT_INSTANCE_HELPER()\ \ DEFINE_SCRIPTFUNC( Destroy, "" )\ DEFINE_SCRIPTFUNC( MakeReadyForUse, "" )\ DEFINE_SCRIPTFUNC( GetName, "" )\ DEFINE_SCRIPTFUNC( AddTickSignal, "" )\ \ DEFINE_SCRIPTFUNC( GetParent, "" )\ DEFINE_SCRIPTFUNC( SetParent, "" )\ DEFINE_SCRIPTFUNC( GetChildren, "" )\ \ DEFINE_SCRIPTFUNC( GetXPos, "" )\ DEFINE_SCRIPTFUNC( GetYPos, "" )\ DEFINE_SCRIPTFUNC( SetPos, "" )\ \ DEFINE_SCRIPTFUNC( GetZPos, "" )\ DEFINE_SCRIPTFUNC( SetZPos, "" )\ \ DEFINE_SCRIPTFUNC( SetSize, "" )\ DEFINE_SCRIPTFUNC( GetWide, "" )\ DEFINE_SCRIPTFUNC( SetWide, "" )\ \ DEFINE_SCRIPTFUNC( GetTall, "" )\ DEFINE_SCRIPTFUNC( SetTall, "" )\ \ DEFINE_SCRIPTFUNC( GetAlpha, "" )\ DEFINE_SCRIPTFUNC( SetAlpha, "" )\ \ DEFINE_SCRIPTFUNC( SetVisible, "" )\ DEFINE_SCRIPTFUNC( IsVisible, "" )\ \ DEFINE_SCRIPTFUNC( IsWithin, "" )\ \ DEFINE_SCRIPTFUNC( SetEnabled, "" )\ DEFINE_SCRIPTFUNC( IsEnabled, "" )\ \ DEFINE_SCRIPTFUNC( SetPaintEnabled, "" )\ DEFINE_SCRIPTFUNC( SetPaintBackgroundEnabled, "" )\ DEFINE_SCRIPTFUNC( SetPaintBorderEnabled, "" )\ DEFINE_SCRIPTFUNC( SetPostChildPaintEnabled, "" )\ DEFINE_SCRIPTFUNC( SetPaintBackgroundType, "" )\ \ DEFINE_SCRIPTFUNC( SetFgColor, "" )\ DEFINE_SCRIPTFUNC( SetBgColor, "" )\ \ DEFINE_SCRIPTFUNC( SetCursor, "" )\ DEFINE_SCRIPTFUNC( IsCursorOver, "" )\ DEFINE_SCRIPTFUNC( HasFocus, "" )\ DEFINE_SCRIPTFUNC( RequestFocus, "" )\ DEFINE_SCRIPTFUNC( MakePopup, "" )\ DEFINE_SCRIPTFUNC( MoveToFront, "" )\ DEFINE_SCRIPTFUNC( SetMouseInputEnabled, "" )\ DEFINE_SCRIPTFUNC( SetKeyBoardInputEnabled, "" )\ \ DEFINE_SCRIPTFUNC( DrawBox, "" )\ DEFINE_SCRIPTFUNC( DrawBoxFade, "" )\ //-------------------------------------------------------------- //-------------------------------------------------------------- // These need more testing. // TODO: IScript_Panel::FindChildByName() // TODO: DECLARE_BUILD_FACTORY_SCRIPT() to create overridable script panels from controls file // TODO: CScript_EditablePanel::ApplySchemeSettings() callback // (IScheme parameter can be passed as null until schemes are also tested) #if BUILD_GROUPS_ENABLED CLASS_HELPER_INTERFACE( EditablePanel, Panel ) { public: // Call on creation or on ApplySchemeSettings() void LoadControlSettings( const char *resName ) { __base()->LoadControlSettings( resName ); } }; #define DEFINE_VGUI_SCRIPTFUNC_EditablePanel()\ DEFINE_VGUI_SCRIPTFUNC_Panel()\ DEFINE_SCRIPTFUNC( LoadControlSettings, "" ) #endif //-------------------------------------------------------------- //-------------------------------------------------------------- CLASS_HELPER_INTERFACE( Label, Panel ) { public: void SetText( const char *text ) { wchar_t wcs[512]; g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); __base()->SetText( wcs ); } void SetFont( int i ) { __base()->SetFont( IntToFontHandle(i) ); } void SetAllCaps( bool i ) { __base()->SetAllCaps(i); } void SetWrap( bool i ) { __base()->SetWrap(i); } void SetCenterWrap( bool i ) { __base()->SetCenterWrap(i); } void SetContentAlignment( int i ) { __base()->SetContentAlignment( (Label::Alignment)i ); } void SetTextInset( int x, int y ) { __base()->SetTextInset( x, y ); } void SizeToContents() { __base()->SizeToContents(); } void SetAssociatedControl( HSCRIPT control ) { IScriptVGUIObject *obj = ToScriptVGUIObj( control ); if ( obj ) { __base()->SetAssociatedControl( ipanel()->GetPanel( obj->GetVPanel(), GetControlsModuleName() ) ); } } void AddColorChange( int r, int g, int b, int a, int iTextStreamIndex ) { __base()->GetTextImage()->AddColorChange( Color( r, g, b, a ), iTextStreamIndex ); } void ClearColorChangeStream() { __base()->GetTextImage()->ClearColorChangeStream(); } #if 0 void SetTextImageIndex( int index ) { __base()->SetTextImageIndex( index ); } void SetImageAtIndex( int index, const char *imageName, bool hardwareFilter, int offset ) { return __base()->SetImageAtIndex( index, vgui_GetImage( imageName, hardwareFilter ), offset ); } int AddImage( const char *imageName, bool hardwareFilter, int offset ) { return __base()->AddImage( vgui_GetImage( imageName, hardwareFilter ), offset ); } #endif }; #define DEFINE_VGUI_SCRIPTFUNC_Label()\ DEFINE_VGUI_SCRIPTFUNC_Panel()\ DEFINE_SCRIPTFUNC( SetText, "" )\ DEFINE_SCRIPTFUNC( SetFont, "" )\ DEFINE_SCRIPTFUNC( SetAllCaps, "" )\ DEFINE_SCRIPTFUNC( SetWrap, "" )\ DEFINE_SCRIPTFUNC( SetCenterWrap, "" )\ DEFINE_SCRIPTFUNC( SetContentAlignment, "" )\ DEFINE_SCRIPTFUNC( SetTextInset, "" )\ DEFINE_SCRIPTFUNC( SizeToContents, "" )\ DEFINE_SCRIPTFUNC( SetAssociatedControl, "" )\ DEFINE_SCRIPTFUNC( AddColorChange, "" )\ DEFINE_SCRIPTFUNC( ClearColorChangeStream, "" )\ //-------------------------------------------------------------- //-------------------------------------------------------------- CLASS_HELPER_INTERFACE( Button, Label ) { public: #if SCRIPT_VGUI_SIGNAL_INTERFACE // Sets the command message to send to the action signal target when the button is pressed void SetCommand( const char *command ) { if ( !V_strnicmp( command, "url ", 4 ) ) { __base()->SetCommand( (KeyValues*)NULL ); g_pScriptVM->RaiseException("invalid button command"); return; } __base()->SetCommand( command ); } #endif void SetButtonActivationType( int activationType ) { __base()->SetButtonActivationType( (Button::ActivationType_t)activationType ); } bool IsArmed() { return __base()->IsArmed(); } void SetArmed( bool state ) { __base()->SetArmed(state); } bool IsSelected() { return __base()->IsSelected(); } void SetSelected( bool state ) { __base()->SetSelected(state); } bool IsDepressed() { return __base()->IsDepressed(); } void ForceDepressed( bool state ) { __base()->ForceDepressed(state); } void SetMouseClickEnabled( int code, bool state ) { __base()->SetMouseClickEnabled( (MouseCode)code, state ); } bool IsMouseClickEnabled( int code ) { return __base()->IsMouseClickEnabled( (MouseCode)code ); } void SetDefaultColor( int fr, int fg, int fb, int fa, int br, int bg, int bb, int ba ) { __base()->SetDefaultColor( Color(fr, fg, fb, fa), Color(br, bg, bb, ba) ); } void SetArmedColor( int fr, int fg, int fb, int fa, int br, int bg, int bb, int ba ) { __base()->SetArmedColor( Color(fr, fg, fb, fa), Color(br, bg, bb, ba) ); } void SetSelectedColor( int fr, int fg, int fb, int fa, int br, int bg, int bb, int ba ) { __base()->SetSelectedColor( Color(fr, fg, fb, fa), Color(br, bg, bb, ba) ); } void SetDepressedColor( int fr, int fg, int fb, int fa, int br, int bg, int bb, int ba ) { __base()->SetDepressedColor( Color(fr, fg, fb, fa), Color(br, bg, bb, ba) ); } void SetArmedSound( const char *sound ) { __base()->SetArmedSound( sound ); } void SetDepressedSound( const char *sound ) { __base()->SetDepressedSound( sound ); } void SetReleasedSound( const char *sound ) { __base()->SetReleasedSound( sound ); } }; #define DEFINE_VGUI_SCRIPTFUNC_Button()\ DEFINE_VGUI_SCRIPTFUNC_Label()\ DEFINE_SCRIPTFUNC( SetButtonActivationType, "" )\ DEFINE_SCRIPTFUNC( IsArmed, "" )\ DEFINE_SCRIPTFUNC( SetArmed, "" )\ DEFINE_SCRIPTFUNC( IsSelected, "" )\ DEFINE_SCRIPTFUNC( SetSelected, "" )\ DEFINE_SCRIPTFUNC( IsDepressed, "" )\ DEFINE_SCRIPTFUNC( ForceDepressed, "" )\ DEFINE_SCRIPTFUNC( SetMouseClickEnabled, "" )\ DEFINE_SCRIPTFUNC( IsMouseClickEnabled, "" )\ DEFINE_SCRIPTFUNC( SetDefaultColor, "" )\ DEFINE_SCRIPTFUNC( SetArmedColor, "" )\ DEFINE_SCRIPTFUNC( SetSelectedColor, "" )\ DEFINE_SCRIPTFUNC( SetDepressedColor, "" )\ DEFINE_SCRIPTFUNC( SetArmedSound, "" )\ DEFINE_SCRIPTFUNC( SetDepressedSound, "" )\ DEFINE_SCRIPTFUNC( SetReleasedSound, "" )\ //-------------------------------------------------------------- //-------------------------------------------------------------- CLASS_HELPER_INTERFACE( ImagePanel, Panel ) { public: void SetImage( const char *imageName, bool hardwareFilter ) { __base()->EvictImage(); __base()->SetImage( vgui_GetImage( imageName, hardwareFilter ) ); } void SetDrawColor( int r, int g, int b, int a ) { __base()->SetDrawColor( Color( r, g, b, a ) ); } void SetTileImage( bool bTile ) { __base()->SetTileImage( bTile ); } void SetShouldScaleImage( bool state ) { __base()->SetShouldScaleImage( state ); } #if 0 void SetFrame( int nFrame ) { __base()->SetFrame( nFrame ); } #endif }; #define DEFINE_VGUI_SCRIPTFUNC_ImagePanel()\ DEFINE_VGUI_SCRIPTFUNC_Panel()\ DEFINE_SCRIPTFUNC( SetImage, "" )\ DEFINE_SCRIPTFUNC( SetDrawColor, "" )\ DEFINE_SCRIPTFUNC( SetTileImage, "" )\ DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" )\ //-------------------------------------------------------------- //-------------------------------------------------------------- CLASS_HELPER_INTERFACE( Frame, Panel ) { public: void SetMinimumSize( int wide, int tall ) { __base()->SetMinimumSize( wide, tall ); } void SetTitle( const char* titel ) { __base()->SetTitle( titel, false ); } void Close() { __base()->Close(); } void SetDeleteSelfOnClose( bool state ) { __base()->SetDeleteSelfOnClose( state ); } void SetMoveable( bool state ) { __base()->SetMoveable( state ); } void SetSizeable( bool state ) { __base()->SetSizeable( state ); } void SetCloseButtonVisible( bool state ) { __base()->SetCloseButtonVisible( state ); } void SetTitleBarVisible( bool state ) { __base()->SetTitleBarVisible( state ); } }; #define DEFINE_VGUI_SCRIPTFUNC_Frame()\ DEFINE_VGUI_SCRIPTFUNC_Panel()\ DEFINE_SCRIPTFUNC( SetMinimumSize, "" )\ DEFINE_SCRIPTFUNC( SetTitle, "" )\ DEFINE_SCRIPTFUNC( Close, "" )\ DEFINE_SCRIPTFUNC( SetDeleteSelfOnClose, "" )\ DEFINE_SCRIPTFUNC( SetMoveable, "" )\ DEFINE_SCRIPTFUNC( SetSizeable, "" )\ DEFINE_SCRIPTFUNC( SetCloseButtonVisible, "" )\ DEFINE_SCRIPTFUNC( SetTitleBarVisible, "" )\ //-------------------------------------------------------------- //-------------------------------------------------------------- CLASS_HELPER_INTERFACE( RichText, Panel ) { public: void SetText( const char* text ) { __base()->SetText( text ); } void SetFont( int font ) { __base()->SetFont( IntToFontHandle(font) ); } void InsertString( const char* text ) { __base()->InsertString( text ); } void SetPanelInteractive( bool bInteractive ) { __base()->SetPanelInteractive( bInteractive ); } void SetUnusedScrollbarInvisible( bool bInvis ) { __base()->SetUnusedScrollbarInvisible( bInvis ); } void GotoTextStart() { __base()->GotoTextStart(); } void GotoTextEnd() { __base()->GotoTextEnd(); } void SetMaximumCharCount( int maxChars ) { __base()->SetMaximumCharCount( maxChars ); } void InsertColorChange( int r, int g, int b, int a ) { __base()->InsertColorChange( Color( r, g, b, a ) ); } int GetNumLines() { return __base()->GetNumLines(); } void SetDrawTextOnly() { __base()->SetDrawTextOnly(); } }; #define DEFINE_VGUI_SCRIPTFUNC_RichText()\ DEFINE_VGUI_SCRIPTFUNC_Panel()\ DEFINE_SCRIPTFUNC( SetText, "" )\ DEFINE_SCRIPTFUNC( SetFont, "" )\ DEFINE_SCRIPTFUNC( InsertString, "" )\ DEFINE_SCRIPTFUNC( SetPanelInteractive, "" )\ DEFINE_SCRIPTFUNC( SetUnusedScrollbarInvisible, "" )\ DEFINE_SCRIPTFUNC( GotoTextStart, "" )\ DEFINE_SCRIPTFUNC( GotoTextEnd, "" )\ DEFINE_SCRIPTFUNC( SetMaximumCharCount, "" )\ DEFINE_SCRIPTFUNC( InsertColorChange, "" )\ DEFINE_SCRIPTFUNC( GetNumLines, "" )\ DEFINE_SCRIPTFUNC( SetDrawTextOnly, "" )\ //-------------------------------------------------------------- //-------------------------------------------------------------- CLASS_HELPER_INTERFACE( TextEntry, Panel ) { public: void SetText( const char* text ) { wchar_t wcs[512]; g_pVGuiLocalize->ConvertANSIToUnicode( text, wcs, sizeof(wcs) ); __base()->SetText( wcs ); } const char *GetText() { static char sz[512]; __base()->GetText( sz, sizeof(sz) ); return sz; } void SetFont( int font ) { __base()->SetFont( IntToFontHandle(font) ); } void SetEditable( bool state ) { __base()->SetEditable( state ); } void GotoTextStart() { __base()->GotoTextStart(); } void GotoTextEnd() { __base()->GotoTextEnd(); } void InsertString( const char* text ) { __base()->InsertString( text ); } void SelectNone() { __base()->SelectNone(); } void SetMultiline( bool state ) { __base()->SetMultiline( state ); } void SetVerticalScrollbar( bool state ) { __base()->SetVerticalScrollbar( state ); } #if 0 void SetHorizontalScrolling( bool status ) { __base()->SetHorizontalScrolling( status ); } #endif void SetCatchEnterKey( bool state ) { __base()->SetCatchEnterKey( state ); } void SetMaximumCharCount( int maxChars ) { __base()->SetMaximumCharCount( maxChars ); } #if 0 void SetWrap( bool wrap ) { __base()->SetWrap( wrap ); } #endif void SetAllowNumericInputOnly( bool state ) { __base()->SetAllowNumericInputOnly( state ); } #if 0 void SetDisabledBgColor( int r, int g, int b, int a ) { __base()->SetDisabledBgColor( Color( r, g, b, a ) ); } void SetSelectionTextColor( int r, int g, int b, int a ) { __base()->SetSelectionTextColor( Color( r, g, b, a ) ); } void SetSelectionBgColor( int r, int g, int b, int a ) { __base()->SetSelectionBgColor( Color( r, g, b, a ) ); } void SetSelectionUnfocusedBgColor( int r, int g, int b, int a ) { __base()->SetSelectionUnfocusedBgColor( Color( r, g, b, a ) ); } #endif }; #define DEFINE_VGUI_SCRIPTFUNC_TextEntry()\ DEFINE_VGUI_SCRIPTFUNC_Panel()\ DEFINE_SCRIPTFUNC( SetText, "" )\ DEFINE_SCRIPTFUNC( GetText, "" )\ DEFINE_SCRIPTFUNC( SetFont, "" )\ DEFINE_SCRIPTFUNC( SetEditable, "" )\ DEFINE_SCRIPTFUNC( GotoTextStart, "" )\ DEFINE_SCRIPTFUNC( GotoTextEnd, "" )\ DEFINE_SCRIPTFUNC( InsertString, "" )\ DEFINE_SCRIPTFUNC( SelectNone, "" )\ DEFINE_SCRIPTFUNC( SetMultiline, "" )\ DEFINE_SCRIPTFUNC( SetVerticalScrollbar, "" )\ DEFINE_SCRIPTFUNC( SetCatchEnterKey, "" )\ DEFINE_SCRIPTFUNC( SetMaximumCharCount, "" )\ DEFINE_SCRIPTFUNC( SetAllowNumericInputOnly, "" )\ //-------------------------------------------------------------- //-------------------------------------------------------------- #if !defined(NO_STEAM) CLASS_HELPER_INTERFACE( AvatarImage, Panel ) { public: void SetPlayer( const char *steam2id, int eAvatarSize ) { uint32 __SteamInstanceID; uint32 __SteamLocalUserID_Low32Bits; uint32 __SteamLocalUserID_High32Bits; int c = sscanf( steam2id, "STEAM_%u:%u:%u", &__SteamInstanceID, &__SteamLocalUserID_High32Bits, &__SteamLocalUserID_Low32Bits ); if ( c < 3 ) return; CSteamID id( __SteamLocalUserID_Low32Bits * 2 + __SteamLocalUserID_High32Bits, k_EUniversePublic, k_EAccountTypeIndividual ); __base()->SetPlayer( id, (EAvatarSize)eAvatarSize ); } void SetPlayerByIndex( int entindex, int eAvatarSize ) { if ( !entindex ) { __base()->ClearAvatar(); return; } __base()->SetPlayer( entindex, (EAvatarSize)eAvatarSize ); } void SetDefaultAvatar( const char *imageName ) { __base()->SetDefaultAvatar( vgui_GetImage( imageName, false ) ); } void SetShouldScaleImage( bool state ) { __base()->SetShouldScaleImage( state ); } }; #define DEFINE_VGUI_SCRIPTFUNC_AvatarImage()\ DEFINE_VGUI_SCRIPTFUNC_Panel()\ DEFINE_SCRIPTFUNC( SetPlayer, "" )\ DEFINE_SCRIPTFUNC( SetPlayerByIndex, "" )\ DEFINE_SCRIPTFUNC( SetDefaultAvatar, "" )\ DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" ) #endif //-------------------------------------------------------------- //-------------------------------------------------------------- #if VGUI_TGA_IMAGE_PANEL CLASS_HELPER_INTERFACE( TGAImagePanel, Panel ) { public: void SetTGAImage( const char *p ) { __base()->SetTGAImage( p ); } void SetDrawColor( int r, int g, int b, int a ) { __base()->SetDrawColor( r, g, b, a ); } void SetShouldScaleImage( bool i ) { __base()->SetShouldScaleImage( i ); } }; #define DEFINE_VGUI_SCRIPTFUNC_TGAImagePanel()\ DEFINE_VGUI_SCRIPTFUNC_Panel()\ DEFINE_SCRIPTFUNC( SetTGAImage, "" )\ DEFINE_SCRIPTFUNC( SetDrawColor, "" )\ DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" ) #endif //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- //============================================================== //============================================================== static inline void SetHScript( HSCRIPT &var, HSCRIPT val ) { if ( var && g_pScriptVM ) g_pScriptVM->ReleaseScript( var ); var = val; } #define CheckCallback(s)\ if ( FStrEq( cb, #s ) )\ {\ SetHScript( m_hfn##s, fn );\ return;\ } //-------------------------------------------------------- // C++ objects for vgui overrides and messages. //-------------------------------------------------------- class CScript_Panel : public Panel { DECLARE_SCRIPTVGUI_CLASS( Panel ); private: HSCRIPT m_hfnPaint; HSCRIPT m_hfnPaintBackground; HSCRIPT m_hfnPostChildPaint; HSCRIPT m_hfnPerformLayout; HSCRIPT m_hfnOnTick; HSCRIPT m_hfnOnScreenSizeChanged; HSCRIPT m_hfnOnCursorEntered; HSCRIPT m_hfnOnCursorExited; HSCRIPT m_hfnOnCursorMoved; HSCRIPT m_hfnOnMousePressed; HSCRIPT m_hfnOnMouseDoublePressed; HSCRIPT m_hfnOnMouseReleased; HSCRIPT m_hfnOnMouseWheeled; HSCRIPT m_hfnOnKeyCodePressed; HSCRIPT m_hfnOnKeyCodeReleased; HSCRIPT m_hfnOnKeyCodeTyped; #if SCRIPT_VGUI_SIGNAL_INTERFACE HSCRIPT m_hfnOnCommand; #endif public: CScript_Panel( Panel *parent, const char *name ) : BaseClass( parent, name ), m_hfnPaint(NULL), m_hfnPaintBackground(NULL), m_hfnPostChildPaint(NULL), m_hfnPerformLayout(NULL), m_hfnOnTick(NULL), m_hfnOnScreenSizeChanged(NULL), m_hfnOnCursorEntered(NULL), m_hfnOnCursorExited(NULL), m_hfnOnCursorMoved(NULL), m_hfnOnMousePressed(NULL), m_hfnOnMouseDoublePressed(NULL), m_hfnOnMouseReleased(NULL), m_hfnOnMouseWheeled(NULL), m_hfnOnKeyCodePressed(NULL), m_hfnOnKeyCodeReleased(NULL), m_hfnOnKeyCodeTyped(NULL) #if SCRIPT_VGUI_SIGNAL_INTERFACE , m_hfnOnCommand(NULL) #endif {} void Shutdown() { ivgui()->RemoveTickSignal( GetVPanel() ); SetHScript( m_hfnPaint, NULL ); SetHScript( m_hfnPaintBackground, NULL ); SetHScript( m_hfnPostChildPaint, NULL ); SetHScript( m_hfnPerformLayout, NULL ); SetHScript( m_hfnOnTick, NULL ); SetHScript( m_hfnOnScreenSizeChanged, NULL ); SetHScript( m_hfnOnCursorEntered, NULL ); SetHScript( m_hfnOnCursorExited, NULL ); SetHScript( m_hfnOnCursorMoved, NULL ); SetHScript( m_hfnOnMousePressed, NULL ); SetHScript( m_hfnOnMouseDoublePressed, NULL ); SetHScript( m_hfnOnMouseReleased, NULL ); SetHScript( m_hfnOnMouseWheeled, NULL ); SetHScript( m_hfnOnKeyCodePressed, NULL ); SetHScript( m_hfnOnKeyCodeReleased, NULL ); SetHScript( m_hfnOnKeyCodeTyped, NULL ); #if SCRIPT_VGUI_SIGNAL_INTERFACE SetHScript( m_hfnOnCommand, NULL ); #endif } public: void Paint() { g_pScriptVM->ExecuteFunction( m_hfnPaint, NULL, 0, NULL, NULL, true ); } void PaintBackground() { if ( m_hfnPaintBackground ) { g_pScriptVM->ExecuteFunction( m_hfnPaintBackground, NULL, 0, NULL, NULL, true ); } else { BaseClass::PaintBackground(); } } void PostChildPaint() { g_pScriptVM->ExecuteFunction( m_hfnPostChildPaint, NULL, 0, NULL, NULL, true ); } void PerformLayout() { BaseClass::PerformLayout(); if ( m_hfnPerformLayout ) { g_pScriptVM->ExecuteFunction( m_hfnPerformLayout, NULL, 0, NULL, NULL, true ); } } void OnTick() { g_pScriptVM->ExecuteFunction( m_hfnOnTick, NULL, 0, NULL, NULL, true ); } void OnScreenSizeChanged( int oldwide, int oldtall ) { BaseClass::OnScreenSizeChanged( oldwide, oldtall ); if ( m_hfnOnScreenSizeChanged ) { ScriptVariant_t args[2] = { oldwide, oldtall }; g_pScriptVM->ExecuteFunction( m_hfnOnScreenSizeChanged, args, 2, NULL, NULL, true ); } } #if SCRIPT_VGUI_SIGNAL_INTERFACE void OnCommand( const char *command ) { if ( m_hfnOnCommand ) { ScriptVariant_t ret, arg = command; g_pScriptVM->ExecuteFunction( m_hfnOnCommand, &arg, 1, &ret, NULL, true ); // Return true to swallow if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) return; } BaseClass::OnCommand( command ); } #endif void OnCursorEntered() { if ( m_hfnOnCursorEntered ) { g_pScriptVM->ExecuteFunction( m_hfnOnCursorEntered, NULL, 0, NULL, NULL, true ); } } void OnCursorExited() { if ( m_hfnOnCursorExited ) { g_pScriptVM->ExecuteFunction( m_hfnOnCursorExited, NULL, 0, NULL, NULL, true ); } } void OnCursorMoved( int x, int y ) { if ( m_hfnOnCursorMoved ) { ScriptVariant_t args[2] = { x, y }; g_pScriptVM->ExecuteFunction( m_hfnOnCursorMoved, args, 2, NULL, NULL, true ); } else { Assert( !ParentNeedsCursorMoveEvents() ); } } void OnMousePressed( MouseCode code ) { if ( m_hfnOnMousePressed ) { ScriptVariant_t arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnMousePressed, &arg, 1, NULL, NULL, true ); } } void OnMouseDoublePressed( MouseCode code ) { if ( m_hfnOnMouseDoublePressed ) { ScriptVariant_t arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnMouseDoublePressed, &arg, 1, NULL, NULL, true ); } } void OnMouseReleased( MouseCode code ) { if ( m_hfnOnMouseReleased ) { ScriptVariant_t arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnMouseReleased, &arg, 1, NULL, NULL, true ); } } void OnMouseWheeled( int delta ) { if ( m_hfnOnMouseWheeled ) { ScriptVariant_t arg = (int)delta; g_pScriptVM->ExecuteFunction( m_hfnOnMouseWheeled, &arg, 1, NULL, NULL, true ); } } void OnKeyCodePressed( KeyCode code ) { if ( m_hfnOnKeyCodePressed ) { ScriptVariant_t ret, arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodePressed, &arg, 1, &ret, NULL, true ); // Return true to swallow if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) return; } BaseClass::OnKeyCodePressed( code ); } void OnKeyCodeReleased( KeyCode code ) { if ( m_hfnOnKeyCodeReleased ) { ScriptVariant_t ret, arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodeReleased, &arg, 1, &ret, NULL, true ); // Return true to swallow if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) return; } BaseClass::OnKeyCodeReleased( code ); } void OnKeyCodeTyped( KeyCode code ) { if ( m_hfnOnKeyCodeTyped ) { ScriptVariant_t ret, arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodeTyped, &arg, 1, &ret, NULL, true ); // Return true to swallow if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) return; } BaseClass::OnKeyCodeTyped( code ); } public: void SetCallback( const char* cb, HSCRIPT fn ) { CheckCallback( Paint ); CheckCallback( PaintBackground ); CheckCallback( PostChildPaint ); CheckCallback( PerformLayout ); CheckCallback( OnTick ); CheckCallback( OnScreenSizeChanged ); CheckCallback( OnCursorEntered ); CheckCallback( OnCursorExited ); CheckCallback( OnCursorMoved ); CheckCallback( OnMousePressed ); CheckCallback( OnMouseDoublePressed ); CheckCallback( OnMouseReleased ); CheckCallback( OnMouseWheeled ); CheckCallback( OnKeyCodePressed ); CheckCallback( OnKeyCodeReleased ); CheckCallback( OnKeyCodeTyped ); #if SCRIPT_VGUI_SIGNAL_INTERFACE CheckCallback( OnCommand ); #endif g_pScriptVM->RaiseException("invalid callback"); } }; //-------------------------------------------------------------- //-------------------------------------------------------------- class CScript_Frame : public Frame { DECLARE_SCRIPTVGUI_CLASS( Frame ); private: HSCRIPT m_hfnPaint; HSCRIPT m_hfnPaintBackground; HSCRIPT m_hfnPerformLayout; HSCRIPT m_hfnOnTick; HSCRIPT m_hfnOnScreenSizeChanged; HSCRIPT m_hfnOnCursorEntered; HSCRIPT m_hfnOnCursorExited; HSCRIPT m_hfnOnCursorMoved; HSCRIPT m_hfnOnMousePressed; HSCRIPT m_hfnOnMouseDoublePressed; HSCRIPT m_hfnOnMouseReleased; HSCRIPT m_hfnOnMouseWheeled; HSCRIPT m_hfnOnKeyCodePressed; HSCRIPT m_hfnOnKeyCodeReleased; HSCRIPT m_hfnOnKeyCodeTyped; #if SCRIPT_VGUI_SIGNAL_INTERFACE HSCRIPT m_hfnOnCommand; #endif public: CScript_Frame( Panel *parent, const char *name ) : // Start without popup BaseClass( parent, name, false, false ), m_hfnPaint(NULL), m_hfnPaintBackground(NULL), m_hfnPerformLayout(NULL), m_hfnOnTick(NULL), m_hfnOnScreenSizeChanged(NULL), m_hfnOnCursorEntered(NULL), m_hfnOnCursorExited(NULL), m_hfnOnCursorMoved(NULL), m_hfnOnMousePressed(NULL), m_hfnOnMouseDoublePressed(NULL), m_hfnOnMouseReleased(NULL), m_hfnOnMouseWheeled(NULL), m_hfnOnKeyCodePressed(NULL), m_hfnOnKeyCodeReleased(NULL), m_hfnOnKeyCodeTyped(NULL) #if SCRIPT_VGUI_SIGNAL_INTERFACE , m_hfnOnCommand(NULL) #endif { SetFadeEffectDisableOverride( true ); } void Shutdown() { ivgui()->RemoveTickSignal( GetVPanel() ); SetHScript( m_hfnPaint, NULL ); SetHScript( m_hfnPaintBackground, NULL ); SetHScript( m_hfnPerformLayout, NULL ); SetHScript( m_hfnOnTick, NULL ); SetHScript( m_hfnOnScreenSizeChanged, NULL ); SetHScript( m_hfnOnMousePressed, NULL ); SetHScript( m_hfnOnMouseDoublePressed, NULL ); SetHScript( m_hfnOnMouseReleased, NULL ); SetHScript( m_hfnOnMouseWheeled, NULL ); SetHScript( m_hfnOnKeyCodePressed, NULL ); SetHScript( m_hfnOnKeyCodeReleased, NULL ); SetHScript( m_hfnOnKeyCodeTyped, NULL ); #if SCRIPT_VGUI_SIGNAL_INTERFACE SetHScript( m_hfnOnCommand, NULL ); #endif } public: void Paint() { g_pScriptVM->ExecuteFunction( m_hfnPaint, NULL, 0, NULL, NULL, true ); } void PaintBackground() { if ( m_hfnPaintBackground ) { g_pScriptVM->ExecuteFunction( m_hfnPaintBackground, NULL, 0, NULL, NULL, true ); } else { BaseClass::PaintBackground(); } } void PerformLayout() { BaseClass::PerformLayout(); if ( m_hfnPerformLayout ) { g_pScriptVM->ExecuteFunction( m_hfnPerformLayout, NULL, 0, NULL, NULL, true ); } } void OnTick() { g_pScriptVM->ExecuteFunction( m_hfnOnTick, NULL, 0, NULL, NULL, true ); } void OnScreenSizeChanged( int oldwide, int oldtall ) { BaseClass::OnScreenSizeChanged( oldwide, oldtall ); if ( m_hfnOnScreenSizeChanged ) { ScriptVariant_t args[2] = { oldwide, oldtall }; g_pScriptVM->ExecuteFunction( m_hfnOnScreenSizeChanged, args, 2, NULL, NULL, true ); } } #if SCRIPT_VGUI_SIGNAL_INTERFACE void OnCommand( const char *command ) { if ( m_hfnOnCommand ) { ScriptVariant_t ret, arg = command; g_pScriptVM->ExecuteFunction( m_hfnOnCommand, &arg, 1, &ret, NULL, true ); // Return true to swallow if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) return; } BaseClass::OnCommand( command ); } #endif void OnCursorEntered() { if ( m_hfnOnCursorEntered ) { g_pScriptVM->ExecuteFunction( m_hfnOnCursorEntered, NULL, 0, NULL, NULL, true ); } } void OnCursorExited() { if ( m_hfnOnCursorExited ) { g_pScriptVM->ExecuteFunction( m_hfnOnCursorExited, NULL, 0, NULL, NULL, true ); } } void OnCursorMoved( int x, int y ) { if ( m_hfnOnCursorMoved ) { ScriptVariant_t args[2] = { x, y }; g_pScriptVM->ExecuteFunction( m_hfnOnCursorMoved, args, 2, NULL, NULL, true ); } else { Assert( !ParentNeedsCursorMoveEvents() ); } } void OnMousePressed( MouseCode code ) { BaseClass::OnMousePressed( code ); if ( m_hfnOnMousePressed ) { ScriptVariant_t arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnMousePressed, &arg, 1, NULL, NULL, true ); } } void OnMouseDoublePressed( MouseCode code ) { if ( m_hfnOnMouseDoublePressed ) { ScriptVariant_t arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnMouseDoublePressed, &arg, 1, NULL, NULL, true ); } } void OnMouseReleased( MouseCode code ) { if ( m_hfnOnMouseReleased ) { ScriptVariant_t arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnMouseReleased, &arg, 1, NULL, NULL, true ); } } void OnMouseWheeled( int delta ) { if ( m_hfnOnMouseWheeled ) { ScriptVariant_t arg = (int)delta; g_pScriptVM->ExecuteFunction( m_hfnOnMouseWheeled, &arg, 1, NULL, NULL, true ); } } void OnKeyCodePressed( KeyCode code ) { if ( m_hfnOnKeyCodePressed ) { ScriptVariant_t ret, arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodePressed, &arg, 1, &ret, NULL, true ); // Return true to swallow if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) return; } BaseClass::OnKeyCodePressed( code ); } void OnKeyCodeReleased( KeyCode code ) { if ( m_hfnOnKeyCodeReleased ) { ScriptVariant_t ret, arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodeReleased, &arg, 1, &ret, NULL, true ); // Return true to swallow if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) return; } BaseClass::OnKeyCodeReleased( code ); } void OnKeyCodeTyped( KeyCode code ) { if ( m_hfnOnKeyCodeTyped ) { ScriptVariant_t ret, arg = (int)code; g_pScriptVM->ExecuteFunction( m_hfnOnKeyCodeTyped, &arg, 1, &ret, NULL, true ); // Return true to swallow the CanChainKeysToParent() override check and fallback, // which by default swallows the input. if ( ret.m_type == FIELD_BOOLEAN && ret.m_bool ) return; if ( CanChainKeysToParent() ) { BaseClass::OnKeyCodeTyped( code ); } } else { BaseClass::OnKeyCodeTyped( code ); } } public: void SetCallback( const char* cb, HSCRIPT fn ) { CheckCallback( Paint ); CheckCallback( PaintBackground ); CheckCallback( PerformLayout ); CheckCallback( OnTick ); CheckCallback( OnScreenSizeChanged ); CheckCallback( OnCursorEntered ); CheckCallback( OnCursorExited ); CheckCallback( OnCursorMoved ); CheckCallback( OnMousePressed ); CheckCallback( OnMouseDoublePressed ); CheckCallback( OnMouseReleased ); CheckCallback( OnMouseWheeled ); CheckCallback( OnKeyCodePressed ); CheckCallback( OnKeyCodeReleased ); CheckCallback( OnKeyCodeTyped ); #if SCRIPT_VGUI_SIGNAL_INTERFACE CheckCallback( OnCommand ); #endif g_pScriptVM->RaiseException("invalid callback"); } }; //-------------------------------------------------------------- //-------------------------------------------------------------- class CScript_Button : public Button { DECLARE_SCRIPTVGUI_CLASS( Button ); private: HSCRIPT m_hfnPaint; HSCRIPT m_hfnPaintBackground; HSCRIPT m_hfnDoClick; public: CScript_Button( Panel *parent, const char *name, const char *text ) : BaseClass( parent, name, text ), m_hfnPaint(NULL), m_hfnPaintBackground(NULL), m_hfnDoClick(NULL) {} void Shutdown() { SetHScript( m_hfnPaint, NULL ); SetHScript( m_hfnPaintBackground, NULL ); SetHScript( m_hfnDoClick, NULL ); } public: void Paint() { if ( m_hfnPaint ) { g_pScriptVM->ExecuteFunction( m_hfnPaint, NULL, 0, NULL, NULL, true ); } else { BaseClass::Paint(); } } void PaintBackground() { if ( m_hfnPaintBackground ) { g_pScriptVM->ExecuteFunction( m_hfnPaintBackground, NULL, 0, NULL, NULL, true ); } else { BaseClass::PaintBackground(); } } void DoClick() { BaseClass::DoClick(); if ( m_hfnDoClick ) { g_pScriptVM->ExecuteFunction( m_hfnDoClick, NULL, 0, NULL, NULL, true ); } } public: void SetCallback( const char* cb, HSCRIPT fn ) { CheckCallback( Paint ); CheckCallback( PaintBackground ); CheckCallback( DoClick ); g_pScriptVM->RaiseException("invalid callback"); } }; //-------------------------------------------------------------- //-------------------------------------------------------------- class CScript_TextEntry : public TextEntry { DECLARE_SCRIPTVGUI_CLASS( TextEntry ); private: HSCRIPT m_hfnTextChanged; public: CScript_TextEntry( Panel *parent, const char *name ) : BaseClass( parent, name ), m_hfnTextChanged(NULL) {} void Shutdown() { SetHScript( m_hfnTextChanged, NULL ); } public: //--------------------------------------------- // On "TextMessage" message. // Used for responding to user input as it is typed. //--------------------------------------------- void FireActionSignal() { BaseClass::FireActionSignal(); if ( m_hfnTextChanged ) { g_pScriptVM->ExecuteFunction( m_hfnTextChanged, NULL, 0, NULL, NULL, true ); } } public: void SetCallback( const char* cb, HSCRIPT fn ) { CheckCallback( TextChanged ); g_pScriptVM->RaiseException("invalid callback"); } }; //-------------------------------------------------------------- //-------------------------------------------------------------- #if !defined(NO_STEAM) class CScript_AvatarImage : public CAvatarImagePanel { DECLARE_SCRIPTVGUI_CLASS_EX( CScript_AvatarImage, CAvatarImagePanel ); public: CScript_AvatarImage( Panel *parent, const char *name ) : BaseClass( parent, name ) { SetShouldDrawFriendIcon( false ); } DEBUG_DESTRUCTOR( ~CScript_AvatarImage, CAvatarImagePanel ) void Shutdown() {} }; #endif //-------------------------------------------------------------- //-------------------------------------------------------------- #if VGUI_TGA_IMAGE_PANEL class CTGAImagePanel : public Panel { DECLARE_SCRIPTVGUI_CLASS_EX( CTGAImagePanel, Panel ); private: int m_iTextureID; int m_nWidth; int m_nHeight; Color m_ImageColor; bool m_bScaleImage; public: CTGAImagePanel( Panel *parent, const char *name ) : BaseClass( parent, name ), m_iTextureID(-1), m_bScaleImage(0), m_ImageColor( 255, 255, 255, 255 ) { SetPaintBackgroundEnabled( false ); } ~CTGAImagePanel() { DebugDestructor( CTGAImagePanel ); if ( m_iTextureID != -1 ) { surface()->DestroyTextureID( m_iTextureID ); } } void Shutdown() {} public: void Paint() { if ( m_iTextureID != -1 ) { surface()->DrawSetColor( m_ImageColor ); surface()->DrawSetTexture( m_iTextureID ); if ( m_bScaleImage ) { int w, t; GetSize( w, t ); surface()->DrawTexturedRect( 0, 0, w, t ); } else { surface()->DrawTexturedRect( 0, 0, m_nWidth, m_nHeight ); } } else { int w, t; GetSize( w, t ); surface()->DrawSetColor( 200, 50, 150, 255 ); surface()->DrawFilledRect( 0, 0, w, t ); } } public: void SetTGAImage( const char *fileName ) { if ( V_stricmp( V_GetFileExtension( fileName ), "tga" ) != 0 ) return; CUtlMemory< unsigned char > tga; if ( TGALoader::LoadRGBA8888( fileName, tga, m_nWidth, m_nHeight ) ) { if ( m_iTextureID == -1 ) { m_iTextureID = surface()->CreateNewTextureID( true ); } surface()->DrawSetTextureRGBA( m_iTextureID, tga.Base(), m_nWidth, m_nHeight, false, false ); } else { Warning( "Failed to load TGA image: '%s'\n", fileName ); } } void SetDrawColor( int r, int g, int b, int a ) { m_ImageColor.SetColor( r, g, b, a ); } void SetShouldScaleImage( bool state ) { m_bScaleImage = state; } }; #endif //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- //============================================================== //============================================================== //-------------------------------------------------------- // Script objects //-------------------------------------------------------- DEFINE_VGUI_CLASS_EMPTY_DEFAULT_TEXT( Label ) DEFINE_VGUI_CLASS_EMPTY( ImagePanel ) DEFINE_VGUI_CLASS_EMPTY( RichText ) //-------------------------------------------------------------- //-------------------------------------------------------------- BEGIN_VGUI_HELPER( Panel ) void SetCallback( const char *a, HSCRIPT b ) { __base()->SetCallback( a, b ); } END_VGUI_HELPER() BEGIN_SCRIPTDESC_VGUI( Panel ) DEFINE_SCRIPTFUNC( SetCallback, "" ) END_SCRIPTDESC() //-------------------------------------------------------------- //-------------------------------------------------------------- BEGIN_VGUI_HELPER( Frame ) void SetCallback( const char *a, HSCRIPT b ) { __base()->SetCallback( a, b ); } END_VGUI_HELPER() BEGIN_SCRIPTDESC_VGUI( Frame ) DEFINE_SCRIPTFUNC( SetCallback, "" ) END_SCRIPTDESC() //-------------------------------------------------------------- //-------------------------------------------------------------- BEGIN_VGUI_HELPER_DEFAULT_TEXT( Button ) void SetCallback( const char *a, HSCRIPT b ) { __base()->SetCallback( a, b ); } END_VGUI_HELPER() BEGIN_SCRIPTDESC_VGUI( Button ) DEFINE_SCRIPTFUNC( SetCallback, "" ) END_SCRIPTDESC() //-------------------------------------------------------------- //-------------------------------------------------------------- BEGIN_VGUI_HELPER( TextEntry ) void SetCallback( const char *a, HSCRIPT b ) { __base()->SetCallback( a, b ); } END_VGUI_HELPER() BEGIN_SCRIPTDESC_VGUI( TextEntry ) DEFINE_SCRIPTFUNC( SetCallback, "" ) END_SCRIPTDESC() //-------------------------------------------------------------- //-------------------------------------------------------------- #if !defined(NO_STEAM) BEGIN_VGUI_HELPER( AvatarImage ) END_VGUI_HELPER() BEGIN_SCRIPTDESC_VGUI( AvatarImage ) END_SCRIPTDESC() #endif //-------------------------------------------------------------- //-------------------------------------------------------------- #if VGUI_TGA_IMAGE_PANEL BEGIN_VGUI_HELPER_EX( TGAImagePanel, CTGAImagePanel ) END_VGUI_HELPER() BEGIN_SCRIPTDESC_VGUI( TGAImagePanel ) END_SCRIPTDESC() #endif //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- //============================================================== //============================================================== struct hudelementcache_t { CUtlConstString name; int bits; }; CUtlVector< hudelementcache_t > m_HudElementCache; // Check if hud elements were changed in this level to shortcut on level shutdown bool m_bHudVisiblityChangedThisLevel = false; class CScriptVGUI : public CAutoGameSystem { public: void LevelShutdownPostEntity(); void Shutdown(); public: HSCRIPT CreatePanel( const char* panelClass, HSCRIPT parent, const char* panelName, int root ); //void LoadSchemeFromFile( const char *filename, const char *tag ); } script_vgui; BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptVGUI, "IVGui", SCRIPT_SINGLETON ) DEFINE_SCRIPTFUNC( CreatePanel, SCRIPT_HIDE ) END_SCRIPTDESC() HSCRIPT CScriptVGUI::CreatePanel( const char* panelClass, HSCRIPT parent, const char* panelName, int root ) { if ( (unsigned)g_ScriptPanels.Count() >= (unsigned)g_ScriptPanels.InvalidIndex()-1 ) { Warning( "CScriptVGUI::CreatePanel() exhausted vgui panel storage!\n" ); return NULL; } #define Check( _name )\ if ( FStrEq( panelClass, #_name ) )\ {\ CScript_##_name##_Helper *helper = AllocScriptPanel< CScript_##_name##_Helper >();\ helper->CreateFromScript< CScript_##_name##_Helper >( (HSCRIPT)parent, panelName, root );\ DebugDevMsg( "%3d | Create vgui %s '%s' %s\n", g_ScriptPanels.Count(), panelClass, panelName, helper->GetDebugName() );\ return helper->GetScriptInstance();\ } Check( Panel ); Check( Label ); Check( Button ); Check( ImagePanel ); Check( Frame ); Check( RichText ); Check( TextEntry ); #if !defined(NO_STEAM) Check( AvatarImage ); #endif #if VGUI_TGA_IMAGE_PANEL Check( TGAImagePanel ); #endif g_pScriptVM->RaiseException("invalid vgui class"); return NULL; #undef Check } void CScriptVGUI::LevelShutdownPostEntity() { DebugMsg( "LevelShutdownPostEntity()\n" ); while ( g_ScriptPanels.Count() ) { Assert( g_ScriptPanels.Head() != g_ScriptPanels.InvalidIndex() ); int head = g_ScriptPanels.Head(); g_ScriptPanels[ head ]->Destroy( head ); } g_ScriptPanels.Purge(); FOR_EACH_VEC( g_ScriptTextureIDs, i ) { #ifdef _DEBUG char tex[MAX_PATH]; surface()->DrawGetTextureFile( g_ScriptTextureIDs[i], tex, sizeof(tex)-1 ); DebugMsg( "Destroy texture [%i]%s\n", g_ScriptTextureIDs[i], tex ); #endif surface()->DestroyTextureID( g_ScriptTextureIDs[i] ); } g_ScriptTextureIDs.Purge(); // // Reset hud element visibility // if ( m_bHudVisiblityChangedThisLevel ) { m_bHudVisiblityChangedThisLevel = false; FOR_EACH_VEC( m_HudElementCache, i ) { const hudelementcache_t &cache = m_HudElementCache[i]; Assert( !cache.name.IsEmpty() ); CHudElement *elem = gHUD.FindElement( cache.name ); Assert( elem ); if ( elem ) { elem->SetHiddenBits( cache.bits ); } } } } void CScriptVGUI::Shutdown() { VGUI_DestroyScriptRootPanels(); FOR_EACH_DICT_FAST( g_ScriptFonts, i ) { fontalias_t &alias = g_ScriptFonts[i]; for ( int j = 0; j < alias.Count(); ++j ) { char *pName = alias.Element(j).name; if ( pName ) { free( pName ); alias.Element(j).name = NULL; } } alias.Purge(); } g_ScriptFonts.Purge(); m_HudElementCache.Purge(); } void SetHudElementVisible( const char *name, bool state ) { CHudElement *elem = gHUD.FindElement( name ); if ( !elem ) return; int iOldBits = -2; FOR_EACH_VEC( m_HudElementCache, i ) { const hudelementcache_t &cache = m_HudElementCache[i]; if ( !V_stricmp( cache.name, name ) ) { iOldBits = cache.bits; break; } } if ( iOldBits == -2 ) { if ( state ) // no change return; // First time setting the visibility of this element, save the original bits hudelementcache_t &cache = m_HudElementCache.Element( m_HudElementCache.AddToTail() ); cache.name.Set( name ); cache.bits = elem->GetHiddenBits(); } elem->SetHiddenBits( state ? iOldBits : -1 ); m_bHudVisiblityChangedThisLevel = true; } #ifdef _DEBUG CON_COMMAND( dump_hud_elements, "" ) { int size = gHUD.m_HudList.Size(); CUtlVector< const char* > list( 0, size ); for ( int i = 0; i < size; i++ ) { list.AddToTail( gHUD.m_HudList[i]->GetName() ); } struct _cmp { static int __cdecl fn( const char * const *a, const char * const *b ) { return strcmp( *a, *b ); } }; list.Sort( _cmp::fn ); for ( int i = 0; i < size; i++ ) { Msg( "%s\n", list[i] ); } } #endif class CScriptIInput { public: void MakeWeaponSelection( HSCRIPT weapon ) { ::input->MakeWeaponSelection( HScriptToClass< C_BaseCombatWeapon >( weapon ) ); } #if 0 int GetButtonBits() { return ::input->GetButtonBits(0); } void ClearInputButton( int i ) { return ::input->ClearInputButton(i); } #endif void SetCursorPos( int x, int y ) { vgui::input()->SetCursorPos( x, y ); } int GetAnalogValue( int code ) { Assert( code >= 0 && code < ANALOG_CODE_LAST ); if ( code < 0 || code >= ANALOG_CODE_LAST ) return 0; return inputsystem->GetAnalogValue( (AnalogCode_t)code ); } int GetAnalogDelta( int code ) { Assert( code >= 0 && code < ANALOG_CODE_LAST ); if ( code < 0 || code >= ANALOG_CODE_LAST ) return 0; return inputsystem->GetAnalogDelta( (AnalogCode_t)code ); } bool IsButtonDown( int code ) { Assert( code >= BUTTON_CODE_NONE && code < BUTTON_CODE_LAST ); if ( code < BUTTON_CODE_NONE || code >= BUTTON_CODE_LAST ) return 0; return inputsystem->IsButtonDown( (ButtonCode_t)code ); } // key -> button int StringToButtonCode( const char *key ) { return inputsystem->StringToButtonCode( key ); } // button -> key const char *ButtonCodeToString( int code ) { Assert( code >= BUTTON_CODE_NONE && code < BUTTON_CODE_LAST ); if ( code < BUTTON_CODE_NONE || code >= BUTTON_CODE_LAST ) return 0; return inputsystem->ButtonCodeToString( (ButtonCode_t)code ); } // bind -> key const char *LookupBinding( const char *bind ) { return engine->Key_LookupBinding( bind ); } // button -> bind const char *BindingForKey( int code ) { return engine->Key_BindingForKey( (ButtonCode_t)code ); } #if 0 const char *GetIMELanguageShortCode() { static char ret[5]; wchar_t get[5]; get[0] = L'\0'; vgui::input()->GetIMELanguageShortCode( get, wcslen(get) ); g_pVGuiLocalize->ConvertUnicodeToANSI( get, ret, sizeof(ret) ); return ret; } #endif } script_input; BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptIInput, "IInput", SCRIPT_SINGLETON ) DEFINE_SCRIPTFUNC( MakeWeaponSelection, "" ) DEFINE_SCRIPTFUNC( SetCursorPos, "" ) DEFINE_SCRIPTFUNC( GetAnalogValue, "" ) DEFINE_SCRIPTFUNC( GetAnalogDelta, "" ) DEFINE_SCRIPTFUNC( IsButtonDown, "" ) DEFINE_SCRIPTFUNC( StringToButtonCode, "" ) DEFINE_SCRIPTFUNC( ButtonCodeToString, "" ) DEFINE_SCRIPTFUNC( LookupBinding, "" ) DEFINE_SCRIPTFUNC( BindingForKey, "" ) END_SCRIPTDESC() void SetClipboardText( const char *text ) { system()->SetClipboardText( text, V_strlen(text) ); } //============================================================== //============================================================== #if 0 //----------------------------------------------------------------------------- // Get world position in screen space [0,1]. Return true if on screen. //----------------------------------------------------------------------------- inline bool WorldToScreen( const Vector &pos, int &ix, int &iy ) { int scrw, scrh; surface()->GetScreenSize( scrw, scrh ); const VMatrix &worldToScreen = engine->WorldToScreenMatrix(); bool bOnScreen; // VMatrix * Vector (position projective) vec_t w = worldToScreen[3][0] * pos[0] + worldToScreen[3][1] * pos[1] + worldToScreen[3][2] * pos[2] + worldToScreen[3][3]; vec_t fx = worldToScreen[0][0] * pos[0] + worldToScreen[0][1] * pos[1] + worldToScreen[0][2] * pos[2] + worldToScreen[0][3]; vec_t fy = worldToScreen[1][0] * pos[0] + worldToScreen[1][1] * pos[1] + worldToScreen[1][2] * pos[2] + worldToScreen[1][3]; if ( w < 0.001f ) { fx *= 1e5f; fy *= 1e5f; bOnScreen = false; } else { w = 1.0f / w; fx *= w; fy *= w; bOnScreen = true; } ix = (int)( scrw * 0.5f * ( 1.0f + fx ) + 0.5f ); iy = (int)( scrh * 0.5f * ( 1.0f - fy ) + 0.5f ); return bOnScreen; } #endif //----------------------------------------------------------------------------- // Get screen pixel position [0,1] in world space. //----------------------------------------------------------------------------- inline void ScreenToWorld( int x, int y, Vector &out ) { int scrw, scrh; surface()->GetScreenSize( scrw, scrh ); float scrx = (float)x / (float)scrw; float scry = (float)y / (float)scrh; vec_t tmp[2]; tmp[0] = 2.0f * scrx - 1.0f; tmp[1] = 1.0f - 2.0f * scry; //tmp[2] = 1.0f; //tmp[3] = 1.0f; VMatrix screenToWorld; MatrixInverseGeneral( engine->WorldToScreenMatrix(), screenToWorld ); // VMatrix * Vector (position projective) vec_t iw = 1.0f / ( screenToWorld[3][0] * tmp[0] + screenToWorld[3][1] * tmp[1] + screenToWorld[3][2] + screenToWorld[3][3] ); out[0] = iw * ( screenToWorld[0][0] * tmp[0] + screenToWorld[0][1] * tmp[1] + screenToWorld[0][2] + screenToWorld[0][3] ); out[1] = iw * ( screenToWorld[1][0] * tmp[0] + screenToWorld[1][1] * tmp[1] + screenToWorld[1][2] + screenToWorld[1][3] ); out[2] = iw * ( screenToWorld[2][0] * tmp[0] + screenToWorld[2][1] * tmp[1] + screenToWorld[2][2] + screenToWorld[2][3] ); } #if 0 static bool ScriptWorldToScreen( const Vector &pos, HSCRIPT out ) { int ix, iy; bool r = WorldToScreen( pos, ix, iy ); g_pScriptVM->SetValue( out, (ScriptVariant_t)0, ix ); g_pScriptVM->SetValue( out, 1, iy ); return r; } #endif static const Vector& ScriptScreenToWorld( int x, int y ) { static Vector out; ScreenToWorld( x, y, out ); return out; } static const Vector& ScreenToRay( int x, int y ) { static Vector out; ScreenToWorld( x, y, out ); VectorSubtract( out, CurrentViewOrigin(), out ); VectorNormalize( out ); return out; } //----------------------------------------------------------------------------- // Get world position normalised in screen space. Return true if on screen. //----------------------------------------------------------------------------- int ScreenTransform( const Vector& point, Vector& screen ); static bool ScriptScreenTransform( const Vector &pos, HSCRIPT out ) { Vector v; bool r = ScreenTransform( pos, v ); float x = 0.5f * ( 1.0f + v[0] ); float y = 0.5f * ( 1.0f - v[1] ); g_pScriptVM->SetValue( out, (ScriptVariant_t)0, x ); g_pScriptVM->SetValue( out, 1, y ); return !r; } int ScriptScreenWidth() { int w, h; surface()->GetScreenSize( w, h ); return w; } int ScriptScreenHeight() { int w, h; surface()->GetScreenSize( w, h ); return h; } // // Saving the static (ScreenWidth/640) ratio in a script closure // messes up on save/restore at differing resolutions - // the closure and the user script funcs retain the ratio at the time of the save. // It is not possible to update restored script closure outer variables without writing language specific functions. // // NOTE: Returns int! int usage is more common than float operations. // static int ScriptXRES( float x ) { return x * ( (float)ScriptScreenWidth() / 640.0f ); } static int ScriptYRES( float y ) { return y * ( (float)ScriptScreenHeight() / 480.0f ); } vgui::HFont GetScriptFont( const char *name, bool proportional ) { return script_surface.GetFont( name, proportional, NULL ); } void RegisterScriptVGUI() { ScriptRegisterFunction( g_pScriptVM, SetHudElementVisible, "" ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptXRES, "XRES", "" ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptYRES, "YRES", "" ); ScriptRegisterFunction( g_pScriptVM, SetClipboardText, "" ); //ScriptRegisterFunctionNamed( g_pScriptVM, ScriptWorldToScreen, "WorldToScreen", "Get world position in screen space [0,1]. Return true if on screen." ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenToWorld, "ScreenToWorld", "Get screen pixel position [0,1] in world space." ); ScriptRegisterFunction( g_pScriptVM, ScreenToRay, "Get a ray from screen pixel position to world space." ); ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenTransform, "ScreenTransform", "Get world position normalised in screen space. Return true if on screen." ); g_pScriptVM->Run( g_Script_vgui_init ); g_pScriptVM->RegisterInstance( &script_surface, "surface" ); g_pScriptVM->RegisterInstance( &script_input, "input" ); g_pScriptVM->RegisterInstance( &script_vgui, "vgui" ); }