From 5a1b03ac20c16a0db0e4e138a9a5a9b708d1c522 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 14 Apr 2018 01:49:14 +0300 Subject: [PATCH] Integrate FWGS vgui_support --- engine/client/cl_game.c | 17 +- engine/client/cl_scrn.c | 4 +- engine/client/cl_view.c | 4 +- engine/client/vgui/vgui_draw.c | 685 ++++++++- engine/client/vgui/vgui_draw.h | 58 +- engine/client/vgui/vgui_input.cpp | 290 ---- engine/client/vgui/vgui_int.cpp | 129 -- engine/client/vgui/vgui_main.h | 117 -- engine/client/vgui/vgui_surf.cpp | 465 ------ engine/common/common.h | 6 + engine/common/input.c | 154 +- engine/common/input.h | 5 +- engine/common/keys.c | 5 +- engine/vgui_api.h | 215 +++ vgui_support/Android.mk | 23 + vgui_support/CMakeLists.txt | 89 ++ vgui_support/Makefile.linux | 29 + vgui_support/cl.bat | 5 + vgui_support/utlmemory.h | 368 +++++ vgui_support/utlrbtree.h | 1289 +++++++++++++++++ vgui_support/utlvector.h | 605 ++++++++ .../vgui => vgui_support}/vgui_clip.cpp | 28 +- vgui_support/vgui_font.cpp | 185 +++ vgui_support/vgui_input.cpp | 86 ++ vgui_support/vgui_int.cpp | 132 ++ vgui_support/vgui_main.h | 225 +++ vgui_support/vgui_surf.cpp | 339 +++++ 27 files changed, 4275 insertions(+), 1282 deletions(-) delete mode 100644 engine/client/vgui/vgui_input.cpp delete mode 100644 engine/client/vgui/vgui_int.cpp delete mode 100644 engine/client/vgui/vgui_main.h delete mode 100644 engine/client/vgui/vgui_surf.cpp create mode 100644 engine/vgui_api.h create mode 100644 vgui_support/Android.mk create mode 100644 vgui_support/CMakeLists.txt create mode 100644 vgui_support/Makefile.linux create mode 100644 vgui_support/cl.bat create mode 100644 vgui_support/utlmemory.h create mode 100644 vgui_support/utlrbtree.h create mode 100644 vgui_support/utlvector.h rename {engine/client/vgui => vgui_support}/vgui_clip.cpp (75%) create mode 100644 vgui_support/vgui_font.cpp create mode 100644 vgui_support/vgui_input.cpp create mode 100644 vgui_support/vgui_int.cpp create mode 100644 vgui_support/vgui_main.h create mode 100644 vgui_support/vgui_surf.cpp diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index b3f49ed9..66f768f9 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -3476,6 +3476,11 @@ float Voice_GetControlFloat( VoiceTweakControl iControl ) return 1.0f; } +static void GAME_EXPORT VGui_ViewportPaintBackground( int extents[4] ) +{ + // stub +} + // shared between client and server triangleapi_t gTriApi = { @@ -3758,7 +3763,6 @@ void CL_UnloadProgs( void ) CL_FreeParticles(); CL_ClearAllRemaps(); Mod_ClearUserData(); - VGui_Shutdown(); // NOTE: HLFX 0.5 has strange bug: hanging on exit if no map was loaded if( Q_stricmp( GI->gamedir, "hlfx" ) || GI->version != 0.5f ) @@ -3768,6 +3772,7 @@ void CL_UnloadProgs( void ) Cvar_FullSet( "host_clientloaded", "0", FCVAR_READ_ONLY ); COM_FreeLibrary( clgame.hInstance ); + VGui_Shutdown(); Mem_FreePool( &cls.mempool ); Mem_FreePool( &clgame.mempool ); memset( &clgame, 0, sizeof( clgame )); @@ -3792,6 +3797,11 @@ qboolean CL_LoadProgs( const char *name ) clgame.mempool = Mem_AllocPool( "Client Edicts Zone" ); clgame.entities = NULL; + // NOTE: important stuff! + // vgui must startup BEFORE loading client.dll to avoid get error ERROR_NOACESS + // during LoadLibrary + VGui_Startup( gameui.globals->scrWidth, gameui.globals->scrHeight ); + clgame.hInstance = COM_LoadLibrary( name, false, false ); if( !clgame.hInstance ) return false; @@ -3887,9 +3897,6 @@ qboolean CL_LoadProgs( const char *name ) CL_InitStudioAPI( ); - // initialize VGui - VGui_Startup (); - // trying to grab them from client.dll cl_righthand = Cvar_FindVar( "cl_righthand" ); @@ -3897,4 +3904,4 @@ qboolean CL_LoadProgs( const char *name ) cl_righthand = Cvar_Get( "cl_righthand", "0", FCVAR_ARCHIVE, "flip viewmodel (left to right)" ); return true; -} \ No newline at end of file +} diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c index 542f50a3..1692c258 100644 --- a/engine/client/cl_scrn.c +++ b/engine/client/cl_scrn.c @@ -683,7 +683,7 @@ void SCR_VidInit( void ) gameui.globals->scrWidth = glState.width; gameui.globals->scrHeight = glState.height; - VGui_Startup (); + VGui_Startup( glState.width, glState.height ); CL_ClearSpriteTextures(); // now all hud sprites are invalid @@ -754,4 +754,4 @@ void SCR_Shutdown( void ) UI_UnloadProgs(); scr_init = false; -} \ No newline at end of file +} diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index 28bffe78..c832c332 100644 --- a/engine/client/cl_view.c +++ b/engine/client/cl_view.c @@ -361,7 +361,7 @@ void V_PostRender( void ) { SCR_TileClear(); CL_DrawHUD( CL_ACTIVE ); - VGui_Paint( true ); + VGui_Paint(); } switch( cls.scrshot_action ) @@ -393,4 +393,4 @@ void V_PostRender( void ) SCR_MakeScreenShot(); R_AllowFog( true ); R_EndFrame(); -} \ No newline at end of file +} diff --git a/engine/client/vgui/vgui_draw.c b/engine/client/vgui/vgui_draw.c index ef087985..3335cb56 100644 --- a/engine/client/vgui/vgui_draw.c +++ b/engine/client/vgui/vgui_draw.c @@ -13,14 +13,520 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ +#ifndef XASH_DEDICATED + #include "common.h" #include "client.h" #include "gl_local.h" #include "vgui_draw.h" +#include "vgui_api.h" +#include "library.h" +#include +#include "../keydefs.h" -convar_t *vgui_colorstrings; int g_textures[VGUI_MAX_TEXTURES]; int g_textureId = 0; +int g_iBoundTexture; +static enum VGUI_KeyCode s_pVirtualKeyTrans[256]; +static enum VGUI_DefaultCursor s_currentCursor; +#ifdef XASH_SDL +#include +#include "platform/sdl/events.h" +static SDL_Cursor* s_pDefaultCursor[20]; +#endif +static void *s_pVGuiSupport; // vgui_support library + +void VGUI_DrawInit( void ); +void VGUI_DrawShutdown( void ); +void VGUI_SetupDrawingText( int *pColor ); +void VGUI_SetupDrawingRect( int *pColor ); +void VGUI_SetupDrawingImage( int *pColor ); +void VGUI_BindTexture( int id ); +void VGUI_EnableTexture( qboolean enable ); +void VGUI_CreateTexture( int id, int width, int height ); +void VGUI_UploadTexture( int id, const char *buffer, int width, int height ); +void VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight ); +void VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr ); +void VGUI_GetTextureSizes( int *width, int *height ); +int VGUI_GenerateTexture( void ); + +// Helper functions for vgui backend + +/*void VGUI_HideCursor( void ) +{ + host.mouse_visible = false; + SDL_HideCursor(); +} + +void VGUI_ShowCursor( void ) +{ + host.mouse_visible = true; + SDL_ShowCursor(); +}*/ + +void GAME_EXPORT *VGUI_EngineMalloc(size_t size) +{ + return Z_Malloc( size ); +} + +qboolean GAME_EXPORT VGUI_IsInGame( void ) +{ + return cls.state == ca_active && cls.key_dest == key_game; +} + +void GAME_EXPORT VGUI_GetMousePos( int *_x, int *_y ) +{ + float xscale = scr_width->value / (float)clgame.scrInfo.iWidth; + float yscale = scr_height->value / (float)clgame.scrInfo.iHeight; + int x, y; + + CL_GetMousePosition( &x, &y ); + *_x = x / xscale, *_y = y / yscale; +} + +void VGUI_InitCursors( void ) +{ + // load up all default cursors +#ifdef XASH_SDL + s_pDefaultCursor[dc_none] = NULL; + s_pDefaultCursor[dc_arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + s_pDefaultCursor[dc_ibeam] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + s_pDefaultCursor[dc_hourglass]= SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT); + s_pDefaultCursor[dc_crosshair]= SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR); + s_pDefaultCursor[dc_up] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + s_pDefaultCursor[dc_sizenwse] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); + s_pDefaultCursor[dc_sizenesw] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); + s_pDefaultCursor[dc_sizewe] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); + s_pDefaultCursor[dc_sizens] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); + s_pDefaultCursor[dc_sizeall] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); + s_pDefaultCursor[dc_no] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); + s_pDefaultCursor[dc_hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); + //host.mouse_visible = true; + SDL_SetCursor( s_pDefaultCursor[dc_arrow] ); +#endif +} + +void GAME_EXPORT VGUI_CursorSelect(enum VGUI_DefaultCursor cursor ) +{ + qboolean visible; + if( cls.key_dest != key_game || cl.refdef.paused ) + return; + + switch( cursor ) + { + case dc_user: + case dc_none: + visible = false; + break; + default: + visible = true; + break; + } + +#ifdef XASH_SDL + if( host.mouse_visible ) + { + SDL_SetRelativeMouseMode( SDL_FALSE ); + SDL_SetCursor( s_pDefaultCursor[cursor] ); + SDL_ShowCursor( true ); + } + else + { + SDL_ShowCursor( false ); + if( host.mouse_visible ) + SDL_GetRelativeMouseState( NULL, NULL ); + } + //SDL_SetRelativeMouseMode(false); +#endif + if( s_currentCursor == cursor ) + return; + + s_currentCursor = cursor; + host.mouse_visible = visible; +} + +byte GAME_EXPORT VGUI_GetColor( int i, int j) +{ + return g_color_table[i][j]; +} + +// Define and initialize vgui API + +void GAME_EXPORT VGUI_SetVisible( qboolean state ) +{ + host.mouse_visible=state; +#ifdef XASH_SDL + SDL_ShowCursor( state ); + if( !state ) + SDL_GetRelativeMouseState( NULL, NULL ); + + SDLash_EnableTextInput( state, true ); +#endif +} + +int GAME_EXPORT VGUI_UtfProcessChar( int in ) +{ + if( vgui_utf8->integer ) + return Con_UtfProcessCharForce( in ); + else + return in; +} + +vguiapi_t vgui = +{ + false, // Not initialized yet + VGUI_DrawInit, + VGUI_DrawShutdown, + VGUI_SetupDrawingText, + VGUI_SetupDrawingRect, + VGUI_SetupDrawingImage, + VGUI_BindTexture, + VGUI_EnableTexture, + VGUI_CreateTexture, + VGUI_UploadTexture, + VGUI_UploadTextureBlock, + VGUI_DrawQuad, + VGUI_GetTextureSizes, + VGUI_GenerateTexture, + VGUI_EngineMalloc, +/* VGUI_ShowCursor, + VGUI_HideCursor,*/ + VGUI_CursorSelect, + VGUI_GetColor, + VGUI_IsInGame, + VGUI_SetVisible, + VGUI_GetMousePos, + VGUI_UtfProcessChar, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +qboolean VGui_IsActive( void ) +{ + return vgui.initialized; +} + +/* +================ +VGui_Startup + +Load vgui_support library and call VGui_Startup +================ +*/ +void VGui_Startup( int width, int height ) +{ + static qboolean failed = false; + + void (*F) ( vguiapi_t * ); + char vguiloader[256]; + char vguilib[256]; + + vguiloader[0] = vguilib[0] = '\0'; + + if( failed ) + return; + + if( !vgui.initialized ) + { +#ifdef XASH_INTERNAL_GAMELIBS + s_pVGuiSupport = Com_LoadLibrary( "client", false ); + + if( s_pVGuiSupport ) + { + F = Com_GetProcAddress( s_pVGuiSupport, "InitVGUISupportAPI" ); + if( F ) + { + F( &vgui ); + vgui.initialized = true; + VGUI_InitCursors(); + MsgDev( D_INFO, "vgui_support: found interal client support\n" ); + } + } +#endif // XASH_INTERNAL_GAMELIBS + + Com_ResetLibraryError(); + + // HACKHACK: load vgui with correct path first if specified. + // it will be reused while resolving vgui support and client deps + if( Sys_GetParmFromCmdLine( "-vguilib", vguilib ) ) + { + if( Q_strstr( vguilib, ".dll") ) + Q_strncpy( vguiloader, "vgui_support.dll", 256 ); + else + Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 ); + + if( !Com_LoadLibrary( vguilib, false ) ) + MsgDev( D_WARN, "VGUI preloading failed. Default library will be used!\n"); + } + + if( Q_strstr( GI->client_lib, ".dll" ) ) + Q_strncpy( vguiloader, "vgui_support.dll", 256 ); + + if( !vguiloader[0] && !Sys_GetParmFromCmdLine( "-vguiloader", vguiloader ) ) + Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 ); + + s_pVGuiSupport = Com_LoadLibrary( vguiloader, false ); + + if( !s_pVGuiSupport ) + { + s_pVGuiSupport = Com_LoadLibrary( va( "../%s", vguiloader ), false ); + } + + if( !s_pVGuiSupport ) + { + if( FS_SysFileExists( vguiloader, false ) ) + MsgDev( D_ERROR, "Failed to load vgui_support library: %s", Com_GetLibraryError() ); + else + MsgDev( D_INFO, "vgui_support: not found\n" ); + } + else + { + F = Com_GetProcAddress( s_pVGuiSupport, "InitAPI" ); + if( F ) + { + F( &vgui ); + vgui.initialized = true; + VGUI_InitCursors(); + } + else + MsgDev( D_ERROR, "Failed to find vgui_support library entry point!\n" ); + } + + } + + if( height < 480 ) + height = 480; + + if( width <= 640 ) + width = 640; + else if( width <= 800 ) + width = 800; + else if( width <= 1024 ) + width = 1024; + else if( width <= 1152 ) + width = 1152; + else if( width <= 1280 ) + width = 1280; + else if( width <= 1600 ) + width = 1600; +#ifdef DLL_LOADER + else if ( Q_strstr( vguiloader, ".dll" ) ) + width = 1600; +#endif + + + if( vgui.initialized ) + { + //host.mouse_visible = true; + vgui.Startup( width, height ); + } + else failed = true; +} + + + +/* +================ +VGui_Shutdown + +Unload vgui_support library and call VGui_Shutdown +================ +*/ +void VGui_Shutdown( void ) +{ + if( vgui.Shutdown ) + vgui.Shutdown(); + + if( s_pVGuiSupport ) + Com_FreeLibrary( s_pVGuiSupport ); + s_pVGuiSupport = NULL; + + vgui.initialized = false; +} + + +void VGUI_InitKeyTranslationTable( void ) +{ + static qboolean bInitted = false; + + if( bInitted ) + return; + bInitted = true; + + // set virtual key translation table + Q_memset( s_pVirtualKeyTrans, -1, sizeof( s_pVirtualKeyTrans ) ); + + s_pVirtualKeyTrans['0'] = KEY_0; + s_pVirtualKeyTrans['1'] = KEY_1; + s_pVirtualKeyTrans['2'] = KEY_2; + s_pVirtualKeyTrans['3'] = KEY_3; + s_pVirtualKeyTrans['4'] = KEY_4; + s_pVirtualKeyTrans['5'] = KEY_5; + s_pVirtualKeyTrans['6'] = KEY_6; + s_pVirtualKeyTrans['7'] = KEY_7; + s_pVirtualKeyTrans['8'] = KEY_8; + s_pVirtualKeyTrans['9'] = KEY_9; + s_pVirtualKeyTrans['A'] = s_pVirtualKeyTrans['a'] = KEY_A; + s_pVirtualKeyTrans['B'] = s_pVirtualKeyTrans['b'] = KEY_B; + s_pVirtualKeyTrans['C'] = s_pVirtualKeyTrans['c'] = KEY_C; + s_pVirtualKeyTrans['D'] = s_pVirtualKeyTrans['d'] = KEY_D; + s_pVirtualKeyTrans['E'] = s_pVirtualKeyTrans['e'] = KEY_E; + s_pVirtualKeyTrans['F'] = s_pVirtualKeyTrans['f'] = KEY_F; + s_pVirtualKeyTrans['G'] = s_pVirtualKeyTrans['g'] = KEY_G; + s_pVirtualKeyTrans['H'] = s_pVirtualKeyTrans['h'] = KEY_H; + s_pVirtualKeyTrans['I'] = s_pVirtualKeyTrans['i'] = KEY_I; + s_pVirtualKeyTrans['J'] = s_pVirtualKeyTrans['j'] = KEY_J; + s_pVirtualKeyTrans['K'] = s_pVirtualKeyTrans['k'] = KEY_K; + s_pVirtualKeyTrans['L'] = s_pVirtualKeyTrans['l'] = KEY_L; + s_pVirtualKeyTrans['M'] = s_pVirtualKeyTrans['m'] = KEY_M; + s_pVirtualKeyTrans['N'] = s_pVirtualKeyTrans['n'] = KEY_N; + s_pVirtualKeyTrans['O'] = s_pVirtualKeyTrans['o'] = KEY_O; + s_pVirtualKeyTrans['P'] = s_pVirtualKeyTrans['p'] = KEY_P; + s_pVirtualKeyTrans['Q'] = s_pVirtualKeyTrans['q'] = KEY_Q; + s_pVirtualKeyTrans['R'] = s_pVirtualKeyTrans['r'] = KEY_R; + s_pVirtualKeyTrans['S'] = s_pVirtualKeyTrans['s'] = KEY_S; + s_pVirtualKeyTrans['T'] = s_pVirtualKeyTrans['t'] = KEY_T; + s_pVirtualKeyTrans['U'] = s_pVirtualKeyTrans['u'] = KEY_U; + s_pVirtualKeyTrans['V'] = s_pVirtualKeyTrans['v'] = KEY_V; + s_pVirtualKeyTrans['W'] = s_pVirtualKeyTrans['w'] = KEY_W; + s_pVirtualKeyTrans['X'] = s_pVirtualKeyTrans['x'] = KEY_X; + s_pVirtualKeyTrans['Y'] = s_pVirtualKeyTrans['y'] = KEY_Y; + s_pVirtualKeyTrans['Z'] = s_pVirtualKeyTrans['z'] = KEY_Z; + + s_pVirtualKeyTrans[K_KP_5 - 5] = KEY_PAD_0; + s_pVirtualKeyTrans[K_KP_5 - 4] = KEY_PAD_1; + s_pVirtualKeyTrans[K_KP_5 - 3] = KEY_PAD_2; + s_pVirtualKeyTrans[K_KP_5 - 2] = KEY_PAD_3; + s_pVirtualKeyTrans[K_KP_5 - 1] = KEY_PAD_4; + s_pVirtualKeyTrans[K_KP_5 - 0] = KEY_PAD_5; + s_pVirtualKeyTrans[K_KP_5 + 1] = KEY_PAD_6; + s_pVirtualKeyTrans[K_KP_5 + 2] = KEY_PAD_7; + s_pVirtualKeyTrans[K_KP_5 + 3] = KEY_PAD_8; + s_pVirtualKeyTrans[K_KP_5 + 4] = KEY_PAD_9; + s_pVirtualKeyTrans[K_KP_SLASH] = KEY_PAD_DIVIDE; + s_pVirtualKeyTrans['*'] = KEY_PAD_MULTIPLY; + s_pVirtualKeyTrans[K_KP_MINUS] = KEY_PAD_MINUS; + s_pVirtualKeyTrans[K_KP_PLUS] = KEY_PAD_PLUS; + s_pVirtualKeyTrans[K_KP_ENTER] = KEY_PAD_ENTER; + //s_pVirtualKeyTrans[K_KP_DECIMAL] = KEY_PAD_DECIMAL; + s_pVirtualKeyTrans['['] = KEY_LBRACKET; + s_pVirtualKeyTrans[']'] = KEY_RBRACKET; + s_pVirtualKeyTrans[';'] = KEY_SEMICOLON; + s_pVirtualKeyTrans['\''] = KEY_APOSTROPHE; + s_pVirtualKeyTrans['`'] = KEY_BACKQUOTE; + s_pVirtualKeyTrans[','] = KEY_COMMA; + s_pVirtualKeyTrans['.'] = KEY_PERIOD; + s_pVirtualKeyTrans[K_KP_SLASH] = KEY_SLASH; + s_pVirtualKeyTrans['\\'] = KEY_BACKSLASH; + s_pVirtualKeyTrans['-'] = KEY_MINUS; + s_pVirtualKeyTrans['='] = KEY_EQUAL; + s_pVirtualKeyTrans[K_ENTER] = KEY_ENTER; + s_pVirtualKeyTrans[K_SPACE] = KEY_SPACE; + s_pVirtualKeyTrans[K_BACKSPACE] = KEY_BACKSPACE; + s_pVirtualKeyTrans[K_TAB] = KEY_TAB; + s_pVirtualKeyTrans[K_CAPSLOCK] = KEY_CAPSLOCK; + s_pVirtualKeyTrans[K_KP_NUMLOCK] = KEY_NUMLOCK; + s_pVirtualKeyTrans[K_ESCAPE] = KEY_ESCAPE; + //s_pVirtualKeyTrans[K_KP_SCROLLLOCK] = KEY_SCROLLLOCK; + s_pVirtualKeyTrans[K_INS] = KEY_INSERT; + s_pVirtualKeyTrans[K_DEL] = KEY_DELETE; + s_pVirtualKeyTrans[K_HOME] = KEY_HOME; + s_pVirtualKeyTrans[K_END] = KEY_END; + s_pVirtualKeyTrans[K_PGUP] = KEY_PAGEUP; + s_pVirtualKeyTrans[K_PGDN] = KEY_PAGEDOWN; + s_pVirtualKeyTrans[K_PAUSE] = KEY_BREAK; + //s_pVirtualKeyTrans[K_SHIFT] = KEY_RSHIFT; + s_pVirtualKeyTrans[K_SHIFT] = KEY_LSHIFT; // SHIFT -> left SHIFT + //s_pVirtualKeyTrans[SDLK_RALT] = KEY_RALT; + s_pVirtualKeyTrans[K_ALT] = KEY_LALT; // ALT -> left ALT + //s_pVirtualKeyTrans[SDLK_RCTRL] = KEY_RCONTROL; + s_pVirtualKeyTrans[K_CTRL] = KEY_LCONTROL; // CTRL -> left CTRL + s_pVirtualKeyTrans[K_WIN] = KEY_LWIN; + //s_pVirtualKeyTrans[SDLK_APPLICATION] = KEY_RWIN; + //s_pVirtualKeyTrans[K_WIN] = KEY_APP; + s_pVirtualKeyTrans[K_UPARROW] = KEY_UP; + s_pVirtualKeyTrans[K_LEFTARROW] = KEY_LEFT; + s_pVirtualKeyTrans[K_DOWNARROW] = KEY_DOWN; + s_pVirtualKeyTrans[K_RIGHTARROW] = KEY_RIGHT; + s_pVirtualKeyTrans[K_F1] = KEY_F1; + s_pVirtualKeyTrans[K_F2] = KEY_F2; + s_pVirtualKeyTrans[K_F3] = KEY_F3; + s_pVirtualKeyTrans[K_F4] = KEY_F4; + s_pVirtualKeyTrans[K_F5] = KEY_F5; + s_pVirtualKeyTrans[K_F6] = KEY_F6; + s_pVirtualKeyTrans[K_F7] = KEY_F7; + s_pVirtualKeyTrans[K_F8] = KEY_F8; + s_pVirtualKeyTrans[K_F9] = KEY_F9; + s_pVirtualKeyTrans[K_F10] = KEY_F10; + s_pVirtualKeyTrans[K_F11] = KEY_F11; + s_pVirtualKeyTrans[K_F12] = KEY_F12; +} + +enum VGUI_KeyCode VGUI_MapKey( int keyCode ) +{ + VGUI_InitKeyTranslationTable(); + + if( keyCode < 0 || keyCode >= (int)sizeof( s_pVirtualKeyTrans ) / (int)sizeof( s_pVirtualKeyTrans[0] )) + { + //Assert( false ); + return (enum VGUI_KeyCode)-1; + } + else + { + return s_pVirtualKeyTrans[keyCode]; + } +} + +void VGui_KeyEvent( int key, int down ) +{ + if( !vgui.initialized ) + return; + +#ifdef XASH_SDL + if( host.mouse_visible ) + SDLash_EnableTextInput( 1, false ); +#endif + + switch( key ) + { + case K_MOUSE1: + vgui.Mouse( down?MA_PRESSED:MA_RELEASED, MOUSE_LEFT ); + return; + case K_MOUSE2: + vgui.Mouse( down?MA_PRESSED:MA_RELEASED, MOUSE_RIGHT ); + return; + case K_MOUSE3: + vgui.Mouse( down?MA_PRESSED:MA_RELEASED, MOUSE_MIDDLE ); + return; + case K_MWHEELDOWN: + vgui.Mouse( MA_WHEEL, 1 ); + return; + case K_MWHEELUP: + vgui.Mouse( MA_WHEEL, -1 ); + return; + default: + break; + } + + if( down == 2 ) + vgui.Key( KA_TYPED, VGUI_MapKey( key ) ); + else + vgui.Key( down?KA_PRESSED:KA_RELEASED, VGUI_MapKey( key ) ); + //Msg("VGui_KeyEvent %d %d %d\n", key, VGUI_MapKey( key ), down ); +} + +void VGui_MouseMove( int x, int y ) +{ + float xscale = scr_width->value / (float)clgame.scrInfo.iWidth; + float yscale = scr_height->value / (float)clgame.scrInfo.iHeight; + if( vgui.initialized ) + vgui.MouseMove( x / xscale, y / yscale ); +} /* ================ @@ -29,22 +535,20 @@ VGUI_DrawInit Startup VGUI backend ================ */ -void VGUI_DrawInit( void ) +void GAME_EXPORT VGUI_DrawInit( void ) { - memset( g_textures, 0, sizeof( g_textures )); - g_textureId = 0; - - vgui_colorstrings = Cvar_Get( "vgui_colorstrings", "0", FCVAR_ARCHIVE, "allow colorstrings in VGUI texts" ); + Q_memset( g_textures, 0, sizeof( g_textures )); + g_textureId = g_iBoundTexture = 0; } /* ================ VGUI_DrawShutdown -Release all the textures +Release all textures ================ */ -void VGUI_DrawShutdown( void ) +void GAME_EXPORT VGUI_DrawShutdown( void ) { int i; @@ -61,10 +565,10 @@ VGUI_GenerateTexture generate unique texture number ================ */ -int VGUI_GenerateTexture( void ) +int GAME_EXPORT VGUI_GenerateTexture( void ) { if( ++g_textureId >= VGUI_MAX_TEXTURES ) - Host_Error( "VGUI_GenerateTexture: VGUI_MAX_TEXTURES limit exceeded\n" ); + Sys_Error( "VGUI_GenerateTexture: VGUI_MAX_TEXTURES limit exceeded\n" ); return g_textureId; } @@ -75,7 +579,7 @@ VGUI_UploadTexture Upload texture into video memory ================ */ -void VGUI_UploadTexture( int id, const char *buffer, int width, int height ) +void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int width, int height ) { rgbdata_t r_image; char texName[32]; @@ -87,7 +591,7 @@ void VGUI_UploadTexture( int id, const char *buffer, int width, int height ) } Q_snprintf( texName, sizeof( texName ), "*vgui%i", id ); - memset( &r_image, 0, sizeof( r_image )); + Q_memset( &r_image, 0, sizeof( r_image )); r_image.width = width; r_image.height = height; @@ -97,16 +601,56 @@ void VGUI_UploadTexture( int id, const char *buffer, int width, int height ) r_image.buffer = (byte *)buffer; g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE, false ); + GL_SetTextureType( g_textures[id], TEX_VGUI ); + g_iBoundTexture = id; } /* ================ -VGUI_SetupDrawingRect +VGUI_CreateTexture -setup transparency etc +Create empty rgba texture and upload them into video memory ================ */ -void VGUI_SetupDrawingRect( int *pColor ) +void GAME_EXPORT VGUI_CreateTexture( int id, int width, int height ) +{ + rgbdata_t r_image; + char texName[32]; + + if( id <= 0 || id >= VGUI_MAX_TEXTURES ) + { + MsgDev( D_ERROR, "VGUI_CreateTexture: bad texture %i. Ignored\n", id ); + return; + } + + Q_snprintf( texName, sizeof( texName ), "*vgui%i", id ); + Q_memset( &r_image, 0, sizeof( r_image )); + + r_image.width = width; + r_image.height = height; + r_image.type = PF_RGBA_32; + r_image.size = r_image.width * r_image.height * 4; + r_image.flags = IMAGE_HAS_ALPHA; + r_image.buffer = NULL; + + g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE|TF_NEAREST, false ); + GL_SetTextureType( g_textures[id], TEX_VGUI ); + g_iBoundTexture = id; +} + +void GAME_EXPORT VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight ) +{ + if( id <= 0 || id >= VGUI_MAX_TEXTURES || g_textures[id] == 0 || g_textures[id] == cls.fillImage ) + { + MsgDev( D_ERROR, "VGUI_UploadTextureBlock: bad texture %i. Ignored\n", id ); + return; + } + + pglTexSubImage2D( GL_TEXTURE_2D, 0, drawX, drawY, blockWidth, blockHeight, GL_RGBA, GL_UNSIGNED_BYTE, rgba ); + g_iBoundTexture = id; +} + +void GAME_EXPORT VGUI_SetupDrawingRect( int *pColor ) { pglEnable( GL_BLEND ); pglDisable( GL_ALPHA_TEST ); @@ -114,42 +658,62 @@ void VGUI_SetupDrawingRect( int *pColor ) pglColor4ub( pColor[0], pColor[1], pColor[2], 255 - pColor[3] ); } -/* -================ -VGUI_SetupDrawingImage - -setup transparency etc -================ -*/ -void VGUI_SetupDrawingImage( int *pColor ) +void GAME_EXPORT VGUI_SetupDrawingText( int *pColor ) { pglEnable( GL_BLEND ); pglEnable( GL_ALPHA_TEST ); + pglAlphaFunc( GL_GREATER, 0.0f ); pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); pglColor4ub( pColor[0], pColor[1], pColor[2], 255 - pColor[3] ); } -/* -================ -VGUI_BindTexture +void GAME_EXPORT VGUI_SetupDrawingImage( int *pColor ) +{ + pglEnable( GL_BLEND ); + pglEnable( GL_ALPHA_TEST ); + pglAlphaFunc( GL_GREATER, 0.0f ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + pglColor4ub( pColor[0], pColor[1], pColor[2], 255 - pColor[3] ); +} -bind VGUI texture through private index -================ -*/ -void VGUI_BindTexture( int id ) +void GAME_EXPORT VGUI_BindTexture( int id ) { if( id > 0 && id < VGUI_MAX_TEXTURES && g_textures[id] ) { - GL_Bind( GL_TEXTURE0, g_textures[id] ); + GL_Bind( XASH_TEXTURE0, g_textures[id] ); + g_iBoundTexture = id; } else { // NOTE: same as bogus index 2700 in GoldSrc - GL_Bind( GL_TEXTURE0, g_textures[1] ); + id = g_iBoundTexture = 1; + GL_Bind( XASH_TEXTURE0, g_textures[id] ); } } +/* +================ +VGUI_GetTextureSizes + +returns wide and tall for currently binded texture +================ +*/ +void GAME_EXPORT VGUI_GetTextureSizes( int *width, int *height ) +{ + gltexture_t *glt; + int texnum; + + if( g_iBoundTexture ) + texnum = g_textures[g_iBoundTexture]; + else texnum = tr.defaultTexture; + + glt = R_GetTexture( texnum ); + if( width ) *width = glt->srcWidth; + if( height ) *height = glt->srcHeight; +} + /* ================ VGUI_EnableTexture @@ -157,7 +721,7 @@ VGUI_EnableTexture disable texturemode for fill rectangle ================ */ -void VGUI_EnableTexture( qboolean enable ) +void GAME_EXPORT VGUI_EnableTexture( qboolean enable ) { if( enable ) pglEnable( GL_TEXTURE_2D ); else pglDisable( GL_TEXTURE_2D ); @@ -170,49 +734,44 @@ VGUI_DrawQuad generic method to fill rectangle ================ */ -void VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr ) +void GAME_EXPORT VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr ) { + float xscale = scr_width->value / (float)clgame.scrInfo.iWidth; + float yscale = scr_height->value / (float)clgame.scrInfo.iHeight; + + ASSERT( ul != NULL && lr != NULL ); + pglBegin( GL_QUADS ); pglTexCoord2f( ul->coord[0], ul->coord[1] ); - pglVertex2f( ul->point[0], ul->point[1] ); + pglVertex2f( ul->point[0] * xscale, ul->point[1] * yscale ); pglTexCoord2f( lr->coord[0], ul->coord[1] ); - pglVertex2f( lr->point[0], ul->point[1] ); + pglVertex2f( lr->point[0] * xscale, ul->point[1] * yscale ); pglTexCoord2f( lr->coord[0], lr->coord[1] ); - pglVertex2f( lr->point[0], lr->point[1] ); + pglVertex2f( lr->point[0] * xscale, lr->point[1] * yscale ); pglTexCoord2f( ul->coord[0], lr->coord[1] ); - pglVertex2f( ul->point[0], lr->point[1] ); + pglVertex2f( ul->point[0] * xscale, lr->point[1] * yscale ); pglEnd(); } -/* -================ -VGUI_DrawBuffer - -render the quads array -================ -*/ -void VGUI_DrawBuffer( const vpoint_t *buffer, int numVerts ) +void VGui_Paint() { - if( numVerts <= 0 ) return; + if(vgui.initialized) + vgui.Paint(); +} - pglEnable( GL_BLEND ); - pglEnable( GL_ALPHA_TEST ); - pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); +void VGui_RunFrame() +{ + //stub +} - pglEnableClientState( GL_VERTEX_ARRAY ); - pglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - pglEnableClientState( GL_COLOR_ARRAY ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vpoint_t ), &buffer->coord[0] ); - pglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( vpoint_t ), &buffer->color[0] ); - pglVertexPointer( 2, GL_FLOAT, sizeof( vpoint_t ), &buffer->point[0] ); - pglDrawArrays( GL_QUADS, 0, numVerts ); - - pglDisableClientState( GL_VERTEX_ARRAY ); - pglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - pglDisableClientState( GL_COLOR_ARRAY ); -} \ No newline at end of file +void *GAME_EXPORT VGui_GetPanel() +{ + if( vgui.initialized ) + return vgui.GetPanel(); + return NULL; +} +#endif diff --git a/engine/client/vgui/vgui_draw.h b/engine/client/vgui/vgui_draw.h index a4169d0e..3b252b47 100644 --- a/engine/client/vgui/vgui_draw.h +++ b/engine/client/vgui/vgui_draw.h @@ -20,58 +20,22 @@ GNU General Public License for more details. extern "C" { #endif +#include "port.h" + #define VGUI_MAX_TEXTURES 2048 // a half of total textures count -extern rgba_t g_color_table[8]; // for colored strings support -extern convar_t *vgui_colorstrings; - -// VGUI generic vertex -typedef struct -{ - vec2_t point; - vec2_t coord; - byte color[4]; -} vpoint_t; - // -// vgui_backend.c +// vgui_draw.c // - -void VGUI_DrawInit( void ); -void VGUI_DrawShutdown( void ); -void VGUI_SetupDrawingRect( int *pColor ); -void VGUI_SetupDrawingImage( int *pColor ); -void VGUI_BindTexture( int id ); -void VGUI_EnableTexture( qboolean enable ); -void VGUI_UploadTexture( int id, const char *buffer, int width, int height ); -LONG VGUI_SurfaceWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); -void VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr ); -void VGUI_DrawBuffer( const vpoint_t *buffer, int numVerts ); -int VGUI_GenerateTexture( void ); -void *VGui_GetPanel( void ); - -#ifdef __cplusplus -void EnableScissor( qboolean enable ); -void SetScissorRect( int left, int top, int right, int bottom ); -qboolean ClipRect( const vpoint_t &inUL, const vpoint_t &inLR, vpoint_t *pOutUL, vpoint_t *pOutLR ); -#endif - -// -// gl_vidnt.c -// -qboolean R_DescribeVIDMode( int width, int height ); - -// -// vgui_int.c -// -void VGui_Startup( void ); +void VGui_Startup( int width, int height ); void VGui_Shutdown( void ); -void *VGui_GetPanel( void ); -void VGui_Paint( int paintAll ); -void VGui_RunFrame( void ); -void VGui_ViewportPaintBackground( int extents[4] ); - +void VGui_Paint(); +void VGui_RunFrame(); +void VGui_KeyEvent( int key, int down ); +void VGui_MouseMove( int x, int y ); +qboolean VGui_IsActive( void ); +void *VGui_GetPanel(); #ifdef __cplusplus } #endif -#endif//VGUI_DRAW_H \ No newline at end of file +#endif//VGUI_DRAW_H diff --git a/engine/client/vgui/vgui_input.cpp b/engine/client/vgui/vgui_input.cpp deleted file mode 100644 index f6afb6d4..00000000 --- a/engine/client/vgui/vgui_input.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* -vgui_input.cpp - handle kb & mouse -Copyright (C) 2011 Uncle Mike - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -*/ - -#define OEMRESOURCE // for OCR_* cursor junk - -#include "common.h" -#include "client.h" -#include "vgui_draw.h" -#include "vgui_main.h" -#include "input.h" - -static KeyCode s_pVirtualKeyTrans[256]; -static HICON s_pDefaultCursor[20]; -static HICON s_hCurrentCursor = NULL; - -void VGUI_InitCursors( void ) -{ - // load up all default cursors - s_pDefaultCursor[Cursor::dc_none] = NULL; - s_pDefaultCursor[Cursor::dc_arrow] = (HICON)LoadCursor( NULL, (LPCTSTR)OCR_NORMAL ); - s_pDefaultCursor[Cursor::dc_ibeam] = (HICON)LoadCursor( NULL, (LPCTSTR)OCR_IBEAM ); - s_pDefaultCursor[Cursor::dc_hourglass]= (HICON)LoadCursor( NULL, (LPCTSTR)OCR_WAIT ); - s_pDefaultCursor[Cursor::dc_crosshair]= (HICON)LoadCursor( NULL, (LPCTSTR)OCR_CROSS ); - s_pDefaultCursor[Cursor::dc_up] = (HICON)LoadCursor( NULL, (LPCTSTR)OCR_UP ); - s_pDefaultCursor[Cursor::dc_sizenwse] = (HICON)LoadCursor( NULL, (LPCTSTR)OCR_SIZENWSE ); - s_pDefaultCursor[Cursor::dc_sizenesw] = (HICON)LoadCursor( NULL, (LPCTSTR)OCR_SIZENESW ); - s_pDefaultCursor[Cursor::dc_sizewe] = (HICON)LoadCursor( NULL, (LPCTSTR)OCR_SIZEWE ); - s_pDefaultCursor[Cursor::dc_sizens] = (HICON)LoadCursor( NULL, (LPCTSTR)OCR_SIZENS ); - s_pDefaultCursor[Cursor::dc_sizeall] = (HICON)LoadCursor( NULL, (LPCTSTR)OCR_SIZEALL ); - s_pDefaultCursor[Cursor::dc_no] = (HICON)LoadCursor( NULL, (LPCTSTR)OCR_NO ); - s_pDefaultCursor[Cursor::dc_hand] = (HICON)LoadCursor( NULL, (LPCTSTR)32649 ); - - s_hCurrentCursor = s_pDefaultCursor[Cursor::dc_arrow]; - host.mouse_visible = true; -} - -void VGUI_CursorSelect( Cursor *cursor ) -{ - Assert( cursor != NULL ); - - host.mouse_visible = true; - - switch( cursor->getDefaultCursor( )) - { - case Cursor::dc_user: - case Cursor::dc_none: - host.mouse_visible = false; - break; - case Cursor::dc_arrow: - case Cursor::dc_ibeam: - case Cursor::dc_hourglass: - case Cursor::dc_crosshair: - case Cursor::dc_up: - case Cursor::dc_sizenwse: - case Cursor::dc_sizenesw: - case Cursor::dc_sizewe: - case Cursor::dc_sizens: - case Cursor::dc_sizeall: - case Cursor::dc_no: - case Cursor::dc_hand: - s_hCurrentCursor = s_pDefaultCursor[cursor->getDefaultCursor()]; - break; - default: - host.mouse_visible = false; - Assert( 0 ); - break; - } - - VGUI_ActivateCurrentCursor(); -} - -void VGUI_ActivateCurrentCursor( void ) -{ - if( cls.key_dest != key_game || cl.paused ) - return; - - if( host.mouse_visible ) - { - while( ShowCursor( true ) < 0 ); - SetCursor( s_hCurrentCursor ); - } - else - { - while( ShowCursor( false ) >= 0 ); - SetCursor( NULL ); - } -} - -void VGUI_InitKeyTranslationTable( void ) -{ - static bool bInitted = false; - - if( bInitted ) return; - bInitted = true; - - // set virtual key translation table - memset( s_pVirtualKeyTrans, -1, sizeof( s_pVirtualKeyTrans )); - - s_pVirtualKeyTrans['0'] = KEY_0; - s_pVirtualKeyTrans['1'] = KEY_1; - s_pVirtualKeyTrans['2'] = KEY_2; - s_pVirtualKeyTrans['3'] = KEY_3; - s_pVirtualKeyTrans['4'] = KEY_4; - s_pVirtualKeyTrans['5'] = KEY_5; - s_pVirtualKeyTrans['6'] = KEY_6; - s_pVirtualKeyTrans['7'] = KEY_7; - s_pVirtualKeyTrans['8'] = KEY_8; - s_pVirtualKeyTrans['9'] = KEY_9; - s_pVirtualKeyTrans['A'] = s_pVirtualKeyTrans['a'] = KEY_A; - s_pVirtualKeyTrans['B'] = s_pVirtualKeyTrans['b'] = KEY_B; - s_pVirtualKeyTrans['C'] = s_pVirtualKeyTrans['c'] = KEY_C; - s_pVirtualKeyTrans['D'] = s_pVirtualKeyTrans['d'] = KEY_D; - s_pVirtualKeyTrans['E'] = s_pVirtualKeyTrans['e'] = KEY_E; - s_pVirtualKeyTrans['F'] = s_pVirtualKeyTrans['f'] = KEY_F; - s_pVirtualKeyTrans['G'] = s_pVirtualKeyTrans['g'] = KEY_G; - s_pVirtualKeyTrans['H'] = s_pVirtualKeyTrans['h'] = KEY_H; - s_pVirtualKeyTrans['I'] = s_pVirtualKeyTrans['i'] = KEY_I; - s_pVirtualKeyTrans['J'] = s_pVirtualKeyTrans['j'] = KEY_J; - s_pVirtualKeyTrans['K'] = s_pVirtualKeyTrans['k'] = KEY_K; - s_pVirtualKeyTrans['L'] = s_pVirtualKeyTrans['l'] = KEY_L; - s_pVirtualKeyTrans['M'] = s_pVirtualKeyTrans['m'] = KEY_M; - s_pVirtualKeyTrans['N'] = s_pVirtualKeyTrans['n'] = KEY_N; - s_pVirtualKeyTrans['O'] = s_pVirtualKeyTrans['o'] = KEY_O; - s_pVirtualKeyTrans['P'] = s_pVirtualKeyTrans['p'] = KEY_P; - s_pVirtualKeyTrans['Q'] = s_pVirtualKeyTrans['q'] = KEY_Q; - s_pVirtualKeyTrans['R'] = s_pVirtualKeyTrans['r'] = KEY_R; - s_pVirtualKeyTrans['S'] = s_pVirtualKeyTrans['s'] = KEY_S; - s_pVirtualKeyTrans['T'] = s_pVirtualKeyTrans['t'] = KEY_T; - s_pVirtualKeyTrans['U'] = s_pVirtualKeyTrans['u'] = KEY_U; - s_pVirtualKeyTrans['V'] = s_pVirtualKeyTrans['v'] = KEY_V; - s_pVirtualKeyTrans['W'] = s_pVirtualKeyTrans['w'] = KEY_W; - s_pVirtualKeyTrans['X'] = s_pVirtualKeyTrans['x'] = KEY_X; - s_pVirtualKeyTrans['Y'] = s_pVirtualKeyTrans['y'] = KEY_Y; - s_pVirtualKeyTrans['Z'] = s_pVirtualKeyTrans['z'] = KEY_Z; - s_pVirtualKeyTrans[VK_NUMPAD0] = KEY_PAD_0; - s_pVirtualKeyTrans[VK_NUMPAD1] = KEY_PAD_1; - s_pVirtualKeyTrans[VK_NUMPAD2] = KEY_PAD_2; - s_pVirtualKeyTrans[VK_NUMPAD3] = KEY_PAD_3; - s_pVirtualKeyTrans[VK_NUMPAD4] = KEY_PAD_4; - s_pVirtualKeyTrans[VK_NUMPAD5] = KEY_PAD_5; - s_pVirtualKeyTrans[VK_NUMPAD6] = KEY_PAD_6; - s_pVirtualKeyTrans[VK_NUMPAD7] = KEY_PAD_7; - s_pVirtualKeyTrans[VK_NUMPAD8] = KEY_PAD_8; - s_pVirtualKeyTrans[VK_NUMPAD9] = KEY_PAD_9; - s_pVirtualKeyTrans[VK_DIVIDE] = KEY_PAD_DIVIDE; - s_pVirtualKeyTrans[VK_MULTIPLY] = KEY_PAD_MULTIPLY; - s_pVirtualKeyTrans[VK_SUBTRACT] = KEY_PAD_MINUS; - s_pVirtualKeyTrans[VK_ADD] = KEY_PAD_PLUS; - s_pVirtualKeyTrans[VK_RETURN] = KEY_PAD_ENTER; - s_pVirtualKeyTrans[VK_DECIMAL] = KEY_PAD_DECIMAL; - s_pVirtualKeyTrans[0xdb] = KEY_LBRACKET; - s_pVirtualKeyTrans[0xdd] = KEY_RBRACKET; - s_pVirtualKeyTrans[0xba] = KEY_SEMICOLON; - s_pVirtualKeyTrans[0xde] = KEY_APOSTROPHE; - s_pVirtualKeyTrans[0xc0] = KEY_BACKQUOTE; - s_pVirtualKeyTrans[0xbc] = KEY_COMMA; - s_pVirtualKeyTrans[0xbe] = KEY_PERIOD; - s_pVirtualKeyTrans[0xbf] = KEY_SLASH; - s_pVirtualKeyTrans[0xdc] = KEY_BACKSLASH; - s_pVirtualKeyTrans[0xbd] = KEY_MINUS; - s_pVirtualKeyTrans[0xbb] = KEY_EQUAL; - s_pVirtualKeyTrans[VK_RETURN] = KEY_ENTER; - s_pVirtualKeyTrans[VK_SPACE] = KEY_SPACE; - s_pVirtualKeyTrans[VK_BACK] = KEY_BACKSPACE; - s_pVirtualKeyTrans[VK_TAB] = KEY_TAB; - s_pVirtualKeyTrans[VK_CAPITAL] = KEY_CAPSLOCK; - s_pVirtualKeyTrans[VK_NUMLOCK] = KEY_NUMLOCK; - s_pVirtualKeyTrans[VK_ESCAPE] = KEY_ESCAPE; - s_pVirtualKeyTrans[VK_SCROLL] = KEY_SCROLLLOCK; - s_pVirtualKeyTrans[VK_INSERT] = KEY_INSERT; - s_pVirtualKeyTrans[VK_DELETE] = KEY_DELETE; - s_pVirtualKeyTrans[VK_HOME] = KEY_HOME; - s_pVirtualKeyTrans[VK_END] = KEY_END; - s_pVirtualKeyTrans[VK_PRIOR] = KEY_PAGEUP; - s_pVirtualKeyTrans[VK_NEXT] = KEY_PAGEDOWN; - s_pVirtualKeyTrans[VK_PAUSE] = KEY_BREAK; - s_pVirtualKeyTrans[VK_SHIFT] = KEY_RSHIFT; - s_pVirtualKeyTrans[VK_SHIFT] = KEY_LSHIFT; // SHIFT -> left SHIFT - s_pVirtualKeyTrans[VK_MENU] = KEY_RALT; - s_pVirtualKeyTrans[VK_MENU] = KEY_LALT; // ALT -> left ALT - s_pVirtualKeyTrans[VK_CONTROL] = KEY_RCONTROL; - s_pVirtualKeyTrans[VK_CONTROL] = KEY_LCONTROL; // CTRL -> left CTRL - s_pVirtualKeyTrans[VK_LWIN] = KEY_LWIN; - s_pVirtualKeyTrans[VK_RWIN] = KEY_RWIN; - s_pVirtualKeyTrans[VK_APPS] = KEY_APP; - s_pVirtualKeyTrans[VK_UP] = KEY_UP; - s_pVirtualKeyTrans[VK_LEFT] = KEY_LEFT; - s_pVirtualKeyTrans[VK_DOWN] = KEY_DOWN; - s_pVirtualKeyTrans[VK_RIGHT] = KEY_RIGHT; - s_pVirtualKeyTrans[VK_F1] = KEY_F1; - s_pVirtualKeyTrans[VK_F2] = KEY_F2; - s_pVirtualKeyTrans[VK_F3] = KEY_F3; - s_pVirtualKeyTrans[VK_F4] = KEY_F4; - s_pVirtualKeyTrans[VK_F5] = KEY_F5; - s_pVirtualKeyTrans[VK_F6] = KEY_F6; - s_pVirtualKeyTrans[VK_F7] = KEY_F7; - s_pVirtualKeyTrans[VK_F8] = KEY_F8; - s_pVirtualKeyTrans[VK_F9] = KEY_F9; - s_pVirtualKeyTrans[VK_F10] = KEY_F10; - s_pVirtualKeyTrans[VK_F11] = KEY_F11; - s_pVirtualKeyTrans[VK_F12] = KEY_F12; -} - -KeyCode VGUI_MapKey( int keyCode ) -{ - VGUI_InitKeyTranslationTable(); - - if( keyCode < 0 || keyCode >= ARRAYSIZE( s_pVirtualKeyTrans )) - { - Assert( 0 ); - return (KeyCode)-1; - } - else - { - return s_pVirtualKeyTrans[keyCode]; - } -} - -LONG VGUI_SurfaceWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - if( !engSurface ) - return 0; - - switch( uMsg ) - { - case WM_SETCURSOR: - VGUI_ActivateCurrentCursor(); - break; - case WM_MOUSEMOVE: - engApp->internalCursorMoved((short)LOWORD( lParam ), (short)HIWORD( lParam ), engSurface ); - break; - case WM_LBUTTONDOWN: - engApp->internalMousePressed( MOUSE_LEFT, engSurface ); - break; - case WM_RBUTTONDOWN: - engApp->internalMousePressed( MOUSE_RIGHT, engSurface ); - break; - case WM_MBUTTONDOWN: - engApp->internalMousePressed( MOUSE_MIDDLE, engSurface ); - break; - case WM_LBUTTONUP: - engApp->internalMouseReleased( MOUSE_LEFT, engSurface ); - break; - case WM_RBUTTONUP: - engApp->internalMouseReleased( MOUSE_RIGHT, engSurface ); - break; - case WM_MBUTTONUP: - engApp->internalMouseReleased( MOUSE_MIDDLE, engSurface ); - break; - case WM_LBUTTONDBLCLK: - engApp->internalMouseDoublePressed( MOUSE_LEFT, engSurface ); - break; - case WM_RBUTTONDBLCLK: - engApp->internalMouseDoublePressed( MOUSE_RIGHT, engSurface ); - break; - case WM_MBUTTONDBLCLK: - engApp->internalMouseDoublePressed( MOUSE_MIDDLE, engSurface ); - break; - case WM_MOUSEWHEEL: - engApp->internalMouseWheeled(((short)HIWORD( wParam )) / WHEEL_DELTA, engSurface ); - break; - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - if( !FBitSet( lParam, BIT( 30 ))) - engApp->internalKeyPressed( VGUI_MapKey( wParam ), engSurface ); - engApp->internalKeyTyped( VGUI_MapKey( wParam ), engSurface ); - break; - case WM_CHAR: - case WM_SYSCHAR: - // already handled in Key_Event - break; - case WM_KEYUP: - case WM_SYSKEYUP: - engApp->internalKeyReleased( VGUI_MapKey( wParam ), engSurface ); - break; - } - return 1; -} \ No newline at end of file diff --git a/engine/client/vgui/vgui_int.cpp b/engine/client/vgui/vgui_int.cpp deleted file mode 100644 index 7971c441..00000000 --- a/engine/client/vgui/vgui_int.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* -vgui_int.cpp - vgui dll interaction -Copyright (C) 2011 Uncle Mike - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -*/ - -#include "common.h" -#include "client.h" -#include "const.h" -#include "vgui_draw.h" -#include "vgui_main.h" - -Panel *rootPanel = NULL; -CEngineSurface *engSurface = NULL; -CEngineApp staticApp, *engApp; - -void CEngineApp :: setCursorPos( int x, int y ) -{ - POINT pt; - - pt.x = x; - pt.y = y; - - ClientToScreen( (HWND)host.hWnd, &pt ); - - ::SetCursorPos( pt.x, pt.y ); -} - -void CEngineApp :: getCursorPos( int &x,int &y ) -{ - POINT pt; - - // find mouse movement - ::GetCursorPos( &pt ); - ScreenToClient((HWND)host.hWnd, &pt ); - - x = pt.x; - y = pt.y; -} - -void VGui_RunFrame( void ) -{ - if( GetModuleHandle( "fraps32.dll" ) || GetModuleHandle( "fraps64.dll" )) - host.force_draw_version = true; - else host.force_draw_version = false; -} - -void VGui_SetRootPanelSize( void ) -{ - if( rootPanel != NULL ) - rootPanel->setBounds( 0, 0, gameui.globals->scrWidth, gameui.globals->scrHeight ); -} - -void VGui_Startup( void ) -{ - if( engSurface ) return; - - engApp = (CEngineApp *)App::getInstance(); - engApp->reset(); - engApp->setMinimumTickMillisInterval( 0 ); // paint every frame - - rootPanel = new Panel( 0, 0, 320, 240 ); // size will be changed in VGui_SetRootPanelSize - rootPanel->setPaintBorderEnabled( false ); - rootPanel->setPaintBackgroundEnabled( false ); - rootPanel->setPaintEnabled( false ); - rootPanel->setCursor( engApp->getScheme()->getCursor( Scheme::scu_none )); - - engSurface = new CEngineSurface( rootPanel ); - - VGui_SetRootPanelSize (); - VGUI_DrawInit (); -} - -void VGui_Shutdown( void ) -{ - delete rootPanel; - delete engSurface; - engSurface = NULL; - rootPanel = NULL; -} - -void VGui_Paint( int paintAll ) -{ - int extents[4]; - - if( cls.state != ca_active || !rootPanel ) - return; - - VGui_SetRootPanelSize (); - rootPanel->repaint(); - EnableScissor( true ); - - if( cls.key_dest == key_game ) - { - App::getInstance()->externalTick(); - } - - if( paintAll ) - { - // paint everything - rootPanel->paintTraverse(); - } - else - { - rootPanel->getAbsExtents( extents[0], extents[1], extents[2], extents[3] ); - VGui_ViewportPaintBackground( extents ); - } - - EnableScissor( false ); -} - -void VGui_ViewportPaintBackground( int extents[4] ) -{ -// Msg( "Vgui_ViewportPaintBackground( %i, %i, %i, %i )\n", extents[0], extents[1], extents[2], extents[3] ); -} - -void *VGui_GetPanel( void ) -{ - return (void *)rootPanel; -} \ No newline at end of file diff --git a/engine/client/vgui/vgui_main.h b/engine/client/vgui/vgui_main.h deleted file mode 100644 index 9d8145ca..00000000 --- a/engine/client/vgui/vgui_main.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -vgui_main.h - vgui main header -Copyright (C) 2011 Uncle Mike - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -*/ - -#ifndef VGUI_MAIN_H -#define VGUI_MAIN_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace vgui; - -struct PaintStack -{ - Panel *m_pPanel; - int iTranslateX; - int iTranslateY; - int iScissorLeft; - int iScissorRight; - int iScissorTop; - int iScissorBottom; -}; - -class CEngineSurface : public SurfaceBase -{ -private: - void InitVertex( vpoint_t &vertex, int x, int y, float u, float v ); -public: - CEngineSurface( Panel *embeddedPanel ); - ~CEngineSurface(); -public: - // not used in engine instance - virtual bool setFullscreenMode( int wide, int tall, int bpp ) { return false; } - virtual void setWindowedMode( void ) { } - virtual void setTitle( const char *title ) { } - virtual void createPopup( Panel* embeddedPanel ) { } - virtual bool isWithin( int x, int y ) { return true; } - void SetupPaintState( const PaintStack *paintState ); -#ifdef NEW_VGUI_DLL - virtual void GetMousePos( int &x, int &y ) { } -#endif - virtual bool hasFocus( void ) { return true; } -protected: - virtual int createNewTextureID( void ); - virtual void drawSetColor( int r, int g, int b, int a ); - virtual void drawSetTextColor( int r, int g, int b, int a ); - virtual void drawFilledRect( int x0, int y0, int x1, int y1 ); - virtual void drawOutlinedRect( int x0,int y0,int x1,int y1 ); - virtual void drawSetTextFont( Font *font ); - virtual void drawSetTextPos( int x, int y ); - virtual void drawPrintText( const char* text, int textLen ); - virtual void drawSetTextureRGBA( int id, const char* rgba, int wide, int tall ); - virtual void drawSetTexture( int id ); - virtual void drawTexturedRect( int x0, int y0, int x1, int y1 ); - virtual void drawPrintChar( int x, int y, int wide, int tall, float s0, float t0, float s1, float t1, int color[4] ); - virtual void addCharToBuffer( const vpoint_t *ul, const vpoint_t *lr, int color[4] ); - virtual void setCursor( Cursor* cursor ); - virtual void pushMakeCurrent( Panel* panel, bool useInsets ); - virtual void popMakeCurrent( Panel* panel ); - // not used in engine instance - virtual bool createPlat( void ) { return false; } - virtual bool recreateContext( void ) { return false; } - virtual void enableMouseCapture( bool state ) { } - virtual void invalidate( Panel *panel ) { } - virtual void setAsTopMost( bool state ) { } - virtual void applyChanges( void ) { } - virtual void swapBuffers( void ) { } - virtual void flushBuffer( void ); -protected: - int _drawTextPos[2]; - int _drawColor[4]; - int _drawTextColor[4]; - int _translateX, _translateY; - int _currentTexture; -}; - -// initialize VGUI::App as external (part of engine) -class CEngineApp : public App -{ -public: - virtual void main( int argc, char* argv[] ) { } - virtual void setCursorPos( int x, int y ); // we need to recompute abs position to window - virtual void getCursorPos( int &x,int &y ); -protected: - virtual void platTick(void) { } -}; - -extern Panel *rootPanel; -extern CEngineSurface *engSurface; -extern CEngineApp *engApp; - -// -// vgui_input.cpp -// -void VGUI_InitCursors( void ); -void VGUI_CursorSelect( Cursor *cursor ); -void VGUI_ActivateCurrentCursor( void ); - -#endif//VGUI_MAIN_H \ No newline at end of file diff --git a/engine/client/vgui/vgui_surf.cpp b/engine/client/vgui/vgui_surf.cpp deleted file mode 100644 index 9e28a9c8..00000000 --- a/engine/client/vgui/vgui_surf.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/* -vgui_surf.cpp - main vgui layer -Copyright (C) 2011 Uncle Mike - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -*/ - -#include "common.h" -#include "client.h" -#include "vgui_draw.h" -#include "vgui_main.h" - -#define MAXVERTEXBUFFERS 1024 -#define MAX_PAINT_STACK 8 -#define FONT_SIZE 512 -#define FONT_PAGES 8 - -static char staticRGBA[FONT_SIZE * FONT_SIZE * 4]; -static vpoint_t g_VertexBuffer[MAXVERTEXBUFFERS]; -static int g_iVertexBufferEntriesUsed = 0; -static int staticContextCount = 0; - -struct FontInfo -{ - int id; - int pageCount; - int pageForChar[256]; - int bindIndex[FONT_PAGES]; - float texCoord[256][FONT_PAGES]; - int contextCount; -}; - -static Font* staticFont = NULL; -static FontInfo* staticFontInfo; -static Dar staticFontInfoDar; -static PaintStack paintStack[MAX_PAINT_STACK]; -static staticPaintStackPos = 0; - -CEngineSurface :: CEngineSurface( Panel *embeddedPanel ):SurfaceBase( embeddedPanel ) -{ - _drawTextColor[0] = _drawTextColor[1] = _drawTextColor[2] = _drawTextColor[3] = 255; - _drawColor[0] = _drawColor[1] = _drawColor[2] = _drawColor[3] = 255; - _drawTextPos[0] = _drawTextPos[1] = _currentTexture = 0; - - staticFont = NULL; - staticFontInfo = NULL; - staticFontInfoDar.setCount( 0 ); - staticPaintStackPos = 0; - staticContextCount++; - - VGUI_InitCursors (); -} - -CEngineSurface :: ~CEngineSurface( void ) -{ - VGUI_DrawShutdown (); -} - -void CEngineSurface :: setCursor( Cursor *cursor ) -{ - _currentCursor = cursor; - VGUI_CursorSelect( cursor ); -} - -void CEngineSurface :: SetupPaintState( const PaintStack *paintState ) -{ - _translateX = paintState->iTranslateX; - _translateY = paintState->iTranslateY; - SetScissorRect( paintState->iScissorLeft, paintState->iScissorTop, paintState->iScissorRight, paintState->iScissorBottom ); -} - -void CEngineSurface :: InitVertex( vpoint_t &vertex, int x, int y, float u, float v ) -{ - vertex.point[0] = x + _translateX; - vertex.point[1] = y + _translateY; - vertex.coord[0] = u; - vertex.coord[1] = v; -} - -int CEngineSurface :: createNewTextureID( void ) -{ - return VGUI_GenerateTexture(); -} - -void CEngineSurface :: drawSetColor( int r, int g, int b, int a ) -{ - _drawColor[0] = r; - _drawColor[1] = g; - _drawColor[2] = b; - _drawColor[3] = a; -} - -void CEngineSurface :: drawSetTextColor( int r, int g, int b, int a ) -{ - _drawTextColor[0] = r; - _drawTextColor[1] = g; - _drawTextColor[2] = b; - _drawTextColor[3] = a; -} - -void CEngineSurface :: drawFilledRect( int x0, int y0, int x1, int y1 ) -{ - vpoint_t rect[2]; - vpoint_t clippedRect[2]; - - if( _drawColor[3] >= 255 ) return; - - InitVertex( rect[0], x0, y0, 0, 0 ); - InitVertex( rect[1], x1, y1, 0, 0 ); - - // fully clipped? - if( !ClipRect( rect[0], rect[1], &clippedRect[0], &clippedRect[1] )) - return; - - VGUI_SetupDrawingRect( _drawColor ); - VGUI_EnableTexture( false ); - VGUI_DrawQuad( &clippedRect[0], &clippedRect[1] ); - VGUI_EnableTexture( true ); -} - -void CEngineSurface :: drawOutlinedRect( int x0, int y0, int x1, int y1 ) -{ - if( _drawColor[3] >= 255 ) return; - - drawFilledRect( x0, y0, x1, y0 + 1 ); // top - drawFilledRect( x0, y1 - 1, x1, y1 ); // bottom - drawFilledRect( x0, y0 + 1, x0 + 1, y1 - 1 ); // left - drawFilledRect( x1 - 1, y0 + 1, x1, y1 - 1 ); // right -} - -void CEngineSurface :: drawSetTextFont( Font *font ) -{ - staticFont = font; - - if( font ) - { - bool buildFont = false; - - staticFontInfo = NULL; - - for( int i = 0; i < staticFontInfoDar.getCount(); i++ ) - { - if( staticFontInfoDar[i]->id == font->getId( )) - { - staticFontInfo = staticFontInfoDar[i]; - if( staticFontInfo->contextCount != staticContextCount ) - buildFont = true; - } - } - - if( !staticFontInfo || buildFont ) - { - staticFontInfo = new FontInfo; - staticFontInfo->id = 0; - staticFontInfo->pageCount = 0; - staticFontInfo->bindIndex[0] = 0; - staticFontInfo->bindIndex[1] = 0; - staticFontInfo->bindIndex[2] = 0; - staticFontInfo->bindIndex[3] = 0; - memset( staticFontInfo->pageForChar, 0, sizeof( staticFontInfo->pageForChar )); - staticFontInfo->contextCount = -1; - staticFontInfo->id = staticFont->getId(); - staticFontInfoDar.putElement( staticFontInfo ); - staticFontInfo->contextCount = staticContextCount; - - int currentPage = 0; - int x = 0, y = 0; - - memset( staticRGBA, 0, sizeof( staticRGBA )); - - for( int i = 0; i < 256; i++ ) - { - int abcA, abcB, abcC; - staticFont->getCharABCwide( i, abcA, abcB, abcC ); - - int wide = abcB; - - if( isspace( i )) continue; - - int tall = staticFont->getTall(); - - if( x + wide + 1 > FONT_SIZE ) - { - x = 0; - y += tall + 1; - } - - if( y + tall + 1 > FONT_SIZE ) - { - if( !staticFontInfo->bindIndex[currentPage] ) - { - int bindIndex = createNewTextureID(); - staticFontInfo->bindIndex[currentPage] = bindIndex; - } - - drawSetTextureRGBA( staticFontInfo->bindIndex[currentPage], staticRGBA, FONT_SIZE, FONT_SIZE ); - currentPage++; - - if( currentPage == FONT_PAGES ) - break; - - memset( staticRGBA, 0, sizeof( staticRGBA )); - x = y = 0; - } - - staticFont->getCharRGBA( i, x, y, FONT_SIZE, FONT_SIZE, (byte *)staticRGBA ); - staticFontInfo->pageForChar[i] = currentPage; - staticFontInfo->texCoord[i][0] = (float)((double)x / (double)FONT_SIZE ); - staticFontInfo->texCoord[i][1] = (float)((double)y / (double)FONT_SIZE ); - staticFontInfo->texCoord[i][2] = (float)((double)(x + wide)/(double)FONT_SIZE ); - staticFontInfo->texCoord[i][3] = (float)((double)(y + tall)/(double)FONT_SIZE ); - x += wide + 1; - } - - if( currentPage != FONT_PAGES ) - { - if( !staticFontInfo->bindIndex[currentPage] ) - { - int bindIndex = createNewTextureID(); - staticFontInfo->bindIndex[currentPage] = bindIndex; - } - - drawSetTextureRGBA( staticFontInfo->bindIndex[currentPage], staticRGBA, FONT_SIZE, FONT_SIZE ); - } - staticFontInfo->pageCount = currentPage + 1; - } - } -} - -void CEngineSurface :: drawSetTextPos( int x, int y ) -{ - _drawTextPos[0] = x; - _drawTextPos[1] = y; -} - -void CEngineSurface :: addCharToBuffer( const vpoint_t *ul, const vpoint_t *lr, int color[4] ) -{ - if( g_iVertexBufferEntriesUsed >= MAXVERTEXBUFFERS ) - flushBuffer(); - - g_VertexBuffer[g_iVertexBufferEntriesUsed + 0].coord[0] = ul->coord[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 0].coord[1] = ul->coord[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 0].point[0] = ul->point[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 0].point[1] = ul->point[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 0].color[0] = color[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 0].color[1] = color[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 0].color[2] = color[2]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 0].color[3] = 255 - color[3]; - - g_VertexBuffer[g_iVertexBufferEntriesUsed + 1].coord[0] = lr->coord[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 1].coord[1] = ul->coord[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 1].point[0] = lr->point[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 1].point[1] = ul->point[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 1].color[0] = color[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 1].color[1] = color[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 1].color[2] = color[2]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 1].color[3] = 255 - color[3]; - - g_VertexBuffer[g_iVertexBufferEntriesUsed + 2].coord[0] = lr->coord[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 2].coord[1] = lr->coord[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 2].point[0] = lr->point[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 2].point[1] = lr->point[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 2].color[0] = color[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 2].color[1] = color[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 2].color[2] = color[2]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 2].color[3] = 255 - color[3]; - - g_VertexBuffer[g_iVertexBufferEntriesUsed + 3].coord[0] = ul->coord[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 3].coord[1] = lr->coord[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 3].point[0] = ul->point[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 3].point[1] = lr->point[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 3].color[0] = color[0]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 3].color[1] = color[1]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 3].color[2] = color[2]; - g_VertexBuffer[g_iVertexBufferEntriesUsed + 3].color[3] = 255 - color[3]; - - g_iVertexBufferEntriesUsed += 4; -} - -void CEngineSurface :: flushBuffer( void ) -{ - if( g_iVertexBufferEntriesUsed <= 0 ) - return; - - VGUI_DrawBuffer( g_VertexBuffer, g_iVertexBufferEntriesUsed ); - g_iVertexBufferEntriesUsed = 0; -} - -void CEngineSurface :: drawPrintChar( int x, int y, int wide, int tall, float s0, float t0, float s1, float t1, int color[4] ) -{ - vpoint_t ul, lr; - - ul.point[0] = x; - ul.point[1] = y; - lr.point[0] = x + wide; - lr.point[1] = y + tall; - - // gets at the texture coords for this character in its texture page - ul.coord[0] = s0; - ul.coord[1] = t0; - lr.coord[0] = s1; - lr.coord[1] = t1; - - vpoint_t clippedRect[2]; - - if( !ClipRect( ul, lr, &clippedRect[0], &clippedRect[1] )) - return; -#if 1 - // TESTTEST: needs to be more tested - addCharToBuffer( &clippedRect[0], &clippedRect[1], color ); -#else - VGUI_SetupDrawingImage( color ); - VGUI_DrawQuad( &clippedRect[0], &clippedRect[1] ); // draw the letter -#endif -} - -void CEngineSurface :: drawPrintText( const char *text, int textLen ) -{ - static bool hasColor = 0; - static int numColor = 7; - - if( !text || !staticFont || !staticFontInfo ) - return; - - int x = _drawTextPos[0] + _translateX; - int y = _drawTextPos[1] + _translateY; - int tall = staticFont->getTall(); - int curTextColor[4]; - - // HACKHACK: allow color strings in VGUI - if( numColor != 7 && vgui_colorstrings->value ) - { - for( int j = 0; j < 3; j++ ) // grab predefined color - curTextColor[j] = g_color_table[numColor][j]; - } - else - { - for( int j = 0; j < 3; j++ ) // revert default color - curTextColor[j] = _drawTextColor[j]; - } - curTextColor[3] = _drawTextColor[3]; // copy alpha - - if( textLen == 1 && vgui_colorstrings->value ) - { - if( *text == '^' ) - { - hasColor = true; - return; // skip '^' - } - else if( hasColor && isdigit( *text )) - { - numColor = ColorIndex( *text ); - hasColor = false; // handled - return; // skip colornum - } - else hasColor = false; - } - - for( int i = 0; i < textLen; i++ ) - { - int abcA, abcB, abcC; - int curCh = (byte)text[i]; - - staticFont->getCharABCwide( curCh, abcA, abcB, abcC ); - - float s0 = staticFontInfo->texCoord[curCh][0]; - float t0 = staticFontInfo->texCoord[curCh][1]; - float s1 = staticFontInfo->texCoord[curCh][2]; - float t1 = staticFontInfo->texCoord[curCh][3]; - int wide = abcB; - - drawSetTexture( staticFontInfo->bindIndex[staticFontInfo->pageForChar[curCh]] ); - drawPrintChar( x, y, wide, tall, s0, t0, s1, t1, curTextColor ); - x += abcA + abcB + abcC; - } - - _drawTextPos[0] += x; -} - -void CEngineSurface :: drawSetTextureRGBA( int id, const char* rgba, int wide, int tall ) -{ - VGUI_UploadTexture( id, rgba, wide, tall ); - _currentTexture = id; -} - -void CEngineSurface :: drawSetTexture( int id ) -{ - if( _currentTexture != id ) - { - _currentTexture = id; - flushBuffer(); - } - VGUI_BindTexture( id ); -} - -void CEngineSurface :: drawTexturedRect( int x0, int y0, int x1, int y1 ) -{ - vpoint_t rect[2]; - vpoint_t clippedRect[2]; - - InitVertex( rect[0], x0, y0, 0, 0 ); - InitVertex( rect[1], x1, y1, 1, 1 ); - - // fully clipped? - if( !ClipRect( rect[0], rect[1], &clippedRect[0], &clippedRect[1] )) - return; - - VGUI_SetupDrawingImage( _drawColor ); - VGUI_DrawQuad( &clippedRect[0], &clippedRect[1] ); -} - -void CEngineSurface :: pushMakeCurrent( Panel* panel, bool useInsets ) -{ - int insets[4] = { 0, 0, 0, 0 }; - int absExtents[4]; - int clipRect[4]; - - if( useInsets ) - panel->getInset( insets[0], insets[1], insets[2], insets[3] ); - panel->getAbsExtents( absExtents[0], absExtents[1], absExtents[2], absExtents[3] ); - panel->getClipRect( clipRect[0], clipRect[1], clipRect[2], clipRect[3] ); - - PaintStack *paintState = &paintStack[staticPaintStackPos]; - - ASSERT( staticPaintStackPos < MAX_PAINT_STACK ); - - paintState->m_pPanel = panel; - - // determine corrected top left origin - paintState->iTranslateX = insets[0] + absExtents[0]; - paintState->iTranslateY = insets[1] + absExtents[1]; - // setup clipping rectangle for scissoring - paintState->iScissorLeft = clipRect[0]; - paintState->iScissorTop = clipRect[1]; - paintState->iScissorRight = clipRect[2]; - paintState->iScissorBottom = clipRect[3]; - - SetupPaintState( paintState ); - staticPaintStackPos++; -} - -void CEngineSurface :: popMakeCurrent( Panel *panel ) -{ - flushBuffer(); - - int top = staticPaintStackPos - 1; - - // more pops that pushes? - Assert( top >= 0 ); - - // didn't pop in reverse order of push? - Assert( paintStack[top].m_pPanel == panel ); - - staticPaintStackPos--; - - if( top > 0 ) SetupPaintState( &paintStack[top-1] ); -} \ No newline at end of file diff --git a/engine/common/common.h b/engine/common/common.h index 77b92ee8..23a3c717 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -110,6 +110,12 @@ XASH SPECIFIC - sort of hack that works only in Xash3D not in GoldSrc #define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' ) #define ColorIndex( c ) ((( c ) - '0' ) & 7 ) +#if defined __i386__ && defined __GNUC__ +#define GAME_EXPORT __attribute__((force_align_arg_pointer)) +#else +#define GAME_EXPORT +#endif + typedef unsigned long dword; typedef unsigned int uint; typedef char string[MAX_STRING]; diff --git a/engine/common/input.c b/engine/common/input.c index c4a246cd..2618bebf 100644 --- a/engine/common/input.c +++ b/engine/common/input.c @@ -156,7 +156,7 @@ static void IN_ActivateCursor( void ) } } -void IN_SetCursor( HICON hCursor ) +void IN_SetCursor( void *hCursor ) { in_mousecursor = hCursor; @@ -338,6 +338,8 @@ void IN_MouseMove( void ) GetCursorPos( ¤t_pos ); ScreenToClient( host.hWnd, ¤t_pos ); + VGui_MouseMove( current_pos.x, current_pos.y ); + // if the menu is visible, move the menu cursor UI_MouseMove( current_pos.x, current_pos.y ); @@ -435,153 +437,3 @@ void Host_InputFrame( void ) IN_ActivateMouse( false ); IN_MouseMove(); } - -/* -==================== -IN_WndProc - -main window procedure -==================== -*/ -LONG IN_WndProc( HWND hWnd, UINT uMsg, UINT wParam, LONG lParam ) -{ - int i, temp = 0; - qboolean fActivate; - - if( uMsg == in_mouse_wheel ) - uMsg = WM_MOUSEWHEEL; - - VGUI_SurfaceWndProc( hWnd, uMsg, wParam, lParam ); - - switch( uMsg ) - { - case WM_KILLFOCUS: - if( Cvar_VariableInteger( "fullscreen" )) - ShowWindow( host.hWnd, SW_SHOWMINNOACTIVE ); - break; - case WM_SETCURSOR: - IN_ActivateCursor(); - break; - case WM_MOUSEWHEEL: - if( !in_mouseactive ) - break; - if(( short )HIWORD( wParam ) > 0 ) - { - Key_Event( K_MWHEELUP, true ); - Key_Event( K_MWHEELUP, false ); - } - else - { - Key_Event( K_MWHEELDOWN, true ); - Key_Event( K_MWHEELDOWN, false ); - } - break; - case WM_CREATE: - host.hWnd = hWnd; - GetWindowRect( host.hWnd, &real_rect ); - RegisterHotKey( host.hWnd, PRINTSCREEN_ID, 0, VK_SNAPSHOT ); - break; - case WM_CLOSE: - Sys_Quit(); - break; - case WM_ACTIVATE: - if( host.status == HOST_SHUTDOWN ) - break; // no need to activate - if( HIWORD( wParam )) - host.status = HOST_SLEEP; - else if( LOWORD( wParam ) == WA_INACTIVE ) - host.status = HOST_NOFOCUS; - else host.status = HOST_FRAME; - fActivate = (host.status == HOST_FRAME) ? true : false; - wnd_caption = GetSystemMetrics( SM_CYCAPTION ) + WND_BORDER; - - S_Activate( fActivate, host.hWnd ); - IN_ActivateMouse( fActivate ); - Key_ClearStates(); - - if( host.status == HOST_FRAME ) - { - SetForegroundWindow( hWnd ); - ShowWindow( hWnd, SW_RESTORE ); - } - else if( Cvar_VariableInteger( "fullscreen" )) - { - ShowWindow( hWnd, SW_MINIMIZE ); - } - break; - case WM_MOVE: - if( !Cvar_VariableInteger( "fullscreen" )) - { - RECT rect; - int xPos, yPos, style; - - xPos = (short)LOWORD( lParam ); // horizontal position - yPos = (short)HIWORD( lParam ); // vertical position - - rect.left = rect.top = 0; - rect.right = rect.bottom = 1; - style = GetWindowLong( hWnd, GWL_STYLE ); - AdjustWindowRect( &rect, style, FALSE ); - - Cvar_SetValue( "_window_xpos", xPos + rect.left ); - Cvar_SetValue( "_window_ypos", yPos + rect.top ); - GetWindowRect( host.hWnd, &real_rect ); - } - break; - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_XBUTTONDOWN: - case WM_XBUTTONUP: - case WM_MOUSEMOVE: - for( i = 0; i < in_mouse_buttons; i++ ) - { - if( wParam & mouse_buttons[i] ) - temp |= (1<>./Makefile.dep + +include Makefile.dep diff --git a/vgui_support/cl.bat b/vgui_support/cl.bat new file mode 100644 index 00000000..c0f59c0d --- /dev/null +++ b/vgui_support/cl.bat @@ -0,0 +1,5 @@ + set MSVCDir=Z:\path\to\msvc + set INCLUDE=%MSVCDir%\include + set LIB=%MSVCDir%\lib + set PATH=%MSVCDir%\bin;%PATH% +cl.exe %* \ No newline at end of file diff --git a/vgui_support/utlmemory.h b/vgui_support/utlmemory.h new file mode 100644 index 00000000..027a3bd6 --- /dev/null +++ b/vgui_support/utlmemory.h @@ -0,0 +1,368 @@ +//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// $Header: $ +// $NoKeywords: $ +// +// A growable memory class. +//============================================================================= + +#ifndef UTLMEMORY_H +#define UTLMEMORY_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "port.h" +#include +#ifdef NO_STL +template +void *operator new(size_t count, T *ptr) { +return ptr; +} +#elif defined _WIN32 +#include +#else +#include +#endif +#include +#include +//----------------------------------------------------------------------------- +// Methods to invoke the constructor, copy constructor, and destructor +//----------------------------------------------------------------------------- + +template +inline void Construct( T* pMemory ) +{ + new( pMemory ) T; +} + +template +inline void CopyConstruct( T* pMemory, T const& src ) +{ + new( pMemory ) T(src); +} + +template +inline void Destruct( T* pMemory ) +{ + pMemory->~T(); + +#ifdef _DEBUG + memset( pMemory, 0xDD, sizeof(T) ); +#endif +} + +#pragma warning (disable:4100) +#pragma warning (disable:4514) + +//----------------------------------------------------------------------------- +// The CUtlMemory class: +// A growable memory class which doubles in size by default. +//----------------------------------------------------------------------------- +template< class T > +class CUtlMemory +{ +public: + // constructor, destructor + CUtlMemory( int nGrowSize = 0, int nInitSize = 0 ); + CUtlMemory( T* pMemory, int numElements ); + ~CUtlMemory(); + + // element access + T& operator[]( int i ); + T const& operator[]( int i ) const; + T& Element( int i ); + T const& Element( int i ) const; + + // Can we use this index? + bool IsIdxValid( int i ) const; + + // Gets the base address (can change when adding elements!) + T* Base(); + T const* Base() const; + + // Attaches the buffer to external memory.... + void SetExternalBuffer( T* pMemory, int numElements ); + + // Size + int NumAllocated() const; + int Count() const; + + // Grows the memory, so that at least allocated + num elements are allocated + void Grow( int num = 1 ); + + // Makes sure we've got at least this much memory + void EnsureCapacity( int num ); + + // Memory deallocation + void Purge(); + + // is the memory externally allocated? + bool IsExternallyAllocated() const; + + // Set the size by which the memory grows + void SetGrowSize( int size ); + +private: + enum + { + EXTERNAL_BUFFER_MARKER = -1 + }; + + T* m_pMemory; + int m_nAllocationCount; + int m_nGrowSize; +}; + + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- +template< class T > +CUtlMemory::CUtlMemory( int nGrowSize, int nInitAllocationCount ) : m_pMemory(0), + m_nAllocationCount( nInitAllocationCount ), m_nGrowSize( nGrowSize ) +{ + Assert( (nGrowSize >= 0) && (nGrowSize != EXTERNAL_BUFFER_MARKER) ); + if (m_nAllocationCount) + { + m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); + } +} + +template< class T > +CUtlMemory::CUtlMemory( T* pMemory, int numElements ) : m_pMemory(pMemory), + m_nAllocationCount( numElements ) +{ + // Special marker indicating externally supplied memory + m_nGrowSize = EXTERNAL_BUFFER_MARKER; +} + +template< class T > +CUtlMemory::~CUtlMemory() +{ + Purge(); +} + + +//----------------------------------------------------------------------------- +// Attaches the buffer to external memory.... +//----------------------------------------------------------------------------- +template< class T > +void CUtlMemory::SetExternalBuffer( T* pMemory, int numElements ) +{ + // Blow away any existing allocated memory + Purge(); + + m_pMemory = pMemory; + m_nAllocationCount = numElements; + + // Indicate that we don't own the memory + m_nGrowSize = EXTERNAL_BUFFER_MARKER; +} + + +//----------------------------------------------------------------------------- +// element access +//----------------------------------------------------------------------------- +template< class T > +inline T& CUtlMemory::operator[]( int i ) +{ + Assert( IsIdxValid(i) ); + return m_pMemory[i]; +} + +template< class T > +inline T const& CUtlMemory::operator[]( int i ) const +{ + Assert( IsIdxValid(i) ); + return m_pMemory[i]; +} + +template< class T > +inline T& CUtlMemory::Element( int i ) +{ + Assert( IsIdxValid(i) ); + return m_pMemory[i]; +} + +template< class T > +inline T const& CUtlMemory::Element( int i ) const +{ + Assert( IsIdxValid(i) ); + return m_pMemory[i]; +} + + +//----------------------------------------------------------------------------- +// is the memory externally allocated? +//----------------------------------------------------------------------------- +template< class T > +bool CUtlMemory::IsExternallyAllocated() const +{ + return m_nGrowSize == EXTERNAL_BUFFER_MARKER; +} + + +template< class T > +void CUtlMemory::SetGrowSize( int nSize ) +{ + Assert( (nSize >= 0) && (nSize != EXTERNAL_BUFFER_MARKER) ); + m_nGrowSize = nSize; +} + + +//----------------------------------------------------------------------------- +// Gets the base address (can change when adding elements!) +//----------------------------------------------------------------------------- +template< class T > +inline T* CUtlMemory::Base() +{ + return m_pMemory; +} + +template< class T > +inline T const* CUtlMemory::Base() const +{ + return m_pMemory; +} + + +//----------------------------------------------------------------------------- +// Size +//----------------------------------------------------------------------------- +template< class T > +inline int CUtlMemory::NumAllocated() const +{ + return m_nAllocationCount; +} + +template< class T > +inline int CUtlMemory::Count() const +{ + return m_nAllocationCount; +} + + +//----------------------------------------------------------------------------- +// Is element index valid? +//----------------------------------------------------------------------------- +template< class T > +inline bool CUtlMemory::IsIdxValid( int i ) const +{ + return (i >= 0) && (i < m_nAllocationCount); +} + + +//----------------------------------------------------------------------------- +// Grows the memory +//----------------------------------------------------------------------------- +template< class T > +void CUtlMemory::Grow( int num ) +{ + Assert( num > 0 ); + + if (IsExternallyAllocated()) + { + // Can't grow a buffer whose memory was externally allocated + Assert(0); + return; + } + + // Make sure we have at least numallocated + num allocations. + // Use the grow rules specified for this memory (in m_nGrowSize) + int nAllocationRequested = m_nAllocationCount + num; + while (m_nAllocationCount < nAllocationRequested) + { + if ( m_nAllocationCount != 0 ) + { + if (m_nGrowSize) + { + m_nAllocationCount += m_nGrowSize; + } + else + { + m_nAllocationCount += m_nAllocationCount; + } + } + else + { + // Compute an allocation which is at least as big as a cache line... + m_nAllocationCount = (31 + sizeof(T)) / sizeof(T); + Assert(m_nAllocationCount != 0); + } + } + + if (m_pMemory) + { + T* pTempMemory = ( T* )realloc( m_pMemory, m_nAllocationCount * sizeof( T ) ); + + if( !pTempMemory ) + return; + + m_pMemory = pTempMemory; + } + else + { + m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); + } +} + + +//----------------------------------------------------------------------------- +// Makes sure we've got at least this much memory +//----------------------------------------------------------------------------- +template< class T > +inline void CUtlMemory::EnsureCapacity( int num ) +{ + if (m_nAllocationCount >= num) + return; + + if (IsExternallyAllocated()) + { + // Can't grow a buffer whose memory was externally allocated + Assert(0); + return; + } + + m_nAllocationCount = num; + if (m_pMemory) + { + T* pTempMemory = ( T* )realloc( m_pMemory, m_nAllocationCount * sizeof( T ) ); + + if( !pTempMemory ) + return; + + m_pMemory = pTempMemory; + } + else + { + m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); + } +} + + +//----------------------------------------------------------------------------- +// Memory deallocation +//----------------------------------------------------------------------------- +template< class T > +void CUtlMemory::Purge() +{ + if (!IsExternallyAllocated()) + { + if (m_pMemory) + { + free( (void*)m_pMemory ); + m_pMemory = 0; + } + m_nAllocationCount = 0; + } +} + + +#endif//UTLMEMORY_H diff --git a/vgui_support/utlrbtree.h b/vgui_support/utlrbtree.h new file mode 100644 index 00000000..a0cfd8a7 --- /dev/null +++ b/vgui_support/utlrbtree.h @@ -0,0 +1,1289 @@ +//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//============================================================================= + +#ifndef UTLRBTREE_H +#define UTLRBTREE_H + +#include "port.h" +#include "utlmemory.h" +//----------------------------------------------------------------------------- +// Tool to generate a default compare function for any type that implements +// operator<, including all simple types +//----------------------------------------------------------------------------- + +template +class CDefOps +{ +public: + static bool LessFunc( const T &lhs, const T &rhs ) { return ( lhs < rhs ); } +}; + +#define DefLessFunc( type ) CDefOps::LessFunc + +//------------------------------------- + +inline bool StringLessThan( const char * const &lhs, const char * const &rhs) { return ( strcmp( lhs, rhs) < 0 ); } +inline bool CaselessStringLessThan( const char * const &lhs, const char * const &rhs ) { return ( strcasecmp( lhs, rhs) < 0 ); } + +//------------------------------------- +// inline these two templates to stop multiple definitions of the same code +template <> inline bool CDefOps::LessFunc( const char * const &lhs, const char * const &rhs ) { return StringLessThan( lhs, rhs ); } +template <> inline bool CDefOps::LessFunc( char * const &lhs, char * const &rhs ) { return StringLessThan( lhs, rhs ); } + +//------------------------------------- + +template +void SetDefLessFunc( RBTREE_T &RBTree ) +{ +#ifdef _WIN32 + RBTree.SetLessFunc( DefLessFunc( RBTREE_T::KeyType_t ) ); +#elif _LINUX + RBTree.SetLessFunc( DefLessFunc( typename RBTREE_T::KeyType_t ) ); +#endif +} + +//----------------------------------------------------------------------------- +// A red-black binary search tree +//----------------------------------------------------------------------------- + +template +class CUtlRBTree +{ +public: + // Less func typedef + // Returns true if the first parameter is "less" than the second + typedef bool (*LessFunc_t)( T const &, T const & ); + + typedef T KeyType_t; + typedef T ElemType_t; + typedef I IndexType_t; + + // constructor, destructor + // Left at growSize = 0, the memory will first allocate 1 element and double in size + // at each increment. + // LessFunc_t is required, but may be set after the constructor using SetLessFunc() below + CUtlRBTree( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 ); + ~CUtlRBTree( ); + + // gets particular elements + T& Element( I i ); + T const &Element( I i ) const; + T& operator[]( I i ); + T const &operator[]( I i ) const; + + // Gets the root + I Root() const; + + // Num elements + unsigned int Count() const; + + // Max "size" of the vector + I MaxElement() const; + + // Gets the children + I Parent( I i ) const; + I LeftChild( I i ) const; + I RightChild( I i ) const; + + // Tests if a node is a left or right child + bool IsLeftChild( I i ) const; + bool IsRightChild( I i ) const; + + // Tests if root or leaf + bool IsRoot( I i ) const; + bool IsLeaf( I i ) const; + + // Checks if a node is valid and in the tree + bool IsValidIndex( I i ) const; + + // Checks if the tree as a whole is valid + bool IsValid() const; + + // Invalid index + static I InvalidIndex(); + + // returns the tree depth (not a very fast operation) + int Depth( I node ) const; + int Depth() const; + + // Sets the less func + void SetLessFunc( LessFunc_t func ); + + // Allocation method + I NewNode(); + + // Insert method (inserts in order) + I Insert( T const &insert ); + void Insert( const T *pArray, int nItems ); + + // Find method + I Find( T const &search ) const; + + // Remove methods + void RemoveAt( I i ); + bool Remove( T const &remove ); + void RemoveAll( ); + + // Allocation, deletion + void FreeNode( I i ); + + // Iteration + I FirstInorder() const; + I NextInorder( I i ) const; + I PrevInorder( I i ) const; + I LastInorder() const; + + I FirstPreorder() const; + I NextPreorder( I i ) const; + I PrevPreorder( I i ) const; + I LastPreorder( ) const; + + I FirstPostorder() const; + I NextPostorder( I i ) const; + + // If you change the search key, this can be used to reinsert the + // element into the tree. + void Reinsert( I elem ); + +protected: + enum NodeColor_t + { + RED = 0, + BLACK + }; + + struct Links_t + { + I m_Left; + I m_Right; + I m_Parent; + I m_Tag; + }; + + struct Node_t : public Links_t + { + T m_Data; + }; + + // Sets the children + void SetParent( I i, I parent ); + void SetLeftChild( I i, I child ); + void SetRightChild( I i, I child ); + void LinkToParent( I i, I parent, bool isLeft ); + + // Gets at the links + Links_t const &Links( I i ) const; + Links_t &Links( I i ); + + // Checks if a link is red or black + bool IsRed( I i ) const; + bool IsBlack( I i ) const; + + // Sets/gets node color + NodeColor_t Color( I i ) const; + void SetColor( I i, NodeColor_t c ); + + // operations required to preserve tree balance + void RotateLeft(I i); + void RotateRight(I i); + void InsertRebalance(I i); + void RemoveRebalance(I i); + + // Insertion, removal + I InsertAt( I parent, bool leftchild ); + + // copy constructors not allowed + CUtlRBTree( CUtlRBTree const &tree ); + + // Inserts a node into the tree, doesn't copy the data in. + void FindInsertionPosition( T const &insert, I &parent, bool &leftchild ); + + // Remove and add back an element in the tree. + void Unlink( I elem ); + void Link( I elem ); + + // Used for sorting. + LessFunc_t m_LessFunc; + + CUtlMemory m_Elements; + I m_Root; + I m_NumElements; + I m_FirstFree; + I m_TotalElements; + + Node_t* m_pElements; + + void ResetDbgInfo() + { + m_pElements = (Node_t*)m_Elements.Base(); + } +}; + + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- + +template +CUtlRBTree::CUtlRBTree( int growSize, int initSize, LessFunc_t lessfunc ) : + m_Elements( growSize, initSize ), + m_LessFunc( lessfunc ), + m_Root( InvalidIndex() ), + m_NumElements( 0 ), m_TotalElements( 0 ), + m_FirstFree( InvalidIndex() ) +{ + ResetDbgInfo(); +} + +template +CUtlRBTree::~CUtlRBTree() +{ +} + +//----------------------------------------------------------------------------- +// gets particular elements +//----------------------------------------------------------------------------- + +template +inline T &CUtlRBTree::Element( I i ) +{ + return m_Elements[i].m_Data; +} + +template +inline T const &CUtlRBTree::Element( I i ) const +{ + return m_Elements[i].m_Data; +} + +template +inline T &CUtlRBTree::operator[]( I i ) +{ + return Element(i); +} + +template +inline T const &CUtlRBTree::operator[]( I i ) const +{ + return Element(i); +} + +//----------------------------------------------------------------------------- +// +// various accessors +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Gets the root +//----------------------------------------------------------------------------- + +template +inline I CUtlRBTree::Root() const +{ + return m_Root; +} + +//----------------------------------------------------------------------------- +// Num elements +//----------------------------------------------------------------------------- + +template +inline unsigned int CUtlRBTree::Count() const +{ + return (unsigned int)m_NumElements; +} + +//----------------------------------------------------------------------------- +// Max "size" of the vector +//----------------------------------------------------------------------------- + +template +inline I CUtlRBTree::MaxElement() const +{ + return (I)m_TotalElements; +} + + +//----------------------------------------------------------------------------- +// Gets the children +//----------------------------------------------------------------------------- + +template +inline I CUtlRBTree::Parent( I i ) const +{ + return Links(i).m_Parent; +} + +template +inline I CUtlRBTree::LeftChild( I i ) const +{ + return Links(i).m_Left; +} + +template +inline I CUtlRBTree::RightChild( I i ) const +{ + return Links(i).m_Right; +} + +//----------------------------------------------------------------------------- +// Tests if a node is a left or right child +//----------------------------------------------------------------------------- + +template +inline bool CUtlRBTree::IsLeftChild( I i ) const +{ + return LeftChild(Parent(i)) == i; +} + +template +inline bool CUtlRBTree::IsRightChild( I i ) const +{ + return RightChild(Parent(i)) == i; +} + + +//----------------------------------------------------------------------------- +// Tests if root or leaf +//----------------------------------------------------------------------------- + +template +inline bool CUtlRBTree::IsRoot( I i ) const +{ + return i == m_Root; +} + +template +inline bool CUtlRBTree::IsLeaf( I i ) const +{ + return (LeftChild(i) == InvalidIndex()) && (RightChild(i) == InvalidIndex()); +} + + +//----------------------------------------------------------------------------- +// Checks if a node is valid and in the tree +//----------------------------------------------------------------------------- + +template +inline bool CUtlRBTree::IsValidIndex( I i ) const +{ + return LeftChild(i) != i; +} + + +//----------------------------------------------------------------------------- +// Invalid index +//----------------------------------------------------------------------------- + +template +I CUtlRBTree::InvalidIndex() +{ + return (I)~0; +} + + +//----------------------------------------------------------------------------- +// returns the tree depth (not a very fast operation) +//----------------------------------------------------------------------------- + +template +inline int CUtlRBTree::Depth() const +{ + return Depth(Root()); +} + +//----------------------------------------------------------------------------- +// Sets the children +//----------------------------------------------------------------------------- + +template +inline void CUtlRBTree::SetParent( I i, I parent ) +{ + Links(i).m_Parent = parent; +} + +template +inline void CUtlRBTree::SetLeftChild( I i, I child ) +{ + Links(i).m_Left = child; +} + +template +inline void CUtlRBTree::SetRightChild( I i, I child ) +{ + Links(i).m_Right = child; +} + +//----------------------------------------------------------------------------- +// Gets at the links +//----------------------------------------------------------------------------- +static const int s_Sentinel[4] = {-1, -1, -1, 1}; +template +inline typename CUtlRBTree::Links_t const &CUtlRBTree::Links( I i ) const +{ + // Sentinel node, makes life easier + + return (i != InvalidIndex()) ? *(Links_t*)&m_Elements[i] : + *(Links_t*)&s_Sentinel; +} + +template +inline typename CUtlRBTree::Links_t &CUtlRBTree::Links( I i ) +{ + Assert(i != InvalidIndex()); + return *(Links_t *)&m_Elements[i]; +} + +//----------------------------------------------------------------------------- +// Checks if a link is red or black +//----------------------------------------------------------------------------- + +template +inline bool CUtlRBTree::IsRed( I i ) const +{ + return (Links(i).m_Tag == RED); +} + +template +inline bool CUtlRBTree::IsBlack( I i ) const +{ + return (Links(i).m_Tag == BLACK); +} + + +//----------------------------------------------------------------------------- +// Sets/gets node color +//----------------------------------------------------------------------------- + +template +inline typename CUtlRBTree::NodeColor_t CUtlRBTree::Color( I i ) const +{ + return (NodeColor_t)Links(i).m_Tag; +} + +template +inline void CUtlRBTree::SetColor( I i, typename CUtlRBTree::NodeColor_t c ) +{ + Links(i).m_Tag = (I)c; +} + +//----------------------------------------------------------------------------- +// Allocates/ deallocates nodes +//----------------------------------------------------------------------------- + +template +I CUtlRBTree::NewNode() +{ + I newElem; + + // Nothing in the free list; add. + if (m_FirstFree == InvalidIndex()) + { + if (m_Elements.NumAllocated() == m_TotalElements) + m_Elements.Grow(); + newElem = m_TotalElements++; + } + else + { + newElem = m_FirstFree; + m_FirstFree = RightChild(m_FirstFree); + } + +#ifdef _DEBUG + // reset links to invalid.... + Links_t &node = Links(newElem); + node.m_Left = node.m_Right = node.m_Parent = InvalidIndex(); +#endif + + Construct( &Element(newElem) ); + ResetDbgInfo(); + + return newElem; +} + +template +void CUtlRBTree::FreeNode( I i ) +{ + Assert( IsValidIndex(i) && (i != InvalidIndex()) ); + Destruct( &Element(i) ); + SetLeftChild( i, i ); // indicates it's in not in the tree + SetRightChild( i, m_FirstFree ); + m_FirstFree = i; +} + + +//----------------------------------------------------------------------------- +// Rotates node i to the left +//----------------------------------------------------------------------------- + +template +void CUtlRBTree::RotateLeft(I elem) +{ + I rightchild = RightChild(elem); + SetRightChild( elem, LeftChild(rightchild) ); + if (LeftChild(rightchild) != InvalidIndex()) + SetParent( LeftChild(rightchild), elem ); + + if (rightchild != InvalidIndex()) + SetParent( rightchild, Parent(elem) ); + if (!IsRoot(elem)) + { + if (IsLeftChild(elem)) + SetLeftChild( Parent(elem), rightchild ); + else + SetRightChild( Parent(elem), rightchild ); + } + else + m_Root = rightchild; + + SetLeftChild( rightchild, elem ); + if (elem != InvalidIndex()) + SetParent( elem, rightchild ); +} + + +//----------------------------------------------------------------------------- +// Rotates node i to the right +//----------------------------------------------------------------------------- + +template +void CUtlRBTree::RotateRight(I elem) +{ + I leftchild = LeftChild(elem); + SetLeftChild( elem, RightChild(leftchild) ); + if (RightChild(leftchild) != InvalidIndex()) + SetParent( RightChild(leftchild), elem ); + + if (leftchild != InvalidIndex()) + SetParent( leftchild, Parent(elem) ); + if (!IsRoot(elem)) + { + if (IsRightChild(elem)) + SetRightChild( Parent(elem), leftchild ); + else + SetLeftChild( Parent(elem), leftchild ); + } + else + m_Root = leftchild; + + SetRightChild( leftchild, elem ); + if (elem != InvalidIndex()) + SetParent( elem, leftchild ); +} + + +//----------------------------------------------------------------------------- +// Rebalances the tree after an insertion +//----------------------------------------------------------------------------- + +template +void CUtlRBTree::InsertRebalance(I elem) +{ + while ( !IsRoot(elem) && (Color(Parent(elem)) == RED) ) + { + I parent = Parent(elem); + I grandparent = Parent(parent); + + /* we have a violation */ + if (IsLeftChild(parent)) + { + I uncle = RightChild(grandparent); + if (IsRed(uncle)) + { + /* uncle is RED */ + SetColor(parent, BLACK); + SetColor(uncle, BLACK); + SetColor(grandparent, RED); + elem = grandparent; + } + else + { + /* uncle is BLACK */ + if (IsRightChild(elem)) + { + /* make x a left child, will change parent and grandparent */ + elem = parent; + RotateLeft(elem); + parent = Parent(elem); + grandparent = Parent(parent); + } + /* recolor and rotate */ + SetColor(parent, BLACK); + SetColor(grandparent, RED); + RotateRight(grandparent); + } + } + else + { + /* mirror image of above code */ + I uncle = LeftChild(grandparent); + if (IsRed(uncle)) + { + /* uncle is RED */ + SetColor(parent, BLACK); + SetColor(uncle, BLACK); + SetColor(grandparent, RED); + elem = grandparent; + } + else + { + /* uncle is BLACK */ + if (IsLeftChild(elem)) + { + /* make x a right child, will change parent and grandparent */ + elem = parent; + RotateRight(parent); + parent = Parent(elem); + grandparent = Parent(parent); + } + /* recolor and rotate */ + SetColor(parent, BLACK); + SetColor(grandparent, RED); + RotateLeft(grandparent); + } + } + } + SetColor( m_Root, BLACK ); +} + + +//----------------------------------------------------------------------------- +// Insert a node into the tree +//----------------------------------------------------------------------------- + +template +I CUtlRBTree::InsertAt( I parent, bool leftchild ) +{ + I i = NewNode(); + LinkToParent( i, parent, leftchild ); + ++m_NumElements; + return i; +} + +template +void CUtlRBTree::LinkToParent( I i, I parent, bool isLeft ) +{ + Links_t &elem = Links(i); + elem.m_Parent = parent; + elem.m_Left = elem.m_Right = InvalidIndex(); + elem.m_Tag = RED; + + /* insert node in tree */ + if (parent != InvalidIndex()) + { + if (isLeft) + Links(parent).m_Left = i; + else + Links(parent).m_Right = i; + } + else + { + m_Root = i; + } + + InsertRebalance(i); + + Assert(IsValid()); +} + +//----------------------------------------------------------------------------- +// Rebalance the tree after a deletion +//----------------------------------------------------------------------------- + +template +void CUtlRBTree::RemoveRebalance(I elem) +{ + while (elem != m_Root && IsBlack(elem)) + { + I parent = Parent(elem); + + // If elem is the left child of the parent + if (elem == LeftChild(parent)) + { + // Get our sibling + I sibling = RightChild(parent); + if (IsRed(sibling)) + { + SetColor(sibling, BLACK); + SetColor(parent, RED); + RotateLeft(parent); + + // We may have a new parent now + parent = Parent(elem); + sibling = RightChild(parent); + } + if ( (IsBlack(LeftChild(sibling))) && (IsBlack(RightChild(sibling))) ) + { + if (sibling != InvalidIndex()) + SetColor(sibling, RED); + elem = parent; + } + else + { + if (IsBlack(RightChild(sibling))) + { + SetColor(LeftChild(sibling), BLACK); + SetColor(sibling, RED); + RotateRight(sibling); + + // rotation may have changed this + parent = Parent(elem); + sibling = RightChild(parent); + } + SetColor( sibling, Color(parent) ); + SetColor( parent, BLACK ); + SetColor( RightChild(sibling), BLACK ); + RotateLeft( parent ); + elem = m_Root; + } + } + else + { + // Elem is the right child of the parent + I sibling = LeftChild(parent); + if (IsRed(sibling)) + { + SetColor(sibling, BLACK); + SetColor(parent, RED); + RotateRight(parent); + + // We may have a new parent now + parent = Parent(elem); + sibling = LeftChild(parent); + } + if ( (IsBlack(RightChild(sibling))) && (IsBlack(LeftChild(sibling))) ) + { + if (sibling != InvalidIndex()) + SetColor( sibling, RED ); + elem = parent; + } + else + { + if (IsBlack(LeftChild(sibling))) + { + SetColor( RightChild(sibling), BLACK ); + SetColor( sibling, RED ); + RotateLeft( sibling ); + + // rotation may have changed this + parent = Parent(elem); + sibling = LeftChild(parent); + } + SetColor( sibling, Color(parent) ); + SetColor( parent, BLACK ); + SetColor( LeftChild(sibling), BLACK ); + RotateRight( parent ); + elem = m_Root; + } + } + } + SetColor( elem, BLACK ); +} + +template +void CUtlRBTree::Unlink( I elem ) +{ + if ( elem != InvalidIndex() ) + { + I x, y; + + if ((LeftChild(elem) == InvalidIndex()) || + (RightChild(elem) == InvalidIndex())) + { + /* y has a NIL node as a child */ + y = elem; + } + else + { + /* find tree successor with a NIL node as a child */ + y = RightChild(elem); + while (LeftChild(y) != InvalidIndex()) + y = LeftChild(y); + } + + /* x is y's only child */ + if (LeftChild(y) != InvalidIndex()) + x = LeftChild(y); + else + x = RightChild(y); + + /* remove y from the parent chain */ + if (x != InvalidIndex()) + SetParent( x, Parent(y) ); + if (!IsRoot(y)) + { + if (IsLeftChild(y)) + SetLeftChild( Parent(y), x ); + else + SetRightChild( Parent(y), x ); + } + else + m_Root = x; + + // need to store this off now, we'll be resetting y's color + NodeColor_t ycolor = Color(y); + if (y != elem) + { + // Standard implementations copy the data around, we cannot here. + // Hook in y to link to the same stuff elem used to. + SetParent( y, Parent(elem) ); + SetRightChild( y, RightChild(elem) ); + SetLeftChild( y, LeftChild(elem) ); + + if (!IsRoot(elem)) + if (IsLeftChild(elem)) + SetLeftChild( Parent(elem), y ); + else + SetRightChild( Parent(elem), y ); + else + m_Root = y; + + if (LeftChild(y) != InvalidIndex()) + SetParent( LeftChild(y), y ); + if (RightChild(y) != InvalidIndex()) + SetParent( RightChild(y), y ); + + SetColor( y, Color(elem) ); + } + + if ((x != InvalidIndex()) && (ycolor == BLACK)) + RemoveRebalance(x); + } +} + +template +void CUtlRBTree::Link( I elem ) +{ + if ( elem != InvalidIndex() ) + { + I parent; + bool leftchild; + + FindInsertionPosition( Element( elem ), parent, leftchild ); + + LinkToParent( elem, parent, leftchild ); + } +} + +//----------------------------------------------------------------------------- +// Delete a node from the tree +//----------------------------------------------------------------------------- + +template +void CUtlRBTree::RemoveAt(I elem) +{ + if ( elem != InvalidIndex() ) + { + Unlink( elem ); + + FreeNode(elem); + --m_NumElements; + } +} + + +//----------------------------------------------------------------------------- +// remove a node in the tree +//----------------------------------------------------------------------------- + +template bool CUtlRBTree::Remove( T const &search ) +{ + I node = Find( search ); + if (node != InvalidIndex()) + { + RemoveAt(node); + return true; + } + return false; +} + + +//----------------------------------------------------------------------------- +// Removes all nodes from the tree +//----------------------------------------------------------------------------- + +template +void CUtlRBTree::RemoveAll() +{ + // Just iterate through the whole list and add to free list + // much faster than doing all of the rebalancing + // also, do it so the free list is pointing to stuff in order + // to get better cache coherence when re-adding stuff to this tree. + I prev = InvalidIndex(); + for (int i = (int)m_TotalElements; --i >= 0; ) + { + I idx = (I)i; + if (IsValidIndex(idx)) + Destruct( &Element(idx) ); + SetRightChild( idx, prev ); + SetLeftChild( idx, idx ); + prev = idx; + } + m_FirstFree = m_TotalElements ? (I)0 : InvalidIndex(); + m_Root = InvalidIndex(); + m_NumElements = 0; +} + + +//----------------------------------------------------------------------------- +// iteration +//----------------------------------------------------------------------------- + +template +I CUtlRBTree::FirstInorder() const +{ + I i = m_Root; + while (LeftChild(i) != InvalidIndex()) + i = LeftChild(i); + return i; +} + +template +I CUtlRBTree::NextInorder( I i ) const +{ + Assert(IsValidIndex(i)); + + if (RightChild(i) != InvalidIndex()) + { + i = RightChild(i); + while (LeftChild(i) != InvalidIndex()) + i = LeftChild(i); + return i; + } + + I parent = Parent(i); + while (IsRightChild(i)) + { + i = parent; + if (i == InvalidIndex()) break; + parent = Parent(i); + } + return parent; +} + +template +I CUtlRBTree::PrevInorder( I i ) const +{ + Assert(IsValidIndex(i)); + + if (LeftChild(i) != InvalidIndex()) + { + i = LeftChild(i); + while (RightChild(i) != InvalidIndex()) + i = RightChild(i); + return i; + } + + I parent = Parent(i); + while (IsLeftChild(i)) + { + i = parent; + if (i == InvalidIndex()) break; + parent = Parent(i); + } + return parent; +} + +template +I CUtlRBTree::LastInorder() const +{ + I i = m_Root; + while (RightChild(i) != InvalidIndex()) + i = RightChild(i); + return i; +} + +template +I CUtlRBTree::FirstPreorder() const +{ + return m_Root; +} + +template +I CUtlRBTree::NextPreorder( I i ) const +{ + if (LeftChild(i) != InvalidIndex()) + return LeftChild(i); + + if (RightChild(i) != InvalidIndex()) + return RightChild(i); + + I parent = Parent(i); + while( parent != InvalidIndex()) + { + if (IsLeftChild(i) && (RightChild(parent) != InvalidIndex())) + return RightChild(parent); + i = parent; + parent = Parent(parent); + } + return InvalidIndex(); +} + +template +I CUtlRBTree::PrevPreorder( I i ) const +{ + Assert(0); // not implemented yet + return InvalidIndex(); +} + +template +I CUtlRBTree::LastPreorder() const +{ + I i = m_Root; + while (1) + { + while (RightChild(i) != InvalidIndex()) + i = RightChild(i); + + if (LeftChild(i) != InvalidIndex()) + i = LeftChild(i); + else + break; + } + return i; +} + +template +I CUtlRBTree::FirstPostorder() const +{ + I i = m_Root; + while (!IsLeaf(i)) + { + if (LeftChild(i)) + i = LeftChild(i); + else + i = RightChild(i); + } + return i; +} + +template +I CUtlRBTree::NextPostorder( I i ) const +{ + I parent = Parent(i); + if (parent == InvalidIndex()) + return InvalidIndex(); + + if (IsRightChild(i)) + return parent; + + if (RightChild(parent) == InvalidIndex()) + return parent; + + i = RightChild(parent); + while (!IsLeaf(i)) + { + if (LeftChild(i)) + i = LeftChild(i); + else + i = RightChild(i); + } + return i; +} + + +template +void CUtlRBTree::Reinsert( I elem ) +{ + Unlink( elem ); + Link( elem ); +} + + +//----------------------------------------------------------------------------- +// returns the tree depth (not a very fast operation) +//----------------------------------------------------------------------------- +#ifdef max +#undef max +#endif +#define max(a,b) (a)>(b)?(a):(b) + +template +int CUtlRBTree::Depth( I node ) const +{ + if (node == InvalidIndex()) + return 0; + + int depthright = Depth( RightChild(node) ); + int depthleft = Depth( LeftChild(node) ); + return max(depthright, depthleft) + 1; +} + + +//----------------------------------------------------------------------------- +// Makes sure the tree is valid after every operation +//----------------------------------------------------------------------------- + +template +bool CUtlRBTree::IsValid() const +{ + if ( !Count() ) + return true; + + if (( Root() >= MaxElement()) || ( Parent( Root() ) != InvalidIndex() )) + goto InvalidTree; + +#ifdef UTLTREE_PARANOID + + // First check to see that mNumEntries matches reality. + // count items on the free list + int numFree = 0; + int curr = m_FirstFree; + while (curr != InvalidIndex()) + { + ++numFree; + curr = RightChild(curr); + if ( (curr > MaxElement()) && (curr != InvalidIndex()) ) + goto InvalidTree; + } + if (MaxElement() - numFree != Count()) + goto InvalidTree; + + // iterate over all elements, looking for validity + // based on the self pointers + int numFree2 = 0; + for (curr = 0; curr < MaxElement(); ++curr) + { + if (!IsValidIndex(curr)) + ++numFree2; + else + { + int right = RightChild(curr); + int left = LeftChild(curr); + if ((right == left) && (right != InvalidIndex()) ) + goto InvalidTree; + + if (right != InvalidIndex()) + { + if (!IsValidIndex(right)) + goto InvalidTree; + if (Parent(right) != curr) + goto InvalidTree; + if (IsRed(curr) && IsRed(right)) + goto InvalidTree; + } + + if (left != InvalidIndex()) + { + if (!IsValidIndex(left)) + goto InvalidTree; + if (Parent(left) != curr) + goto InvalidTree; + if (IsRed(curr) && IsRed(left)) + goto InvalidTree; + } + } + } + if (numFree2 != numFree) + goto InvalidTree; + +#endif // UTLTREE_PARANOID + + return true; + +InvalidTree: + return false; +} + + +//----------------------------------------------------------------------------- +// Sets the less func +//----------------------------------------------------------------------------- + +template +void CUtlRBTree::SetLessFunc( typename CUtlRBTree::LessFunc_t func ) +{ + if (!m_LessFunc) + m_LessFunc = func; + else + { + // need to re-sort the tree here.... + Assert(0); + } +} + + +//----------------------------------------------------------------------------- +// inserts a node into the tree +//----------------------------------------------------------------------------- + +// Inserts a node into the tree, doesn't copy the data in. +template +void CUtlRBTree::FindInsertionPosition( T const &insert, I &parent, bool &leftchild ) +{ + Assert( m_LessFunc != NULL ); + + /* find where node belongs */ + I current = m_Root; + parent = InvalidIndex(); + leftchild = false; + while (current != InvalidIndex()) + { + parent = current; + if (m_LessFunc( insert, Element(current) )) + { + leftchild = true; current = LeftChild(current); + } + else + { + leftchild = false; current = RightChild(current); + } + } +} + +template +I CUtlRBTree::Insert( T const &insert ) +{ + // use copy constructor to copy it in + I parent; + bool leftchild; + FindInsertionPosition( insert, parent, leftchild ); + I newNode = InsertAt( parent, leftchild ); + CopyConstruct( &Element( newNode ), insert ); + return newNode; +} + + +template +void CUtlRBTree::Insert( const T *pArray, int nItems ) +{ + while ( nItems-- ) + { + Insert( *pArray++ ); + } +} + +//----------------------------------------------------------------------------- +// finds a node in the tree +//----------------------------------------------------------------------------- + +template +I CUtlRBTree::Find( T const &search ) const +{ + Assert( m_LessFunc != NULL ); + + I current = m_Root; + while (current != InvalidIndex()) + { + if (m_LessFunc( search, Element(current) )) + current = LeftChild(current); + else if (m_LessFunc( Element(current), search )) + current = RightChild(current); + else + break; + } + return current; +} + +#endif//UTLRBTREE_H diff --git a/vgui_support/utlvector.h b/vgui_support/utlvector.h new file mode 100644 index 00000000..3cd4ddb6 --- /dev/null +++ b/vgui_support/utlvector.h @@ -0,0 +1,605 @@ +//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// $Header: $ +// $NoKeywords: $ +// +// A growable array class that maintains a free list and keeps elements +// in the same location +//============================================================================= + +#ifndef UTLVECTOR_H +#define UTLVECTOR_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "port.h" +#include +#include "utlmemory.h" + + +//----------------------------------------------------------------------------- +// The CUtlVector class: +// A growable array class which doubles in size by default. +// It will always keep all elements consecutive in memory, and may move the +// elements around in memory (via a realloc) when elements are inserted or +// removed. Clients should therefore refer to the elements of the vector +// by index (they should *never* maintain pointers to elements in the vector). +//----------------------------------------------------------------------------- + +template< class T > +class CUtlVector +{ +public: + typedef T ElemType_t; + + // constructor, destructor + CUtlVector( int growSize = 0, int initSize = 0 ); + CUtlVector( T* pMemory, int numElements ); + ~CUtlVector(); + + // Copy the array. + CUtlVector& operator=( const CUtlVector &other ); + + // element access + T& operator[]( int i ); + T const& operator[]( int i ) const; + T& Element( int i ); + T const& Element( int i ) const; + + // Gets the base address (can change when adding elements!) + T* Base(); + T const* Base() const; + + // Returns the number of elements in the vector + // SIZE IS DEPRECATED! + int Count() const; + int Size() const; // don't use me! + + // Is element index valid? + bool IsValidIndex( int i ) const; + static int InvalidIndex( void ); + + // Adds an element, uses default constructor + int AddToHead(); + int AddToTail(); + int InsertBefore( int elem ); + int InsertAfter( int elem ); + + // Adds an element, uses copy constructor + int AddToHead( T const& src ); + int AddToTail( T const& src ); + int InsertBefore( int elem, T const& src ); + int InsertAfter( int elem, T const& src ); + + // Adds multiple elements, uses default constructor + int AddMultipleToHead( int num ); + int AddMultipleToTail( int num, const T *pToCopy=NULL ); + int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); // If pToCopy is set, then it's an array of length 'num' and + int InsertMultipleAfter( int elem, int num ); + + // Calls RemoveAll() then AddMultipleToTail. + void SetSize( int size ); + void SetCount( int count ); + + // Calls SetSize and copies each element. + void CopyArray( T const *pArray, int size ); + + // Add the specified array to the tail. + int AddVectorToTail( CUtlVector const &src ); + + // Finds an element (element needs operator== defined) + int Find( T const& src ) const; + + bool HasElement( T const& src ); + + // Makes sure we have enough memory allocated to store a requested # of elements + void EnsureCapacity( int num ); + + // Makes sure we have at least this many elements + void EnsureCount( int num ); + + // Element removal + void FastRemove( int elem ); // doesn't preserve order + void Remove( int elem ); // preserves order, shifts elements + void FindAndRemove( T const& src ); // removes first occurrence of src, preserves order, shifts elements + void RemoveMultiple( int elem, int num ); // preserves order, shifts elements + void RemoveAll(); // doesn't deallocate memory + + // Memory deallocation + void Purge(); + + // Purges the list and calls delete on each element in it. + void PurgeAndDeleteElements(); + + // Set the size by which it grows when it needs to allocate more memory. + void SetGrowSize( int size ); + +protected: + // Can't copy this unless we explicitly do it! + CUtlVector( CUtlVector const& vec ) { Assert(0); } + + // Grows the vector + void GrowVector( int num = 1 ); + + // Shifts elements.... + void ShiftElementsRight( int elem, int num = 1 ); + void ShiftElementsLeft( int elem, int num = 1 ); + + // For easier access to the elements through the debugger + void ResetDbgInfo(); + + CUtlMemory m_Memory; + int m_Size; + + // For easier access to the elements through the debugger + // it's in release builds so this can be used in libraries correctly + T *m_pElements; +}; + + +//----------------------------------------------------------------------------- +// For easier access to the elements through the debugger +//----------------------------------------------------------------------------- + +template< class T > +inline void CUtlVector::ResetDbgInfo() +{ + m_pElements = m_Memory.Base(); +} + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- + +template< class T > +inline CUtlVector::CUtlVector( int growSize, int initSize ) : + m_Memory(growSize, initSize), m_Size(0) +{ + ResetDbgInfo(); +} + +template< class T > +inline CUtlVector::CUtlVector( T* pMemory, int numElements ) : + m_Memory(pMemory, numElements), m_Size(0) +{ + ResetDbgInfo(); +} + +template< class T > +inline CUtlVector::~CUtlVector() +{ + Purge(); +} + +template +inline CUtlVector& CUtlVector::operator=( const CUtlVector &other ) +{ + CopyArray( other.Base(), other.Count() ); + return *this; +} + +//----------------------------------------------------------------------------- +// element access +//----------------------------------------------------------------------------- + +template< class T > +inline T& CUtlVector::operator[]( int i ) +{ + Assert( IsValidIndex(i) ); + return m_Memory[i]; +} + +template< class T > +inline T const& CUtlVector::operator[]( int i ) const +{ + Assert( IsValidIndex(i) ); + return m_Memory[i]; +} + +template< class T > +inline T& CUtlVector::Element( int i ) +{ + Assert( IsValidIndex(i) ); + return m_Memory[i]; +} + +template< class T > +inline T const& CUtlVector::Element( int i ) const +{ + Assert( IsValidIndex(i) ); + return m_Memory[i]; +} + + +//----------------------------------------------------------------------------- +// Gets the base address (can change when adding elements!) +//----------------------------------------------------------------------------- + +template< class T > +inline T* CUtlVector::Base() +{ + return m_Memory.Base(); +} + +template< class T > +inline T const* CUtlVector::Base() const +{ + return m_Memory.Base(); +} + +//----------------------------------------------------------------------------- +// Count +//----------------------------------------------------------------------------- + +template< class T > +inline int CUtlVector::Size() const +{ + return m_Size; +} + +template< class T > +inline int CUtlVector::Count() const +{ + return m_Size; +} + + +//----------------------------------------------------------------------------- +// Is element index valid? +//----------------------------------------------------------------------------- + +template< class T > +inline bool CUtlVector::IsValidIndex( int i ) const +{ + return (i >= 0) && (i < m_Size); +} + + +//----------------------------------------------------------------------------- +// Returns in invalid index +//----------------------------------------------------------------------------- +template< class T > +inline int CUtlVector::InvalidIndex( void ) +{ + return -1; +} + + +//----------------------------------------------------------------------------- +// Grows the vector +//----------------------------------------------------------------------------- +template< class T > +void CUtlVector::GrowVector( int num ) +{ + if (m_Size + num - 1 >= m_Memory.NumAllocated()) + { + m_Memory.Grow( m_Size + num - m_Memory.NumAllocated() ); + } + + m_Size += num; + ResetDbgInfo(); +} + + +//----------------------------------------------------------------------------- +// Makes sure we have enough memory allocated to store a requested # of elements +//----------------------------------------------------------------------------- +template< class T > +void CUtlVector::EnsureCapacity( int num ) +{ + m_Memory.EnsureCapacity(num); + ResetDbgInfo(); +} + + +//----------------------------------------------------------------------------- +// Makes sure we have at least this many elements +//----------------------------------------------------------------------------- +template< class T > +void CUtlVector::EnsureCount( int num ) +{ + if (Count() < num) + AddMultipleToTail( num - Count() ); +} + + +//----------------------------------------------------------------------------- +// Shifts elements +//----------------------------------------------------------------------------- +template< class T > +void CUtlVector::ShiftElementsRight( int elem, int num ) +{ + Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 )); + int numToMove = m_Size - elem - num; + if ((numToMove > 0) && (num > 0)) + memmove( &Element(elem+num), &Element(elem), numToMove * sizeof(T) ); +} + +template< class T > +void CUtlVector::ShiftElementsLeft( int elem, int num ) +{ + Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 )); + int numToMove = m_Size - elem - num; + if ((numToMove > 0) && (num > 0)) + { + memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) ); + +#ifdef _DEBUG + memset( &Element(m_Size-num), 0xDD, num * sizeof(T) ); +#endif + } +} + +//----------------------------------------------------------------------------- +// Adds an element, uses default constructor +//----------------------------------------------------------------------------- + +template< class T > +inline int CUtlVector::AddToHead() +{ + return InsertBefore(0); +} + +template< class T > +inline int CUtlVector::AddToTail() +{ + return InsertBefore( m_Size ); +} + +template< class T > +inline int CUtlVector::InsertAfter( int elem ) +{ + return InsertBefore( elem + 1 ); +} + +template< class T > +int CUtlVector::InsertBefore( int elem ) +{ + // Can insert at the end + Assert( (elem == Count()) || IsValidIndex(elem) ); + + GrowVector(); + ShiftElementsRight(elem); + Construct( &Element(elem) ); + return elem; +} + + +//----------------------------------------------------------------------------- +// Adds an element, uses copy constructor +//----------------------------------------------------------------------------- + +template< class T > +inline int CUtlVector::AddToHead( T const& src ) +{ + return InsertBefore( 0, src ); +} + +template< class T > +inline int CUtlVector::AddToTail( T const& src ) +{ + return InsertBefore( m_Size, src ); +} + +template< class T > +inline int CUtlVector::InsertAfter( int elem, T const& src ) +{ + return InsertBefore( elem + 1, src ); +} + +template< class T > +int CUtlVector::InsertBefore( int elem, T const& src ) +{ + // Can insert at the end + Assert( (elem == Count()) || IsValidIndex(elem) ); + + GrowVector(); + ShiftElementsRight(elem); + CopyConstruct( &Element(elem), src ); + return elem; +} + + +//----------------------------------------------------------------------------- +// Adds multiple elements, uses default constructor +//----------------------------------------------------------------------------- + +template< class T > +inline int CUtlVector::AddMultipleToHead( int num ) +{ + return InsertMultipleBefore( 0, num ); +} + +template< class T > +inline int CUtlVector::AddMultipleToTail( int num, const T *pToCopy ) +{ + return InsertMultipleBefore( m_Size, num, pToCopy ); +} + +template< class T > +int CUtlVector::InsertMultipleAfter( int elem, int num ) +{ + return InsertMultipleBefore( elem + 1, num ); +} + + +template< class T > +void CUtlVector::SetCount( int count ) +{ + RemoveAll(); + AddMultipleToTail( count ); +} + +template< class T > +inline void CUtlVector::SetSize( int size ) +{ + SetCount( size ); +} + +template< class T > +void CUtlVector::CopyArray( T const *pArray, int size ) +{ + SetSize( size ); + for( int i=0; i < size; i++ ) + (*this)[i] = pArray[i]; +} + +template< class T > +int CUtlVector::AddVectorToTail( CUtlVector const &src ) +{ + int base = Count(); + + // Make space. + AddMultipleToTail( src.Count() ); + + // Copy the elements. + for ( int i=0; i < src.Count(); i++ ) + (*this)[base + i] = src[i]; + + return base; +} + +template< class T > +inline int CUtlVector::InsertMultipleBefore( int elem, int num, const T *pToInsert ) +{ + if( num == 0 ) + return elem; + + // Can insert at the end + Assert( (elem == Count()) || IsValidIndex(elem) ); + + GrowVector(num); + ShiftElementsRight(elem, num); + + // Invoke default constructors + for (int i = 0; i < num; ++i) + Construct( &Element(elem+i) ); + + // Copy stuff in? + if ( pToInsert ) + { + for ( int i=0; i < num; i++ ) + { + Element( elem+i ) = pToInsert[i]; + } + } + + return elem; +} + +//----------------------------------------------------------------------------- +// Finds an element (element needs operator== defined) +//----------------------------------------------------------------------------- +template< class T > +int CUtlVector::Find( T const& src ) const +{ + for ( int i = 0; i < Count(); ++i ) + { + if (Element(i) == src) + return i; + } + return -1; +} + +template< class T > +bool CUtlVector::HasElement( T const& src ) +{ + return ( Find(src) >= 0 ); +} + +//----------------------------------------------------------------------------- +// Element removal +//----------------------------------------------------------------------------- + +template< class T > +void CUtlVector::FastRemove( int elem ) +{ + Assert( IsValidIndex(elem) ); + + Destruct( &Element(elem) ); + if (m_Size > 0) + { + memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) ); + --m_Size; + } +} + +template< class T > +void CUtlVector::Remove( int elem ) +{ + Destruct( &Element(elem) ); + ShiftElementsLeft(elem); + --m_Size; +} + +template< class T > +void CUtlVector::FindAndRemove( T const& src ) +{ + int elem = Find( src ); + if ( elem != -1 ) + { + Remove( elem ); + } +} + +template< class T > +void CUtlVector::RemoveMultiple( int elem, int num ) +{ + Assert( IsValidIndex(elem) ); + Assert( elem + num <= Count() ); + + for (int i = elem + num; --i >= elem; ) + Destruct(&Element(i)); + + ShiftElementsLeft(elem, num); + m_Size -= num; +} + +template< class T > +void CUtlVector::RemoveAll() +{ + for (int i = m_Size; --i >= 0; ) + Destruct(&Element(i)); + + m_Size = 0; +} + + +//----------------------------------------------------------------------------- +// Memory deallocation +//----------------------------------------------------------------------------- + +template< class T > +void CUtlVector::Purge() +{ + RemoveAll(); + m_Memory.Purge( ); + ResetDbgInfo(); +} + + +template +inline void CUtlVector::PurgeAndDeleteElements() +{ + for( int i=0; i < m_Size; i++ ) + delete Element(i); + + Purge(); +} + + +template< class T > +void CUtlVector::SetGrowSize( int size ) +{ + m_Memory.SetGrowSize( size ); +} + + +#endif//UTLVECTOR_H diff --git a/engine/client/vgui/vgui_clip.cpp b/vgui_support/vgui_clip.cpp similarity index 75% rename from engine/client/vgui/vgui_clip.cpp rename to vgui_support/vgui_clip.cpp index c3b91848..ea30e771 100644 --- a/engine/client/vgui/vgui_clip.cpp +++ b/vgui_support/vgui_clip.cpp @@ -11,10 +11,19 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +In addition, as a special exception, the author gives permission +to link the code of this program with VGUI library developed by +Valve, L.L.C ("Valve"). You must obey the GNU General Public License +in all respects for all of the code used other than VGUI library. +If you modify this file, you may extend this exception to your +version of the file, but you are not obligated to do so. If +you do not wish to do so, delete this exception statement +from your version. + */ -#include "common.h" -#include "vgui_draw.h" +#include "vgui_main.h" #include "wrect.h" //----------------------------------------------------------------------------- @@ -22,7 +31,7 @@ GNU General Public License for more details. //----------------------------------------------------------------------------- static wrect_t g_ScissorRect; static qboolean g_bScissor = false; - +namespace vgui_support { //----------------------------------------------------------------------------- // Enable/disable scissoring... //----------------------------------------------------------------------------- @@ -95,11 +104,15 @@ qboolean ClipRect( const vpoint_t &inUL, const vpoint_t &inLR, vpoint_t *pOutUL, return false; } - pOutUL->coord[0] = InterpTCoord(pOutUL->point[0], inUL.point[0], inLR.point[0], inUL.coord[0], inLR.coord[0] ); - pOutLR->coord[0] = InterpTCoord(pOutLR->point[0], inUL.point[0], inLR.point[0], inUL.coord[0], inLR.coord[0] ); + pOutUL->coord[0] = InterpTCoord(pOutUL->point[0], + inUL.point[0], inLR.point[0], inUL.coord[0], inLR.coord[0] ); + pOutLR->coord[0] = InterpTCoord(pOutLR->point[0], + inUL.point[0], inLR.point[0], inUL.coord[0], inLR.coord[0] ); - pOutUL->coord[1] = InterpTCoord(pOutUL->point[1], inUL.point[1], inLR.point[1], inUL.coord[1], inLR.coord[1] ); - pOutLR->coord[1] = InterpTCoord(pOutLR->point[1], inUL.point[1], inLR.point[1], inUL.coord[1], inLR.coord[1] ); + pOutUL->coord[1] = InterpTCoord(pOutUL->point[1], + inUL.point[1], inLR.point[1], inUL.coord[1], inLR.coord[1] ); + pOutLR->coord[1] = InterpTCoord(pOutLR->point[1], + inUL.point[1], inLR.point[1], inUL.coord[1], inLR.coord[1] ); } else { @@ -107,4 +120,5 @@ qboolean ClipRect( const vpoint_t &inUL, const vpoint_t &inLR, vpoint_t *pOutUL, *pOutLR = inLR; } return true; +} } \ No newline at end of file diff --git a/vgui_support/vgui_font.cpp b/vgui_support/vgui_font.cpp new file mode 100644 index 00000000..99369508 --- /dev/null +++ b/vgui_support/vgui_font.cpp @@ -0,0 +1,185 @@ +/* +vgui_font.cpp - fonts management +Copyright (C) 2011 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the author gives permission +to link the code of this program with VGUI library developed by +Valve, L.L.C ("Valve"). You must obey the GNU General Public License +in all respects for all of the code used other than VGUI library. +If you modify this file, you may extend this exception to your +version of the file, but you are not obligated to do so. If +you do not wish to do so, delete this exception statement +from your version. + +*/ + +#include "vgui_main.h" + +int FontCache::s_pFontPageSize[FONT_PAGE_SIZE_COUNT] = { 16, 32, 64, 128 }; + +FontCache::FontCache() : m_CharCache( 0, 256, CacheEntryLessFunc ) +{ + CacheEntry_t listHead = { 0, 0 }; + + m_LRUListHeadIndex = m_CharCache.Insert( listHead ); + m_CharCache[m_LRUListHeadIndex].nextEntry = m_LRUListHeadIndex; + m_CharCache[m_LRUListHeadIndex].prevEntry = m_LRUListHeadIndex; + for( int i = 0; i < FONT_PAGE_SIZE_COUNT; i++ ) + { + m_pCurrPage[i] = -1; + } +} + +bool FontCache::CacheEntryLessFunc( CacheEntry_t const &lhs, CacheEntry_t const &rhs ) +{ + if( lhs.font < rhs.font ) + return true; + else if( lhs.font > rhs.font ) + return false; + + return ( lhs.ch < rhs.ch ); +} + +bool FontCache::GetTextureForChar( Font *font, char ch, int *textureID, float **texCoords ) +{ + static CacheEntry_t cacheitem; + + cacheitem.font = font; + cacheitem.ch = ch; + + Assert( texCoords != NULL ); + + *texCoords = cacheitem.texCoords; + + HCacheEntry cacheHandle = m_CharCache.Find( cacheitem ); + + if( cacheHandle != 65535 && m_CharCache.IsValidIndex( cacheHandle )) + { + // we have an entry already, return that + int page = m_CharCache[cacheHandle].page; + *textureID = m_PageList[page].textureID; + //else return false; + *texCoords = m_CharCache[cacheHandle].texCoords; + return true; + } + + // get the char details + int fontTall = font->getTall(); + int a, b, c; + font->getCharABCwide( (byte)ch, a, b, c ); + int fontWide = b; + + // get a texture to render into + int page, drawX, drawY, twide, ttall; + if( !AllocatePageForChar( fontWide, fontTall, page, drawX, drawY, twide, ttall )) + return false; + + // create a buffer and render the character into it + int nByteCount = s_pFontPageSize[FONT_PAGE_SIZE_COUNT-1] * s_pFontPageSize[FONT_PAGE_SIZE_COUNT-1] * 4; + byte * rgba = (byte *)g_api->EngineMalloc(nByteCount);//(byte *)Z_Malloc( nByteCount ); + font->getCharRGBA( (byte)ch, 0, 0, fontWide, fontTall, rgba ); + + // upload the new sub texture + g_api->BindTexture( m_PageList[page].textureID ); + g_api->UploadTextureBlock( m_PageList[page].textureID, drawX, drawY, rgba, fontWide, fontTall ); + + // set the cache info + cacheitem.page = page; + + cacheitem.texCoords[0] = (float)((double)drawX / ((double)twide)); + cacheitem.texCoords[1] = (float)((double)drawY / ((double)ttall)); + cacheitem.texCoords[2] = (float)((double)(drawX + fontWide) / (double)twide); + cacheitem.texCoords[3] = (float)((double)(drawY + fontTall) / (double)ttall); + + m_CharCache.Insert( cacheitem ); + + // return the data + *textureID = m_PageList[page].textureID; + // memcpy( texCoords, cacheitem.texCoords, sizeof( float ) * 4 ); + return true; +} + +int FontCache::ComputePageType( int charTall ) const +{ + for( int i = 0; i < FONT_PAGE_SIZE_COUNT; i++ ) + { + if( charTall < s_pFontPageSize[i] ) + return i; + } + return -1; +} + +bool FontCache::AllocatePageForChar( int charWide, int charTall, int &pageIndex, int &drawX, int &drawY, int &twide, int &ttall ) +{ + // see if there is room in the last page for this character + int nPageType = ComputePageType( charTall ); + + if( nPageType < 0 ) + return false; + + pageIndex = m_pCurrPage[nPageType]; + + int nNextX = 0; + bool bNeedsNewPage = true; + + if( pageIndex > -1 ) + { + Page_t &page = m_PageList[pageIndex]; + + nNextX = page.nextX + charWide; + + // make sure we have room on the current line of the texture page + if( nNextX > page.wide ) + { + // move down a line + page.nextX = 0; + nNextX = charWide; + page.nextY += page.fontHeight + 1; + } + + bNeedsNewPage = (( page.nextY + page.fontHeight + 1 ) > page.tall ); + } + + if( bNeedsNewPage ) + { + // allocate a new page + pageIndex = m_PageList.AddToTail(); + Page_t &newPage = m_PageList[pageIndex]; + m_pCurrPage[nPageType] = pageIndex; + + newPage.textureID = g_api->GenerateTexture(); + + newPage.fontHeight = s_pFontPageSize[nPageType]; + newPage.wide = 256; + newPage.tall = 256; + newPage.nextX = 0; + newPage.nextY = 0; + + nNextX = charWide; + + // create empty texture + g_api->CreateTexture( newPage.textureID, 256, 256 ); + } + + // output the position + Page_t &page = m_PageList[pageIndex]; + drawX = page.nextX; + drawY = page.nextY; + twide = page.wide; + ttall = page.tall; + + // update the next position to draw in + page.nextX = nNextX + 1; + + return true; +} diff --git a/vgui_support/vgui_input.cpp b/vgui_support/vgui_input.cpp new file mode 100644 index 00000000..5280b5b7 --- /dev/null +++ b/vgui_support/vgui_input.cpp @@ -0,0 +1,86 @@ +/* +vgui_input.cpp - handle kb & mouse +Copyright (C) 2011 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the author gives permission +to link the code of this program with VGUI library developed by +Valve, L.L.C ("Valve"). You must obey the GNU General Public License +in all respects for all of the code used other than VGUI library. +If you modify this file, you may extend this exception to your +version of the file, but you are not obligated to do so. If +you do not wish to do so, delete this exception statement +from your version. + +*/ + +#define OEMRESOURCE // for OCR_* cursor junk + +#include "vgui_main.h" + +namespace vgui_support { +void VGUI_Key(VGUI_KeyAction action, VGUI_KeyCode code) +{ + App *pApp = App::getInstance(); + if(!surface) + return; + switch( action ) + { + case KA_PRESSED: + pApp->internalKeyPressed( (KeyCode) code, surface ); + break; + case KA_RELEASED: + pApp->internalKeyReleased( (KeyCode) code, surface ); + break; + case KA_TYPED: + pApp->internalKeyTyped( (KeyCode) code, surface ); + break; + } + //fprintf(stdout,"vgui_support: VGUI key action %d %d\n", action, code); + //fflush(stdout); +} + +void VGUI_Mouse(VGUI_MouseAction action, int code) +{ + App *pApp = App::getInstance(); + if(!surface) + return; + switch( action ) + { + case MA_PRESSED: + pApp->internalMousePressed( (MouseCode) code, surface ); + break; + case MA_RELEASED: + pApp->internalMouseReleased( (MouseCode) code, surface ); + break; + case MA_DOUBLE: + pApp->internalMouseDoublePressed( (MouseCode) code, surface ); + break; + case MA_WHEEL: + //fprintf(stdout, "vgui_support: VGUI mouse wheeled %d %d\n", action, code); + pApp->internalMouseWheeled( code, surface ); + break; + } + //fprintf(stdout, "vgui_support: VGUI mouse action %d %d\n", action, code); + //fflush(stdout); +} + +void VGUI_MouseMove(int x, int y) +{ + App *pApp = App::getInstance(); + //fprintf(stdout, "vgui_support: VGUI mouse move %d %d %p\n", x, y, surface); + //fflush(stdout); + if(!surface) + return; + pApp->internalCursorMoved( x, y, surface ); +} +} diff --git a/vgui_support/vgui_int.cpp b/vgui_support/vgui_int.cpp new file mode 100644 index 00000000..2c61df88 --- /dev/null +++ b/vgui_support/vgui_int.cpp @@ -0,0 +1,132 @@ +/* +vgui_int.c - vgui dll interaction +Copyright (C) 2011 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the author gives permission +to link the code of this program with VGUI library developed by +Valve, L.L.C ("Valve"). You must obey the GNU General Public License +in all respects for all of the code used other than VGUI library. +If you modify this file, you may extend this exception to your +version of the file, but you are not obligated to do so. If +you do not wish to do so, delete this exception statement +from your version. + +*/ + +#include "vgui_main.h" +namespace vgui_support { + +vguiapi_t *g_api; + +FontCache *g_FontCache = 0; + +Panel *rootpanel = NULL; +CEngineSurface *surface = NULL; +CEngineApp staticApp; + +void VGui_Startup( int width, int height ) +{ + if( !g_FontCache ) + { + g_FontCache = new FontCache(); + } + + if( rootpanel ) + { + rootpanel->setSize( width, height ); + return; + } + + rootpanel = new Panel; + rootpanel->setSize( width, height ); + rootpanel->setPaintBorderEnabled( false ); + rootpanel->setPaintBackgroundEnabled( false ); + rootpanel->setVisible( true ); + rootpanel->setCursor( new Cursor( Cursor::dc_none )); + + staticApp.start(); + staticApp.setMinimumTickMillisInterval( 0 ); + + surface = new CEngineSurface( rootpanel ); + rootpanel->setSurfaceBaseTraverse( surface ); + + + //ASSERT( rootpanel->getApp() != NULL ); + //ASSERT( rootpanel->getSurfaceBase() != NULL ); + + g_api->DrawInit (); +} + +void VGui_Shutdown( void ) +{ + staticApp.stop(); + + delete rootpanel; + delete surface; + + rootpanel = NULL; + surface = NULL; +} + +void VGui_Paint( void ) +{ + int w, h; + + //if( cls.state != ca_active || !rootpanel ) + // return; + if( !g_api->IsInGame() || !rootpanel ) + return; + + // setup the base panel to cover the screen + Panel *pVPanel = surface->getEmbeddedPanel(); + if( !pVPanel ) return; + //SDL_GetWindowSize(host.hWnd, &w, &h); + //host.input_enabled = rootpanel->isVisible(); + rootpanel->getSize(w, h); + EnableScissor( true ); + + staticApp.externalTick (); + + pVPanel->setBounds( 0, 0, w, h ); + pVPanel->repaint(); + + // paint everything + pVPanel->paintTraverse(); + + EnableScissor( false ); +} +void *VGui_GetPanel( void ) +{ + return (void *)rootpanel; +} +} + +#ifdef INTERNAL_VGUI_SUPPORT +#define InitAPI InitVGUISupportAPI +#endif + +#ifdef _WIN32 +extern "C" void _declspec( dllexport ) InitAPI(vguiapi_t * api) +#else +extern "C" void InitAPI(vguiapi_t * api) +#endif +{ + g_api = api; + g_api->Startup = VGui_Startup; + g_api->Shutdown = VGui_Shutdown; + g_api->GetPanel = VGui_GetPanel; + g_api->Paint = VGui_Paint; + g_api->Mouse = VGUI_Mouse; + g_api->MouseMove = VGUI_MouseMove; + g_api->Key = VGUI_Key; +} diff --git a/vgui_support/vgui_main.h b/vgui_support/vgui_main.h new file mode 100644 index 00000000..5bed5d8d --- /dev/null +++ b/vgui_support/vgui_main.h @@ -0,0 +1,225 @@ +/* +vgui_main.h - vgui main header +Copyright (C) 2011 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the author gives permission +to link the code of this program with VGUI library developed by +Valve, L.L.C ("Valve"). You must obey the GNU General Public License +in all respects for all of the code used other than VGUI library. +If you modify this file, you may extend this exception to your +version of the file, but you are not obligated to do so. If +you do not wish to do so, delete this exception statement +from your version. + +*/ +#ifndef VGUI_MAIN_H +#define VGUI_MAIN_H + +#define Assert(x) + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "vgui_api.h" +#include "utlvector.h" +#include "utlrbtree.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vgui_support +{ +extern vguiapi_t *g_api; + +using namespace vgui; + +class FontCache +{ +public: + FontCache(); + ~FontCache() { } + + // returns a texture ID and a pointer to an array of 4 texture coords for the given character & font + // uploads more texture if necessary + bool GetTextureForChar( Font *font, char ch, int *textureID, float **texCoords ); +private: + // NOTE: If you change this, change s_pFontPageSize + enum + { + FONT_PAGE_SIZE_16, + FONT_PAGE_SIZE_32, + FONT_PAGE_SIZE_64, + FONT_PAGE_SIZE_128, + FONT_PAGE_SIZE_COUNT + }; + + // a single character in the cache + typedef unsigned short HCacheEntry; + struct CacheEntry_t + { + Font *font; + char ch; + byte page; + float texCoords[4]; + + HCacheEntry nextEntry; // doubly-linked list for use in the LRU + HCacheEntry prevEntry; + }; + + // a single texture page + struct Page_t + { + short textureID; + short fontHeight; + short wide, tall; // total size of the page + short nextX, nextY; // position to draw any new character positions + }; + + // allocates a new page for a given character + bool AllocatePageForChar( int charWide, int charTall, int &pageIndex, int &drawX, int &drawY, int &twide, int &ttall ); + + // Computes the page size given a character height + int ComputePageType( int charTall ) const; + + static bool CacheEntryLessFunc( const CacheEntry_t &lhs, const CacheEntry_t &rhs ); + + // cache + typedef CUtlVector FontPageList_t; + + CUtlRBTree m_CharCache; + FontPageList_t m_PageList; + int m_pCurrPage[FONT_PAGE_SIZE_COUNT]; + HCacheEntry m_LRUListHeadIndex; + + static int s_pFontPageSize[FONT_PAGE_SIZE_COUNT]; +}; + +class CEngineSurface : public SurfaceBase +{ +private: + struct paintState_t + { + Panel *m_pPanel; + int iTranslateX; + int iTranslateY; + int iScissorLeft; + int iScissorRight; + int iScissorTop; + int iScissorBottom; + }; + + // point translation for current panel + int _translateX; + int _translateY; + + // the size of the window to draw into + int _surfaceExtents[4]; + + CUtlVector _paintStack; + + void SetupPaintState( const paintState_t &paintState ); + void InitVertex( vpoint_t &vertex, int x, int y, float u, float v ); +public: + CEngineSurface( Panel *embeddedPanel ); + ~CEngineSurface(); +public: + virtual Panel *getEmbeddedPanel( void ); + virtual bool setFullscreenMode( int wide, int tall, int bpp ); + virtual void setWindowedMode( void ); + virtual void setTitle( const char *title ) { } + virtual void createPopup( Panel* embeddedPanel ) { } + virtual bool isWithin( int x, int y ) { return true; } + virtual bool hasFocus( void ); + // now it's not abstract class, yay + virtual void GetMousePos(int &x, int &y) { + g_api->GetCursorPos(&x, &y); + } +protected: + virtual int createNewTextureID( void ); + virtual void drawSetColor( int r, int g, int b, int a ); + virtual void drawSetTextColor( int r, int g, int b, int a ); + virtual void drawFilledRect( int x0, int y0, int x1, int y1 ); + virtual void drawOutlinedRect( int x0,int y0,int x1,int y1 ); + virtual void drawSetTextFont( Font *font ); + virtual void drawSetTextPos( int x, int y ); + virtual void drawPrintText( const char* text, int textLen ); + virtual void drawSetTextureRGBA( int id, const char* rgba, int wide, int tall ); + virtual void drawSetTexture( int id ); + virtual void drawTexturedRect( int x0, int y0, int x1, int y1 ); + virtual bool createPlat( void ) { return false; } + virtual bool recreateContext( void ) { return false; } + virtual void setCursor( Cursor* cursor ); + virtual void pushMakeCurrent( Panel* panel, bool useInsets ); + virtual void popMakeCurrent( Panel* panel ); + + // not used in engine instance + virtual void enableMouseCapture( bool state ) { } + virtual void invalidate( Panel *panel ) { } + virtual void setAsTopMost( bool state ) { } + virtual void applyChanges( void ) { } + virtual void swapBuffers( void ) { } +protected: + Font* _hCurrentFont; + Cursor* _hCurrentCursor; + int _drawTextPos[2]; + int _drawColor[4]; + int _drawTextColor[4]; + friend class App; + friend class Panel; +}; + +// initialize VGUI::App as external (part of engine) +class CEngineApp : public App +{ +public: + CEngineApp( bool externalMain = true ) : App( externalMain ) { } + virtual void main( int argc, char* argv[] ) { } // stub +}; + +// +// vgui_input.cpp +// +void VGUI_InitCursors( void ); +void VGUI_CursorSelect( Cursor *cursor ); +void VGUI_ActivateCurrentCursor( void ); +void *VGui_GetPanel( void ); +void VGui_RunFrame( void ); +void VGui_Paint( void ); +void VGUI_Mouse(VGUI_MouseAction action, int code); +void VGUI_Key(VGUI_KeyAction action, VGUI_KeyCode code); +void VGUI_MouseMove(int x, int y); +// +// vgui_clip.cpp +// +void EnableScissor( qboolean enable ); +void SetScissorRect( int left, int top, int right, int bottom ); +qboolean ClipRect( const vpoint_t &inUL, const vpoint_t &inLR, vpoint_t *pOutUL, vpoint_t *pOutLR ); + +extern FontCache *g_FontCache; + + +extern CEngineSurface *surface; +extern Panel *root; +} +using namespace vgui_support; +#endif//VGUI_MAIN_H diff --git a/vgui_support/vgui_surf.cpp b/vgui_support/vgui_surf.cpp new file mode 100644 index 00000000..9e4d07cc --- /dev/null +++ b/vgui_support/vgui_surf.cpp @@ -0,0 +1,339 @@ +/* +vgui_surf.cpp - main vgui layer +Copyright (C) 2011 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the author gives permission +to link the code of this program with VGUI library developed by +Valve, L.L.C ("Valve"). You must obey the GNU General Public License +in all respects for all of the code used other than VGUI library. +If you modify this file, you may extend this exception to your +version of the file, but you are not obligated to do so. If +you do not wish to do so, delete this exception statement +from your version. + +*/ + +#include +#include "vgui_main.h" + +#define ColorIndex( c )((( c ) - '0' ) & 7 ) + +CEngineSurface :: CEngineSurface( Panel *embeddedPanel ):SurfaceBase( embeddedPanel ) +{ + _embeddedPanel = embeddedPanel; + _drawColor[0] = _drawColor[1] = _drawColor[2] = _drawColor[3] = 255; + _drawTextColor[0] = _drawTextColor[1] = _drawTextColor[2] = _drawTextColor[3] = 255; + + _surfaceExtents[0] = _surfaceExtents[1] = 0; + //_surfaceExtents[2] = menu.globals->scrWidth; + //_surfaceExtents[3] = menu.globals->scrHeight; + embeddedPanel->getSize(_surfaceExtents[2], _surfaceExtents[3]); + _drawTextPos[0] = _drawTextPos[1] = 0; + _hCurrentFont = null; + _hCurrentCursor = null; + _translateX = _translateY = 0; +} + +CEngineSurface :: ~CEngineSurface( void ) +{ + g_api->DrawShutdown (); +} + +Panel *CEngineSurface :: getEmbeddedPanel( void ) +{ + return _embeddedPanel; +} + +bool CEngineSurface :: hasFocus( void ) +{ + // What differs when window does not has focus? + //return host.state != HOST_NOFOCUS; + return true; +} + +void CEngineSurface :: setCursor( Cursor *cursor ) +{ + _currentCursor = cursor; + g_api->CursorSelect( (VGUI_DefaultCursor)cursor->getDefaultCursor() ); +} + +void CEngineSurface :: SetupPaintState( const paintState_t &paintState ) +{ + _translateX = paintState.iTranslateX; + _translateY = paintState.iTranslateY; + SetScissorRect( paintState.iScissorLeft, paintState.iScissorTop, + paintState.iScissorRight, paintState.iScissorBottom ); +} + +void CEngineSurface :: InitVertex( vpoint_t &vertex, int x, int y, float u, float v ) +{ + vertex.point[0] = x + _translateX; + vertex.point[1] = y + _translateY; + vertex.coord[0] = u; + vertex.coord[1] = v; +} + +int CEngineSurface :: createNewTextureID( void ) +{ + return g_api->GenerateTexture(); +} + +void CEngineSurface :: drawSetColor( int r, int g, int b, int a ) +{ + _drawColor[0] = r; + _drawColor[1] = g; + _drawColor[2] = b; + _drawColor[3] = a; +} + +void CEngineSurface :: drawSetTextColor( int r, int g, int b, int a ) +{ + _drawTextColor[0] = r; + _drawTextColor[1] = g; + _drawTextColor[2] = b; + _drawTextColor[3] = a; +} + +void CEngineSurface :: drawFilledRect( int x0, int y0, int x1, int y1 ) +{ + vpoint_t rect[2]; + vpoint_t clippedRect[2]; + + if( _drawColor[3] >= 255 ) return; + + InitVertex( rect[0], x0, y0, 0, 0 ); + InitVertex( rect[1], x1, y1, 0, 0 ); + + // fully clipped? + if( !ClipRect( rect[0], rect[1], &clippedRect[0], &clippedRect[1] )) + return; + + g_api->SetupDrawingRect( _drawColor ); + g_api->EnableTexture( false ); + g_api->DrawQuad( &clippedRect[0], &clippedRect[1] ); + g_api->EnableTexture( true ); +} + +void CEngineSurface :: drawOutlinedRect( int x0, int y0, int x1, int y1 ) +{ + if( _drawColor[3] >= 255 ) return; + + drawFilledRect( x0, y0, x1, y0 + 1 ); // top + drawFilledRect( x0, y1 - 1, x1, y1 ); // bottom + drawFilledRect( x0, y0 + 1, x0 + 1, y1 - 1 ); // left + drawFilledRect( x1 - 1, y0 + 1, x1, y1 - 1 ); // right +} + +void CEngineSurface :: drawSetTextFont( Font *font ) +{ + _hCurrentFont = font; +} + +void CEngineSurface :: drawSetTextPos( int x, int y ) +{ + _drawTextPos[0] = x; + _drawTextPos[1] = y; +} + +void CEngineSurface :: drawPrintText( const char* text, int textLen ) +{ + //return; + static bool hasColor = 0; + static int numColor = 7; + + if( !text || !_hCurrentFont || _drawTextColor[3] >= 255 ) + return; + + int x = _drawTextPos[0] + _translateX; + int y = _drawTextPos[1] + _translateY; + + int iTall = _hCurrentFont->getTall(); + + int j, iTotalWidth = 0; + int curTextColor[4]; + + // HACKHACK: allow color strings in VGUI + if( numColor != 7 ) + { + for( j = 0; j < 3; j++ ) // grab predefined color + curTextColor[j] = g_api->GetColor(numColor,j); + } + else + { + for( j = 0; j < 3; j++ ) // revert default color + curTextColor[j] = _drawTextColor[j]; + } + curTextColor[3] = _drawTextColor[3]; // copy alpha + + if( textLen == 1 ) + { + if( *text == '^' ) + { + hasColor = true; + return; // skip '^' + } + else if( hasColor && isdigit( *text )) + { + numColor = ColorIndex( *text ); + hasColor = false; // handled + return; // skip colornum + } + else hasColor = false; + } + for( int i = 0; i < textLen; i++ ) + { + char ch = g_api->ProcessUtfChar( (unsigned char)text[i] ); + if( !ch ) + { + continue; + } + + int abcA,abcB,abcC; + _hCurrentFont->getCharABCwide( ch, abcA, abcB, abcC ); + + iTotalWidth += abcA; + int iWide = abcB; + + //if( !iswspace( ch )) + { + // get the character texture from the cache + int iTexId = 0; + float *texCoords = NULL; + + if( !g_FontCache->GetTextureForChar( _hCurrentFont, ch, &iTexId, &texCoords )) + { + continue; + } + + Assert( texCoords != NULL ); + + vpoint_t ul, lr; + + ul.point[0] = x + iTotalWidth; + ul.point[1] = y; + lr.point[0] = ul.point[0] + iWide; + lr.point[1] = ul.point[1] + iTall; + + // gets at the texture coords for this character in its texture page + ul.coord[0] = texCoords[0]; + ul.coord[1] = texCoords[1]; + lr.coord[0] = texCoords[2]; + lr.coord[1] = texCoords[3]; + + vpoint_t clippedRect[2]; + + if( !ClipRect( ul, lr, &clippedRect[0], &clippedRect[1] )) + continue; + + drawSetTexture( iTexId ); + g_api->SetupDrawingText( curTextColor ); + g_api->DrawQuad( &clippedRect[0], &clippedRect[1] ); // draw the letter + } + + iTotalWidth += iWide + abcC; + } + + _drawTextPos[0] += iTotalWidth; +} + +void CEngineSurface :: drawSetTextureRGBA( int id, const char* rgba, int wide, int tall ) +{ + g_api->UploadTexture( id, rgba, wide, tall ); +} + +void CEngineSurface :: drawSetTexture( int id ) +{ + g_api->BindTexture( id ); +} + +void CEngineSurface :: drawTexturedRect( int x0, int y0, int x1, int y1 ) +{ + vpoint_t rect[2]; + vpoint_t clippedRect[2]; + + InitVertex( rect[0], x0, y0, 0, 0 ); + InitVertex( rect[1], x1, y1, 1, 1 ); + + // fully clipped? + if( !ClipRect( rect[0], rect[1], &clippedRect[0], &clippedRect[1] )) + return; + + g_api->SetupDrawingImage( _drawColor ); + g_api->DrawQuad( &clippedRect[0], &clippedRect[1] ); +} + +void CEngineSurface :: pushMakeCurrent( Panel* panel, bool useInsets ) +{ + int inSets[4] = { 0, 0, 0, 0 }; + int absExtents[4]; + int clipRect[4]; + + if( useInsets ) + { + panel->getInset( inSets[0], inSets[1], inSets[2], inSets[3] ); + } + + panel->getAbsExtents( absExtents[0], absExtents[1], absExtents[2], absExtents[3] ); + panel->getClipRect( clipRect[0], clipRect[1], clipRect[2], clipRect[3] ); + + int i = _paintStack.AddToTail(); + paintState_t &paintState = _paintStack[i]; + paintState.m_pPanel = panel; + + // determine corrected top left origin + paintState.iTranslateX = inSets[0] + absExtents[0] - _surfaceExtents[0]; + paintState.iTranslateY = inSets[1] + absExtents[1] - _surfaceExtents[1]; + + // setup clipping rectangle for scissoring + paintState.iScissorLeft = clipRect[0] - _surfaceExtents[0]; + paintState.iScissorTop = clipRect[1] - _surfaceExtents[1]; + paintState.iScissorRight = clipRect[2] - _surfaceExtents[0]; + paintState.iScissorBottom = clipRect[3] - _surfaceExtents[1]; + + SetupPaintState( paintState ); +} + +void CEngineSurface :: popMakeCurrent( Panel *panel ) +{ + int top = _paintStack.Count() - 1; + + // more pops that pushes? + Assert( top >= 0 ); + + // didn't pop in reverse order of push? + Assert( _paintStack[top].m_pPanel == panel ); + + _paintStack.Remove( top ); + + if( top > 0 ) SetupPaintState( _paintStack[top-1] ); +} + +bool CEngineSurface :: setFullscreenMode( int wide, int tall, int bpp ) +{ + // NOTE: Xash3D always working in 32-bit mode + // Skip it now. VGUI cannot change video modes + /*if( R_DescribeVIDMode( wide, tall )) + { + Cvar_SetFloat( "fullscreen", 1.0f ); + return true; + }*/ + return false; +} + +void CEngineSurface :: setWindowedMode( void ) +{ + // Skip it now. VGUI cannot change video modes + /* + Cvar_SetFloat( "fullscreen", 0.0f ); + */ +}