#include "fgui/fgui.h" #include "filesystem.h" #include "rendering.h" #include "tier1/utlvector.h" #include "fgui/widget.h" #include "ctype.h" float fgui_fRectColor[4]; float fgui_fTextColor[4]; float fgui_fTextPosition[2]; float fgui_fGlyphScale[2]; CFont *fgui_pTextFont; float fgui_fOffset[2]; IGraphicsPipeline *fgui_RectPipeline; IGraphicsPipeline *fgui_TextPipeline; IVertexBuffer *fgui_pRectangleBuffer; IVertexBuffer *fgui_pUVRectangleBuffer; CUtlVector fgui_widgets; void IFGUI::Init( void ) { } void IFGUI::Frame( void ) { for (auto &widget: fgui_widgets) { widget->Frame(); } } //---------------------------------------------------------------------------- // Sets offset of the drawn widget //---------------------------------------------------------------------------- void IFGUI::AddOffset( float x, float y) { fgui_fOffset[0] += x; fgui_fOffset[1] += y; } //---------------------------------------------------------------------------- // Reset offset of the drawn widget //---------------------------------------------------------------------------- void IFGUI::ResetOffset() { fgui_fOffset[0] = 0; fgui_fOffset[1] = 0; } //---------------------------------------------------------------------------- // Creates new widget in the world //---------------------------------------------------------------------------- void IFGUI::AppendWidget( CFGUI_Widget *pWidget ) { fgui_widgets.AppendTail(pWidget); } //---------------------------------------------------------------------------- // Destroys widget //---------------------------------------------------------------------------- void IFGUI::DestroyWidget( CFGUI_Widget *pWidget ) { size_t i = 0; for (auto &widget: fgui_widgets) { if (widget == pWidget) { fgui_widgets.RemoveAt(i); return; } i++; } } //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- void IFGUI::SetRectColor( float r, float g, float b, float a ) { fgui_fRectColor[0] = r; fgui_fRectColor[1] = g; fgui_fRectColor[2] = b; fgui_fRectColor[3] = a; } //---------------------------------------------------------------------------- // Draws rectangle on the screen //---------------------------------------------------------------------------- void IFGUI::DrawRect( int32_t iPosX, int32_t iPosY, uint32_t uSizeX, uint32_t uSizeY ) { Renderer()->BindPipeline(fgui_RectPipeline); struct RectConstants_t { uint32_t nResolution[2]; uint32_t nSize[2]; int32_t nPosition[2]; float offest0[2]; float fColor[4]; } constants; constants.nResolution[0] = g_nWindowWidth; constants.nResolution[1] = g_nWindowHeight; constants.nPosition[0] = fgui_fOffset[0] + iPosX; constants.nPosition[1] = fgui_fOffset[1] + iPosY; constants.nSize[0] = uSizeX; constants.nSize[1] = uSizeY; for ( int i = 0; i < 4; i++ ) constants.fColor[i] = fgui_fRectColor[i]; Renderer()->SetConstants(sizeof(RectConstants_t), &constants); Renderer()->Draw(fgui_pRectangleBuffer, NULL); } CUtlVector fgui_fonts; CFont *fgui_pCurrentFont; //---------------------------------------------------------------------------- // Loads new font //---------------------------------------------------------------------------- CFont *IFGUI::LoadFont( CUtlString szFontPath ) { for (auto &font: fgui_fonts) { if (font->szName == szFontPath) return font; }; CFont *pFont = new CFont; pFont->szName = szFontPath; pFont->pTexture = ITextureManager::LoadTexture(CUtlString("%s.png", szFontPath.GetString())); FileHandle_t f = FileSystem()->Open(CUtlString("%s.fontdata", szFontPath.GetString()), IFILE_READ); CUtlBuffer b = FileSystem()->Size(f)+1; FileSystem()->Read(f, b.GetMemory(), FileSystem()->Size(f)); FileSystem()->Close(f); char cCharacterSet[256] = {}; V_memset(cCharacterSet, 0, 256); uint32_t nElementsWidth; uint32_t nElementsHeight; V_sscanf(b, "%u %u %255s", &nElementsWidth, &nElementsHeight, cCharacterSet); uint32_t nGlyphWidth = pFont->pTexture->x / nElementsWidth; uint32_t nGlyphHeight = pFont->pTexture->y / nElementsHeight; for ( int i = 0; i < 255; i++ ) { if (isprint(cCharacterSet[i]) && !isspace(cCharacterSet[i])) pFont->cCharacterSet[cCharacterSet[i]] = i; else pFont->cCharacterSet[cCharacterSet[i]] = -1; } pFont->glyphWidth = nGlyphWidth; pFont->glyphHeight = nGlyphHeight; pFont->nGlyphsPerRow = nElementsWidth; pFont->nGlyphsPerColumn = nElementsHeight; return pFont; } void IFGUI::SetGlyphScale( float x, float y ) { fgui_fGlyphScale[0] = x; fgui_fGlyphScale[1] = y; }; void IFGUI::SetTextFont( CFont *pFont ) { fgui_pTextFont = pFont; } void IFGUI::SetTextPos( float x, float y ) { fgui_fTextPosition[0] = x; fgui_fTextPosition[1] = y; } void IFGUI::SetTextColor( float r, float g, float b, float a ) { fgui_fRectColor[0] = r; fgui_fRectColor[1] = g; fgui_fRectColor[2] = b; fgui_fRectColor[3] = a; } void IFGUI::DrawText( CUtlString psz ) { if (fgui_pTextFont == NULL) { V_printf("Forgot to call IFGUI::SetTextFont()?\n"); return; } Renderer()->BindPipeline(fgui_TextPipeline); struct RectConstants_t { uint32_t nResolution[2]; uint32_t nSize[2]; int32_t nPosition[2]; float offest0[2]; float fColor[4]; float fGlyphPos[2]; float fGlyphSize[2]; uint32_t nFont; } constants; constants.nResolution[0] = g_nWindowWidth; constants.nResolution[1] = g_nWindowHeight; constants.nPosition[0] = fgui_fOffset[0] + fgui_fTextPosition[0]; constants.nPosition[1] = fgui_fOffset[1] + fgui_fTextPosition[1]; constants.nSize[0] = fgui_pTextFont->glyphWidth * fgui_fGlyphScale[0]; constants.nSize[1] = fgui_pTextFont->glyphHeight * fgui_fGlyphScale[1]; constants.fGlyphSize[0] = 1.0 / fgui_pTextFont->nGlyphsPerRow; constants.fGlyphSize[1] = 1.0 / fgui_pTextFont->nGlyphsPerColumn; constants.nFont = ITextureManager::GetTextureID(fgui_pTextFont->pTexture); for ( int i = 0; i < 4; i++ ) constants.fColor[i] = fgui_fRectColor[i]; for ( int i = 0; psz[i]; i++) { constants.fGlyphPos[0] = fgui_pTextFont->cCharacterSet[psz[i]] % fgui_pTextFont->nGlyphsPerRow; constants.fGlyphPos[1] = fgui_pTextFont->cCharacterSet[psz[i]] / fgui_pTextFont->nGlyphsPerRow; if (isprint(psz[i]) && !isspace(psz[i])) { Renderer()->SetConstants(sizeof(RectConstants_t), &constants); Renderer()->Draw(fgui_pUVRectangleBuffer, NULL); } constants.nPosition[0] += constants.nSize[0]; } } class CFGUI_Rendering: public IRenderingPipelineStep { public: virtual void Init() override; virtual void Frame( float fDelta ) override; virtual void Deinit() override; }; DECLARE_UI_RENDERING_STAGE(CFGUI_Rendering, fgui_rendering); void CFGUI_Rendering::Init() { fgui_RectPipeline = Renderer()->CreateGraphicsPipeline( { {"gfx/fgui_rect_vert.shader", SHADER_TYPE_VERTEX}, {"gfx/fgui_rect_frag.shader", SHADER_TYPE_FRAGMENT}, }, {}, 48, 8, {{0,0,VERTEX_FORMAT_X32Y32}}, {IMAGE_FORMAT_WINDOW}, true ); fgui_TextPipeline = Renderer()->CreateGraphicsPipeline( { {"gfx/fgui_text_vert.shader", SHADER_TYPE_VERTEX}, {"gfx/fgui_text_frag.shader", SHADER_TYPE_FRAGMENT}, }, { {SHADER_INPUT_TYPE_TEXTURES, 29}, }, 80, 16, {{0,0, VERTEX_FORMAT_X32Y32},{8,1, VERTEX_FORMAT_X32Y32}}, {IMAGE_FORMAT_WINDOW}, true ); { float vertices[6*2] = { 0,0, 0,1, 1,0, 1,0, 0,1, 1,1, }; fgui_pRectangleBuffer = Renderer()->CreateVertexBuffer(sizeof(vertices)); void *pMapping = fgui_pRectangleBuffer->Map(); V_memcpy(pMapping, vertices, sizeof(vertices)); fgui_pRectangleBuffer->Unmap(); } { float vertices[6*4] = { 0,0, 0,0, 0,1, 0,1, 1,0, 1,0, 1,0, 1,0, 0,1, 0,1, 1,1, 1,1, }; fgui_pUVRectangleBuffer = Renderer()->CreateVertexBuffer(sizeof(vertices)); void *pMapping = fgui_pUVRectangleBuffer->Map(); V_memcpy(pMapping, vertices, sizeof(vertices)); fgui_pUVRectangleBuffer->Unmap(); } }; void CFGUI_Rendering::Frame( float fDelta ) { fgui_TextPipeline->PushBindings(); Renderer()->Begin(g_nWindowWidth, g_nWindowHeight, { { Renderer()->GetOutputImage(), NULL, ATTACHMENT_LOAD_MODE_LOAD, ATTACHMENT_STORE_MODE_STORE, } }, {}); Renderer()->ResetState(); Renderer()->SetDepthMode(DEPTH_MODE_LESS); for (auto &widget: fgui_widgets) { if (!widget->IsVisible()) { continue; } IFGUI::ResetOffset(); widget->ComputeOffset(); widget->Draw(); } Renderer()->End(); }; void CFGUI_Rendering::Deinit() { };