diff --git a/.gitmodules b/.gitmodules index 25dfc14..5863fcf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "vgui-dev"] path = vgui-dev url = https://github.com/FWGS/vgui-dev +[submodule "vgui2-dev"] + path = vgui2-dev + url = https://github.com/FWGS/vgui2-dev.git diff --git a/vgui2-dev b/vgui2-dev new file mode 160000 index 0000000..6fde440 --- /dev/null +++ b/vgui2-dev @@ -0,0 +1 @@ +Subproject commit 6fde44035c31c0ed098bdbd907bda6627846651d diff --git a/vgui2_gameui.cpp b/vgui2_gameui.cpp new file mode 100644 index 0000000..7e0eac9 --- /dev/null +++ b/vgui2_gameui.cpp @@ -0,0 +1,70 @@ +/* +vgui2_gameui.cpp - implement IGameUIFuncs for vgui2 support +Copyright (C) 2022 FWGS + +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" +#include "vgui2_gameui.h" + +bool GameUIFuncs::IsKeyDown( const char *keyname, bool &isdown ) +{ + isdown = false; + return false; +} + +const char *GameUIFuncs::Key_NameForKey( int keynum ) +{ + return ""; +} + +const char *GameUIFuncs::Key_BindingForKey( int keynum ) +{ + return ""; +} + +vgui2::KeyCode GameUIFuncs::GetVGUI2KeyCodeForBind( const char *bind ) +{ + return vgui2::KEY_TAB; +} + +void GameUIFuncs::GetVideoModes( vmode_t **liststart, int *count ) +{ +} + +void GameUIFuncs::GetCurrentVideoMode( int *wide, int *tall, int *bpp ) +{ +} + +void GameUIFuncs::GetCurrentRenderer( char *name, int namelen, int *windowed, int *hdmodels, int *addons_folder, int *vid_level ) +{ +} + +bool GameUIFuncs::IsConnectedToVACSecureServer() +{ + return false; +} + +int GameUIFuncs::Key_KeyStringToKeyNum( const char *pchKey ) +{ + return 0; +} diff --git a/vgui2_gameui.h b/vgui2_gameui.h new file mode 100644 index 0000000..f8010b9 --- /dev/null +++ b/vgui2_gameui.h @@ -0,0 +1,45 @@ +/* +vgui2_gameui.h - vgui2 GameUIFuncs header +Copyright (C) 2022 FWGS + +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 VGUI2_GAMEUI_H +#define VGUI2_GAMEUI_H + +#include + +class GameUIFuncs : public IGameUIFuncs +{ +public: + bool IsKeyDown( const char *keyname, bool &isdown ) override; + const char *Key_NameForKey( int keynum ) override; + const char *Key_BindingForKey( int keynum ) override; + vgui2::KeyCode GetVGUI2KeyCodeForBind( const char *bind ) override; + void GetVideoModes( vmode_t **liststart, int *count ) override; + void GetCurrentVideoMode( int *wide, int *tall, int *bpp ) override; + void GetCurrentRenderer( char *name, int namelen, int *windowed, int *hdmodels, int *addons_folder, int *vid_level ) override; + bool IsConnectedToVACSecureServer() override; + int Key_KeyStringToKeyNum( const char *pchKey ) override; +}; + +#endif // VGUI2_GAMEUI_H diff --git a/vgui2_int.cpp b/vgui2_int.cpp new file mode 100644 index 0000000..703738a --- /dev/null +++ b/vgui2_int.cpp @@ -0,0 +1,387 @@ +/* +vgui2_int.cpp - vgui2 dll interaction +Copyright (C) 2022 FWGS + +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 +#include +#include +#include +#include "vgui_main.h" +#include "vgui2_surf.h" +#include "vgui2_gameui.h" +#include "filesystem.h" + +namespace vgui_support +{ +class RootPanel : public vgui2::Panel +{ +public: + RootPanel( vgui2::Panel *parent, const char *panelName ) : vgui2::Panel( parent, panelName ) { } + + vgui2::VPANEL IsWithinTraverse( int x, int y, bool traversePopups ) override + { + auto panel = vgui2::Panel::IsWithinTraverse( x, y, traversePopups ); + if( panel == GetVPanel() ) + return 0; + + return panel; + } +}; + +class BaseUI : public IBaseUI +{ +public: + BaseUI() : initialized( 0 ), numFactories( 0 ) { } + void Initialize( CreateInterfaceFn *factories, int count ) override; + void Start( int width, int height ) override; + void Shutdown() override; + int Key_Event( int down, int keynum, const char *pszCurrentBinding ) override; + void CallEngineSurfaceAppHandler( void *event, void *userData ) override; + void Paint( int x, int y, int right, int bottom ) override; + void HideGameUI() override; + void ActivateGameUI() override; + void HideConsole() override; + void ShowConsole() override; + +private: + static constexpr int MAX_NUM_FACTORIES = 6; + + int initialized; + CreateInterfaceFn factoryList[MAX_NUM_FACTORIES]; + int numFactories; + void *vgui2Module; + void *chromeModule; +}; + +static RootPanel *rootPanel; +static IClientVGUI *clientVGUI; +static void *fileSystemModule; +static fs_api_t *fs; + +static VGUI2Surface vgui2Surface; +static BaseUI baseUI; +static GameUIFuncs gameUIFuncs; + +static inline void *LoadModule( const char *module ) +{ + return g_api->LoadLibrary( module, false, false ); +} + +static inline CreateInterfaceFn GetFactory( void *module ) +{ + return (CreateInterfaceFn)g_api->GetProcAddress( module, "CreateInterface" ); +} + +static inline void UnloadModule( void *module ) +{ + g_api->FreeLibrary( module ); +} + +void BaseUI::Initialize( CreateInterfaceFn *factories, int count ) +{ + if( initialized ) + return; + + vgui2Module = LoadModule( "vgui2." OS_LIB_EXT ); + chromeModule = LoadModule( "chromehtml." OS_LIB_EXT ); + + // a1ba: make VGUI2 optional + if( !vgui2Module || !chromeModule ) + return; + + factoryList[numFactories++] = factories[0]; + factoryList[numFactories++] = GetFactory( vgui2Module ); + factoryList[numFactories++] = factories[1]; + factoryList[numFactories++] = GetFactory( chromeModule ); + + if( factories[2] != nullptr ) + { + factoryList[numFactories++] = factories[2]; + clientVGUI = (IClientVGUI *)factoryList[4]( VCLIENTVGUI_INTERFACE_VERSION, nullptr ); + } + + vgui2::InitializeVGui2Interfaces( "BaseUI", factoryList, numFactories ); + + initialized = 1; +} + +void BaseUI::Start( int width, int height ) +{ + if( !initialized ) + return; + + rootPanel = new RootPanel( nullptr, "RootPanel" ); + rootPanel->SetCursor( vgui2::dc_none ); + rootPanel->SetBounds( 0, 0, width, height ); + rootPanel->SetPaintBorderEnabled( false ); + rootPanel->SetPaintBackgroundEnabled( false ); + rootPanel->SetPaintEnabled( false ); + rootPanel->SetVisible( true ); + rootPanel->SetZPos( 0 ); + + auto chromeController = (IHTMLChromeController *)factoryList[3]( CHROME_HTML_CONTROLLER_INTERFACE_VERSION, nullptr ); + vgui2Surface.Init( rootPanel->GetVPanel(), chromeController ); + vgui2Surface.SetIgnoreMouseVisCalc( true ); + + vgui2::scheme()->LoadSchemeFromFile( "resource/trackerscheme.res", "BaseUI" ); + + vgui2::localize()->AddFile( vgui2::filesystem(), "resource/platform_%language%.txt" ); + vgui2::localize()->AddFile( vgui2::filesystem(), "resource/vgui_%language%.txt" ); + vgui2::localize()->AddFile( vgui2::filesystem(), "resource/gameui_%language%.txt" ); + vgui2::localize()->AddFile( vgui2::filesystem(), "resource/valve_%language%.txt" ); + + char szMod[32]; + // doesn't work on Linux + // vgui2::system()->GetCommandLineParamValue( "-game", szMod, sizeof( szMod ) ); + Q_strncpy( szMod, fs->GetFileSystemGlobals()->GameInfo->gamefolder, sizeof( szMod )); + char szLocalizeFile[260]; + + Q_snprintf( szLocalizeFile, sizeof( szLocalizeFile ), "resource/%s_%%language%%.txt", szMod ); + vgui2::localize()->AddFile( vgui2::filesystem(), szLocalizeFile ); + + // TODO: Load localization from fallback directory + + vgui2::ivgui()->Start(); + vgui2::ivgui()->SetSleep( false ); + + if( clientVGUI ) + clientVGUI->Initialize( factoryList, numFactories ); + + rootPanel->SetScheme( "ClientScheme" ); + + if( clientVGUI ) + { + clientVGUI->Start(); + clientVGUI->SetParent( rootPanel->GetVPanel() ); + } + + vgui2Surface.SetIgnoreMouseVisCalc( false ); +} + +void BaseUI::Shutdown() +{ + if( !initialized ) + return; + + vgui2::ivgui()->RunFrame(); + vgui2::ivgui()->Shutdown(); + + if( clientVGUI ) + { + clientVGUI->Shutdown(); + clientVGUI = nullptr; + } + + vgui2::system()->SaveUserConfigFile(); + vgui2::surface()->Shutdown(); + + UnloadModule( chromeModule ); + chromeModule = nullptr; + UnloadModule( vgui2Module ); + vgui2Module = nullptr; +} + +int BaseUI::Key_Event( int down, int keynum, const char *pszCurrentBinding ) +{ + if( !initialized ) + return 0; + + return vgui2::surface()->NeedKBInput(); +} + +void BaseUI::CallEngineSurfaceAppHandler( void *event, void *userData ) +{ +} + +void BaseUI::Paint( int x, int y, int right, int bottom ) +{ + if( !initialized ) + return; + + vgui2::VPANEL panel = vgui2::surface()->GetEmbeddedPanel(); + if( !panel ) + return; + + vgui2::ivgui()->RunFrame(); + vgui2Surface.SetScreenBounds( x, y, right - x, bottom - y ); + rootPanel->SetBounds( 0, 0, right, bottom ); + rootPanel->Repaint(); + vgui2::surface()->PaintTraverse( panel ); + vgui2::surface()->CalculateMouseVisible(); +} + +void BaseUI::HideGameUI() +{ +} + +void BaseUI::ActivateGameUI() +{ +} + +void BaseUI::HideConsole() +{ +} + +void BaseUI::ShowConsole() +{ +} + +extern "C" EXPORT void *CreateInterface( const char *pName, int *pReturnCode ) +{ + if( pReturnCode ) + *pReturnCode = IFACE_OK; + + if( !Q_strcmp( pName, BASEUI_INTERFACE_VERSION ) ) + return &baseUI; + + if( !Q_strcmp( pName, VGUI_SURFACE_INTERFACE_VERSION ) ) + return &vgui2Surface; + + if( !Q_strcmp( pName, VENGINE_GAMEUIFUNCS_VERSION ) ) + return &gameUIFuncs; + + if( pReturnCode ) + *pReturnCode = IFACE_FAILED; + + return nullptr; +} + +void VGUI2_Startup( void *clientInstance, int width, int height ) +{ + if( rootPanel == nullptr && clientInstance != nullptr ) + { + fileSystemModule = LoadModule( "filesystem_stdio." OS_LIB_EXT ); + auto fileSystemFactory = GetFactory( fileSystemModule ); + fs = (fs_api_t *)fileSystemFactory( FS_API_CREATEINTERFACE_TAG, NULL ); + + CreateInterfaceFn factories[] = + { + CreateInterface, + fileSystemFactory, + GetFactory( clientInstance ) + }; + + baseUI.Initialize( factories, sizeof( factories ) / sizeof( factories[0] )); + baseUI.Start( width, height ); + } + + if( rootPanel != nullptr ) + rootPanel->SetBounds( 0, 0, width, height ); +} + +void VGUI2_Shutdown() +{ + if( rootPanel == nullptr ) + return; + + baseUI.Shutdown(); + fileSystemModule = nullptr; + fs = nullptr; +} + +void VGUI2_ScreenSize( int &width, int &height ) +{ + if( rootPanel ) + rootPanel->GetSize( width, height ); +} + +bool VGUI2_UseVGUI1( void ) +{ + if( clientVGUI ) + return clientVGUI->UseVGUI1(); + return true; +} + +void VGUI2_Paint( void ) +{ + if( rootPanel == nullptr ) + return; + + int wide, tall; + VGUI2_ScreenSize( wide, tall ); + baseUI.Paint( 0, 0, wide, tall ); +} + +void VGUI2_Key( VGUI_KeyAction action, VGUI_KeyCode code ) +{ + if( rootPanel == nullptr ) + return; + + if( !baseUI.Key_Event( action == KA_PRESSED, code + 1, "" ) ) + return; + + switch ( action ) + { + case KA_PRESSED: + vgui2::inputinternal()->InternalKeyCodePressed( ( vgui2::KeyCode )( code + 1 ) ); + break; + case KA_RELEASED: + vgui2::inputinternal()->InternalKeyCodeReleased( ( vgui2::KeyCode )( code + 1 ) ); + break; + case KA_TYPED: + vgui2::inputinternal()->InternalKeyCodeTyped( ( vgui2::KeyCode )( code + 1 ) ); + break; + } +} + +void VGUI2_Mouse( VGUI_MouseAction action, int code ) +{ + if( rootPanel == nullptr ) + return; + + if( !vgui2::surface()->IsCursorVisible() ) + return; + + switch ( action ) + { + case MA_PRESSED: + vgui2::inputinternal()->InternalMousePressed( (vgui2::MouseCode)code ); + break; + case MA_RELEASED: + vgui2::inputinternal()->InternalMouseReleased( (vgui2::MouseCode)code ); + break; + case MA_DOUBLE: + vgui2::inputinternal()->InternalMouseDoublePressed( (vgui2::MouseCode)code ); + break; + case MA_WHEEL: + vgui2::inputinternal()->InternalMouseWheeled( code ); + break; + } +} + +void VGUI2_MouseMove( int x, int y ) +{ + if( rootPanel == nullptr ) + return; + + vgui2::inputinternal()->InternalCursorMoved( x, y ); +} + +void VGUI2_TextInput( const char *text ) +{ + for( const char *c = text; *c; c++ ) + vgui2::inputinternal()->InternalKeyTyped( *c ); +} +} // namespace vgui_support diff --git a/vgui2_surf.cpp b/vgui2_surf.cpp new file mode 100644 index 0000000..20417f9 --- /dev/null +++ b/vgui2_surf.cpp @@ -0,0 +1,806 @@ +/* +vgui2_surf.cpp - vgui2 surface implementation +Copyright (C) 2022 FWGS + +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 +#include +#include "vgui_main.h" +#include "vgui2_surf.h" + +using namespace vgui_support; + +static const auto VPANEL_NORMAL = ( (vgui2::SurfacePlat *)NULL ); +static const auto VPANEL_MINIMIZED = ( (vgui2::SurfacePlat *)0x00000001 ); + +void VGUI2Surface::Shutdown() +{ + if( chromeController ) + chromeController->Shutdown(); +} + +void VGUI2Surface::RunFrame() +{ + if( chromeController ) + chromeController->RunFrame(); +} + +vgui2::VPANEL VGUI2Surface::GetEmbeddedPanel() +{ + return embeddedPanel; +} + +void VGUI2Surface::SetEmbeddedPanel( vgui2::VPANEL panel ) +{ + embeddedPanel = panel; +} + +void VGUI2Surface::PushMakeCurrent( vgui2::VPANEL panel, bool useInsets ) +{ + int insets[4] = { 0, 0, 0, 0 }; + int absExtents[4]; + int clipRect[4]; + int wide, tall; + + if( useInsets ) + vgui2::ipanel()->GetInset( panel, insets[0], insets[1], insets[2], insets[3] ); + + vgui2::ipanel()->GetAbsPos( panel, absExtents[0], absExtents[1] ); + vgui2::ipanel()->GetSize( panel, wide, tall ); + absExtents[2] = absExtents[0] + wide; + absExtents[3] = absExtents[1] + tall; + + vgui2::ipanel()->GetClipRect( panel, clipRect[0], clipRect[1], clipRect[2], clipRect[3] ); + + VGUIPanel p( panel ); + surface->PushMakeCurrent( p, insets, absExtents, clipRect ); +} + +void VGUI2Surface::PopMakeCurrent( vgui2::VPANEL panel ) +{ + VGUIPanel p( panel ); + surface->PopMakeCurrent( p ); +} + +void VGUI2Surface::DrawSetColor( int r, int g, int b, int a ) +{ + // VGUI2 inverts alpha + + surface->drawSetColor( r, g, b, 255 - a ); +} + +void VGUI2Surface::DrawSetColor( Color col ) +{ + DrawSetColor( col[0], col[1], col[2], col[3] ); +} + +void VGUI2Surface::DrawFilledRect( int x0, int y0, int x1, int y1 ) +{ + surface->drawFilledRect( x0, y0, x1, y1 ); +} + +void VGUI2Surface::DrawOutlinedRect( int x0, int y0, int x1, int y1 ) +{ + surface->drawOutlinedRect( x0, y0, x1, y1 ); +} + +void VGUI2Surface::DrawLine( int x0, int y0, int x1, int y1 ) +{ + surface->drawLine( x0, y0, x1, y1 ); +} + +void VGUI2Surface::DrawPolyLine( int *px, int *py, int numPoints ) +{ + surface->drawPolyLine( px, py, numPoints ); +} + +void VGUI2Surface::DrawSetTextFont( vgui2::HFont font ) +{ + surface->drawSetTextFont( font ); +} + +void VGUI2Surface::DrawSetTextColor( int r, int g, int b, int a ) +{ + surface->drawSetTextColor( r, g, b, 255 - a ); +} + +void VGUI2Surface::DrawSetTextColor( Color col ) +{ + DrawSetTextColor( col[0], col[1], col[2], col[3] ); +} + +void VGUI2Surface::DrawSetTextPos( int x, int y ) +{ + surface->drawSetTextPos( x, y ); +} + +void VGUI2Surface::DrawGetTextPos( int &x, int &y ) +{ + surface->drawGetTextPos( x, y ); +} + +void VGUI2Surface::DrawPrintText( const wchar_t *text, int textLen ) +{ + if( !text || textLen <= 0 ) + return; + + auto str = new char[textLen + 1]; + + wcstombs( str, text, textLen ); + surface->drawPrintText( str, textLen ); + + delete[] str; + // engineSurface->DrawPrintText( text, textLen ); +} + +void VGUI2Surface::DrawUnicodeChar( wchar_t wch ) +{ + char s[16]; // MB_CUR_MAX makes it VLA + auto len = wctomb( s, wch ); + + surface->drawPrintText( s, len ); +} + +void VGUI2Surface::DrawUnicodeCharAdd( wchar_t wch ) +{ + // TODO: any difference? + DrawUnicodeChar( wch ); +} + +void VGUI2Surface::DrawFlushText() +{ + // TODO: stub +} + +vgui2::IHTML *VGUI2Surface::CreateHTMLWindow( vgui2::IHTMLEvents *events, vgui2::VPANEL context ) +{ + return nullptr; +} + +void VGUI2Surface::PaintHTMLWindow( vgui2::IHTML *htmlwin ) +{ +} + +void VGUI2Surface::DeleteHTMLWindow( vgui2::IHTML *htmlwin ) +{ +} + +void VGUI2Surface::DrawSetTextureFile( int id, const char *filename, int hardwareFilter, bool forceReload ) +{ + surface->drawSetTextureFile( id, filename ); +} + +void VGUI2Surface::DrawSetTextureRGBA( int id, const unsigned char *rgba, int wide, int tall, int hardwareFilter, bool forceReload ) +{ + surface->drawSetTextureRGBA( id, (const char *)rgba, wide, tall ); +} + +void VGUI2Surface::DrawSetTexture( int id ) +{ + surface->drawSetTexture( id ); +} + +void VGUI2Surface::DrawGetTextureSize( int id, int &wide, int &tall ) +{ + surface->drawGetTextureSize( id, wide, tall ); +} + +void VGUI2Surface::DrawTexturedRect( int x0, int y0, int x1, int y1 ) +{ + surface->drawTexturedRect( x0, y0, x1, y1 ); +} + +bool VGUI2Surface::IsTextureIDValid( int id ) +{ + // TODO: do anything here? + return true; +} + +int VGUI2Surface::CreateNewTextureID( bool procedural ) +{ + return surface->createNewTextureID(); +} + +void VGUI2Surface::GetScreenSize( int &wide, int &tall ) +{ + VGUI2_ScreenSize( wide, tall ); +} + +void VGUI2Surface::SetAsTopMost( vgui2::VPANEL panel, bool state ) +{ +} + +void VGUI2Surface::BringToFront( vgui2::VPANEL panel ) +{ + vgui2::ipanel()->MoveToFront( panel ); + + if( vgui2::ipanel()->IsPopup( panel ) ) + MovePopupToFront( panel ); +} + +void VGUI2Surface::SetForegroundWindow( vgui2::VPANEL panel ) +{ + BringToFront( panel ); +} + +void VGUI2Surface::SetPanelVisible( vgui2::VPANEL panel, bool state ) +{ +} + +void VGUI2Surface::SetMinimized( vgui2::VPANEL panel, bool state ) +{ + if( !state ) + { + vgui2::ipanel()->SetPlat( panel, VPANEL_NORMAL ); + return; + } + + vgui2::ipanel()->SetPlat( panel, VPANEL_MINIMIZED ); + vgui2::ipanel()->SetVisible( panel, false ); +} + +bool VGUI2Surface::IsMinimized( vgui2::VPANEL panel ) +{ + return vgui2::ipanel()->Plat( panel ) == VPANEL_MINIMIZED; +} + +void VGUI2Surface::FlashWindow( vgui2::VPANEL panel, bool state ) +{ +} + +void VGUI2Surface::SetTitle( vgui2::VPANEL panel, const wchar_t *title ) +{ +} + +void VGUI2Surface::SetAsToolBar( vgui2::VPANEL panel, bool state ) +{ +} + +void VGUI2Surface::CreatePopup( vgui2::VPANEL panel, bool minimised, bool showTaskbarIcon, bool disabled, bool mouseInput, bool kbInput ) +{ + if( vgui2::ipanel()->GetParent( panel ) == NULL ) + vgui2::ipanel()->SetParent( panel, GetEmbeddedPanel() ); + + vgui2::ipanel()->SetPopup( panel, true ); + vgui2::ipanel()->SetKeyBoardInputEnabled( panel, kbInput ); + vgui2::ipanel()->SetMouseInputEnabled( panel, mouseInput ); + + if( !popups.hasElement( panel ) ) + popups.addElement( panel ); +} + +void VGUI2Surface::SwapBuffers( vgui2::VPANEL panel ) +{ +} + +void VGUI2Surface::Invalidate( vgui2::VPANEL panel ) +{ +} + +void VGUI2Surface::SetCursor( vgui2::HCursor cursor ) +{ + // These cursors are not available in VGUI1, so ignore them for now. + if( cursor >= vgui2::dc_last || cursor == vgui2::dc_waitarrow || cursor == vgui2::dc_blank ) + return; + + if( currentCursor != cursor ) + { + currentCursor = cursor; + + // Hack to make it compatible with VGUI1 + if( cursor > vgui2::dc_waitarrow ) + --cursor; + + g_api->CursorSelect( (VGUI_DefaultCursor)cursor ); + } +} + +bool VGUI2Surface::IsCursorVisible() +{ + return currentCursor != vgui2::dc_none; +} + +void VGUI2Surface::ApplyChanges() +{ +} + +bool VGUI2Surface::IsWithin( int x, int y ) +{ + return true; +} + +bool VGUI2Surface::HasFocus() +{ + return true; +} + +bool VGUI2Surface::SupportsFeature( SurfaceFeature_e feature ) +{ + return false; +} + +void VGUI2Surface::RestrictPaintToSinglePanel( vgui2::VPANEL panel ) +{ + restrictedPanel = panel; + vgui2::input()->SetAppModalSurface( panel ); +} + +void VGUI2Surface::SetModalPanel( vgui2::VPANEL panel ) +{ +} + +vgui2::VPANEL VGUI2Surface::GetModalPanel() +{ + return restrictedPanel; +} + +void VGUI2Surface::UnlockCursor() +{ + cursorLocked = false; +} + +void VGUI2Surface::LockCursor() +{ + cursorLocked = true; +} + +void VGUI2Surface::SetTranslateExtendedKeys( bool state ) +{ + translateExtendedKeys = state; +} + +vgui2::VPANEL VGUI2Surface::GetTopmostPopup() +{ + if( popups.getCount() > 0 ) + return popups[popups.getCount() - 1]; + + return NULL; +} + +void VGUI2Surface::SetTopLevelFocus( vgui2::VPANEL panel ) +{ + while ( panel ) + { + if( vgui2::ipanel()->IsPopup( panel ) && vgui2::ipanel()->IsMouseInputEnabled( panel ) ) + { + BringToFront( panel ); + break; + } + + panel = vgui2::ipanel()->GetParent( panel ); + } +} + +vgui2::HFont VGUI2Surface::CreateFont() +{ + return surface->createFont(); +} + +bool VGUI2Surface::AddGlyphSetToFont( vgui2::HFont font, const char *fontName, int tall, int weight, int blur, int scanlines, int flags, int lowRange, int highRange ) +{ + return surface->addGlyphSetToFont( font, fontName, tall, weight, flags & FONTFLAG_ITALIC, flags & FONTFLAG_UNDERLINE, flags & FONTFLAG_STRIKEOUT, flags & FONTFLAG_SYMBOL ); +} + +bool VGUI2Surface::AddCustomFontFile( const char *fontFileName ) +{ + return surface->addCustomFontFile( fontFileName ); +} + +int VGUI2Surface::GetFontTall( vgui2::HFont font ) +{ + return surface->getFontTall( font ); +} + +void VGUI2Surface::GetCharABCwide( vgui2::HFont font, int ch, int &a, int &b, int &c ) +{ + a = b = c = 1; + surface->getCharABCWide( font,ch, a, b, c ); +} + +int VGUI2Surface::GetCharacterWidth( vgui2::HFont font, int ch ) +{ + int a, b, c; + GetCharABCwide( font, ch, a, b, c ); + return a + b + c; +} + +void VGUI2Surface::GetTextSize( vgui2::HFont font, const wchar_t *text, int &wide, int &tall ) +{ + if( !text ) + { + wide = 1; + tall = 1; + return; + } + + auto len = wcslen( text ); + auto str = new char[len + 1]; + + wcstombs( str, text, len ); + surface->getTextSize( font, str, wide, tall ); + + delete[] str; +} + +vgui2::VPANEL VGUI2Surface::GetNotifyPanel() +{ + return NULL; +} + +void VGUI2Surface::SetNotifyIcon( vgui2::VPANEL context, vgui2::HTexture icon, vgui2::VPANEL panelToReceiveMessages, const char *text ) +{ +} + +void VGUI2Surface::PlaySound( const char *fileName ) +{ + surface->playSound( fileName ); +} + +int VGUI2Surface::GetPopupCount() +{ + return popups.getCount(); +} + +vgui2::VPANEL VGUI2Surface::GetPopup( int index ) +{ + if( 0 <= index && index < popups.getCount() ) + return popups[index]; + + return NULL; +} + +bool VGUI2Surface::ShouldPaintChildPanel( vgui2::VPANEL panel ) +{ + if( restrictedPanel != NULL && vgui2::ipanel()->HasParent( panel, restrictedPanel ) ) + return false; + + if( !vgui2::ipanel()->IsPopup( panel ) ) + return true; + + if( popups.hasElement( panel ) ) + vgui2::ipanel()->Render_SetPopupVisible( panel, true ); + + return false; +} + +bool VGUI2Surface::RecreateContext( vgui2::VPANEL panel ) +{ + return true; +} + +void VGUI2Surface::AddPanel( vgui2::VPANEL panel ) +{ + if( !vgui2::ipanel()->IsPopup( panel ) ) + return; + + CreatePopup( panel, false, false, false, true, true ); +} + +void VGUI2Surface::ReleasePanel( vgui2::VPANEL panel ) +{ + popups.removeElement( panel ); + + if( restrictedPanel == panel ) + restrictedPanel = NULL; +} + +void VGUI2Surface::MovePopupToFront( vgui2::VPANEL panel ) +{ + if( popups.hasElement( panel ) ) + { + popups.removeElement( panel ); + popups.addElement( panel ); + } +} + +void VGUI2Surface::MovePopupToBack( vgui2::VPANEL panel ) +{ + if( popups.hasElement( panel ) ) + { + popups.removeElement( panel ); + popups.insertElementAt( panel, 0 ); + } +} + +void VGUI2Surface::SolveTraverse( vgui2::VPANEL panel, bool forceApplySchemeSettings ) +{ + InternalSchemeSettingsTraverse( panel, forceApplySchemeSettings ); + InternalThinkTraverse( panel ); + InternalSolveTraverse( panel ); +} + +void VGUI2Surface::PaintTraverse( vgui2::VPANEL panel ) +{ + if( !vgui2::ipanel()->IsVisible( panel ) ) + return; + + if( panel != GetEmbeddedPanel() ) + { + vgui2::ipanel()->PaintTraverse( panel, true, true ); + return; + } + + if( restrictedPanel ) + panel = restrictedPanel; + + for( int i = 0; i < popups.getCount(); ++i ) + vgui2::ipanel()->Render_SetPopupVisible( popups[i], false ); + + vgui2::ipanel()->PaintTraverse( panel, true, true ); + + for( int i = 0; i < popups.getCount(); ++i ) + { + if( vgui2::ipanel()->Render_GetPopupVisible( popups[i] ) ) + vgui2::ipanel()->PaintTraverse( popups[i], true, true ); + } +} + +void VGUI2Surface::EnableMouseCapture( vgui2::VPANEL panel, bool state ) +{ +} + +void VGUI2Surface::GetWorkspaceBounds( int &x, int &y, int &wide, int &tall ) +{ + x = 0; + y = 0; + vgui2::ipanel()->GetSize( embeddedPanel, wide, tall ); +} + +void VGUI2Surface::GetAbsoluteWindowBounds( int &x, int &y, int &wide, int &tall ) +{ + x = surfaceBounds[0]; + y = surfaceBounds[1]; + wide = surfaceBounds[2]; + tall = surfaceBounds[3]; +} + +void VGUI2Surface::GetProportionalBase( int &width, int &height ) +{ + width = 640; + height = 480; +} + +void VGUI2Surface::CalculateMouseVisible() +{ + if( ignoreMouseVisCalc ) + return; + + needMouse = false; + needKB = false; + + for( int i = 0; i < popups.getCount(); ++i ) + { + bool visible = vgui2::ipanel()->IsVisible( popups[i] ); + vgui2::VPANEL parent = vgui2::ipanel()->GetParent( popups[i] ); + + while ( parent != NULL && visible ) + { + if( !vgui2::ipanel()->IsVisible( parent ) ) + { + visible = false; + break; + } + + parent = vgui2::ipanel()->GetParent( parent ); + } + + if( !visible ) + continue; + + // TODO: Uncomment these once fully implemented to enable input capture + needMouse = needMouse || vgui2::ipanel()->IsMouseInputEnabled( popups[i] ); + needKB = needKB || vgui2::ipanel()->IsKeyBoardInputEnabled( popups[i] ); + } + + UnlockCursor(); + + if( needMouse ) + { + SetCursor( vgui2::dc_arrow ); + } + else + { + SetCursor( vgui2::dc_none ); + LockCursor(); + } +} + +bool VGUI2Surface::NeedKBInput() +{ + return needKB; +} + +bool VGUI2Surface::HasCursorPosFunctions() +{ + return true; +} + +void VGUI2Surface::SurfaceGetCursorPos( int &x, int &y ) +{ + g_api->GetCursorPos( &x, &y ); +} + +void VGUI2Surface::SurfaceSetCursorPos( int x, int y ) +{ + // g_api->SetCursorPos( x, y ); +} + +void VGUI2Surface::DrawTexturedPolygon( vgui2::VGuiVertex *pVertices, int n ) +{ + surface->drawTexturedPolygon( pVertices, n ); +} + +int VGUI2Surface::GetFontAscent( vgui2::HFont font, wchar_t wch ) +{ + return surface->getFontAscent( font, wch ); +} + +void VGUI2Surface::SetAllowHTMLJavaScript( bool state ) +{ + allowJavaScript = state; +} + +void VGUI2Surface::SetLanguage( const char *pchLang ) +{ + if( pchLang != nullptr ) + { + Q_strncpy( language, pchLang, sizeof( language )); + } + else + { + Q_strncpy( language, "english", sizeof( language )); + } +} + +const char *VGUI2Surface::GetLanguage() +{ + return language; +} + +bool VGUI2Surface::DeleteTextureByID( int id ) +{ + return surface->deleteTextureByID( id ); +} + +void VGUI2Surface::DrawUpdateRegionTextureBGRA( int id, int x, int y, const unsigned char *bgra, int wide, int tall ) +{ + auto p = new unsigned char[wide * tall * 4]; + for( int i = 0; i < wide * tall * 4; i += 4 ) + { + p[i + 0] = bgra[i + 2]; + p[i + 1] = bgra[i + 1]; + p[i + 2] = bgra[i + 0]; + p[i + 3] = bgra[i + 3]; + } + surface->drawSubTextureRGBA( id, x, y, p, wide, tall ); + delete[] p; +} + +void VGUI2Surface::DrawSetTextureBGRA( int id, const unsigned char *bgra, int wide, int tall ) +{ + auto p = new unsigned char[wide * tall * 4]; + for( int i = 0; i < wide * tall * 4; i += 4 ) + { + p[i + 0] = bgra[i + 2]; + p[i + 1] = bgra[i + 1]; + p[i + 2] = bgra[i + 0]; + p[i + 3] = bgra[i + 3]; + } + surface->drawSetTextureRGBA( id, (const char *)p, wide, tall ); + delete[] p; +} + +void VGUI2Surface::CreateBrowser( vgui2::VPANEL panel, IHTMLResponses *pBrowser, bool bPopupWindow, const char *pchUserAgentIdentifier ) +{ + if( chromeController ) + chromeController->CreateBrowser( pBrowser, false, "Valve Half-Life" ); +} + +void VGUI2Surface::RemoveBrowser( vgui2::VPANEL panel, IHTMLResponses *pBrowser ) +{ + if( chromeController ) + chromeController->RemoveBrowser( pBrowser ); +} + +IHTMLChromeController *VGUI2Surface::AccessChromeHTMLController() +{ + return chromeController; +} + +VGUI2Surface::VGUI2Surface() +{ + embeddedPanel = NULL; + restrictedPanel = NULL; + chromeController = nullptr; + allowJavaScript = false; + cursorLocked = false; + translateExtendedKeys = true; + ignoreMouseVisCalc = false; + currentCursor = vgui2::dc_none; + + // TODO: Change these to true once fully implemented to enable input capture + needKB = false; + needMouse = false; +} + +void VGUI2Surface::Init( vgui2::VPANEL _embeddedPanel, IHTMLChromeController *pChromeController ) +{ + SetEmbeddedPanel( _embeddedPanel ); + + chromeController = pChromeController; + if( chromeController ) + { + chromeController->Init( "htmlcache", "htmlcookies" ); + chromeController->SetCefThreadTargetFrameRate( 60 ); + } +} + +void VGUI2Surface::SetScreenBounds( int x, int y, int wide, int tall ) +{ + surfaceBounds[0] = x; + surfaceBounds[1] = y; + surfaceBounds[2] = wide; + surfaceBounds[3] = tall; +} + +void VGUI2Surface::SetIgnoreMouseVisCalc( bool state ) +{ + ignoreMouseVisCalc = state; +} + +void VGUI2Surface::InternalSchemeSettingsTraverse( vgui2::VPANEL panel, bool forceApplySchemeSettings ) +{ + for( int i = 0; i < vgui2::ipanel()->GetChildCount( panel ); ++i ) + { + vgui2::VPANEL child = vgui2::ipanel()->GetChild( panel, i ); + if( forceApplySchemeSettings || vgui2::ipanel()->IsVisible( child ) ) + InternalSchemeSettingsTraverse( child, forceApplySchemeSettings ); + } + + vgui2::ipanel()->PerformApplySchemeSettings( panel ); +} + +void VGUI2Surface::InternalThinkTraverse( vgui2::VPANEL panel ) +{ + vgui2::ipanel()->Think( panel ); + + for( int i = 0; i < vgui2::ipanel()->GetChildCount( panel ); ++i ) + { + vgui2::VPANEL child = vgui2::ipanel()->GetChild( panel, i ); + if( vgui2::ipanel()->IsVisible( child ) ) + InternalThinkTraverse( child ); + } +} + +void VGUI2Surface::InternalSolveTraverse( vgui2::VPANEL panel ) +{ + vgui2::ipanel()->Solve( panel ); + + for( int i = 0; i < vgui2::ipanel()->GetChildCount( panel ); ++i ) + { + vgui2::VPANEL child = vgui2::ipanel()->GetChild( panel, i ); + if( vgui2::ipanel()->IsVisible( child ) ) + InternalSolveTraverse( child ); + } +} diff --git a/vgui2_surf.h b/vgui2_surf.h new file mode 100644 index 0000000..571f122 --- /dev/null +++ b/vgui2_surf.h @@ -0,0 +1,163 @@ +/* +vgui2_surf.cpp - vgui2 surface header +Copyright (C) 2022 FWGS + +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 VGUI2_SURFACE_H +#define VGUI2_SURFACE_H + +#include +#include +#include +#include + +namespace vgui_support +{ +class VGUI2Surface : public vgui2::ISurface +{ +public: + void Shutdown() override; + void RunFrame() override; + vgui2::VPANEL GetEmbeddedPanel() override; + void SetEmbeddedPanel( vgui2::VPANEL panel ) override; + void PushMakeCurrent( vgui2::VPANEL panel, bool useInsets ) override; + void PopMakeCurrent( vgui2::VPANEL panel ) override; + void DrawSetColor( int r, int g, int b, int a ) override; + void DrawSetColor( Color col ) override; + void DrawFilledRect( int x0, int y0, int x1, int y1 ) override; + void DrawOutlinedRect( int x0, int y0, int x1, int y1 ) override; + void DrawLine( int x0, int y0, int x1, int y1 ) override; + void DrawPolyLine( int *px, int *py, int numPoints ) override; + void DrawSetTextFont( vgui2::HFont font ) override; + void DrawSetTextColor( int r, int g, int b, int a ) override; + void DrawSetTextColor( Color col ) override; + void DrawSetTextPos( int x, int y ) override; + void DrawGetTextPos( int &x, int &y ) override; + void DrawPrintText( const wchar_t *text, int textLen ) override; + void DrawUnicodeChar( wchar_t wch ) override; + void DrawUnicodeCharAdd( wchar_t wch ) override; + void DrawFlushText() override; + vgui2::IHTML *CreateHTMLWindow( vgui2::IHTMLEvents *events, vgui2::VPANEL context ) override; + void PaintHTMLWindow( vgui2::IHTML *htmlwin ) override; + void DeleteHTMLWindow( vgui2::IHTML *htmlwin ) override; + void DrawSetTextureFile( int id, const char *filename, int hardwareFilter, bool forceReload ) override; + void DrawSetTextureRGBA( int id, const unsigned char *rgba, int wide, int tall, int hardwareFilter, bool forceReload ) override; + void DrawSetTexture( int id ) override; + void DrawGetTextureSize( int id, int &wide, int &tall ) override; + void DrawTexturedRect( int x0, int y0, int x1, int y1 ) override; + bool IsTextureIDValid( int id ) override; + int CreateNewTextureID( bool procedural ) override; + void GetScreenSize( int &wide, int &tall ) override; + void SetAsTopMost( vgui2::VPANEL panel, bool state ) override; + void BringToFront( vgui2::VPANEL panel ) override; + void SetForegroundWindow( vgui2::VPANEL panel ) override; + void SetPanelVisible( vgui2::VPANEL panel, bool state ) override; + void SetMinimized( vgui2::VPANEL panel, bool state ) override; + bool IsMinimized( vgui2::VPANEL panel ) override; + void FlashWindow( vgui2::VPANEL panel, bool state ) override; + void SetTitle( vgui2::VPANEL panel, const wchar_t *title ) override; + void SetAsToolBar( vgui2::VPANEL panel, bool state ) override; + void CreatePopup( vgui2::VPANEL panel, bool minimised, bool showTaskbarIcon, bool disabled, bool mouseInput, bool kbInput ) override; + void SwapBuffers( vgui2::VPANEL panel ) override; + void Invalidate( vgui2::VPANEL panel ) override; + void SetCursor( vgui2::HCursor cursor ) override; + bool IsCursorVisible() override; + void ApplyChanges() override; + bool IsWithin( int x, int y ) override; + bool HasFocus() override; + bool SupportsFeature( SurfaceFeature_e feature ) override; + void RestrictPaintToSinglePanel( vgui2::VPANEL panel ) override; + void SetModalPanel( vgui2::VPANEL panel ) override; + vgui2::VPANEL GetModalPanel() override; + void UnlockCursor() override; + void LockCursor() override; + void SetTranslateExtendedKeys( bool state ) override; + vgui2::VPANEL GetTopmostPopup() override; + void SetTopLevelFocus( vgui2::VPANEL panel ) override; + vgui2::HFont CreateFont() override; + bool AddGlyphSetToFont( vgui2::HFont font, const char *fontName, int tall, int weight, int blur, int scanlines, int flags, int lowRange, int highRange ) override; + bool AddCustomFontFile( const char *fontFileName ) override; + int GetFontTall( vgui2::HFont font ) override; + void GetCharABCwide( vgui2::HFont font, int ch, int &a, int &b, int &c ) override; + int GetCharacterWidth( vgui2::HFont font, int ch ) override; + void GetTextSize( vgui2::HFont font, const wchar_t *text, int &wide, int &tall ) override; + vgui2::VPANEL GetNotifyPanel() override; + void SetNotifyIcon( vgui2::VPANEL context, vgui2::HTexture icon, vgui2::VPANEL panelToReceiveMessages, const char *text ) override; + void PlaySound( const char *fileName ) override; + int GetPopupCount() override; + vgui2::VPANEL GetPopup( int index ) override; + bool ShouldPaintChildPanel( vgui2::VPANEL panel ) override; + bool RecreateContext( vgui2::VPANEL panel ) override; + void AddPanel( vgui2::VPANEL panel ) override; + void ReleasePanel( vgui2::VPANEL panel ) override; + void MovePopupToFront( vgui2::VPANEL panel ) override; + void MovePopupToBack( vgui2::VPANEL panel ) override; + void SolveTraverse( vgui2::VPANEL panel, bool forceApplySchemeSettings ) override; + void PaintTraverse( vgui2::VPANEL panel ) override; + void EnableMouseCapture( vgui2::VPANEL panel, bool state ) override; + void GetWorkspaceBounds( int &x, int &y, int &wide, int &tall ) override; + void GetAbsoluteWindowBounds( int &x, int &y, int &wide, int &tall ) override; + void GetProportionalBase( int &width, int &height ) override; + void CalculateMouseVisible() override; + bool NeedKBInput() override; + bool HasCursorPosFunctions() override; + void SurfaceGetCursorPos( int &x, int &y ) override; + void SurfaceSetCursorPos( int x, int y ) override; + void DrawTexturedPolygon( vgui2::VGuiVertex *pVertices, int n ) override; + int GetFontAscent( vgui2::HFont font, wchar_t wch ) override; + void SetAllowHTMLJavaScript( bool state ) override; + void SetLanguage( const char *pchLang ) override; + const char *GetLanguage() override; + bool DeleteTextureByID( int id ) override; + void DrawUpdateRegionTextureBGRA( int nTextureID, int x, int y, const unsigned char *pchData, int wide, int tall ) override; + void DrawSetTextureBGRA( int id, const unsigned char *bgra, int wide, int tall ) override; + void CreateBrowser( vgui2::VPANEL panel, IHTMLResponses *pBrowser, bool bPopupWindow, const char *pchUserAgentIdentifier ) override; + void RemoveBrowser( vgui2::VPANEL panel, IHTMLResponses *pBrowser ) override; + IHTMLChromeController *AccessChromeHTMLController() override; + + VGUI2Surface(); + void Init( vgui2::VPANEL _embeddedPanel, IHTMLChromeController *pChromeController ); + void SetScreenBounds( int x, int y, int wide, int tall ); + void SetIgnoreMouseVisCalc( bool state ); + void InternalSchemeSettingsTraverse( vgui2::VPANEL panel, bool forceApplySchemeSettings ); + void InternalThinkTraverse( vgui2::VPANEL panel ); + void InternalSolveTraverse( vgui2::VPANEL panel ); + +private: + vgui2::VPANEL embeddedPanel; + vgui2::VPANEL restrictedPanel; + char language[32]; + IHTMLChromeController *chromeController; + int surfaceBounds[4]; + vgui::Dar popups; + bool allowJavaScript; + bool needKB; + bool needMouse; + bool cursorLocked; + bool translateExtendedKeys; + bool ignoreMouseVisCalc; + vgui2::HCursor currentCursor; +}; +} // vgui_support + +#endif // VGUI2_SURFACE_H diff --git a/vgui_input.cpp b/vgui_input.cpp index 0a6ee74..f5138de 100644 --- a/vgui_input.cpp +++ b/vgui_input.cpp @@ -24,68 +24,85 @@ 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) +namespace vgui_support +{ +void VGUI_Key( VGUI_KeyAction action, VGUI_KeyCode code ) { - App *pApp = App::getInstance(); - if(!surface) + if( !VGUI2_UseVGUI1( )) + { + VGUI2_Key( action, code ); + return; + } + + if( !surface ) return; + + vgui::App *pApp = vgui::App::getInstance(); + switch( action ) { case KA_PRESSED: - pApp->internalKeyPressed( (KeyCode) code, surface ); + pApp->internalKeyPressed((vgui::KeyCode)code, surface ); break; case KA_RELEASED: - pApp->internalKeyReleased( (KeyCode) code, surface ); + pApp->internalKeyReleased((vgui::KeyCode)code, surface ); break; case KA_TYPED: - pApp->internalKeyTyped( (KeyCode) code, surface ); + pApp->internalKeyTyped((vgui::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) +void VGUI_Mouse( VGUI_MouseAction action, int code ) { - App *pApp = App::getInstance(); - if(!surface) + if( !VGUI2_UseVGUI1( )) + { + VGUI2_Mouse( action, code ); return; + } + + if( !surface ) + return; + + vgui::App *pApp = vgui::App::getInstance(); + switch( action ) { case MA_PRESSED: - pApp->internalMousePressed( (MouseCode) code, surface ); + pApp->internalMousePressed((vgui::MouseCode)code, surface ); break; case MA_RELEASED: - pApp->internalMouseReleased( (MouseCode) code, surface ); + pApp->internalMouseReleased((vgui::MouseCode)code, surface ); break; case MA_DOUBLE: - pApp->internalMouseDoublePressed( (MouseCode) code, surface ); + pApp->internalMouseDoublePressed((vgui::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) +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) + if( !VGUI2_UseVGUI1( )) + { + VGUI2_MouseMove( x, y ); + return; + } + + if( !surface ) return; - pApp->internalCursorMoved( x, y, surface ); + + vgui::App::getInstance()->internalCursorMoved( x, y, surface ); } -void VGUI_TextInput(const char *text) +void VGUI_TextInput( const char *text ) { - // stub -} + if( !VGUI2_UseVGUI1( )) + VGUI2_TextInput( text ); } + +} // namespace vgui_support diff --git a/vgui_int.cpp b/vgui_int.cpp index 1506767..f3343e7 100644 --- a/vgui_int.cpp +++ b/vgui_int.cpp @@ -25,18 +25,38 @@ from your version. #include "vgui_main.h" #include "xash3d_types.h" -namespace vgui_support { -vguiapi_t *g_api; +using namespace vgui; -Panel *rootpanel = NULL; -CEngineSurface *surface = NULL; -CEngineApp staticApp; +namespace vgui_support +{ +vgui_support_api_t *g_api; +CEngineSurface *surface = nullptr; + +static Panel *rootpanel = nullptr; +static class CEngineApp : public App +{ +public: + explicit CEngineApp( bool externalMain = true ); + void main( int argc, char *argv[] ) override; +} staticApp; + +CEngineApp::CEngineApp( bool externalMain ) : + App( externalMain ) +{ + +} -void VGui_Startup( int width, int height ) +void CEngineApp::main( int argc, char *argv[] ) +{ + +} + +static void VGUI_Startup( int width, int height ) { if( rootpanel ) { + VGUI2_Startup( NULL, width, height ); rootpanel->setSize( width, height ); return; } @@ -52,16 +72,13 @@ void VGui_Startup( int width, int height ) staticApp.setMinimumTickMillisInterval( 0 ); surface = new CEngineSurface( rootpanel ); - rootpanel->setSurfaceBaseTraverse( surface ); + rootpanel->setSurfaceBaseTraverse( surface ); - //ASSERT( rootpanel->getApp() != NULL ); - //ASSERT( rootpanel->getSurfaceBase() != NULL ); - - g_api->DrawInit (); + g_api->DrawInit(); } -void VGui_Shutdown( void ) +static void VGUI_Shutdown() { staticApp.stop(); @@ -72,52 +89,71 @@ void VGui_Shutdown( void ) surface = NULL; } -void VGui_Paint( void ) +static void VGUI_Paint() { 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(); + if( !pVPanel ) + return; + rootpanel->getSize(w, h); EnableScissor( true ); - staticApp.externalTick (); + if( VGUI2_UseVGUI1( )) + { + staticApp.externalTick (); - pVPanel->setBounds( 0, 0, w, h ); - pVPanel->repaint(); + pVPanel->setBounds( 0, 0, w, h ); + pVPanel->repaint(); - // paint everything - pVPanel->paintTraverse(); + // paint everything + pVPanel->paintTraverse(); + } + else + { + VGUI2_Paint(); + } EnableScissor( false ); } -void *VGui_GetPanel( void ) + +static void *VGUI_GetPanel() { return (void *)rootpanel; } -} -#ifdef INTERNAL_VGUI_SUPPORT -#define InitAPI InitVGUISupportAPI -#endif - -extern "C" EXPORT void InitAPI(vguiapi_t * api) +static vgui_support_interface_t vguifuncs = +{ + VGUI_Startup, + VGUI_Shutdown, + VGUI_GetPanel, + VGUI_Paint, + VGUI_Mouse, + VGUI_Key, + VGUI_MouseMove, + VGUI_TextInput, + VGUI2_Startup +}; + +extern "C" int EXPORT GetVGUISupportAPI( int version, + vgui_support_interface_t *iface, vgui_support_api_t *engfuncs ) { - 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; - g_api->TextInput = VGUI_TextInput; + static vgui_support_api_t api; + + if( version != VGUI_SUPPORT_API_VERSION ) + return 0; + + memcpy( &api, engfuncs, sizeof( api )); + g_api = &api; + + memcpy( iface, &vguifuncs, sizeof( *iface )); + + return VGUI_SUPPORT_API_VERSION; } + +} // namespace vgui_support diff --git a/vgui_main.h b/vgui_main.h index 5819531..de952db 100644 --- a/vgui_main.h +++ b/vgui_main.h @@ -30,30 +30,54 @@ from your version. #else #include #endif - #include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "vgui_api.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include namespace vgui_support { -extern vguiapi_t *g_api; +extern vgui_support_api_t *g_api; -using namespace vgui; +struct VGUIPanel +{ + VGUIPanel( vgui::Panel *pPanel ) + { + this->pPanel = pPanel; + this->vgui2 = false; + } + VGUIPanel( vgui2::VPANEL vPanel ) + { + this->vPanel = vPanel; + this->vgui2 = true; + } + VGUIPanel() + { + pPanel = nullptr; + vgui2 = false; + } + + union + { + vgui::Panel *pPanel; + vgui2::VPANEL vPanel; + }; + bool vgui2; +}; struct PaintStack { - Panel *m_pPanel; + VGUIPanel panel; int iTranslateX; int iTranslateY; int iScissorLeft; @@ -62,9 +86,69 @@ struct PaintStack int iScissorBottom; }; -class CEngineSurface : public SurfaceBase +class CEngineSurface : public vgui::SurfaceBase { +public: + CEngineSurface( vgui::Panel *embeddedPanel ); + ~CEngineSurface(); + + virtual bool setFullscreenMode( int wide, int tall, int bpp ) override; + virtual void setWindowedMode() override; + virtual void setTitle( const char *title ) override; + virtual void createPopup( vgui::Panel *embeddedPanel ) override; + virtual bool isWithin( int x, int y ) override; + virtual bool hasFocus() override; + virtual void GetMousePos( int &x, int &y ) override; + + vgui::Panel *getEmbeddedPanel(); + void drawPrintChar( int x, int y, int wide, int tall, float s0, float t0, float s1, float t1, int color[] ); + +protected: + virtual int createNewTextureID() override; + virtual void drawSetColor( int r, int g, int b, int a ) override; + virtual void drawSetTextColor( int r, int g, int b, int a ) override; + virtual void drawFilledRect( int x0, int y0, int x1, int y1 ) override; + virtual void drawOutlinedRect( int x0, int y0, int x1, int y1 ) override; + virtual void drawSetTextFont( vgui::Font *font ) override; + virtual void drawSetTextPos( int x, int y ) override; + virtual void drawPrintText( const char *text, int textLen ) override; + virtual void drawSetTextureRGBA( int id, const char *rgba, int wide, int tall ) override; + virtual void drawSetTexture( int id ) override; + virtual void drawTexturedRect( int x0, int y0, int x1, int y1 ) override; + virtual void setCursor( vgui::Cursor *cursor ) override; + virtual void pushMakeCurrent( vgui::Panel *panel, bool useInsets ) override; + virtual void popMakeCurrent( vgui::Panel *panel ) override; + virtual void enableMouseCapture( bool state ); + virtual void invalidate( vgui::Panel *panel ); + virtual void setAsTopMost( bool state ); + virtual void applyChanges(); + virtual void swapBuffers(); + private: + void SetupPaintState( const PaintStack *paintState ); + void InitVertex( vpoint_t &vertex, int x, int y, float u, float v ); + + // VGUI2 Surface funcs + void PushMakeCurrent( VGUIPanel panel, int insets[4], int absExtents[4], int clipRect[4] ); + void PopMakeCurrent( VGUIPanel panel ); + void drawLine( int x0, int y0, int x1, int y1 ); + void drawPolyLine( int *px, int *py, int numPoints ); + void drawGetTextPos( int &x, int &y ); + void drawSetTextureFile( int id, const char *filename ); + void drawGetTextureSize( int id, int &wide, int &tall ); + vgui2::HFont createFont(); + bool addGlyphSetToFont( vgui2::HFont font, const char *fontName, int tall, int weight, bool italic, bool underline, bool strikeout, bool symbol ); + bool addCustomFontFile( const char *fontFileName ); + void drawSetTextFont( vgui2::HFont font ); + int getFontTall( vgui2::HFont font ); + void getCharABCWide( vgui2::HFont font, int ch, int &a, int &b, int &c ); + int getCharWidth( vgui2::HFont font, int ch ); + void getTextSize( vgui2::HFont font, const char *text, int &wide, int &tall ); + void playSound( const char *filename ); + void drawTexturedPolygon( vgui2::VGuiVertex *verts, int n ); + int getFontAscent( vgui2::HFont font, int ch ); + bool deleteTextureByID( int id ); + void drawSubTextureRGBA( int id, int x, int y, const byte *bgra, int wide, int tall ); // point translation for current panel int _translateX; @@ -72,75 +156,25 @@ class CEngineSurface : public SurfaceBase // the size of the window to draw into int _surfaceExtents[4]; - - void SetupPaintState( const PaintStack *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); - } - void drawPrintChar(int x, int y, int wide, int tall, float s0, float t0, float s1, float t1, int color[]); 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: - Cursor* _hCurrentCursor; + vgui::Cursor *_hCurrentCursor; int _drawTextPos[2]; int _drawColor[4]; int _drawTextColor[4]; friend class App; friend class Panel; + friend class VGUI2Surface; }; -// 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 -}; +extern CEngineSurface *surface; // // vgui_input.cpp // -void *VGui_GetPanel( 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); -void VGUI_TextInput(const char *text); +void VGUI_Mouse( VGUI_MouseAction action, int code ); +void VGUI_Key( VGUI_KeyAction action, VGUI_KeyCode code ); +void VGUI_MouseMove( int x, int y ); +void VGUI_TextInput( const char *text ); // // vgui_clip.cpp @@ -149,8 +183,19 @@ 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 CEngineSurface *surface; -extern Panel *root; +// +// vgui2_int.cpp +// +void VGUI2_Startup( void *clientlib, int width, int height ); +void VGUI2_Shutdown(); +bool VGUI2_UseVGUI1(); +void VGUI2_Paint(); +void VGUI2_ScreenSize( int &width, int &height ); +void VGUI2_Key( VGUI_KeyAction action, VGUI_KeyCode code ); +void VGUI2_Mouse( VGUI_MouseAction action, int code ); +void VGUI2_MouseMove( int x, int y ); +void VGUI2_TextInput( const char *text ); + } -using namespace vgui_support; -#endif//VGUI_MAIN_H + +#endif // VGUI_MAIN_H diff --git a/vgui_surf.cpp b/vgui_surf.cpp index 21802da..f5e1fdf 100644 --- a/vgui_surf.cpp +++ b/vgui_surf.cpp @@ -24,12 +24,16 @@ from your version. */ #include +#include #include "vgui_main.h" #define MAX_PAINT_STACK 16 #define FONT_SIZE 512 #define FONT_PAGES 8 +using namespace vgui_support; +using namespace vgui; + struct FontInfo { int id; @@ -50,7 +54,8 @@ static int staticPaintStackPos = 0; #define ColorIndex( c )((( c ) - '0' ) & 7 ) -CEngineSurface :: CEngineSurface( Panel *embeddedPanel ):SurfaceBase( embeddedPanel ) +CEngineSurface::CEngineSurface( Panel *embeddedPanel ) : + SurfaceBase( embeddedPanel ) { _embeddedPanel = embeddedPanel; _drawColor[0] = _drawColor[1] = _drawColor[2] = _drawColor[3] = 255; @@ -72,24 +77,22 @@ CEngineSurface :: CEngineSurface( Panel *embeddedPanel ):SurfaceBase( embeddedPa _translateX = _translateY = 0; } -CEngineSurface :: ~CEngineSurface( void ) +CEngineSurface::~CEngineSurface( void ) { g_api->DrawShutdown (); } -Panel *CEngineSurface :: getEmbeddedPanel( void ) +Panel *CEngineSurface::getEmbeddedPanel( void ) { return _embeddedPanel; } -bool CEngineSurface :: hasFocus( void ) +bool CEngineSurface::hasFocus( void ) { - // What differs when window does not has focus? - //return host.state != HOST_NOFOCUS; return true; } -void CEngineSurface :: setCursor( Cursor *cursor ) +void CEngineSurface::setCursor( Cursor *cursor ) { _currentCursor = cursor; @@ -99,7 +102,7 @@ void CEngineSurface :: setCursor( Cursor *cursor ) } } -void CEngineSurface :: SetupPaintState( const PaintStack *paintState ) +void CEngineSurface::SetupPaintState( const PaintStack *paintState ) { _translateX = paintState->iTranslateX; _translateY = paintState->iTranslateY; @@ -107,7 +110,7 @@ void CEngineSurface :: SetupPaintState( const PaintStack *paintState ) paintState->iScissorRight, paintState->iScissorBottom ); } -void CEngineSurface :: InitVertex( vpoint_t &vertex, int x, int y, float u, float v ) +void CEngineSurface::InitVertex( vpoint_t &vertex, int x, int y, float u, float v ) { vertex.point[0] = x + _translateX; vertex.point[1] = y + _translateY; @@ -115,12 +118,12 @@ void CEngineSurface :: InitVertex( vpoint_t &vertex, int x, int y, float u, floa vertex.coord[1] = v; } -int CEngineSurface :: createNewTextureID( void ) +int CEngineSurface::createNewTextureID( void ) { return g_api->GenerateTexture(); } -void CEngineSurface :: drawSetColor( int r, int g, int b, int a ) +void CEngineSurface::drawSetColor( int r, int g, int b, int a ) { _drawColor[0] = r; _drawColor[1] = g; @@ -128,7 +131,7 @@ void CEngineSurface :: drawSetColor( int r, int g, int b, int a ) _drawColor[3] = a; } -void CEngineSurface :: drawSetTextColor( int r, int g, int b, int a ) +void CEngineSurface::drawSetTextColor( int r, int g, int b, int a ) { _drawTextColor[0] = r; _drawTextColor[1] = g; @@ -136,7 +139,7 @@ void CEngineSurface :: drawSetTextColor( int r, int g, int b, int a ) _drawTextColor[3] = a; } -void CEngineSurface :: drawFilledRect( int x0, int y0, int x1, int y1 ) +void CEngineSurface::drawFilledRect( int x0, int y0, int x1, int y1 ) { vpoint_t rect[2]; vpoint_t clippedRect[2]; @@ -156,7 +159,7 @@ void CEngineSurface :: drawFilledRect( int x0, int y0, int x1, int y1 ) g_api->EnableTexture( true ); } -void CEngineSurface :: drawOutlinedRect( int x0, int y0, int x1, int y1 ) +void CEngineSurface::drawOutlinedRect( int x0, int y0, int x1, int y1 ) { if( _drawColor[3] >= 255 ) return; @@ -166,7 +169,7 @@ void CEngineSurface :: drawOutlinedRect( int x0, int y0, int x1, int y1 ) drawFilledRect( x1 - 1, y0 + 1, x1, y1 - 1 ); // right } -void CEngineSurface :: drawSetTextFont( Font *font ) +void CEngineSurface::drawSetTextFont( Font *font ) { staticFont = font; @@ -257,13 +260,13 @@ void CEngineSurface :: drawSetTextFont( Font *font ) } } -void CEngineSurface :: drawSetTextPos( int x, int y ) +void CEngineSurface::drawSetTextPos( int x, int y ) { _drawTextPos[0] = x; _drawTextPos[1] = y; } -void CEngineSurface :: drawPrintChar( int x, int y, int wide, int tall, float s0, float t0, float s1, float t1, int color[4] ) +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; @@ -287,7 +290,7 @@ void CEngineSurface :: drawPrintChar( int x, int y, int wide, int tall, float s0 g_api->DrawQuad( &clippedRect[0], &clippedRect[1] ); // draw the letter } -void CEngineSurface :: drawPrintText( const char* text, int textLen ) +void CEngineSurface::drawPrintText( const char* text, int textLen ) { //return; static bool hasColor = 0; @@ -304,11 +307,11 @@ void CEngineSurface :: drawPrintText( const char* text, int textLen ) int j, iTotalWidth = 0; int curTextColor[4]; - // HACKHACK: allow color strings in VGUI + // 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); + curTextColor[j] = g_api->GetColor( numColor, j ); } else { @@ -324,7 +327,8 @@ void CEngineSurface :: drawPrintText( const char* text, int textLen ) hasColor = true; return; // skip '^' } - else if( hasColor && isdigit( *text )) + + if( hasColor && isdigit( *text )) { numColor = ColorIndex( *text ); hasColor = false; // handled @@ -332,13 +336,16 @@ void CEngineSurface :: drawPrintText( const char* text, int textLen ) } else hasColor = false; } + + // reset + g_api->ProcessUtfChar( 0 ); + for( int i = 0; i < textLen; i++ ) { int curCh = g_api->ProcessUtfChar( (unsigned char)text[i] ); + if( !curCh ) - { continue; - } int abcA, abcB, abcC; @@ -359,17 +366,17 @@ void CEngineSurface :: drawPrintText( const char* text, int textLen ) _drawTextPos[0] += iTotalWidth; } -void CEngineSurface :: drawSetTextureRGBA( int id, const char* rgba, int wide, int tall ) +void CEngineSurface::drawSetTextureRGBA( int id, const char* rgba, int wide, int tall ) { g_api->UploadTexture( id, rgba, wide, tall ); } -void CEngineSurface :: drawSetTexture( int id ) +void CEngineSurface::drawSetTexture( int id ) { g_api->BindTexture( id ); } -void CEngineSurface :: drawTexturedRect( int x0, int y0, int x1, int y1 ) +void CEngineSurface::drawTexturedRect( int x0, int y0, int x1, int y1 ) { vpoint_t rect[2]; vpoint_t clippedRect[2]; @@ -385,7 +392,7 @@ void CEngineSurface :: drawTexturedRect( int x0, int y0, int x1, int y1 ) g_api->DrawQuad( &clippedRect[0], &clippedRect[1] ); } -void CEngineSurface :: pushMakeCurrent( Panel* panel, bool useInsets ) +void CEngineSurface::pushMakeCurrent( Panel* panel, bool useInsets ) { int insets[4] = { 0, 0, 0, 0 }; int absExtents[4]; @@ -396,11 +403,83 @@ void CEngineSurface :: pushMakeCurrent( Panel* panel, bool useInsets ) panel->getAbsExtents( absExtents[0], absExtents[1], absExtents[2], absExtents[3] ); panel->getClipRect( clipRect[0], clipRect[1], clipRect[2], clipRect[3] ); + VGUIPanel p( panel ); + PushMakeCurrent( p, insets, absExtents, clipRect ); +} + +void CEngineSurface::popMakeCurrent( Panel *panel ) +{ + VGUIPanel p( panel ); + PopMakeCurrent( p ); +} + +void CEngineSurface::GetMousePos( int &x, int &y ) +{ + g_api->GetCursorPos( &x, &y ); +} + +bool CEngineSurface::setFullscreenMode( int wide, int tall, int bpp ) +{ + // stub + return false; +} + +void CEngineSurface::setWindowedMode( void ) +{ + // stub +} + +void CEngineSurface::setTitle( const char *title ) +{ + // stub +} + +void CEngineSurface::createPopup( vgui::Panel *embeddedPanel ) +{ + // stub +} + +bool CEngineSurface::isWithin( int x, int y ) +{ + // stub + return true; +} + +void CEngineSurface::enableMouseCapture( bool state ) +{ + // stub +} + +void CEngineSurface::invalidate( vgui::Panel *panel ) +{ + // stub +} + +void CEngineSurface::setAsTopMost( bool state ) +{ + // stub +} + +void CEngineSurface::applyChanges() +{ + // stub +} + +void CEngineSurface::swapBuffers() +{ + // stub +} + +// +// VGUI2 extended surface +// +void CEngineSurface::PushMakeCurrent( VGUIPanel panel, int insets[4], int absExtents[4], int clipRect[4] ) +{ PaintStack *paintState = &paintStack[staticPaintStackPos]; assert( staticPaintStackPos < MAX_PAINT_STACK ); - paintState->m_pPanel = panel; + paintState->panel = panel; // determine corrected top left origin paintState->iTranslateX = insets[0] + absExtents[0]; @@ -412,29 +491,128 @@ void CEngineSurface :: pushMakeCurrent( Panel* panel, bool useInsets ) paintState->iScissorBottom = clipRect[3]; SetupPaintState( paintState ); + staticPaintStackPos++; } - -void CEngineSurface :: popMakeCurrent( Panel *panel ) + +void CEngineSurface::PopMakeCurrent( VGUIPanel p ) { int top = staticPaintStackPos - 1; // more pops that pushes? assert( top >= 0 ); + // a1ba: replace asserts by proper checks!!! // didn't pop in reverse order of push? - assert( paintStack[top].m_pPanel == panel ); + assert( paintStack[top].panel.vgui2 == p.vgui2 ); + if( p.vgui2 ) + assert( paintStack[top].panel.vPanel == p.vPanel ); + else + assert( paintStack[top].panel.pPanel == p.pPanel ); staticPaintStackPos--; if( top > 0 ) SetupPaintState( &paintStack[top-1] ); } -bool CEngineSurface :: setFullscreenMode( int wide, int tall, int bpp ) +void CEngineSurface::drawLine( int x0, int y0, int x1, int y1 ) +{ + // TODO: implement this + // will require updating RefAPI or implement VGUI drawing + // through TriAPI? +} + +void CEngineSurface::drawPolyLine( int *px, int *py, int numPoints ) +{ + // TODO: see drawLine comment +} + +void CEngineSurface::drawGetTextPos( int &x, int &y ) +{ + x = _drawTextPos[0]; + y = _drawTextPos[1]; +} + +void CEngineSurface::drawSetTextureFile( int id, const char *filename ) +{ + g_api->BindTexture( id ); + g_api->UploadTextureFile( id, filename ); +} + +void CEngineSurface::drawGetTextureSize( int id, int &wide, int &tall ) +{ + g_api->BindTexture( id ); + g_api->GetTextureSizes( &wide, &tall ); +} + +vgui2::HFont CEngineSurface::createFont() +{ + return -1; +} + +bool CEngineSurface::addGlyphSetToFont( vgui2::HFont font, const char *fontName, int tall, int weight, bool italic, bool underline, bool strikeout, bool symbol ) { return false; } - -void CEngineSurface :: setWindowedMode( void ) + +bool CEngineSurface::addCustomFontFile( const char *fontFileName ) +{ + return false; +} + +void CEngineSurface::drawSetTextFont( vgui2::HFont font ) +{ + // TODO: use mainui_cpp font renderer here +} + +int CEngineSurface::getFontTall( vgui2::HFont font ) +{ + // add random tall + return 32; +} + +void CEngineSurface::getCharABCWide( vgui2::HFont font, int ch, int &a, int &b, int &c ) +{ + a = b = c = 1; +} + +void CEngineSurface::getTextSize( vgui2::HFont font, const char *text, int &wide, int &tall ) +{ + int lines = 0; + for( const char *p = text; *p; p = Q_strchrnul( p, '\n' )) + lines++; + + // TODO: add some height because client.dll uses this function to determine + // engine string drawing functions height (as GoldSrc uses VGUI2 internally anyway) + // this will be rewritten to real function later + tall = lines * getFontTall( font ); + wide = 1; +} + +void CEngineSurface::playSound( const char *filename ) +{ + g_api->StartSound( filename ); +} + +void CEngineSurface::drawTexturedPolygon( vgui2::VGuiVertex *verts, int n ) +{ + // TODO: see drawLine comment +} + +int CEngineSurface::getFontAscent( vgui2::HFont font, int ch ) { + return getFontTall( font ) * 0.8; } + +bool CEngineSurface::deleteTextureByID( int id ) +{ + // TODO: see drawLine comment + return false; +} + +void CEngineSurface::drawSubTextureRGBA( int id, int x, int y, const byte *rgba, int wide, int tall ) +{ + g_api->UploadTextureBlock( id, x, y, rgba, wide, tall ); +} + + diff --git a/wscript b/wscript index 8f25bbe..dd0ea94 100644 --- a/wscript +++ b/wscript @@ -12,6 +12,8 @@ VGUI_SUPPORTED_OS = ['win32', 'darwin', 'linux'] def options(opt): grp = opt.add_option_group('VGUI options') + vgui2_dev_path = os.path.join(opt.path.path_from(opt.root), 'vgui2-dev') + grp.add_option('--disable-vgui', action = 'store_true', dest = 'NO_VGUI', default = False, help = 'disable vgui_support [default: %default]') @@ -30,7 +32,7 @@ def build(bld): if bld.env.NO_VGUI: return - libs = [ 'sdk_includes' ] + libs = [ 'public', 'filesystem_includes' ] # basic build: dedicated only, no dependencies if bld.env.DEST_OS != 'win32': @@ -38,9 +40,8 @@ def build(bld): libs.append('VGUI') - source = bld.path.ant_glob(['*.cpp']) - - includes = [ '.' ] + source = bld.path.ant_glob(['*.cpp', 'vgui2-dev/src/*.cpp']) + includes = [ '.', 'vgui2-dev/include' ] bld.shlib( source = source,