From 6fc2f1c34aa78b4160442490118ba3be8efc1b1a Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Wed, 22 Dec 2021 16:20:00 +0300 Subject: [PATCH] Add vscript vgui --- sp/src/game/client/client_mapbase.vpc | 6 +- sp/src/game/client/mapbase/vscript_vgui.cpp | 3690 +++++++++++++++++++ sp/src/game/client/mapbase/vscript_vgui.h | 16 + sp/src/game/client/mapbase/vscript_vgui.nut | 395 ++ sp/src/game/client/vscript_client.cpp | 31 +- 5 files changed, 4113 insertions(+), 25 deletions(-) create mode 100644 sp/src/game/client/mapbase/vscript_vgui.cpp create mode 100644 sp/src/game/client/mapbase/vscript_vgui.h create mode 100644 sp/src/game/client/mapbase/vscript_vgui.nut diff --git a/sp/src/game/client/client_mapbase.vpc b/sp/src/game/client/client_mapbase.vpc index 97a2217d3c..f8860e24ea 100644 --- a/sp/src/game/client/client_mapbase.vpc +++ b/sp/src/game/client/client_mapbase.vpc @@ -59,7 +59,11 @@ $Project $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.h" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\logic_script_client.cpp" [$MAPBASE_VSCRIPT] - + + $File "mapbase\vscript_vgui.cpp" [$MAPBASE_VSCRIPT] + $File "mapbase\vscript_vgui.h" [$MAPBASE_VSCRIPT] + $File "mapbase\vscript_vgui.nut" [$MAPBASE_VSCRIPT] + $File "mapbase\c_func_clientclip.cpp" $File "mapbase\c_func_fake_worldportal.cpp" $File "mapbase\c_func_fake_worldportal.h" diff --git a/sp/src/game/client/mapbase/vscript_vgui.cpp b/sp/src/game/client/mapbase/vscript_vgui.cpp new file mode 100644 index 0000000000..61d95daa1b --- /dev/null +++ b/sp/src/game/client/mapbase/vscript_vgui.cpp @@ -0,0 +1,3690 @@ +//========= 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 + +//#include "bitmap/tgaloader.h" + +#if !defined(NO_STEAM) +#include "steam/steam_api.h" +#include "vgui_avatarimage.h" +#endif + +#include "view.h" + +#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 script 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 + +// 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 + + +#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 + + + +using namespace vgui; +class IScriptVGUIObject; +struct FontData_t; +template< typename T > class CCopyableUtlVectorConservative; + +// Aliases contain only one font definition unless 'yres' was defined +typedef CCopyableUtlVectorConservative< FontData_t > fontalias_t; +typedef CUtlDict< fontalias_t > CFontDict; + +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() ); } +}; + + + +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, int ) + { + // 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()" ); + } + +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 DrawColoredCircle( int x, int y, int radius, int r, int g, int b, int a ); + + 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 ValidateMaterial( const char *materialName, const char *textureGroupName ); + 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 +} + +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 engine root panel. + // 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; + } + + _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 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 b = 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()) ) + { + b = true; + } + else +#endif + for ( int i = PANEL_ROOT; i <= PANEL_CLIENTDLL_TOOLS; ++i ) + { + if ( parent == enginevgui->GetPanel( (VGuiPanel_t)i ) ) + { + b = true; + break; + } + } + + // My parent wasn't registered. + AssertMsg1( b, "'%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() ); + } + // UNDONE: Register C++ created children of script created panels. + // It is safe to do so because their lifetime depends on their script parents. + } + } + + 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: + // NOTE: This is used if DoClick() callback is not implemented in CScript_Button. + // This changes where and how button command is processed - + // whether in the button { DoClick() } or in an external panel { OnCommand(cmd) }. + // It is fine to always use DoClick() instead of vgui messages + // because of the dynamic nature of script closures. +#if VGUI_SIGNAL_INTERFACE + void SetCommand( const char *command ) + { + if ( !V_strncmp( 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); + } +#if 0 + void SetBlink( bool state ) + { + __base()->SetBlink(state); + } +#endif + 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) ); + } +#if 0 + void SetBlinkColor( int r, int g, int b, int a ) + { + __base()->SetBlinkColor( Color(r, g, b, a) ); + } +#endif + 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 0 +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 +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + + +//============================================================== +//============================================================== + + +#define SetHScript( var, 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; + +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) + {} + + 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 ); + } + +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 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 ); + + 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; + +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) + { + 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 ); + } + +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 ); + } + } + + 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 ); + + 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 0 +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 0 +BEGIN_VGUI_HELPER_EX( TGAImagePanel, CTGAImagePanel ) +END_VGUI_HELPER() + +BEGIN_SCRIPTDESC_VGUI( TGAImagePanel ) +END_SCRIPTDESC() +#endif +//-------------------------------------------------------------- +//-------------------------------------------------------------- + +//-------------------------------------------------------------- +//-------------------------------------------------------------- + + +//============================================================== +//============================================================== + + +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 + + 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(); +} + +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(); +} + + +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 ) + { + return inputsystem->GetAnalogValue( (AnalogCode_t)code ); + } + + int GetAnalogDelta( int code ) + { + return inputsystem->GetAnalogDelta( (AnalogCode_t)code ); + } + + bool IsButtonDown( int code ) + { + return inputsystem->IsButtonDown( (ButtonCode_t)code ); + } + + // key -> button + int StringToButtonCode( const char *key ) + { + return inputsystem->StringToButtonCode( key ); + } + + // button -> key + const char *ButtonCodeToString( int code ) + { + 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() +{ + 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" ); +} diff --git a/sp/src/game/client/mapbase/vscript_vgui.h b/sp/src/game/client/mapbase/vscript_vgui.h new file mode 100644 index 0000000000..d521407367 --- /dev/null +++ b/sp/src/game/client/mapbase/vscript_vgui.h @@ -0,0 +1,16 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef VSCRIPT_VGUI_H +#define VSCRIPT_VGUI_H +#ifdef _WIN32 +#pragma once +#endif + +void RegisterScriptVGUI(); + +#endif diff --git a/sp/src/game/client/mapbase/vscript_vgui.nut b/sp/src/game/client/mapbase/vscript_vgui.nut new file mode 100644 index 0000000000..df0285eb81 --- /dev/null +++ b/sp/src/game/client/mapbase/vscript_vgui.nut @@ -0,0 +1,395 @@ +static const char* g_Script_vgui_init = R"script( +local DoCreateFont = ISurface.CreateFont; +ISurface.CreateFont <- function( name, props ) +{ + if ( !("name" in props) || typeof props.name != "string" ) + throw "invalid parameter 'name'"; + + if ( !("tall" in props) || typeof props.tall != "integer" || !props.tall ) + throw "invalid parameter 'tall'"; + + if ( !("weight" in props) || typeof props.weight != "integer" ) + throw "invalid parameter 'weight'"; + + local yres_min = 0, yres_max = 0; + + if ( "yres" in props && typeof props.yres == "string" ) + { + local ss = ::split( props.yres, " " ); + try + { + yres_min = ss[0].tointeger(); + yres_max = ss[1].tointeger(); + } + catch(x) + { + throw "invalid parameter 'yres'"; + } + } + + if ( ( (!("proportional" in props) || typeof props.proportional != "bool") ) && !yres_min ) + { + throw "parameter 'proportional' or 'yres' not found"; + } + else if ( "proportional" in props && props.proportional && yres_min ) + { + throw "resolution definition on a proportional font" + } + + local blur = 0, scanlines = 0, proportional = false, flags = 0; + + if ( "blur" in props && typeof props.blur == "integer" ) + blur = props.blur; + + if ( "scanlines" in props && typeof props.scanlines == "integer" ) + scanlines = props.scanlines; + + if ( "proportional" in props && typeof props.proportional == "bool" ) + proportional = props.proportional; + + if ( "italic" in props && props.italic == true ) + flags = flags | 0x001; + + if ( "underline" in props && props.underline == true ) + flags = flags | 0x002; + + if ( "strikeout" in props && props.strikeout == true ) + flags = flags | 0x004; + + if ( "symbol" in props && props.symbol == true ) + flags = flags | 0x008; + + if ( "antialias" in props && props.antialias == true ) + flags = flags | 0x010; + + if ( "gaussianblur" in props && props.gaussianblur == true ) + flags = flags | 0x020; + + if ( "rotary" in props && props.rotary == true ) + flags = flags | 0x040; + + if ( "dropshadow" in props && props.dropshadow == true ) + flags = flags | 0x080; + + if ( "additive" in props && props.additive == true ) + flags = flags | 0x100; + + if ( "outline" in props && props.outline == true ) + flags = flags | 0x200; + + if ( "custom" in props && props.custom == true ) + flags = flags | 0x400; + + if ( "bitmap" in props && props.bitmap == true ) + flags = flags | 0x800; + + return DoCreateFont( name, props.name, props.tall, props.weight, blur, scanlines, flags, yres_min, yres_max, proportional ); +} + +local _Schemes = {} +local _FontTall = {} +local DoGetFont = ISurface.DoGetFont <- ISurface.GetFont; +local DoGetFontTall = ISurface.GetFontTall; + +ISurface.GetFont <- function( name, proportional = false, sch = "" ) +{ + if ( sch in _Schemes ) + { + local fonts = _Schemes[sch][proportional.tointeger()]; + if ( name in fonts ) + return fonts[name]; + } + else + { + _Schemes[sch] <- [{}, {}]; + } + + local id = DoGetFont( name, proportional, sch ); + if ( id > 0 ) + _Schemes[sch][proportional.tointeger()][name] <- id; + + return id; +} + +ISurface.GetFontTall <- function( id ) +{ + if ( id in _FontTall ) + return _FontTall[id]; + return _FontTall[id] <- DoGetFontTall( id ); +} + +local _Textures = {} +local DoGetTextureID = ISurface.GetTextureID; +local DoValidateTexture = ISurface.ValidateTexture; +local DoSetTextureFile = ISurface.SetTextureFile; + +ISurface.ValidateTexture <- function( filename, hardwareFilter, forceReload = false, procedural = false ) +{ + return DoValidateTexture( filename, hardwareFilter, forceReload, procedural ); +} + +ISurface.SetTextureFile <- function( id, filename, hardwareFilter ) +{ + if ( filename in _Textures ) + delete _Textures[filename]; + + return DoSetTextureFile( id, filename, hardwareFilter ); +} + +ISurface.GetTextureID <- function( name ) +{ + if ( name in _Textures ) + return _Textures[name]; + + local id = DoGetTextureID( name ); + if ( id > 0 ) + _Textures[name] <- id; + + return id; +} + +// Forward compatibility +IVGui.GetRootPanel <- function() { return 1000 } +//IVGui.GetGameUIRootPanel <- function() { return 1001 } +IVGui.GetClientDLLRootPanel <- function() { return 1002 } + +local CreatePanel = IVGui.CreatePanel; +IVGui.CreatePanel <- function( type, parent, name ) +{ + if ( !parent ) + throw "invalid parent"; + + local root = 0; + + if ( typeof parent == "integer" ) + { + switch ( parent ) + { + case 1000: + root = 0; + break; + + case 1001: + root = 1; + break; + + case 1002: + root = 2; + break; + + default: + throw "invalid parent"; + } + parent = null; + } + return CreatePanel( type, parent, name, root ); +} + +ISurface.__OnScreenSizeChanged <- function() +{ + _FontTall.clear(); +} + +// MAX_JOYSTICKS = 1 // ( 1 << MAX_SPLITSCREEN_CLIENT_BITS ) +// MAX_JOYSTICK_AXES = 6 // X,Y,Z,R,U,V +// JOYSTICK_MAX_BUTTON_COUNT = 32 +// JOYSTICK_POV_BUTTON_COUNT = 4 +// JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2 + +enum ButtonCode +{ + KEY_FIRST = 0 + KEY_0 = 1 + KEY_1 = 2 + KEY_2 = 3 + KEY_3 = 4 + KEY_4 = 5 + KEY_5 = 6 + KEY_6 = 7 + KEY_7 = 8 + KEY_8 = 9 + KEY_9 = 10 + KEY_A = 11 + KEY_B = 12 + KEY_C = 13 + KEY_D = 14 + KEY_E = 15 + KEY_F = 16 + KEY_G = 17 + KEY_H = 18 + KEY_I = 19 + KEY_J = 20 + KEY_K = 21 + KEY_L = 22 + KEY_M = 23 + KEY_N = 24 + KEY_O = 25 + KEY_P = 26 + KEY_Q = 27 + KEY_R = 28 + KEY_S = 29 + KEY_T = 30 + KEY_U = 31 + KEY_V = 32 + KEY_W = 33 + KEY_X = 34 + KEY_Y = 35 + KEY_Z = 36 + KEY_PAD_0 = 37 + KEY_PAD_1 = 38 + KEY_PAD_2 = 39 + KEY_PAD_3 = 40 + KEY_PAD_4 = 41 + KEY_PAD_5 = 42 + KEY_PAD_6 = 43 + KEY_PAD_7 = 44 + KEY_PAD_8 = 45 + KEY_PAD_9 = 46 + KEY_PAD_DIVIDE = 47 + KEY_PAD_MULTIPLY = 48 + KEY_PAD_MINUS = 49 + KEY_PAD_PLUS = 50 + KEY_PAD_ENTER = 51 + KEY_PAD_DECIMAL = 52 + KEY_LBRACKET = 53 + KEY_RBRACKET = 54 + KEY_SEMICOLON = 55 + KEY_APOSTROPHE = 56 + KEY_BACKQUOTE = 57 + KEY_COMMA = 58 + KEY_PERIOD = 59 + KEY_SLASH = 60 + KEY_BACKSLASH = 61 + KEY_MINUS = 62 + KEY_EQUAL = 63 + KEY_ENTER = 64 + KEY_SPACE = 65 + KEY_BACKSPACE = 66 + KEY_TAB = 67 + KEY_CAPSLOCK = 68 + KEY_NUMLOCK = 69 + KEY_ESCAPE = 70 + KEY_SCROLLLOCK = 71 + KEY_INSERT = 72 + KEY_DELETE = 73 + KEY_HOME = 74 + KEY_END = 75 + KEY_PAGEUP = 76 + KEY_PAGEDOWN = 77 + KEY_BREAK = 78 + KEY_LSHIFT = 79 + KEY_RSHIFT = 80 + KEY_LALT = 81 + KEY_RALT = 82 + KEY_LCONTROL = 83 + KEY_RCONTROL = 84 + KEY_LWIN = 85 + KEY_RWIN = 86 + KEY_APP = 87 + KEY_UP = 88 + KEY_LEFT = 89 + KEY_DOWN = 90 + KEY_RIGHT = 91 + KEY_F1 = 92 + KEY_F2 = 93 + KEY_F3 = 94 + KEY_F4 = 95 + KEY_F5 = 96 + KEY_F6 = 97 + KEY_F7 = 98 + KEY_F8 = 99 + KEY_F9 = 100 + KEY_F10 = 101 + KEY_F11 = 102 + KEY_F12 = 103 + KEY_CAPSLOCKTOGGLE = 104 + KEY_NUMLOCKTOGGLE = 105 + KEY_SCROLLLOCKTOGGLE = 106 + KEY_LAST = 106 + + MOUSE_FIRST = 107 + MOUSE_LEFT = 107 + MOUSE_RIGHT = 108 + MOUSE_MIDDLE = 109 + MOUSE_4 = 110 + MOUSE_5 = 111 + MOUSE_WHEEL_UP = 112 + MOUSE_WHEEL_DOWN = 113 + MOUSE_LAST = 113 + + JOYSTICK_FIRST = 114 + JOYSTICK_FIRST_BUTTON = 114 + JOYSTICK_LAST_BUTTON = 145 + JOYSTICK_FIRST_POV_BUTTON = 146 + JOYSTICK_LAST_POV_BUTTON = 149 + JOYSTICK_FIRST_AXIS_BUTTON = 150 + JOYSTICK_LAST_AXIS_BUTTON = 161 + JOYSTICK_LAST = 161 +} + +enum AnalogCode +{ + MOUSE_X = 0 + MOUSE_Y = 1 + MOUSE_XY = 2 + MOUSE_WHEEL = 3 + + JOYSTICK_FIRST_AXIS = 4 + JOYSTICK_LAST_AXIS = 9 +} + +enum CursorCode +{ + dc_none = 1 + dc_arrow = 2 + dc_ibeam = 3 + dc_hourglass = 4 + dc_waitarrow = 5 + dc_crosshair = 6 + dc_up = 7 + dc_sizenwse = 8 + dc_sizenesw = 9 + dc_sizewe = 10 + dc_sizens = 11 + dc_sizeall = 12 + dc_no = 13 + dc_hand = 14 + dc_blank = 15 +} + +enum Alignment +{ + northwest = 0 + north = 1 + northeast = 2 + west = 3 + center = 4 + east = 5 + southwest = 6 + south = 7 + southeast = 8 +} + +if ( __Documentation.RegisterHelp != dummy ) +{ + local RegEnum = function( e ) + { + local K = getconsttable()[e]; + __Documentation.RegisterEnumHelp( e, K.len(), "" ); + e += "."; + foreach ( s, v in K ) + { + __Documentation.RegisterConstHelp( e+s, v, "" ); + } + } + RegEnum( "ButtonCode" ); + RegEnum( "AnalogCode" ); + RegEnum( "CursorCode" ); + RegEnum( "Alignment" ); + + __Documentation.RegisterHelp( "ISurface::CreateFont", "void ISurface::CreateFont(string, handle)", "" ); + __Documentation.RegisterHelp( "IVGui::CreatePanel", "handle IVGui::CreatePanel(string, handle, string)", "" ); + __Documentation.RegisterHelp( "IVGui::GetRootPanel", "handle IVGui::GetRootPanel()", "" ); + __Documentation.RegisterHelp( "IVGui::GetClientDLLRootPanel", "handle IVGui::GetClientDLLRootPanel()", "" ); +} +)script"; diff --git a/sp/src/game/client/vscript_client.cpp b/sp/src/game/client/vscript_client.cpp index faf35c16d3..6c8c53719b 100644 --- a/sp/src/game/client/vscript_client.cpp +++ b/sp/src/game/client/vscript_client.cpp @@ -22,6 +22,7 @@ #include "materialsystem/imaterialvar.h" #include "mapbase/matchers.h" #include "mapbase/vscript_singletons.h" +#include "mapbase/vscript_vgui.h" #endif extern IScriptManager *scriptmanager; @@ -521,6 +522,9 @@ bool DoIncludeScript( const char *pszScript, HSCRIPT hScope ) } #ifdef MAPBASE_VSCRIPT +int ScriptScreenWidth(); +int ScriptScreenHeight(); + static float FrameTime() { return gpGlobals->frametime; @@ -536,27 +540,6 @@ static bool IsWindowedMode() return engine->IsWindowedMode(); } -int ScreenTransform( const Vector& point, Vector& screen ); - -//----------------------------------------------------------------------------- -// Input array [x,y], set normalised screen space pos. Return true if on screen -//----------------------------------------------------------------------------- -static bool ScriptScreenTransform( const Vector &pos, HSCRIPT hArray ) -{ - if ( g_pScriptVM->GetNumTableEntries(hArray) >= 2 ) - { - 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( hArray, ScriptVariant_t(0), x ); - g_pScriptVM->SetValue( hArray, 1, y ); - return !r; - } - return false; -} - // Creates a client-side prop HSCRIPT CreateProp( const char *pszEntityName, const Vector &vOrigin, const char *pszModelName, int iAnim ) { @@ -657,10 +640,9 @@ bool VScriptClientInit() #ifdef MAPBASE_VSCRIPT ScriptRegisterFunction( g_pScriptVM, FrameTime, "Get the time spent on the client in the last frame" ); ScriptRegisterFunction( g_pScriptVM, Con_IsVisible, "Returns true if the console is visible" ); - ScriptRegisterFunction( g_pScriptVM, ScreenWidth, "Width of the screen in pixels" ); - ScriptRegisterFunction( g_pScriptVM, ScreenHeight, "Height of the screen in pixels" ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenWidth, "ScreenWidth", "Width of the screen in pixels" ); + ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenHeight, "ScreenHeight", "Height of the screen in pixels" ); ScriptRegisterFunction( g_pScriptVM, IsWindowedMode, "" ); - ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenTransform, "ScreenTransform", "Get the x & y positions of a world position in screen space. Returns true if it's onscreen" ); ScriptRegisterFunction( g_pScriptVM, MainViewOrigin, "" ); ScriptRegisterFunction( g_pScriptVM, MainViewAngles, "" ); @@ -695,6 +677,7 @@ bool VScriptClientInit() RegisterSharedScriptConstants(); RegisterSharedScriptFunctions(); + RegisterScriptVGUI(); #else //g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" ); #endif