diff --git a/data/menu_buttons.png b/data/menu_buttons.png new file mode 100644 index 000000000..89225e366 Binary files /dev/null and b/data/menu_buttons.png differ diff --git a/data/menu_fold.png b/data/menu_fold.png new file mode 100644 index 000000000..d1437a84e Binary files /dev/null and b/data/menu_fold.png differ diff --git a/datasrc/content.py b/datasrc/content.py index 726f0b2d7..5f07b8c81 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -233,6 +233,8 @@ image_fileicons = Image("fileicons", "file_icons.png") image_guibuttons = Image("guibuttons", "gui_buttons.png") image_guiicons = Image("guiicons", "gui_icons.png") image_browsericons = Image("browsericons", "gui_browser_icons.png") +image_checkboxicons = Image("checkboxicons", "menu_buttons.png") +image_foldicons = Image("foldicons", "menu_fold.png") container.images.Add(image_null) container.images.Add(image_game) @@ -251,6 +253,8 @@ container.images.Add(image_guiicons) container.images.Add(image_browsericons) container.images.Add(Image("no_skinpart", "no_skinpart.png")) container.images.Add(Image("hlpicker", "hlpicker.png")) +container.images.Add(image_checkboxicons) +container.images.Add(image_foldicons) container.pickups.Add(Pickup("health")) container.pickups.Add(Pickup("armor")) @@ -274,6 +278,8 @@ set_fileicons = SpriteSet("fileicons", image_fileicons, 8, 1) set_guibuttons = SpriteSet("guibuttons", image_guibuttons, 12, 4) set_guiicons = SpriteSet("guiicons", image_guiicons, 8, 2) set_browsericons = SpriteSet("browsericons", image_browsericons, 14, 1) +set_checkboxicons = SpriteSet("checkboxicons", image_checkboxicons, 2, 1) +set_foldicons = SpriteSet("foldicons", image_foldicons, 2, 1) container.spritesets.Add(set_particles) container.spritesets.Add(set_game) @@ -290,6 +296,8 @@ container.spritesets.Add(set_fileicons) container.spritesets.Add(set_guibuttons) container.spritesets.Add(set_guiicons) container.spritesets.Add(set_browsericons) +container.spritesets.Add(set_checkboxicons) +container.spritesets.Add(set_foldicons) container.sprites.Add(Sprite("part_slice", set_particles, 0,0,1,1)) container.sprites.Add(Sprite("part_ball", set_particles, 1,0,1,1)) @@ -446,6 +454,12 @@ container.sprites.Add(Sprite("browsericon_star_inactive", set_browsericons, 11,0 container.sprites.Add(Sprite("browsericon_heart_active", set_browsericons, 12,0,1,1)) container.sprites.Add(Sprite("browsericon_heart_inactive", set_browsericons, 13,0,1,1)) +container.sprites.Add(Sprite("checkbox_active", set_checkboxicons, 0,0,1,1)) +container.sprites.Add(Sprite("checkbox_inactive", set_checkboxicons, 1,0,1,1)) + +container.sprites.Add(Sprite("fold_expanded", set_foldicons, 0,0,1,1)) +container.sprites.Add(Sprite("fold_collapsed", set_foldicons, 1,0,1,1)) + anim = Animation("base") anim.body.frames.Add(AnimKeyframe(0, 0, -4, 0)) anim.back_foot.frames.Add(AnimKeyframe(0, 0, 10, 0)) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index cb865bae1..69a026ea4 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -388,7 +388,7 @@ void CCommandProcessor_SDL_OpenGL::RunBuffer(CCommandBuffer *pBuffer) // ------------ CGraphicsBackend_SDL_OpenGL -int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags) +int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight) { if(!SDL_WasInit(SDL_INIT_VIDEO)) { @@ -414,6 +414,10 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Width, int *Height *Height = pInfo->current_h; } + // store desktop resolution for settings reset button + *pDesktopWidth = pInfo->current_w; + *pDesktopHeight = pInfo->current_h; + // set flags int SdlFlags = SDL_OPENGL; if(Flags&IGraphicsBackend::INITFLAG_RESIZABLE) diff --git a/src/engine/client/backend_sdl.h b/src/engine/client/backend_sdl.h index 2ef04a1f8..f5e0b9fe9 100644 --- a/src/engine/client/backend_sdl.h +++ b/src/engine/client/backend_sdl.h @@ -198,7 +198,7 @@ class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded ICommandProcessor *m_pProcessor; SGLContext m_GLContext; public: - virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags); + virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight); virtual int Shutdown(); virtual void Minimize(); diff --git a/src/engine/client/graphics.cpp b/src/engine/client/graphics.cpp index d7899d141..b05e05b48 100644 --- a/src/engine/client/graphics.cpp +++ b/src/engine/client/graphics.cpp @@ -37,27 +37,18 @@ static CVideoMode g_aFakeModes[] = { - {320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8}, + {320,200,8,8,8}, {320,240,8,8,8}, {400,300,8,8,8}, + {512,384,8,8,8}, {640,400,8,8,8}, {640,480,8,8,8}, {720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8}, {1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8}, - {1280,768,8,8,8}, {1280,800,8,8,8}, {1280,960,8,8,8}, - {1280,1024,8,8,8}, {1368,768,8,8,8}, {1400,1050,8,8,8}, - {1440,900,8,8,8}, {1440,1050,8,8,8}, {1600,1000,8,8,8}, - {1600,1200,8,8,8}, {1680,1050,8,8,8}, {1792,1344,8,8,8}, - {1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8}, - {1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8}, - {2048,1536,8,8,8}, - - {320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5}, - {720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5}, - {1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5}, - {1280,768,5,6,5}, {1280,800,5,6,5}, {1280,960,5,6,5}, - {1280,1024,5,6,5}, {1368,768,5,6,5}, {1400,1050,5,6,5}, - {1440,900,5,6,5}, {1440,1050,5,6,5}, {1600,1000,5,6,5}, - {1600,1200,5,6,5}, {1680,1050,5,6,5}, {1792,1344,5,6,5}, - {1800,1440,5,6,5}, {1856,1392,5,6,5}, {1920,1080,5,6,5}, - {1920,1200,5,6,5}, {1920,1440,5,6,5}, {1920,2400,5,6,5}, - {2048,1536,5,6,5} + {1280,600,8,8,8}, {1280,720,8,8,8}, {1280,768,8,8,8}, + {1280,800,8,8,8}, {1280,960,8,8,8}, {1280,1024,8,8,8}, + {1360,768,8,8,8}, {1366,768,8,8,8}, {1368,768,8,8,8}, + {1400,1050,8,8,8}, {1440,900,8,8,8}, {1440,1050,8,8,8}, + {1600,900,8,8,8}, {1600,1000,8,8,8}, {1600,1200,8,8,8}, + {1680,1050,8,8,8}, {1792,1344,8,8,8}, {1800,1440,8,8,8}, + {1856,1392,8,8,8}, {1920,1080,8,8,8}, {1920,1200,8,8,8}, + {1920,1440,8,8,8}, {1920,2400,8,8,8}, {2048,1536,8,8,8} }; void CGraphics_OpenGL::Flush() @@ -594,6 +585,17 @@ void CGraphics_OpenGL::SetColor(float r, float g, float b, float a) SetColorVertex(Array, 4); } +void CGraphics_OpenGL::SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight) +{ + dbg_assert(m_Drawing != 0, "called Graphics()->SetColor without begin"); + CColorVertex Array[4] = { + CColorVertex(0, TopLeft.r, TopLeft.g, TopLeft.b, TopLeft.a), + CColorVertex(1, TopRight.r, TopRight.g, TopRight.b, TopRight.a), + CColorVertex(2, BottomRight.r, BottomRight.g, BottomRight.b, BottomRight.a), + CColorVertex(3, BottomLeft.r, BottomLeft.g, BottomLeft.b, BottomLeft.a)}; + SetColorVertex(Array, 4); +} + void CGraphics_OpenGL::QuadsSetSubset(float TlU, float TlV, float BrU, float BrV) { dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetSubset without begin"); @@ -785,6 +787,10 @@ int CGraphics_SDL::TryInit() m_ScreenWidth = g_Config.m_GfxScreenWidth; m_ScreenHeight = g_Config.m_GfxScreenHeight; + // store desktop resolution for settings reset button + m_DesktopScreenWidth = pInfo->current_w; + m_DesktopScreenHeight = pInfo->current_h; + // set flags int Flags = SDL_OPENGL; if(g_Config.m_DbgResizable) diff --git a/src/engine/client/graphics.h b/src/engine/client/graphics.h index 6beeb7b77..29374aaca 100644 --- a/src/engine/client/graphics.h +++ b/src/engine/client/graphics.h @@ -110,6 +110,7 @@ public: virtual void SetColorVertex(const CColorVertex *pArray, int Num); virtual void SetColor(float r, float g, float b, float a); + virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight); virtual void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV); virtual void QuadsSetSubsetFree( @@ -147,6 +148,9 @@ public: virtual int GetVideoModes(CVideoMode *pModes, int MaxModes); + virtual int GetDesktopScreenWidth() { return m_DesktopScreenWidth; } + virtual int GetDesktopScreenHeight() { return m_DesktopScreenHeight; } + // syncronization virtual void InsertSignal(semaphore *pSemaphore); virtual bool IsIdle(); diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index d5c9b26ae..ff9bee34a 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -19,27 +19,18 @@ #include "graphics_threaded.h" static CVideoMode g_aFakeModes[] = { - {320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8}, + {320,200,8,8,8}, {320,240,8,8,8}, {400,300,8,8,8}, + {512,384,8,8,8}, {640,400,8,8,8}, {640,480,8,8,8}, {720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8}, {1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8}, - {1280,768,8,8,8}, {1280,800,8,8,8}, {1280,960,8,8,8}, - {1280,1024,8,8,8}, {1368,768,8,8,8}, {1400,1050,8,8,8}, - {1440,900,8,8,8}, {1440,1050,8,8,8}, {1600,1000,8,8,8}, - {1600,1200,8,8,8}, {1680,1050,8,8,8}, {1792,1344,8,8,8}, - {1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8}, - {1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8}, - {2048,1536,8,8,8}, - - {320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5}, - {720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5}, - {1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5}, - {1280,768,5,6,5}, {1280,800,5,6,5}, {1280,960,5,6,5}, - {1280,1024,5,6,5}, {1368,768,5,6,5}, {1400,1050,5,6,5}, - {1440,900,5,6,5}, {1440,1050,5,6,5}, {1600,1000,5,6,5}, - {1600,1200,5,6,5}, {1680,1050,5,6,5}, {1792,1344,5,6,5}, - {1800,1440,5,6,5}, {1856,1392,5,6,5}, {1920,1080,5,6,5}, - {1920,1200,5,6,5}, {1920,1440,5,6,5}, {1920,2400,5,6,5}, - {2048,1536,5,6,5} + {1280,600,8,8,8}, {1280,720,8,8,8}, {1280,768,8,8,8}, + {1280,800,8,8,8}, {1280,960,8,8,8}, {1280,1024,8,8,8}, + {1360,768,8,8,8}, {1366,768,8,8,8}, {1368,768,8,8,8}, + {1400,1050,8,8,8}, {1440,900,8,8,8}, {1440,1050,8,8,8}, + {1600,900,8,8,8}, {1600,1000,8,8,8}, {1600,1200,8,8,8}, + {1680,1050,8,8,8}, {1792,1344,8,8,8}, {1800,1440,8,8,8}, + {1856,1392,8,8,8}, {1920,1080,8,8,8}, {1920,1200,8,8,8}, + {1920,1440,8,8,8}, {1920,2400,8,8,8}, {2048,1536,8,8,8} }; void CGraphics_Threaded::FlushVertices() @@ -571,6 +562,17 @@ void CGraphics_Threaded::SetColor(float r, float g, float b, float a) SetColorVertex(Array, 4); } +void CGraphics_Threaded::SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight) +{ + dbg_assert(m_Drawing != 0, "called Graphics()->SetColor without begin"); + CColorVertex Array[4] = { + CColorVertex(0, TopLeft.r, TopLeft.g, TopLeft.b, TopLeft.a), + CColorVertex(1, TopRight.r, TopRight.g, TopRight.b, TopRight.a), + CColorVertex(2, BottomRight.r, BottomRight.g, BottomRight.b, BottomRight.a), + CColorVertex(3, BottomLeft.r, BottomLeft.g, BottomLeft.b, BottomLeft.a)}; + SetColorVertex(Array, 4); +} + void CGraphics_Threaded::QuadsSetSubset(float TlU, float TlV, float BrU, float BrV) { dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetSubset without begin"); @@ -722,7 +724,7 @@ int CGraphics_Threaded::IssueInit() if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC; if(g_Config.m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE; - return m_pBackend->Init("Teeworlds", &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags); + return m_pBackend->Init("Teeworlds", &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags, &m_DesktopScreenWidth, &m_DesktopScreenHeight); } int CGraphics_Threaded::InitWindow() diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index 3c7cd5ca4..e08614ce9 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -298,7 +298,7 @@ public: virtual ~IGraphicsBackend() {} - virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags) = 0; + virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight) = 0; virtual int Shutdown() = 0; virtual void Minimize() = 0; @@ -415,6 +415,7 @@ public: virtual void SetColorVertex(const CColorVertex *pArray, int Num); virtual void SetColor(float r, float g, float b, float a); + virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight); virtual void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV); virtual void QuadsSetSubsetFree( @@ -440,6 +441,9 @@ public: virtual int GetVideoModes(CVideoMode *pModes, int MaxModes); + virtual int GetDesktopScreenWidth() { return m_DesktopScreenWidth; } + virtual int GetDesktopScreenHeight() { return m_DesktopScreenHeight; } + // syncronization virtual void InsertSignal(semaphore *pSemaphore); virtual bool IsIdle(); diff --git a/src/engine/graphics.h b/src/engine/graphics.h index 8214758df..791901952 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -3,6 +3,8 @@ #ifndef ENGINE_GRAPHICS_H #define ENGINE_GRAPHICS_H +#include + #include "kernel.h" @@ -42,6 +44,8 @@ class CVideoMode public: int m_Width, m_Height; int m_Red, m_Green, m_Blue; + + bool operator<(const CVideoMode &Other) { return Other.m_Width < m_Width; } }; class IGraphics : public IInterface @@ -50,6 +54,8 @@ class IGraphics : public IInterface protected: int m_ScreenWidth; int m_ScreenHeight; + int m_DesktopScreenWidth; + int m_DesktopScreenHeight; public: /* Constants: Texture Loading Flags TEXLOAD_NORESAMPLE - Prevents the texture from any resampling @@ -147,10 +153,14 @@ public: }; virtual void SetColorVertex(const CColorVertex *pArray, int Num) = 0; virtual void SetColor(float r, float g, float b, float a) = 0; + virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight) = 0; virtual void TakeScreenshot(const char *pFilename) = 0; virtual int GetVideoModes(CVideoMode *pModes, int MaxModes) = 0; + virtual int GetDesktopScreenWidth() = 0; + virtual int GetDesktopScreenHeight() = 0; + virtual void Swap() = 0; // syncronization diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 940500e48..52beb2c9a 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -62,7 +62,6 @@ MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 0, 0, 0, CFGFLAG_SAVE|CFGFL MACRO_CONFIG_INT(GfxBorderless, gfx_borderless, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Borderless window (not to be used with fullscreen)") MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Fullscreen") MACRO_CONFIG_INT(GfxAlphabits, gfx_alphabits, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Alpha bits for framebuffer (fullscreen only)") -MACRO_CONFIG_INT(GfxColorDepth, gfx_color_depth, 24, 16, 24, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Colors bits for framebuffer (fullscreen only)") MACRO_CONFIG_INT(GfxClear, gfx_clear, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Clear screen before rendering") MACRO_CONFIG_INT(GfxVsync, gfx_vsync, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Vertical sync") MACRO_CONFIG_INT(GfxDisplayAllModes, gfx_display_all_modes, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "") diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index b696d81cb..f7b56035d 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -204,7 +204,7 @@ void CMapLayers::OnRender() } // skip rendering if detail layers if not wanted - if(pLayer->m_Flags&LAYERFLAG_DETAIL && !g_Config.m_GfxHighDetail && !IsGameLayer) + if(pLayer->m_Flags&LAYERFLAG_DETAIL && !g_Config.m_GfxHighDetail && !IsGameLayer && (Client()->State() == IClient::STATE_ONLINE || Client()->State() == IClient::STATE_DEMOPLAYBACK)) continue; if(m_Type == -1) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 20c9673e4..2ae3367fb 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -33,7 +32,7 @@ #include "skins.h" float CMenus::ms_ButtonHeight = 25.0f; -float CMenus::ms_ListheaderHeight = 17.0f; +float CMenus::ms_ListheaderHeight = 20.0f; float CMenus::ms_FontmodHeight = 0.8f; IInput::CEvent CMenus::m_aInputEvents[MAX_INPUTEVENTS]; @@ -48,8 +47,7 @@ CMenus::CMenus() m_NeedRestartGraphics = false; m_NeedRestartSound = false; - m_TeePartSelection = NO_SELECTION; - m_TeePartsColorSelection = NO_SELECTION; + m_TeePartSelected = 0; m_aSaveSkinName[0] = 0; m_MenuActive = true; m_UseMouseButtons = true; @@ -125,12 +123,17 @@ int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const { float Seconds = 0.6f; // 0.6 seconds for fade float *pFade = ButtonFade(pID, Seconds); + float FadeVal = *pFade/Seconds; - RenderTools()->DrawUIRect(pRect, vec4(1.0f , 1.0f, 1.0f, 0.5f+(*pFade/Seconds)*0.25f), Corners, r); + RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f+FadeVal*0.5f), Corners, r); CUIRect Temp; pRect->HMargin(pRect->h>=20.0f?2.0f:1.0f, &Temp); Temp.HMargin((Temp.h*FontFactor)/2.0f, &Temp); + TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, 1.0f); + TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f); UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, 0); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); return UI()->DoButtonLogic(pID, pText, Checked, pRect); } @@ -138,8 +141,9 @@ int CMenus::DoButton_MenuImage(const void *pID, const char *pText, int Checked, { float Seconds = 0.6f; // 0.6 seconds for fade float *pFade = ButtonFade(pID, Seconds); + float FadeVal = *pFade/Seconds; - RenderTools()->DrawUIRect(pRect, vec4(1.0f , 1.0f, 1.0f, 0.5f+(*pFade/Seconds)*0.25f), CUI::CORNER_ALL, r); + RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f+FadeVal*0.5f), CUI::CORNER_ALL, r); CUIRect Text, Image; pRect->VSplitRight(pRect->h*4.0f, &Text, &Image); // always correct ratio for image @@ -166,22 +170,31 @@ int CMenus::DoButton_MenuImage(const void *pID, const char *pText, int Checked, } - pRect->HMargin(pRect->h>=20.0f?2.0f:1.0f, &Text); + Text.HMargin(pRect->h>=20.0f?2.0f:1.0f, &Text); Text.HMargin((Text.h*FontFactor)/2.0f, &Text); Text.VSplitLeft(r, 0, &Text); - UI()->DoLabel(&Text, pText, Text.h*ms_FontmodHeight, -1); + TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, 1.0f); + TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f); + UI()->DoLabel(&Text, pText, Text.h*ms_FontmodHeight, 0); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); return UI()->DoButtonLogic(pID, pText, Checked, pRect); } void CMenus::DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { float Seconds = 0.6f; // 0.6 seconds for fade - float *pFade = ButtonFade(pID, Seconds); + float *pFade = ButtonFade(pID, Seconds, Checked); + float FadeVal = *pFade/Seconds; - RenderTools()->DrawUIRect(pRect, vec4(1.0f , 1.0f, 1.0f, 0.5f+(*pFade/Seconds)*0.25f), CUI::CORNER_ALL, 5.0f); + RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f+FadeVal*0.5f), CUI::CORNER_ALL, 5.0f); CUIRect Temp; pRect->HMargin(1.0f, &Temp); + TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, 1.0f); + TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f); UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, 0); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); } int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners) @@ -202,17 +215,21 @@ int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, co return UI()->DoButtonLogic(pID, pText, Checked, pRect); } -int CMenus::DoButton_MenuTabTop(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners) +int CMenus::DoButton_MenuTabTop(const void *pID, const char *pText, int Checked, const CUIRect *pRect, float r, float FontFactor, int Corners) { float Seconds = 0.6f; // 0.6 seconds for fade float *pFade = ButtonFade(pID, Seconds, Checked); + float FadeVal = *pFade/Seconds; - RenderTools()->DrawUIRect(pRect, vec4(1.0f , 1.0f, 1.0f, 0.5f+(*pFade/Seconds)*0.25f), Corners, 12.0f); - + RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f+FadeVal*0.5f), Corners, r); CUIRect Temp; - pRect->HMargin(2.0f, &Temp); + pRect->HMargin(pRect->h>=20.0f?2.0f:1.0f, &Temp); + Temp.HMargin((Temp.h*FontFactor)/2.0f, &Temp); + TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, 1.0f); + TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f); UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, 0); - + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); return UI()->DoButtonLogic(pID, pText, Checked, pRect); } @@ -249,22 +266,31 @@ int CMenus::DoButton_GridHeaderIcon(const void *pID, int ImageID, int SpriteID, return UI()->DoButtonLogic(pID, "", false, pRect); } -int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect) +int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect, bool Checked) //void CMenus::ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra) { + RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + CUIRect c = *pRect; CUIRect t = *pRect; c.w = c.h; t.x += c.w; t.w -= c.w; t.VSplitLeft(5.0f, 0, &t); - - float Seconds = 0.6f; // 0.6 seconds for fade - float *pFade = ButtonFade(pID, Seconds); c.Margin(2.0f, &c); - RenderTools()->DrawUIRect(&c, vec4(1.0f , 1.0f, 1.0f, 0.25f+(*pFade/Seconds)*0.125f), CUI::CORNER_ALL, 3.0f); - c.y += 2; + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CHECKBOXICONS].m_Id); + Graphics()->QuadsBegin(); + Graphics()->SetColor(1.0f, 1.0f, 1.0f, UI()->HotItem() == pID ? 1.0f : 0.6f); + if(Checked) + RenderTools()->SelectSprite(SPRITE_CHECKBOX_ACTIVE); + else + RenderTools()->SelectSprite(SPRITE_CHECKBOX_INACTIVE); + IGraphics::CQuadItem QuadItem(c.x, c.y, c.w, c.h); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + + t.y += 2.0f; // lame fix UI()->DoLabel(&c, pBoxText, pRect->h*ms_FontmodHeight*0.6f, 0); UI()->DoLabel(&t, pText, pRect->h*ms_FontmodHeight*0.8f, -1); return UI()->DoButtonLogic(pID, pText, 0, pRect); @@ -272,10 +298,9 @@ int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const c int CMenus::DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { - return DoButton_CheckBox_Common(pID, pText, Checked?"X":"", pRect); + return DoButton_CheckBox_Common(pID, pText, "", pRect, Checked); } - int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { char aBuf[16]; @@ -332,7 +357,7 @@ int CMenus::DoButton_MouseOver(int ImageID, int SpriteID, const CUIRect *pRect) return Inside; } -int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners) +int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden, int Corners) { int Inside = UI()->MouseInside(pRect); bool ReturnValue = false; @@ -354,10 +379,11 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS s_DoScroll = true; s_ScrollStart = UI()->MouseX(); int MxRel = (int)(UI()->MouseX() - pRect->x); + float Offset = pRect->w/2.0f-TextRender()->TextWidth(0, FontSize, pStr, -1)/2.0f; for(int i = 1; i <= Len; i++) { - if(TextRender()->TextWidth(0, FontSize, pStr, i) - *Offset > MxRel) + if(Offset + TextRender()->TextWidth(0, FontSize, pStr, i) - *pOffset > MxRel) { s_AtIndex = i - 1; break; @@ -418,7 +444,7 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS UI()->SetHotItem(pID); CUIRect Textbox = *pRect; - RenderTools()->DrawUIRect(&Textbox, vec4(1, 1, 1, 0.5f), Corners, 3.0f); + RenderTools()->DrawUIRect(&Textbox, vec4(0.0f, 0.0f, 0.0f, 0.25f), Corners, 5.0f); Textbox.VMargin(2.0f, &Textbox); Textbox.HMargin(2.0f, &Textbox); @@ -440,38 +466,39 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS if(UI()->LastActiveItem() == pID && !JustGotActive && (UpdateOffset || m_NumInputEvents)) { float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex); - if(w-*Offset > Textbox.w) + if(w-*pOffset > Textbox.w) { // move to the left float wt = TextRender()->TextWidth(0, FontSize, pDisplayStr, -1); do { - *Offset += min(wt-*Offset-Textbox.w, Textbox.w/3); + *pOffset += min(wt-*pOffset-Textbox.w, Textbox.w/3); } - while(w-*Offset > Textbox.w); + while(w-*pOffset > Textbox.w); } - else if(w-*Offset < 0.0f) + else if(w-*pOffset < 0.0f) { // move to the right do { - *Offset = max(0.0f, *Offset-Textbox.w/3); + *pOffset = max(0.0f, *pOffset-Textbox.w/3); } - while(w-*Offset < 0.0f); + while(w-*pOffset < 0.0f); } } UI()->ClipEnable(pRect); - Textbox.x -= *Offset; + Textbox.x -= *pOffset; - UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1); + UI()->DoLabel(&Textbox, pDisplayStr, FontSize, 0); // render the cursor if(UI()->LastActiveItem() == pID && !JustGotActive) { - float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex); + float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, -1); Textbox = *pRect; - Textbox.VSplitLeft(2.0f, 0, &Textbox); - Textbox.x += (w-*Offset-TextRender()->TextWidth(0, FontSize, "|", -1)/2); + Textbox.x += Textbox.w/2.0f-w/2.0f; + w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex); + Textbox.x += (w-*pOffset-TextRender()->TextWidth(0, FontSize, "|", -1)/2); if((2*time_get()/time_freq()) % 2) // make it blink UI()->DoLabel(&Textbox, "|", FontSize, -1); @@ -481,6 +508,108 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS return ReturnValue; } +void CMenus::DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset) +{ + RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + CUIRect Label, EditBox; + pRect->VSplitLeft(VSplitVal, &Label, &EditBox); + + char aBuf[32]; + str_format(aBuf, sizeof(aBuf), "%s:", pStr); + Label.y += 2.0f; + UI()->DoLabel(&Label, aBuf, pRect->h*ms_FontmodHeight*0.8f, 0); + + DoEditBox(pID, &EditBox, pOption, OptionLength, pRect->h*ms_FontmodHeight*0.8f, pOffset); +} + +void CMenus::DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, float VSplitVal, int Min, int Max, bool infinite) +{ + RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + CUIRect Label, ScrollBar; + pRect->VSplitLeft(VSplitVal, &Label, &ScrollBar); + + char aBuf[32]; + if(*pOption || !infinite) + str_format(aBuf, sizeof(aBuf), "%s: %i", pStr, *pOption); + else + str_format(aBuf, sizeof(aBuf), "%s: \xe2\x88\x9e", pStr); + Label.VSplitLeft(Label.h+5.0f, 0, &Label); + Label.y += 2.0f; + UI()->DoLabel(&Label, aBuf, pRect->h*ms_FontmodHeight*0.8f, -1); + + ScrollBar.VMargin(4.0f, &ScrollBar); + *pOption = static_cast(DoScrollbarH(pOption, &ScrollBar, (float)(*pOption-Min)/(float)(Max-Min))*(float)(Max-Min)+(float)Min+0.1f); +} + +float CMenus::DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback) +{ + CUIRect View = *pRect; + CUIRect Header, Label; + + bool Active = pID == m_pActiveDropdown; + int Corners = Active ? CUI::CORNER_T : CUI::CORNER_ALL; + + View.HSplitTop(HeaderHeight, &Header, &View); + + // background + RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), Corners, 5.0f); + + // render icon + CUIRect Button; + Header.VSplitLeft(Header.h, &Button, 0); + Button.Margin(2.0f, &Button); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_FOLDICONS].m_Id); + Graphics()->QuadsBegin(); + Graphics()->SetColor(1.0f, 1.0f, 1.0f, UI()->HotItem() == pID ? 1.0f : 0.6f); + if(Active) + RenderTools()->SelectSprite(SPRITE_FOLD_EXPANDED); + else + RenderTools()->SelectSprite(SPRITE_FOLD_COLLAPSED); + IGraphics::CQuadItem QuadItem(Button.x, Button.y, Button.w, Button.h); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + Graphics()->QuadsEnd(); + + // label + Label = Header; + Label.y += 2.0f; + UI()->DoLabel(&Label, pStr, Header.h*ms_FontmodHeight*0.8f, 0); + + if(UI()->DoButtonLogic(pID, 0, 0, &Header)) + { + if(Active) + m_pActiveDropdown = 0; + else + m_pActiveDropdown = (int*)pID; + } + + // render content of expanded menu + if(Active) + return HeaderHeight + pfnCallback(View, this); + + return HeaderHeight; +} + +void CMenus::DoInfoBox(const CUIRect *pRect, const char *pLabel, const char *pValue) +{ + RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + CUIRect Label, Value; + pRect->VSplitMid(&Label, &Value); + + RenderTools()->DrawUIRect(&Value, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + char aBuf[32]; + str_format(aBuf, sizeof(aBuf), "%s:", pLabel); + Label.y += 2.0f; + UI()->DoLabel(&Label, aBuf, pRect->h*ms_FontmodHeight*0.8f, 0); + + Value.y += 2.0f; + UI()->DoLabel(&Value, pValue, pRect->h*ms_FontmodHeight*0.8f, 0); +} + float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) { CUIRect Handle; @@ -520,27 +649,16 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) // render CUIRect Rail; pRect->VMargin(5.0f, &Rail); - RenderTools()->DrawUIRect(&Rail, vec4(1,1,1,0.25f), 0, 0.0f); + RenderTools()->DrawUIRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.w/2.0f); CUIRect Slider = Handle; - Slider.w = Rail.x-Slider.x; - RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f), CUI::CORNER_L, 2.5f); - Slider.x = Rail.x+Rail.w; - RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f), CUI::CORNER_R, 2.5f); + Slider.VMargin(5.0f, &Slider); - Slider = Handle; - Slider.Margin(5.0f, &Slider); - - float Seconds = 0.6f; // 0.6 seconds for fade - float *pFade = ButtonFade(pID, Seconds); - - RenderTools()->DrawUIRect(&Slider, vec4(1.0f , 1.0f, 1.0f, 0.25f+(*pFade/Seconds)*0.125f), CUI::CORNER_ALL, 2.5f); + RenderTools()->DrawUIRect(&Slider, vec4(1.0f , 1.0f, 1.0f, 1.0f), CUI::CORNER_ALL, Slider.w/2.0f); return ReturnValue; } - - float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) { CUIRect Handle; @@ -580,25 +698,244 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) // render CUIRect Rail; pRect->HMargin(5.0f, &Rail); - RenderTools()->DrawUIRect(&Rail, vec4(1,1,1,0.25f), 0, 0.0f); + RenderTools()->DrawUIRect(&Rail, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, Rail.h/2.0f); CUIRect Slider = Handle; - Slider.h = Rail.y-Slider.y; - RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f), CUI::CORNER_T, 2.5f); - Slider.y = Rail.y+Rail.h; - RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f), CUI::CORNER_B, 2.5f); + Slider.HMargin(5.0f, &Slider); - Slider = Handle; - Slider.Margin(5.0f, &Slider); - - float Seconds = 0.6f; // 0.6 seconds for fade - float *pFade = ButtonFade(pID, Seconds); - - RenderTools()->DrawUIRect(&Slider, vec4(1.0f , 1.0f, 1.0f, 0.25f+(*pFade/Seconds)*0.125f), CUI::CORNER_ALL, 2.5f); + RenderTools()->DrawUIRect(&Slider, vec4(1.0f , 1.0f, 1.0f, 1.0f), CUI::CORNER_ALL, Slider.h/2.0f); return ReturnValue; } +static CUIRect gs_ListBoxOriginalView; +static CUIRect gs_ListBoxView; +static float gs_ListBoxRowHeight; +static int gs_ListBoxItemIndex; +static int gs_ListBoxSelectedIndex; +static int gs_ListBoxNewSelected; +static int gs_ListBoxDoneEvents; +static int gs_ListBoxNumItems; +static int gs_ListBoxItemsPerRow; +static float gs_ListBoxScrollValue; +static bool gs_ListBoxItemActivated; + +void CMenus::UiDoListboxHeader(const CUIRect *pRect, const char *pTitle, float HeaderHeight, float Spaceing) +{ + CUIRect Header; + CUIRect View = *pRect; + + // background + View.HSplitTop(ms_ListheaderHeight+Spaceing, &Header, 0); + RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 5.0f); + + // draw header + View.HSplitTop(ms_ListheaderHeight, &Header, &View); + Header.y += 2.0f; + UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight*0.8f, 0); + + View.HSplitTop(Spaceing, &Header, &View); + + // setup the variables + gs_ListBoxOriginalView = View; +} + +void CMenus::UiDoListboxStart(const void *pID, float RowHeight, const char *pBottomText, int NumItems, + int ItemsPerRow, int SelectedIndex, float ScrollValue, const CUIRect *pRect) +{ + CUIRect View, Scroll, Row; + if(pRect) + View = *pRect; + else + View = gs_ListBoxOriginalView; + CUIRect Header, Footer; + + // background + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + + // draw footers + if(pBottomText) + { + View.HSplitBottom(ms_ListheaderHeight, &View, &Footer); + Footer.VSplitLeft(10.0f, 0, &Footer); + Footer.y += 2.0f; + UI()->DoLabel(&Footer, pBottomText, Footer.h*ms_FontmodHeight*0.8f, 0); + } + + // list background + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + // prepare the scroll + View.VSplitRight(20.0f, &View, &Scroll); + + // setup the variables + gs_ListBoxOriginalView = View; + gs_ListBoxSelectedIndex = SelectedIndex; + gs_ListBoxNewSelected = SelectedIndex; + gs_ListBoxItemIndex = 0; + gs_ListBoxRowHeight = RowHeight; + gs_ListBoxNumItems = NumItems; + gs_ListBoxItemsPerRow = ItemsPerRow; + gs_ListBoxDoneEvents = 0; + gs_ListBoxScrollValue = ScrollValue; + gs_ListBoxItemActivated = false; + + // do the scrollbar + View.HSplitTop(gs_ListBoxRowHeight, &Row, 0); + + int NumViewable = (int)(gs_ListBoxOriginalView.h/Row.h) + 1; + int Num = (NumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1; + if(Num < 0) + Num = 0; + if(Num > 0) + { + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP) && UI()->MouseInside(&View)) + gs_ListBoxScrollValue -= 3.0f/Num; + if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN) && UI()->MouseInside(&View)) + gs_ListBoxScrollValue += 3.0f/Num; + + if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f; + if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; + } + + Scroll.HMargin(5.0f, &Scroll); + gs_ListBoxScrollValue = DoScrollbarV(pID, &Scroll, gs_ListBoxScrollValue); + + // the list + gs_ListBoxView = gs_ListBoxOriginalView; + gs_ListBoxView.VMargin(5.0f, &gs_ListBoxView); + UI()->ClipEnable(&gs_ListBoxView); + gs_ListBoxView.y -= gs_ListBoxScrollValue*Num*Row.h; +} + +CMenus::CListboxItem CMenus::UiDoListboxNextRow() +{ + static CUIRect s_RowView; + CListboxItem Item = {0}; + if(gs_ListBoxItemIndex%gs_ListBoxItemsPerRow == 0) + gs_ListBoxView.HSplitTop(gs_ListBoxRowHeight /*-2.0f*/, &s_RowView, &gs_ListBoxView); + + s_RowView.VSplitLeft(s_RowView.w/(gs_ListBoxItemsPerRow-gs_ListBoxItemIndex%gs_ListBoxItemsPerRow)/(UI()->Scale()), &Item.m_Rect, &s_RowView); + + Item.m_Visible = 1; + //item.rect = row; + + Item.m_HitRect = Item.m_Rect; + + //CUIRect select_hit_box = item.rect; + + if(gs_ListBoxSelectedIndex == gs_ListBoxItemIndex) + Item.m_Selected = 1; + + // make sure that only those in view can be selected + if(Item.m_Rect.y+Item.m_Rect.h > gs_ListBoxOriginalView.y) + { + + if(Item.m_HitRect.y < Item.m_HitRect.y) // clip the selection + { + Item.m_HitRect.h -= gs_ListBoxOriginalView.y-Item.m_HitRect.y; + Item.m_HitRect.y = gs_ListBoxOriginalView.y; + } + + } + else + Item.m_Visible = 0; + + // check if we need to do more + if(Item.m_Rect.y > gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h) + Item.m_Visible = 0; + + gs_ListBoxItemIndex++; + return Item; +} + +CMenus::CListboxItem CMenus::UiDoListboxNextItem(const void *pId, bool Selected) +{ + int ThisItemIndex = gs_ListBoxItemIndex; + if(Selected) + { + if(gs_ListBoxSelectedIndex == gs_ListBoxNewSelected) + gs_ListBoxNewSelected = ThisItemIndex; + gs_ListBoxSelectedIndex = ThisItemIndex; + } + + CListboxItem Item = UiDoListboxNextRow(); + + if(Item.m_Visible && UI()->DoButtonLogic(pId, "", gs_ListBoxSelectedIndex == gs_ListBoxItemIndex, &Item.m_HitRect)) + gs_ListBoxNewSelected = ThisItemIndex; + + // process input, regard selected index + if(gs_ListBoxSelectedIndex == ThisItemIndex) + { + if(!gs_ListBoxDoneEvents) + { + gs_ListBoxDoneEvents = 1; + + if(m_EnterPressed || (UI()->ActiveItem() == pId && Input()->MouseDoubleClick())) + { + gs_ListBoxItemActivated = true; + UI()->SetActiveItem(0); + } + else + { + for(int i = 0; i < m_NumInputEvents; i++) + { + int NewIndex = -1; + if(m_aInputEvents[i].m_Flags&IInput::FLAG_PRESS) + { + if(m_aInputEvents[i].m_Key == KEY_DOWN) NewIndex = gs_ListBoxNewSelected + 1; + if(m_aInputEvents[i].m_Key == KEY_UP) NewIndex = gs_ListBoxNewSelected - 1; + } + if(NewIndex > -1 && NewIndex < gs_ListBoxNumItems) + { + // scroll + float Offset = (NewIndex/gs_ListBoxItemsPerRow-gs_ListBoxNewSelected/gs_ListBoxItemsPerRow)*gs_ListBoxRowHeight; + int Scroll = gs_ListBoxOriginalView.y > Item.m_Rect.y+Offset ? -1 : + gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h < Item.m_Rect.y+Item.m_Rect.h+Offset ? 1 : 0; + if(Scroll) + { + int NumViewable = (int)(gs_ListBoxOriginalView.h/gs_ListBoxRowHeight) + 1; + int ScrollNum = (gs_ListBoxNumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1; + if(Scroll < 0) + { + int Num = (gs_ListBoxOriginalView.y-Item.m_Rect.y-Offset+gs_ListBoxRowHeight-1.0f)/gs_ListBoxRowHeight; + gs_ListBoxScrollValue -= (1.0f/ScrollNum)*Num; + } + else + { + int Num = (Item.m_Rect.y+Item.m_Rect.h+Offset-(gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h)+gs_ListBoxRowHeight-1.0f)/ + gs_ListBoxRowHeight; + gs_ListBoxScrollValue += (1.0f/ScrollNum)*Num; + } + if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f; + if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; + } + + gs_ListBoxNewSelected = NewIndex; + } + } + } + } + + //selected_index = i; + CUIRect r = Item.m_Rect; + r.Margin(1.5f, &r); + RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); + } + + return Item; +} + +int CMenus::UiDoListboxEnd(float *pScrollValue, bool *pItemActivated) +{ + UI()->ClipDisable(); + if(pScrollValue) + *pScrollValue = gs_ListBoxScrollValue; + if(pItemActivated) + *pItemActivated = gs_ListBoxItemActivated; + return gs_ListBoxNewSelected; +} + int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key) { // process @@ -667,8 +1004,7 @@ int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key) return NewKey; } - -int CMenus::RenderMenubar(CUIRect r) +void CMenus::RenderMenubar(CUIRect r) { CUIRect Box = r; CUIRect Button; @@ -681,54 +1017,10 @@ int CMenus::RenderMenubar(CUIRect r) if(Client()->State() == IClient::STATE_OFFLINE) { - /*/ offline menus - if(0) // this is not done yet - { - Box.VSplitLeft(90.0f, &Button, &Box); - static int s_NewsButton=0; - if (DoButton_MenuTab(&s_NewsButton, Localize("News"), m_ActivePage==PAGE_NEWS, &Button, 0)) - NewPage = PAGE_NEWS; - Box.VSplitLeft(30.0f, 0, &Box); - } + // render header background + RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); - Box.VSplitLeft(100.0f, &Button, &Box); - static int s_InternetButton=0; - if(DoButton_MenuTab(&s_InternetButton, Localize("Internet"), m_ActivePage==PAGE_INTERNET, &Button, CUI::CORNER_TL|CUI::CORNER_IBL) && m_ActivePage!=PAGE_INTERNET) - { - m_pClient->m_pCamera->ChangePosition(CCamera::POS_INTERNET); - ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET); - NewPage = PAGE_INTERNET; - } - - //Box.VSplitLeft(4.0f, 0, &Box); - Box.VSplitLeft(80.0f, &Button, &Box); - static int s_LanButton=0; - if(DoButton_MenuTab(&s_LanButton, Localize("LAN"), m_ActivePage==PAGE_LAN, &Button, 0) && m_ActivePage!=PAGE_LAN) - { - m_pClient->m_pCamera->ChangePosition(CCamera::POS_LAN); - ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN); - NewPage = PAGE_LAN; - } - - //box.VSplitLeft(4.0f, 0, &box); - Box.VSplitLeft(110.0f, &Button, &Box); - static int s_FavoritesButton=0; - if(DoButton_MenuTab(&s_FavoritesButton, Localize("Favorites"), m_ActivePage==PAGE_FAVORITES, &Button, CUI::CORNER_TR) && m_ActivePage!=PAGE_FAVORITES) - { - m_pClient->m_pCamera->ChangePosition(CCamera::POS_FAVORITES); - ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES); - NewPage = PAGE_FAVORITES; - } - - Box.VSplitLeft(4.0f*5, 0, &Box); - Box.VSplitLeft(100.0f, &Button, &Box); - static int s_DemosButton=0; - if(DoButton_MenuTab(&s_DemosButton, Localize("Demos"), m_ActivePage==PAGE_DEMOS, &Button, CUI::CORNER_T) && m_ActivePage!=PAGE_DEMOS) - { - m_pClient->m_pCamera->ChangePosition(CCamera::POS_DEMOS); - DemolistPopulate(); - NewPage = PAGE_DEMOS; - }*/ + Box.HSplitBottom(25.0f, 0, &Box); // render menu tabs if(m_MenuPage >= PAGE_INTERNET && m_MenuPage <= PAGE_FRIENDS) @@ -756,54 +1048,67 @@ int CMenus::RenderMenubar(CUIRect r) } else if(m_MenuPage == PAGE_SETTINGS) { - Box.VSplitLeft(100.0f, &Button, &Box); + float Spacing = 3.0f; + float ButtonWidth = (Box.w/6.0f)-(Spacing*5.0)/6.0f; + + Box.VSplitLeft(ButtonWidth, &Button, &Box); static int s_GeneralButton=0; - if(DoButton_MenuTabTop(&s_GeneralButton, Localize("General"), g_Config.m_UiSettingsPage==SETTINGS_GENERAL, &Button, CUI::CORNER_T|CUI::CORNER_IBL)) + if(DoButton_MenuTabTop(&s_GeneralButton, Localize("General"), g_Config.m_UiSettingsPage==SETTINGS_GENERAL, &Button)) { g_Config.m_UiSettingsPage = SETTINGS_GENERAL; } - Box.VSplitLeft(100.0f, &Button, &Box); + Box.VSplitLeft(Spacing, 0, &Box); // little space + Box.VSplitLeft(ButtonWidth, &Button, &Box); static int s_PlayerButton=0; - if(DoButton_MenuTabTop(&s_PlayerButton, Localize("Player"), g_Config.m_UiSettingsPage==SETTINGS_PLAYER, &Button, CUI::CORNER_T)) + if(DoButton_MenuTabTop(&s_PlayerButton, Localize("Player"), g_Config.m_UiSettingsPage==SETTINGS_PLAYER, &Button)) { g_Config.m_UiSettingsPage = SETTINGS_PLAYER; } - Box.VSplitLeft(100.0f, &Button, &Box); + Box.VSplitLeft(Spacing, 0, &Box); // little space + Box.VSplitLeft(ButtonWidth, &Button, &Box); static int s_TeeButton=0; - if(DoButton_MenuTabTop(&s_TeeButton, Localize("Tee"), g_Config.m_UiSettingsPage==SETTINGS_TEE, &Button, CUI::CORNER_T)) + if(DoButton_MenuTabTop(&s_TeeButton, Localize("Tee"), g_Config.m_UiSettingsPage==SETTINGS_TEE, &Button)) { g_Config.m_UiSettingsPage = SETTINGS_TEE; } - Box.VSplitLeft(100.0f, &Button, &Box); + Box.VSplitLeft(Spacing, 0, &Box); // little space + Box.VSplitLeft(ButtonWidth, &Button, &Box); static int s_ControlsButton=0; - if(DoButton_MenuTabTop(&s_ControlsButton, Localize("Controls"), g_Config.m_UiSettingsPage==SETTINGS_CONTROLS, &Button, CUI::CORNER_T)) + if(DoButton_MenuTabTop(&s_ControlsButton, Localize("Controls"), g_Config.m_UiSettingsPage==SETTINGS_CONTROLS, &Button)) { g_Config.m_UiSettingsPage = SETTINGS_CONTROLS; } - Box.VSplitLeft(100.0f, &Button, &Box); + Box.VSplitLeft(Spacing, 0, &Box); // little space + Box.VSplitLeft(ButtonWidth, &Button, &Box); static int s_GraphicsButton=0; - if(DoButton_MenuTabTop(&s_GraphicsButton, Localize("Graphics"), g_Config.m_UiSettingsPage==SETTINGS_GRAPHICS, &Button, CUI::CORNER_T)) + if(DoButton_MenuTabTop(&s_GraphicsButton, Localize("Graphics"), g_Config.m_UiSettingsPage==SETTINGS_GRAPHICS, &Button)) { g_Config.m_UiSettingsPage = SETTINGS_GRAPHICS; } - Box.VSplitLeft(100.0f, &Button, &Box); + Box.VSplitLeft(Spacing, 0, &Box); // little space + Box.VSplitLeft(ButtonWidth, &Button, &Box); static int s_SoundButton=0; - if(DoButton_MenuTabTop(&s_SoundButton, Localize("Sound"), g_Config.m_UiSettingsPage==SETTINGS_SOUND, &Button, CUI::CORNER_T)) + if(DoButton_MenuTabTop(&s_SoundButton, Localize("Sound"), g_Config.m_UiSettingsPage==SETTINGS_SOUND, &Button)) { g_Config.m_UiSettingsPage = SETTINGS_SOUND; } } - - // back to menu - Box.VSplitRight(90.0f, &Box, &Button); - static int s_MenuButton=0; - if(DoButton_Menu(&s_MenuButton, Localize("Menu"), 0, &Button, 12.0f, 0.0f, CUI::CORNER_T|CUI::CORNER_IBR)) - NewPage = PAGE_START; + else if(m_MenuPage == PAGE_DEMOS) + { + // make the header look like an active tab + RenderTools()->DrawUIRect(&Box, vec4(1.0f, 1.0f, 1.0f, 0.75f), CUI::CORNER_ALL, 5.0f); + Box.HMargin(2.0f, &Box); + TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); + TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); + UI()->DoLabel(&Box, Localize("Demo"), Box.h*ms_FontmodHeight, 0); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + } } else { @@ -886,8 +1191,6 @@ int CMenus::RenderMenubar(CUIRect r) else m_GamePage = NewPage; } - - return 0; } void CMenus::RenderLoading() @@ -1039,8 +1342,83 @@ const CMenus::CMenuImage *CMenus::FindMenuImage(const char *pName) return 0; } +void CMenus::UpdateVideoFormats() +{ + m_NumVideoFormats = 0; + for(int i = 0; i < m_NumModes; i++) + { + int G = gcd(m_aModes[i].m_Width, m_aModes[i].m_Height); + int Width = m_aModes[i].m_Width/G; + int Height = m_aModes[i].m_Height/G; + + // check if we already have the format + bool Found = false; + for(int j = 0; j < m_NumVideoFormats; j++) + { + if(Width == m_aVideoFormats[j].m_WidthValue && Height == m_aVideoFormats[j].m_HeightValue) + { + Found = true; + break; + } + } + + if(!Found) + { + m_aVideoFormats[m_NumVideoFormats].m_WidthValue = Width; + m_aVideoFormats[m_NumVideoFormats].m_HeightValue = Height; + m_NumVideoFormats++; + + // sort the array + for(int k = 0; k < m_NumVideoFormats-1; k++) // ffs, bubblesort + { + for(int j = 0; j < m_NumVideoFormats-k-1; j++) + { + if((float)m_aVideoFormats[j].m_WidthValue/(float)m_aVideoFormats[j].m_HeightValue > (float)m_aVideoFormats[j+1].m_WidthValue/(float)m_aVideoFormats[j+1].m_HeightValue) + { + CVideoFormat Tmp = m_aVideoFormats[j]; + m_aVideoFormats[j] = m_aVideoFormats[j+1]; + m_aVideoFormats[j+1] = Tmp; + } + } + } + } + } +} + +void CMenus::UpdatedFilteredVideoModes() +{ + m_lFilteredVideoModes.clear(); + for(int i = 0; i < m_NumModes; i++) + { + int G = gcd(m_aModes[i].m_Width, m_aModes[i].m_Height); + if(m_aVideoFormats[m_CurrentVideoFormat].m_WidthValue == m_aModes[i].m_Width/G && m_aVideoFormats[m_CurrentVideoFormat].m_HeightValue == m_aModes[i].m_Height/G) + m_lFilteredVideoModes.add(m_aModes[i]); + } +} + void CMenus::OnInit() { + m_NumModes = Graphics()->GetVideoModes(m_aModes, MAX_RESOLUTIONS); + UpdateVideoFormats(); + + bool Found = false; + for(int i = 0; i < m_NumVideoFormats; i++) + { + int G = gcd(g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight); + if(m_aVideoFormats[i].m_WidthValue == g_Config.m_GfxScreenWidth/G && m_aVideoFormats[i].m_HeightValue == g_Config.m_GfxScreenHeight/G) + { + m_CurrentVideoFormat = i; + Found = true; + break; + } + + } + + if(!Found) + m_CurrentVideoFormat = 0; + + UpdatedFilteredVideoModes(); + // load menu images m_lMenuImages.clear(); Storage()->ListDirectory(IStorage::TYPE_ALL, "menuimages", MenuImageScan, this); @@ -1144,11 +1522,11 @@ int CMenus::Render() if(Client()->State() != IClient::STATE_ONLINE && !m_pClient->m_pMapLayersBackGround->MenuMapLoaded()) RenderBackground(); - CUIRect TabBar; + CUIRect TabBar, BottomView; CUIRect MainView; // some margin around the screen - Screen.Margin(10.0f, &Screen); + //Screen.Margin(10.0f, &Screen); static bool s_SoundCheck = false; if(!s_SoundCheck && m_Popup == POPUP_NONE) @@ -1162,15 +1540,14 @@ int CMenus::Render() { if(m_MenuPage == PAGE_START && Client()->State() == IClient::STATE_OFFLINE) { - RenderLogo(Screen); RenderStartMenu(Screen); + RenderLogo(Screen); } else { // do tab bar Screen.VMargin(Screen.w/2-365.0f, &MainView); - MainView.HMargin(20.0f, &MainView); - MainView.HSplitTop(24.0f, &TabBar, &MainView); + MainView.HSplitTop(60.0f, &TabBar, &MainView); RenderMenubar(TabBar); // news is not implemented yet @@ -1208,6 +1585,23 @@ int CMenus::Render() RenderServerbrowser(MainView); else if(m_MenuPage == PAGE_SETTINGS) RenderSettings(MainView); + + // same size like tabs in top but variables not really needed + float Spacing = 3.0f; + float ButtonWidth = (MainView.w/6.0f)-(Spacing*5.0)/6.0f; + + // render background + MainView.HSplitBottom(60.0f, 0, &MainView); + MainView.VSplitLeft(ButtonWidth, &MainView, 0); + RenderTools()->DrawUIRect4(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + + // back to main menu + CUIRect Button; + MainView.HSplitTop(25.0f, &MainView, 0); + Button = MainView; + static int s_MenuButton=0; + if(DoButton_Menu(&s_MenuButton, Localize("Back"), 0, &Button)) + m_MenuPage = PAGE_START; // handle back with esc if(m_EscapePressed) @@ -1505,7 +1899,8 @@ int CMenus::Render() ActSelection = Country; static float s_ScrollValue = 0.0f; int OldSelected = -1; - UiDoListboxStart(&s_ScrollValue, &Box, 50.0f, Localize("Country"), "", m_pClient->m_pCountryFlags->Num(), 6, OldSelected, s_ScrollValue); + UiDoListboxHeader(&Box, Localize("Country"), 20.0f, 2.0f); + UiDoListboxStart(&s_ScrollValue, 50.0f, "", m_pClient->m_pCountryFlags->Num(), 6, OldSelected, s_ScrollValue); for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i) { @@ -1667,7 +2062,7 @@ int CMenus::Render() } else if(m_Popup == POPUP_SAVE_SKIN) { - CUIRect Yes, No; + CUIRect Yes, No, EditBox; Box.HSplitBottom(20.f, &Box, &Part); Box.HSplitBottom(24.f, &Box, &Part); Part.VMargin(80.0f, &Part); @@ -1677,16 +2072,25 @@ int CMenus::Render() Yes.VMargin(20.0f, &Yes); No.VMargin(20.0f, &No); + Box.HSplitBottom(Box.h/2.0f, 0, &Box); + Box.HSplitTop(20.0f, &EditBox, &Box); + + static float s_OffsetSaveSkin = 0.0f; + DoEditBoxOption(m_aSaveSkinName, m_aSaveSkinName, sizeof(m_aSaveSkinName), &EditBox, Localize("Skin name"), 100.0f, &s_OffsetSaveSkin); + static int s_ButtonAbort = 0; if(DoButton_Menu(&s_ButtonAbort, Localize("No"), 0, &No) || m_EscapePressed) m_Popup = POPUP_NONE; - static int s_ButtonTryAgain = 0; - if(DoButton_Menu(&s_ButtonTryAgain, Localize("Yes"), 0, &Yes) || m_EnterPressed) + if(m_aSaveSkinName[0]) { - m_Popup = POPUP_NONE; - SaveSkinfile(); - m_aSaveSkinName[0] = 0; + static int s_ButtonTryAgain = 0; + if(DoButton_Menu(&s_ButtonTryAgain, Localize("Yes"), 0, &Yes) || m_EnterPressed) + { + m_Popup = POPUP_NONE; + SaveSkinfile(); + m_aSaveSkinName[0] = 0; + } } } else if(m_Popup == POPUP_FIRST_LAUNCH) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 2bdc0130c..1100b44a5 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -28,18 +29,18 @@ public: enum { - NO_SELECTION=0, - SELECTION_SKIN=1, - SELECTION_BODY=2, - SELECTION_TATTOO=4, - SELECTION_DECORATION=8, - SELECTION_HANDS=16, - SELECTION_FEET=32, - SELECTION_EYES=64 + SELECTION_BODY=0, + SELECTION_TATTOO, + SELECTION_DECORATION, + SELECTION_HANDS, + SELECTION_FEET, + SELECTION_EYES }; class CMenus : public CComponent { + typedef float (*FDropdownCallback)(CUIRect View, void *pUser); + float *ButtonFade(const void *pID, float Seconds, int Checked=0); @@ -51,10 +52,10 @@ class CMenus : public CComponent int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, float r=5.0f, float FontFactor=0.0f, int Corners=CUI::CORNER_ALL); int DoButton_MenuImage(const void *pID, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName, float r=5.0f, float FontFactor=0.0f); int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners); - int DoButton_MenuTabTop(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners); + int DoButton_MenuTabTop(const void *pID, const char *pText, int Checked, const CUIRect *pRect, float r=5.0f, float FontFactor=0.0f, int Corners=CUI::CORNER_ALL); int DoButton_Customize(const void *pID, IGraphics::CTextureHandle Texture, int SpriteID, const CUIRect *pRect, float ImageRatio); - int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect); + int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect, bool Checked=false); int DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect); int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect); @@ -77,7 +78,11 @@ class CMenus : public CComponent static void ui_draw_checkbox(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); */ - int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden=false, int Corners=CUI::CORNER_ALL); + int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden=false, int Corners=CUI::CORNER_ALL); + void DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset); + void DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, float VSplitVal, int Min, int Max, bool infinite=false); + float DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback); + void DoInfoBox(const CUIRect *pRect, const char *pLable, const char *pValue); //static int ui_do_edit_box(void *id, const CUIRect *rect, char *str, unsigned str_size, float font_size, bool hidden=false); float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current); @@ -86,7 +91,7 @@ class CMenus : public CComponent int DoKeyReader(void *pID, const CUIRect *pRect, int Key); //static int ui_do_key_reader(void *id, const CUIRect *rect, int key); - void UiDoGetButtons(int Start, int Stop, CUIRect View); + void UiDoGetButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spaceing); struct CListboxItem { @@ -96,8 +101,9 @@ class CMenus : public CComponent CUIRect m_HitRect; }; - void UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems, - int ItemsPerRow, int SelectedIndex, float ScrollValue); + void UiDoListboxHeader(const CUIRect *pRect, const char *pTitle, float HeaderHeight, float Spaceing); + void UiDoListboxStart(const void *pID, float RowHeight, const char *pBottomText, int NumItems, + int ItemsPerRow, int SelectedIndex, float ScrollValue, const CUIRect *pRect=0); CListboxItem UiDoListboxNextItem(const void *pID, bool Selected = false); CListboxItem UiDoListboxNextRow(); int UiDoListboxEnd(float *pScrollValue, bool *pItemActivated); @@ -194,8 +200,7 @@ class CMenus : public CComponent // for settings bool m_NeedRestartGraphics; bool m_NeedRestartSound; - int m_TeePartSelection; - int m_TeePartsColorSelection; + int m_TeePartSelected; char m_aSaveSkinName[24]; void SaveSkinfile(); @@ -216,6 +221,9 @@ class CMenus : public CComponent int m_CallvoteSelectedPlayer; char m_aCallvoteReason[VOTE_REASON_LENGTH]; + // for callbacks + int *m_pActiveDropdown; + // demo struct CDemoItem { @@ -376,11 +384,32 @@ class CMenus : public CComponent static CColumn ms_aCols[NUM_COLS]; + enum + { + MAX_RESOLUTIONS=256, + }; + + CVideoMode m_aModes[MAX_RESOLUTIONS]; + int m_NumModes; + + struct CVideoFormat + { + int m_WidthValue; + int m_HeightValue; + }; + + CVideoFormat m_aVideoFormats[MAX_RESOLUTIONS]; + sorted_array m_lFilteredVideoModes; + int m_NumVideoFormats; + int m_CurrentVideoFormat; + void UpdateVideoFormats(); + void UpdatedFilteredVideoModes(); + // found in menus.cpp int Render(); //void render_background(); //void render_loading(float percent); - int RenderMenubar(CUIRect r); + void RenderMenubar(CUIRect r); void RenderNews(CUIRect MainView); // found in menus_demo.cpp @@ -423,11 +452,20 @@ class CMenus : public CComponent void RenderSettingsGeneral(CUIRect MainView); void RenderSettingsPlayer(CUIRect MainView); void RenderSettingsTee(CUIRect MainView); + void RenderSettingsTeeBasic(CUIRect MainView); + void RenderSettingsTeeCustom(CUIRect MainView); void RenderSettingsControls(CUIRect MainView); void RenderSettingsGraphics(CUIRect MainView); void RenderSettingsSound(CUIRect MainView); void RenderSettings(CUIRect MainView); + // found in menu_callback.cpp + static float RenderSettingsControlsMovement(CUIRect View, void *pUser); + static float RenderSettingsControlsWeapon(CUIRect View, void *pUser); + static float RenderSettingsControlsVoting(CUIRect View, void *pUser); + static float RenderSettingsControlsChat(CUIRect View, void *pUser); + static float RenderSettingsControlsMisc(CUIRect View, void *pUser); + void SetActive(bool Active); void InvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CMenus *pMenu, CUIRect Rect), void *pExtra=0); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 6c1f3b436..1fd551e1d 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1153,7 +1153,8 @@ void CMenus::RenderServerbrowserFriends(CUIRect View) // friends list(remove friend) static float s_ScrollValue = 0; static int s_FriendsList = 0; - UiDoListboxStart(&s_FriendsList, &List, 30.0f, "", "", m_lFriends.size(), 1, m_FriendlistSelectedIndex, s_ScrollValue); + UiDoListboxHeader(&List, "", 20.0f, 2.0f); + UiDoListboxStart(&s_FriendsList, 30.0f, "", m_lFriends.size(), 1, m_FriendlistSelectedIndex, s_ScrollValue); m_lFriends.sort_range(); for(int i = 0; i < m_lFriends.size(); ++i) diff --git a/src/game/client/components/menus_callback.cpp b/src/game/client/components/menus_callback.cpp new file mode 100644 index 000000000..2f5c7658c --- /dev/null +++ b/src/game/client/components/menus_callback.cpp @@ -0,0 +1,264 @@ +/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ +/* If you are missing that file, acquire a complete release at teeworlds.com. */ +#include + +#include "binds.h" +#include "menus.h" + +typedef struct +{ + CLocConstString m_Name; + const char *m_pCommand; + int m_KeyId; +} CKeyInfo; + +static CKeyInfo gs_aKeys[] = +{ + { "Move left", "+left", 0}, // Localize - these strings are localized within CLocConstString + { "Move right", "+right", 0 }, + { "Jump", "+jump", 0 }, + { "Fire", "+fire", 0 }, + { "Hook", "+hook", 0 }, + { "Hammer", "+weapon1", 0 }, + { "Pistol", "+weapon2", 0 }, + { "Shotgun", "+weapon3", 0 }, + { "Grenade", "+weapon4", 0 }, + { "Laser", "+weapon5", 0 }, + { "Next weapon", "+nextweapon", 0 }, + { "Prev. weapon", "+prevweapon", 0 }, + { "Vote yes", "vote yes", 0 }, + { "Vote no", "vote no", 0 }, + { "Chat", "chat all", 0 }, + { "Team chat", "chat team", 0 }, + { "Show chat", "+show_chat", 0 }, + { "Emoticon", "+emote", 0 }, + { "Spectator mode", "+spectate", 0 }, + { "Spectate next", "spectate_next", 0 }, + { "Spectate previous", "spectate_previous", 0 }, + { "Console", "toggle_local_console", 0 }, + { "Remote console", "toggle_remote_console", 0 }, + { "Screenshot", "screenshot", 0 }, + { "Scoreboard", "+scoreboard", 0 }, + { "Respawn", "kill", 0 }, + { "Ready", "ready_change", 0 }, +}; + +/* This is for scripts/update_localization.py to work, don't remove! + Localize("Move left");Localize("Move right");Localize("Jump");Localize("Fire");Localize("Hook");Localize("Hammer"); + Localize("Pistol");Localize("Shotgun");Localize("Grenade");Localize("Laser");Localize("Next weapon");Localize("Prev. weapon"); + Localize("Vote yes");Localize("Vote no");Localize("Chat");Localize("Team chat");Localize("Show chat");Localize("Emoticon"); + Localize("Spectator mode");Localize("Spectate next");Localize("Spectate previous");Localize("Console");Localize("Remote console"); + Localize("Screenshot");Localize("Scoreboard");Localize("Respawn");Localize("Ready"); +*/ + +const int g_KeyCount = sizeof(gs_aKeys) / sizeof(CKeyInfo); + +void CMenus::UiDoGetButtons(int Start, int Stop, CUIRect View, float ButtonHeight, float Spaceing) +{ + for (int i = Start; i < Stop; i++) + { + View.HSplitTop(Spaceing, 0, &View); + + CKeyInfo &Key = gs_aKeys[i]; + CUIRect Button, Label; + View.HSplitTop(ButtonHeight, &Button, &View); + RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + Button.VSplitMid(&Label, &Button); + + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%s:", (const char *)Key.m_Name); + + Label.y += 2.0f; + UI()->DoLabelScaled(&Label, aBuf, 13.0f, 0); + int OldId = Key.m_KeyId; + int NewId = DoKeyReader((void *)&gs_aKeys[i].m_Name, &Button, OldId); + if(NewId != OldId) + { + if(OldId != 0 || NewId == 0) + m_pClient->m_pBinds->Bind(OldId, ""); + if(NewId != 0) + m_pClient->m_pBinds->Bind(NewId, gs_aKeys[i].m_pCommand); + } + } +} + +float CMenus::RenderSettingsControlsMovement(CUIRect View, void *pUser) +{ + CMenus *pSelf = (CMenus*)pUser; + + // this is kinda slow, but whatever + for(int i = 0; i < g_KeyCount; i++) + gs_aKeys[i].m_KeyId = 0; + + for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) + { + const char *pBind = pSelf->m_pClient->m_pBinds->Get(KeyId); + if(!pBind[0]) + continue; + + for(int i = 0; i < g_KeyCount; i++) + if(str_comp(pBind, gs_aKeys[i].m_pCommand) == 0) + { + gs_aKeys[i].m_KeyId = KeyId; + break; + } + } + + int NumOptions = 6; + float ButtonHeight = 20.0f; + float Spaceing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + + View.HSplitTop(BackgroundHeight, &View, 0); + pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + + CUIRect Button; + View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(ButtonHeight, &Button, &View); + pSelf->DoScrollbarOption(&g_Config.m_InpMousesens, &g_Config.m_InpMousesens, &Button, Localize("Mouse sens."), 150.0f, 5, 500); + + pSelf->UiDoGetButtons(0, 5, View, ButtonHeight, Spaceing); + + return BackgroundHeight; +} + +float CMenus::RenderSettingsControlsWeapon(CUIRect View, void *pUser) +{ + CMenus *pSelf = (CMenus*)pUser; + + // this is kinda slow, but whatever + for(int i = 0; i < g_KeyCount; i++) + gs_aKeys[i].m_KeyId = 0; + + for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) + { + const char *pBind = pSelf->m_pClient->m_pBinds->Get(KeyId); + if(!pBind[0]) + continue; + + for(int i = 0; i < g_KeyCount; i++) + if(str_comp(pBind, gs_aKeys[i].m_pCommand) == 0) + { + gs_aKeys[i].m_KeyId = KeyId; + break; + } + } + + int NumOptions = 7; + float ButtonHeight = 20.0f; + float Spaceing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + + View.HSplitTop(BackgroundHeight, &View, 0); + pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + + pSelf->UiDoGetButtons(5, 12, View, ButtonHeight, Spaceing); + + return BackgroundHeight; +} + +float CMenus::RenderSettingsControlsVoting(CUIRect View, void *pUser) +{ + CMenus *pSelf = (CMenus*)pUser; + + // this is kinda slow, but whatever + for(int i = 0; i < g_KeyCount; i++) + gs_aKeys[i].m_KeyId = 0; + + for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) + { + const char *pBind = pSelf->m_pClient->m_pBinds->Get(KeyId); + if(!pBind[0]) + continue; + + for(int i = 0; i < g_KeyCount; i++) + if(str_comp(pBind, gs_aKeys[i].m_pCommand) == 0) + { + gs_aKeys[i].m_KeyId = KeyId; + break; + } + } + + int NumOptions = 2; + float ButtonHeight = 20.0f; + float Spaceing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + + View.HSplitTop(BackgroundHeight, &View, 0); + pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + + pSelf->UiDoGetButtons(12, 14, View, ButtonHeight, Spaceing); + + return BackgroundHeight; +} + +float CMenus::RenderSettingsControlsChat(CUIRect View, void *pUser) +{ + CMenus *pSelf = (CMenus*)pUser; + + // this is kinda slow, but whatever + for(int i = 0; i < g_KeyCount; i++) + gs_aKeys[i].m_KeyId = 0; + + for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) + { + const char *pBind = pSelf->m_pClient->m_pBinds->Get(KeyId); + if(!pBind[0]) + continue; + + for(int i = 0; i < g_KeyCount; i++) + if(str_comp(pBind, gs_aKeys[i].m_pCommand) == 0) + { + gs_aKeys[i].m_KeyId = KeyId; + break; + } + } + + int NumOptions = 3; + float ButtonHeight = 20.0f; + float Spaceing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + + View.HSplitTop(BackgroundHeight, &View, 0); + pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + + pSelf->UiDoGetButtons(14, 17, View, ButtonHeight, Spaceing); + + return BackgroundHeight; +} + +float CMenus::RenderSettingsControlsMisc(CUIRect View, void *pUser) +{ + CMenus *pSelf = (CMenus*)pUser; + + // this is kinda slow, but whatever + for(int i = 0; i < g_KeyCount; i++) + gs_aKeys[i].m_KeyId = 0; + + for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) + { + const char *pBind = pSelf->m_pClient->m_pBinds->Get(KeyId); + if(!pBind[0]) + continue; + + for(int i = 0; i < g_KeyCount; i++) + if(str_comp(pBind, gs_aKeys[i].m_pCommand) == 0) + { + gs_aKeys[i].m_KeyId = KeyId; + break; + } + } + + int NumOptions = 9; + float ButtonHeight = 20.0f; + float Spaceing = 2.0f; + float BackgroundHeight = (float)NumOptions*ButtonHeight+(float)NumOptions*Spaceing; + + View.HSplitTop(BackgroundHeight, &View, 0); + pSelf->RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f); + + pSelf->UiDoGetButtons(17, 26, View, ButtonHeight, Spaceing); + + return BackgroundHeight; +} \ No newline at end of file diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 39bfa2d9b..e1f75895c 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -254,210 +254,6 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) } } -static CUIRect gs_ListBoxOriginalView; -static CUIRect gs_ListBoxView; -static float gs_ListBoxRowHeight; -static int gs_ListBoxItemIndex; -static int gs_ListBoxSelectedIndex; -static int gs_ListBoxNewSelected; -static int gs_ListBoxDoneEvents; -static int gs_ListBoxNumItems; -static int gs_ListBoxItemsPerRow; -static float gs_ListBoxScrollValue; -static bool gs_ListBoxItemActivated; - -void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems, - int ItemsPerRow, int SelectedIndex, float ScrollValue) -{ - CUIRect Scroll, Row; - CUIRect View = *pRect; - CUIRect Header, Footer; - - // draw header - View.HSplitTop(ms_ListheaderHeight, &Header, &View); - RenderTools()->DrawUIRect(&Header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); - UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight, 0); - - // draw footers - View.HSplitBottom(ms_ListheaderHeight, &View, &Footer); - RenderTools()->DrawUIRect(&Footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); - Footer.VSplitLeft(10.0f, 0, &Footer); - UI()->DoLabel(&Footer, pBottomText, Header.h*ms_FontmodHeight, 0); - - // background - RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.15f), 0, 0); - - // prepare the scroll - View.VSplitRight(15, &View, &Scroll); - - // setup the variables - gs_ListBoxOriginalView = View; - gs_ListBoxSelectedIndex = SelectedIndex; - gs_ListBoxNewSelected = SelectedIndex; - gs_ListBoxItemIndex = 0; - gs_ListBoxRowHeight = RowHeight; - gs_ListBoxNumItems = NumItems; - gs_ListBoxItemsPerRow = ItemsPerRow; - gs_ListBoxDoneEvents = 0; - gs_ListBoxScrollValue = ScrollValue; - gs_ListBoxItemActivated = false; - - // do the scrollbar - View.HSplitTop(gs_ListBoxRowHeight, &Row, 0); - - int NumViewable = (int)(gs_ListBoxOriginalView.h/Row.h) + 1; - int Num = (NumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1; - if(Num < 0) - Num = 0; - if(Num > 0) - { - if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP) && UI()->MouseInside(&View)) - gs_ListBoxScrollValue -= 3.0f/Num; - if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN) && UI()->MouseInside(&View)) - gs_ListBoxScrollValue += 3.0f/Num; - - if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f; - if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; - } - - Scroll.HMargin(5.0f, &Scroll); - gs_ListBoxScrollValue = DoScrollbarV(pID, &Scroll, gs_ListBoxScrollValue); - - // the list - gs_ListBoxView = gs_ListBoxOriginalView; - gs_ListBoxView.VMargin(5.0f, &gs_ListBoxView); - UI()->ClipEnable(&gs_ListBoxView); - gs_ListBoxView.y -= gs_ListBoxScrollValue*Num*Row.h; -} - -CMenus::CListboxItem CMenus::UiDoListboxNextRow() -{ - static CUIRect s_RowView; - CListboxItem Item = {0}; - if(gs_ListBoxItemIndex%gs_ListBoxItemsPerRow == 0) - gs_ListBoxView.HSplitTop(gs_ListBoxRowHeight /*-2.0f*/, &s_RowView, &gs_ListBoxView); - - s_RowView.VSplitLeft(s_RowView.w/(gs_ListBoxItemsPerRow-gs_ListBoxItemIndex%gs_ListBoxItemsPerRow)/(UI()->Scale()), &Item.m_Rect, &s_RowView); - - Item.m_Visible = 1; - //item.rect = row; - - Item.m_HitRect = Item.m_Rect; - - //CUIRect select_hit_box = item.rect; - - if(gs_ListBoxSelectedIndex == gs_ListBoxItemIndex) - Item.m_Selected = 1; - - // make sure that only those in view can be selected - if(Item.m_Rect.y+Item.m_Rect.h > gs_ListBoxOriginalView.y) - { - - if(Item.m_HitRect.y < Item.m_HitRect.y) // clip the selection - { - Item.m_HitRect.h -= gs_ListBoxOriginalView.y-Item.m_HitRect.y; - Item.m_HitRect.y = gs_ListBoxOriginalView.y; - } - - } - else - Item.m_Visible = 0; - - // check if we need to do more - if(Item.m_Rect.y > gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h) - Item.m_Visible = 0; - - gs_ListBoxItemIndex++; - return Item; -} - -CMenus::CListboxItem CMenus::UiDoListboxNextItem(const void *pId, bool Selected) -{ - int ThisItemIndex = gs_ListBoxItemIndex; - if(Selected) - { - if(gs_ListBoxSelectedIndex == gs_ListBoxNewSelected) - gs_ListBoxNewSelected = ThisItemIndex; - gs_ListBoxSelectedIndex = ThisItemIndex; - } - - CListboxItem Item = UiDoListboxNextRow(); - - if(Item.m_Visible && UI()->DoButtonLogic(pId, "", gs_ListBoxSelectedIndex == gs_ListBoxItemIndex, &Item.m_HitRect)) - gs_ListBoxNewSelected = ThisItemIndex; - - // process input, regard selected index - if(gs_ListBoxSelectedIndex == ThisItemIndex) - { - if(!gs_ListBoxDoneEvents) - { - gs_ListBoxDoneEvents = 1; - - if(m_EnterPressed || (UI()->ActiveItem() == pId && Input()->MouseDoubleClick())) - { - gs_ListBoxItemActivated = true; - UI()->SetActiveItem(0); - } - else - { - for(int i = 0; i < m_NumInputEvents; i++) - { - int NewIndex = -1; - if(m_aInputEvents[i].m_Flags&IInput::FLAG_PRESS) - { - if(m_aInputEvents[i].m_Key == KEY_DOWN) NewIndex = gs_ListBoxNewSelected + 1; - if(m_aInputEvents[i].m_Key == KEY_UP) NewIndex = gs_ListBoxNewSelected - 1; - } - if(NewIndex > -1 && NewIndex < gs_ListBoxNumItems) - { - // scroll - float Offset = (NewIndex/gs_ListBoxItemsPerRow-gs_ListBoxNewSelected/gs_ListBoxItemsPerRow)*gs_ListBoxRowHeight; - int Scroll = gs_ListBoxOriginalView.y > Item.m_Rect.y+Offset ? -1 : - gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h < Item.m_Rect.y+Item.m_Rect.h+Offset ? 1 : 0; - if(Scroll) - { - int NumViewable = (int)(gs_ListBoxOriginalView.h/gs_ListBoxRowHeight) + 1; - int ScrollNum = (gs_ListBoxNumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1; - if(Scroll < 0) - { - int Num = (gs_ListBoxOriginalView.y-Item.m_Rect.y-Offset+gs_ListBoxRowHeight-1.0f)/gs_ListBoxRowHeight; - gs_ListBoxScrollValue -= (1.0f/ScrollNum)*Num; - } - else - { - int Num = (Item.m_Rect.y+Item.m_Rect.h+Offset-(gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h)+gs_ListBoxRowHeight-1.0f)/ - gs_ListBoxRowHeight; - gs_ListBoxScrollValue += (1.0f/ScrollNum)*Num; - } - if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f; - if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; - } - - gs_ListBoxNewSelected = NewIndex; - } - } - } - } - - //selected_index = i; - CUIRect r = Item.m_Rect; - r.Margin(1.5f, &r); - RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f); - } - - return Item; -} - -int CMenus::UiDoListboxEnd(float *pScrollValue, bool *pItemActivated) -{ - UI()->ClipDisable(); - if(pScrollValue) - *pScrollValue = gs_ListBoxScrollValue; - if(pItemActivated) - *pItemActivated = gs_ListBoxItemActivated; - return gs_ListBoxNewSelected; -} - int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser) { CMenus *pSelf = (CMenus *)pUser; @@ -504,6 +300,13 @@ void CMenus::DemolistOnUpdate(bool Reset) void CMenus::RenderDemoList(CUIRect MainView) { + CUIRect BottomView; + MainView.HSplitTop(20.0f, 0, &MainView); + + // cut view + MainView.HSplitBottom(80.0f, &MainView, &BottomView); + BottomView.HSplitTop(20.f, 0, &BottomView); + static int s_Inited = 0; if(!s_Inited) { @@ -536,91 +339,13 @@ void CMenus::RenderDemoList(CUIRect MainView) } } - // render background - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 10.0f); - MainView.Margin(10.0f, &MainView); - - CUIRect ButtonBar, RefreshRect, PlayRect, DeleteRect, RenameRect, FileIcon, ListBox; - MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar); - ButtonBar.HSplitTop(5.0f, 0, &ButtonBar); - ButtonBar.VSplitRight(130.0f, &ButtonBar, &PlayRect); - ButtonBar.VSplitLeft(130.0f, &RefreshRect, &ButtonBar); - ButtonBar.VSplitLeft(10.0f, 0, &ButtonBar); - ButtonBar.VSplitLeft(120.0f, &DeleteRect, &ButtonBar); - ButtonBar.VSplitLeft(10.0f, 0, &ButtonBar); - ButtonBar.VSplitLeft(120.0f, &RenameRect, &ButtonBar); - MainView.HSplitBottom(140.0f, &ListBox, &MainView); - - // render demo info - MainView.VMargin(5.0f, &MainView); - MainView.HSplitBottom(5.0f, &MainView, 0); - RenderTools()->DrawUIRect(&MainView, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f); - if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) - { - CUIRect Left, Right, Labels; - MainView.Margin(20.0f, &MainView); - MainView.VSplitMid(&Labels, &MainView); - - // left side - Labels.HSplitTop(20.0f, &Left, &Labels); - Left.VSplitLeft(150.0f, &Left, &Right); - UI()->DoLabelScaled(&Left, Localize("Created:"), 14.0f, -1); - UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aTimestamp, 14.0f, -1); - Labels.HSplitTop(5.0f, 0, &Labels); - Labels.HSplitTop(20.0f, &Left, &Labels); - Left.VSplitLeft(150.0f, &Left, &Right); - UI()->DoLabelScaled(&Left, Localize("Type:"), 14.0f, -1); - UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aType, 14.0f, -1); - Labels.HSplitTop(5.0f, 0, &Labels); - Labels.HSplitTop(20.0f, &Left, &Labels); - Left.VSplitLeft(150.0f, &Left, &Right); - UI()->DoLabelScaled(&Left, Localize("Length:"), 14.0f, -1); - int Length = ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[0]<<24)&0xFF000000) | ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[1]<<16)&0xFF0000) | - ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[2]<<8)&0xFF00) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[3]&0xFF); - char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%d:%02d", Length/60, Length%60); - UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); - Labels.HSplitTop(5.0f, 0, &Labels); - Labels.HSplitTop(20.0f, &Left, &Labels); - Left.VSplitLeft(150.0f, &Left, &Right); - UI()->DoLabelScaled(&Left, Localize("Version:"), 14.0f, -1); - str_format(aBuf, sizeof(aBuf), "%d", m_lDemos[m_DemolistSelectedIndex].m_Info.m_Version); - UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); - - // right side - Labels = MainView; - Labels.HSplitTop(20.0f, &Left, &Labels); - Left.VSplitLeft(150.0f, &Left, &Right); - UI()->DoLabelScaled(&Left, Localize("Map:"), 14.0f, -1); - UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapName, 14.0f, -1); - Labels.HSplitTop(5.0f, 0, &Labels); - Labels.HSplitTop(20.0f, &Left, &Labels); - Left.VSplitLeft(20.0f, 0, &Left); - Left.VSplitLeft(130.0f, &Left, &Right); - UI()->DoLabelScaled(&Left, Localize("Size:"), 14.0f, -1); - unsigned Size = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[1]<<16) | - (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[3]); - str_format(aBuf, sizeof(aBuf), Localize("%d Bytes"), Size); - UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); - Labels.HSplitTop(5.0f, 0, &Labels); - Labels.HSplitTop(20.0f, &Left, &Labels); - Left.VSplitLeft(20.0f, 0, &Left); - Left.VSplitLeft(130.0f, &Left, &Right); - UI()->DoLabelScaled(&Left, Localize("Crc:"), 14.0f, -1); - unsigned Crc = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[1]<<16) | - (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[3]); - str_format(aBuf, sizeof(aBuf), "%08x", Crc); - UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1); - Labels.HSplitTop(5.0f, 0, &Labels); - Labels.HSplitTop(20.0f, &Left, &Labels); - Left.VSplitLeft(150.0f, &Left, &Right); - UI()->DoLabelScaled(&Left, Localize("Netversion:"), 14.0f, -1); - UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aNetversion, 14.0f, -1); - } + CUIRect ListBox, Button, Label, FileIcon; + MainView.HSplitTop(230.0f, &ListBox, &MainView); static int s_DemoListId = 0; static float s_ScrollValue = 0; - UiDoListboxStart(&s_DemoListId, &ListBox, 17.0f, Localize("Demos"), aFooterLabel, m_lDemos.size(), 1, m_DemolistSelectedIndex, s_ScrollValue); + UiDoListboxHeader(&ListBox, Localize("Recorded"), 20.0f, 2.0f); + UiDoListboxStart(&s_DemoListId, 20.0f, 0, m_lDemos.size(), 1, m_DemolistSelectedIndex, s_ScrollValue); for(sorted_array::range r = m_lDemos.all(); !r.empty(); r.pop_front()) { CListboxItem Item = UiDoListboxNextItem((void*)(&r.front())); @@ -628,23 +353,140 @@ void CMenus::RenderDemoList(CUIRect MainView) { Item.m_Rect.VSplitLeft(Item.m_Rect.h, &FileIcon, &Item.m_Rect); Item.m_Rect.VSplitLeft(5.0f, 0, &Item.m_Rect); + FileIcon.Margin(3.0f, &FileIcon); + FileIcon.x += 3.0f; DoButton_Icon(IMAGE_FILEICONS, r.front().m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon); - UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight, -1); + if(!str_comp(m_lDemos[m_DemolistSelectedIndex].m_aName, r.front().m_aName)) + { + TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); + TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); + Item.m_Rect.y += 2.0f; + UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, 0); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + } + else + { + Item.m_Rect.y += 2.0f; + UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, 0); + } } } bool Activated = false; m_DemolistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, &Activated); DemolistOnUpdate(false); + // render demo info + int NumOptions = (!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) ? 8 : 0; + float ButtonHeight = 20.0f; + float Spacing = 2.0f; + float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; + + MainView.HSplitTop(10.0f, 0, &MainView); + MainView.HSplitTop(BackgroundHeight, &MainView, 0); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + MainView.HSplitTop(ButtonHeight, &Label, &MainView); + Label.y += 2.0f; + UI()->DoLabel(&Label, aFooterLabel, ButtonHeight*ms_FontmodHeight*0.8f, 0); + if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid) + { + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + DoInfoBox(&Button, Localize("Created"), m_lDemos[m_DemolistSelectedIndex].m_Info.m_aTimestamp); + + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + DoInfoBox(&Button, Localize("Type"), m_lDemos[m_DemolistSelectedIndex].m_Info.m_aType); + + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + int Length = ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[0]<<24)&0xFF000000) | ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[1]<<16)&0xFF0000) | + ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[2]<<8)&0xFF00) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[3]&0xFF); + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%d:%02d", Length/60, Length%60); + DoInfoBox(&Button, Localize("Length"), aBuf); + + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + str_format(aBuf, sizeof(aBuf), "%d", m_lDemos[m_DemolistSelectedIndex].m_Info.m_Version); + DoInfoBox(&Button, Localize("Version"), aBuf); + + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + DoInfoBox(&Button, Localize("Map"), m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapName); + + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + unsigned Size = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[1]<<16) | + (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[3]); + str_format(aBuf, sizeof(aBuf), Localize("%d Bytes"), Size); + DoInfoBox(&Button, Localize("Size"), aBuf); + + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + unsigned Crc = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[1]<<16) | + (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[3]); + str_format(aBuf, sizeof(aBuf), "%08x", Crc); + DoInfoBox(&Button, Localize("Crc"), aBuf); + + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + DoInfoBox(&Button, Localize("Netversion"), m_lDemos[m_DemolistSelectedIndex].m_Info.m_aNetversion); + } + + // demo buttons + int NumButtons = m_DemolistSelectedIsDir ? 2 : 4; + Spacing = 3.0f; + float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; + float BackgroundWidth = ButtonWidth*(float)NumButtons+(float)(NumButtons-1)*Spacing; + + BottomView.VSplitRight(BackgroundWidth, 0, &BottomView); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + + BottomView.HSplitTop(25.0f, &BottomView, 0); + BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); static int s_RefreshButton = 0; - if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect)) + if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button)) { DemolistPopulate(); DemolistOnUpdate(false); } + if(!m_DemolistSelectedIsDir) + { + BottomView.VSplitLeft(Spacing, 0, &BottomView); + BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); + static int s_DeleteButton = 0; + if(DoButton_Menu(&s_DeleteButton, Localize("Delete"), 0, &Button) || m_DeletePressed) + { + if(m_DemolistSelectedIndex >= 0) + { + UI()->SetActiveItem(0); + m_Popup = POPUP_DELETE_DEMO; + return; + } + } + + BottomView.VSplitLeft(Spacing, 0, &BottomView); + BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); + static int s_RenameButton = 0; + if(DoButton_Menu(&s_RenameButton, Localize("Rename"), 0, &Button)) + { + if(m_DemolistSelectedIndex >= 0) + { + UI()->SetActiveItem(0); + m_Popup = POPUP_RENAME_DEMO; + str_copy(m_aCurrentDemoFile, m_lDemos[m_DemolistSelectedIndex].m_aFilename, sizeof(m_aCurrentDemoFile)); + return; + } + } + } + + BottomView.VSplitLeft(Spacing, 0, &BottomView); + BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); static int s_PlayButton = 0; - if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir?Localize("Open"):Localize("Play"), 0, &PlayRect) || Activated) + if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir?Localize("Open"):Localize("Play"), 0, &Button) || Activated) { if(m_DemolistSelectedIndex >= 0) { @@ -677,30 +519,4 @@ void CMenus::RenderDemoList(CUIRect MainView) } } } - - if(!m_DemolistSelectedIsDir) - { - static int s_DeleteButton = 0; - if(DoButton_Menu(&s_DeleteButton, Localize("Delete"), 0, &DeleteRect) || m_DeletePressed) - { - if(m_DemolistSelectedIndex >= 0) - { - UI()->SetActiveItem(0); - m_Popup = POPUP_DELETE_DEMO; - return; - } - } - - static int s_RenameButton = 0; - if(DoButton_Menu(&s_RenameButton, Localize("Rename"), 0, &RenameRect)) - { - if(m_DemolistSelectedIndex >= 0) - { - UI()->SetActiveItem(0); - m_Popup = POPUP_RENAME_DEMO; - str_copy(m_aCurrentDemoFile, m_lDemos[m_DemolistSelectedIndex].m_aFilename, sizeof(m_aCurrentDemoFile)); - return; - } - } - } } diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 7cf63865b..ee0cca9ca 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -353,7 +353,8 @@ void CMenus::RenderServerControlServer(CUIRect MainView) static int s_VoteList = 0; static float s_ScrollValue = 0; CUIRect List = MainView; - UiDoListboxStart(&s_VoteList, &List, 24.0f, "", "", m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, s_ScrollValue); + UiDoListboxHeader(&List, "", 20.0f, 2.0f); + UiDoListboxStart(&s_VoteList, 24.0f, "", m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, s_ScrollValue); for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext) { @@ -389,7 +390,8 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) static int s_VoteList = 0; static float s_ScrollValue = 0; CUIRect List = MainView; - UiDoListboxStart(&s_VoteList, &List, 24.0f, "", "", NumOptions, 1, Selected, s_ScrollValue); + UiDoListboxHeader(&List, "", 20.0f, 2.0f); + UiDoListboxStart(&s_VoteList, 24.0f, "", NumOptions, 1, Selected, s_ScrollValue); for(int i = 0; i < NumOptions; i++) { diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 8c39f2f54..ec57da9c1 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -121,15 +121,15 @@ void CMenus::WriteLineSkinfile(IOHANDLE File, const char *pLine) io_write_newline(File); } -void CMenus::RenderHSLPicker(CUIRect Picker) +void CMenus::RenderHSLPicker(CUIRect MainView) { - CUIRect Label, Button; + CUIRect Label, Button, Picker; bool Modified = false; int ConfigColor = -1; for(int p = 0; p < NUM_SKINPARTS; p++) { - if(!(m_TeePartsColorSelection & gs_aSelectionParts[p])) + if(p != m_TeePartSelected) continue; int Val = (*gs_apColorVariables[p])&0xffffff; if(ConfigColor != -1 && ConfigColor != Val) @@ -140,7 +140,29 @@ void CMenus::RenderHSLPicker(CUIRect Picker) ConfigColor = Val; } - bool UseAlpha = m_TeePartsColorSelection & SELECTION_TATTOO; + // background + float Spacing = 2.0f; + float ButtonHeight = 20.0f; + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + MainView.HSplitTop(ButtonHeight, &Label, &MainView); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Coloration"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + MainView.HSplitTop(Spacing, 0, &MainView); + + // custom color button + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + static int s_CustomColors = 0; + if(DoButton_CheckBox(&s_CustomColors, Localize("Custom colors"), *gs_apUCCVariables[m_TeePartSelected], &Button)) + *gs_apUCCVariables[m_TeePartSelected] ^= 1; + + if(!(*gs_apUCCVariables[m_TeePartSelected])) + return; + + MainView.HSplitTop(Spacing, 0, &MainView); + + bool UseAlpha = m_TeePartSelected == SELECTION_TATTOO; int Hue, Sat, Lgt, Alp; if(ConfigColor != -1) @@ -160,10 +182,15 @@ void CMenus::RenderHSLPicker(CUIRect Picker) else Alp = -1; + MainView.HSplitTop(UseAlpha ? 144.0f : 186.0f, &Picker, &MainView); + RenderTools()->DrawUIRect(&Picker, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + // Hue/Lgt picker : { - Picker.VSplitLeft(256.0f, &Picker, 0); - Picker.HSplitTop(128.0f, &Picker, 0); + Picker.VMargin((Picker.w-256.0f)/2.0f, &Picker); + Picker.HMargin((Picker.h-128.0f)/2.0f, &Picker); + //Picker.VSplitLeft(256.0f, &Picker, 0); + //Picker.HSplitTop(128.0f, &Picker, 0); // picker Graphics()->TextureSet(g_pData->m_aImages[IMAGE_HLPICKER].m_Id); @@ -212,31 +239,37 @@ void CMenus::RenderHSLPicker(CUIRect Picker) } } + MainView.HSplitTop(Spacing, 0, &MainView); + // H/S/L/A sliders : { - static float const aPos[4] = {130.0f, 147.0f, 164.0f, 181.0f}; + int NumBars = UseAlpha ? 4 : 3; const char *const apNames[4] = {Localize("Hue:"), Localize("Sat:"), Localize("Lgt:"), Localize("Alp:")}; int *const apVars[4] = {&Hue, &Sat, &Lgt, &Alp}; static int s_aButtons[12]; - int NumBars = UseAlpha ? 4 : 3; for(int i = 0; i < NumBars; i++) { CUIRect Bar; // label - Picker.HSplitTop(aPos[i], 0, &Label); - Label.HSplitTop(15.0f, &Label, 0); - Label.VSplitLeft(30.0f, &Label, &Button); - UI()->DoLabelScaled(&Label, apNames[i], 12.0f, -1); + MainView.HSplitTop(ButtonHeight, &Label, &MainView); + MainView.HSplitTop(Spacing, 0, &MainView); + RenderTools()->DrawUIRect(&Label, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + Label.VSplitLeft((Label.w-168.0f)/2.0f, &Label, &Button); + Label.y += 2.0f; + UI()->DoLabelScaled(&Label, apNames[i], ButtonHeight*ms_FontmodHeight*0.8f, 0); + // button < - Button.VSplitLeft(20.0f, &Button, &Bar); + Button.VSplitLeft(Button.h, &Button, &Bar); if(DoButton_Menu(&s_aButtons[i*3], "<", 0, &Button, 5.0f, 0.0f, CUI::CORNER_TL|CUI::CORNER_BL)) { *apVars[i] = max(0, *apVars[i]-1); Modified = true; } + // bar - Bar.VSplitLeft(256/2, &Bar, &Button); + Bar.VSplitLeft(256.0f/2.0f, &Bar, &Button); Graphics()->TextureClear(); Graphics()->QuadsBegin(); for(int v = 0; v < 256/2; v++) @@ -259,22 +292,26 @@ void CMenus::RenderHSLPicker(CUIRect Picker) IGraphics::CQuadItem QuadItem(Bar.x+v*UI()->Scale(), Bar.y, 1.0f*UI()->Scale(), Bar.h); Graphics()->QuadsDrawTL(&QuadItem, 1); } + // bar marker Graphics()->SetColor(0.0f, 0.0f, 0.0f, 1.0f); IGraphics::CQuadItem QuadItem(Bar.x + min(127.0f, *apVars[i]/2.0f)*UI()->Scale(), Bar.y, UI()->PixelSize(), Bar.h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); + // button > - Button.VSplitLeft(20.0f, &Button, &Label); + Button.VSplitLeft(Button.h, &Button, &Label); if(DoButton_Menu(&s_aButtons[i*3+1], ">", 0, &Button, 5.0f, 0.0f, CUI::CORNER_TR|CUI::CORNER_BR)) { *apVars[i] = min(255, *apVars[i]+1); Modified = true; } + // label value char aBuf[16]; str_format(aBuf, sizeof(aBuf), "%d", *apVars[i]); - UI()->DoLabelScaled(&Label, aBuf, 12.0f, -1); + Label.y += 2.0f; + UI()->DoLabelScaled(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, 0); // logic int X; int Logic = UI()->DoPickerLogic(&s_aButtons[i*3+2], &Bar, &X, 0); @@ -291,7 +328,7 @@ void CMenus::RenderHSLPicker(CUIRect Picker) int NewVal = (Hue << 16) + (Sat << 8) + Lgt; for(int p = 0; p < NUM_SKINPARTS; p++) { - if(m_TeePartsColorSelection & gs_aSelectionParts[p]) + if(m_TeePartSelected == p) *gs_apColorVariables[p] = NewVal; } if(UseAlpha) @@ -318,15 +355,19 @@ void CMenus::RenderSkinSelection(CUIRect MainView) s_InitSkinlist = false; } - UiDoListboxStart(&s_InitSkinlist, &MainView, 50.0f, Localize("Skins"), "", s_paSkinList.size(), 4, -1, s_ScrollValue); + int OldSelected = -1; + UiDoListboxHeader(&MainView, Localize("Skins"), 20.0f, 2.0f); + UiDoListboxStart(&s_InitSkinlist, 50.0f, 0, s_paSkinList.size(), 12, OldSelected, s_ScrollValue); for(int i = 0; i < s_paSkinList.size(); ++i) { const CSkins::CSkin *s = s_paSkinList[i]; if(s == 0) continue; + if(!str_comp(s->m_aName, g_Config.m_PlayerSkin)) + OldSelected = i; - CListboxItem Item = UiDoListboxNextItem(&s_paSkinList[i], false); + CListboxItem Item = UiDoListboxNextItem(&s_paSkinList[i], OldSelected == i); if(Item.m_Visible) { CTeeRenderInfo Info; @@ -344,14 +385,13 @@ void CMenus::RenderSkinSelection(CUIRect MainView) } } - Info.m_Size = UI()->Scale()*50.0f; + Info.m_Size = 40.0f; Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, 0, vec2(1.0f, 0.0f), vec2(Item.m_Rect.x+Item.m_Rect.w/2, Item.m_Rect.y+Item.m_Rect.h/2)); } } const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0); - static int OldSelected = -1; if(NewSelected != -1) { if(NewSelected != OldSelected) @@ -365,7 +405,6 @@ void CMenus::RenderSkinSelection(CUIRect MainView) *gs_apColorVariables[p] = s->m_aPartColors[p]; } } - m_TeePartSelection = NO_SELECTION; } OldSelected = NewSelected; } @@ -392,27 +431,19 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) s_InitSkinPartList = false; } - int p = -1; - for(int j = 0; j < NUM_SKINPARTS; j++) - { - if(m_TeePartSelection == gs_aSelectionParts[j]) - p = j; - } - if(p < 0) - return; - const char *const s_apTitles[6] = {Localize("Bodies"), Localize("Tattoos"), Localize("Decoration"), Localize("Hands"), Localize("Feet"), Localize("Eyes")}; - UiDoListboxStart(&s_InitSkinPartList, &MainView, 50.0f, s_apTitles[p], "", s_paList[p].size(), 4, -1, s_ScrollValue); + UiDoListboxHeader(&MainView, s_apTitles[m_TeePartSelected], 20.0f, 2.0f); + UiDoListboxStart(&s_InitSkinPartList, 50.0f, 0, s_paList[m_TeePartSelected].size(), 6, -1, s_ScrollValue); - for(int i = 0; i < s_paList[p].size(); ++i) + for(int i = 0; i < s_paList[m_TeePartSelected].size(); ++i) { - const CSkins::CSkinPart *s = s_paList[p][i]; + const CSkins::CSkinPart *s = s_paList[m_TeePartSelected][i]; if(s == 0) continue; - CListboxItem Item = UiDoListboxNextItem(&s_paList[p][i], false); + CListboxItem Item = UiDoListboxNextItem(&s_paList[m_TeePartSelected][i], false); if(Item.m_Visible) { CTeeRenderInfo Info; @@ -422,7 +453,7 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) const CSkins::CSkinPart *pSkinPart = m_pClient->m_pSkins->GetSkinPart(j, SkinPart); if(*gs_apUCCVariables[j]) { - if(p == j) + if(m_TeePartSelected == j) Info.m_aTextures[j] = s->m_ColorTexture; else Info.m_aTextures[j] = pSkinPart->m_ColorTexture; @@ -430,14 +461,14 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) } else { - if(p == j) + if(m_TeePartSelected == j) Info.m_aTextures[j] = s->m_OrgTexture; else Info.m_aTextures[j] = pSkinPart->m_OrgTexture; Info.m_aColors[j] = vec4(1.0f, 1.0f, 1.0f, 1.0f); } } - Info.m_Size = UI()->Scale()*50.0f; + Info.m_Size = 40.0f; Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, 0, vec2(1.0f, 0.0f), vec2(Item.m_Rect.x+Item.m_Rect.w/2, Item.m_Rect.y+Item.m_Rect.h/2)); } @@ -449,10 +480,9 @@ void CMenus::RenderSkinPartSelection(CUIRect MainView) { if(NewSelected != OldSelected) { - const CSkins::CSkinPart *s = s_paList[p][NewSelected]; - mem_copy(gs_apSkinVariables[p], s->m_aName, 24); + const CSkins::CSkinPart *s = s_paList[m_TeePartSelected][NewSelected]; + mem_copy(gs_apSkinVariables[m_TeePartSelected], s->m_aName, 24); } - m_TeePartSelection = NO_SELECTION; } OldSelected = NewSelected; } @@ -551,7 +581,8 @@ void CMenus::RenderLanguageSelection(CUIRect MainView) int OldSelected = s_SelectedLanguage; - UiDoListboxStart(&s_LanguageList , &MainView, 24.0f, Localize("Language"), "", s_Languages.size(), 1, s_SelectedLanguage, s_ScrollValue); + UiDoListboxHeader(&MainView, Localize("Language"), 20.0f, 2.0f); + UiDoListboxStart(&s_LanguageList, 20.0f, 0, s_Languages.size(), 1, s_SelectedLanguage, s_ScrollValue); for(sorted_array::range r = s_Languages.all(); !r.empty(); r.pop_front()) { @@ -565,8 +596,17 @@ void CMenus::RenderLanguageSelection(CUIRect MainView) Rect.HMargin(3.0f, &Rect); vec4 Color(1.0f, 1.0f, 1.0f, 1.0f); m_pClient->m_pCountryFlags->Render(r.front().m_CountryCode, &Color, Rect.x, Rect.y, Rect.w, Rect.h); - Item.m_Rect.HSplitTop(2.0f, 0, &Item.m_Rect); - UI()->DoLabelScaled(&Item.m_Rect, r.front().m_Name, 16.0f, -1); + Item.m_Rect.y += 2.0f; + if(!str_comp(s_Languages[s_SelectedLanguage].m_Name, r.front().m_Name)) + { + TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); + TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); + UI()->DoLabelScaled(&Item.m_Rect, r.front().m_Name, Item.m_Rect.h*ms_FontmodHeight*0.8f, -1); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + } + else + UI()->DoLabelScaled(&Item.m_Rect, r.front().m_Name, Item.m_Rect.h*ms_FontmodHeight*0.8f, -1); } } @@ -581,223 +621,210 @@ void CMenus::RenderLanguageSelection(CUIRect MainView) void CMenus::RenderSettingsGeneral(CUIRect MainView) { - char aBuf[128]; - CUIRect Label, Button, Left, Right, Game, Client, Language; - MainView.HSplitTop(150.0f, &Game, &Client); - Client.HSplitTop(130.0f, &Client, &Language); + CUIRect Label, Button, Game, Client, BottomView; - // game + // cut view + MainView.HSplitBottom(80.0f, &MainView, &BottomView); + BottomView.HSplitTop(20.f, 0, &BottomView); + + // render game menu backgrounds + int NumOptions = g_Config.m_ClNameplates ? 8 : 5; + float ButtonHeight = 20.0f; + float Spacing = 2.0f; + float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; + + MainView.HSplitTop(20.0f, 0, &MainView); + MainView.HSplitTop(BackgroundHeight, &Game, &MainView); + RenderTools()->DrawUIRect(&Game, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + // render client menu background + NumOptions = 2; + if(g_Config.m_ClAutoDemoRecord) NumOptions += 1; + if(g_Config.m_ClAutoScreenshot) NumOptions += 1; + BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; + + MainView.HSplitTop(10.0f, 0, &MainView); + MainView.HSplitTop(BackgroundHeight, &Client, &MainView); + RenderTools()->DrawUIRect(&Client, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + // render game menu + Game.HSplitTop(ButtonHeight, &Label, &Game); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Game"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + Game.HSplitTop(Spacing, 0, &Game); + Game.HSplitTop(ButtonHeight, &Button, &Game); + static int s_DynamicCameraButton = 0; + if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), g_Config.m_ClMouseDeadzone != 0, &Button)) { - // headline - Game.HSplitTop(30.0f, &Label, &Game); - UI()->DoLabelScaled(&Label, Localize("Game"), 20.0f, -1); - Game.Margin(5.0f, &Game); - Game.VSplitMid(&Left, &Right); - Left.VSplitRight(5.0f, &Left, 0); - Right.VMargin(5.0f, &Right); - - // dynamic camera - Left.HSplitTop(20.0f, &Button, &Left); - static int s_DynamicCameraButton = 0; - if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), g_Config.m_ClMouseDeadzone != 0, &Button)) + if(g_Config.m_ClMouseDeadzone) { - if(g_Config.m_ClMouseDeadzone) - { - g_Config.m_ClMouseFollowfactor = 0; - g_Config.m_ClMouseMaxDistance = 400; - g_Config.m_ClMouseDeadzone = 0; - } - else - { - g_Config.m_ClMouseFollowfactor = 60; - g_Config.m_ClMouseMaxDistance = 1000; - g_Config.m_ClMouseDeadzone = 300; - } + g_Config.m_ClMouseFollowfactor = 0; + g_Config.m_ClMouseMaxDistance = 400; + g_Config.m_ClMouseDeadzone = 0; } - - // weapon pickup - Left.HSplitTop(5.0f, 0, &Left); - Left.HSplitTop(20.0f, &Button, &Left); - static int s_AutoswitchWeapons = 0; - if(DoButton_CheckBox(&s_AutoswitchWeapons, Localize("Switch weapon on pickup"), g_Config.m_ClAutoswitchWeapons, &Button)) - g_Config.m_ClAutoswitchWeapons ^= 1; - - // show hud - Left.HSplitTop(5.0f, 0, &Left); - Left.HSplitTop(20.0f, &Button, &Left); - static int s_Showhud = 0; - if(DoButton_CheckBox(&s_Showhud, Localize("Show ingame HUD"), g_Config.m_ClShowhud, &Button)) - g_Config.m_ClShowhud ^= 1; - - // chat messages - Left.HSplitTop(5.0f, 0, &Left); - Left.HSplitTop(20.0f, &Button, &Left); - static int s_Friendchat = 0; - if(DoButton_CheckBox(&s_Friendchat, Localize("Show only chat messages from friends"), g_Config.m_ClShowChatFriends, &Button)) - g_Config.m_ClShowChatFriends ^= 1; - - // name plates - Right.HSplitTop(20.0f, &Button, &Right); - static int s_Nameplates = 0; - if(DoButton_CheckBox(&s_Nameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button)) - g_Config.m_ClNameplates ^= 1; - - if(g_Config.m_ClNameplates) + else { - Right.HSplitTop(2.5f, 0, &Right); - Right.VSplitLeft(30.0f, 0, &Right); - Right.HSplitTop(20.0f, &Button, &Right); - static int s_NameplatesAlways = 0; - if(DoButton_CheckBox(&s_NameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button)) - g_Config.m_ClNameplatesAlways ^= 1; - - Right.HSplitTop(2.5f, 0, &Right); - Right.HSplitTop(20.0f, &Label, &Right); - Right.HSplitTop(20.0f, &Button, &Right); - str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Name plates size"), g_Config.m_ClNameplatesSize); - UI()->DoLabelScaled(&Label, aBuf, 13.0f, -1); - Button.HMargin(2.0f, &Button); - g_Config.m_ClNameplatesSize = (int)(DoScrollbarH(&g_Config.m_ClNameplatesSize, &Button, g_Config.m_ClNameplatesSize/100.0f)*100.0f+0.1f); - - Right.HSplitTop(20.0f, &Button, &Right); - static int s_NameplatesTeamcolors = 0; - if(DoButton_CheckBox(&s_NameplatesTeamcolors, Localize("Use team colors for name plates"), g_Config.m_ClNameplatesTeamcolors, &Button)) - g_Config.m_ClNameplatesTeamcolors ^= 1; + g_Config.m_ClMouseFollowfactor = 60; + g_Config.m_ClMouseMaxDistance = 1000; + g_Config.m_ClMouseDeadzone = 300; } } - // client + Game.HSplitTop(Spacing, 0, &Game); + Game.HSplitTop(ButtonHeight, &Button, &Game); + static int s_AutoswitchWeapons = 0; + if(DoButton_CheckBox(&s_AutoswitchWeapons, Localize("Switch weapon on pickup"), g_Config.m_ClAutoswitchWeapons, &Button)) + g_Config.m_ClAutoswitchWeapons ^= 1; + + Game.HSplitTop(Spacing, 0, &Game); + Game.HSplitTop(ButtonHeight, &Button, &Game); + static int s_Showhud = 0; + if(DoButton_CheckBox(&s_Showhud, Localize("Show ingame HUD"), g_Config.m_ClShowhud, &Button)) + g_Config.m_ClShowhud ^= 1; + + Game.HSplitTop(Spacing, 0, &Game); + Game.HSplitTop(ButtonHeight, &Button, &Game); + static int s_Friendchat = 0; + if(DoButton_CheckBox(&s_Friendchat, Localize("Show only chat messages from friends"), g_Config.m_ClShowChatFriends, &Button)) + g_Config.m_ClShowChatFriends ^= 1; + + Game.HSplitTop(Spacing, 0, &Game); + Game.HSplitTop(ButtonHeight, &Button, &Game); + static int s_Nameplates = 0; + if(DoButton_CheckBox(&s_Nameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button)) + g_Config.m_ClNameplates ^= 1; + + if(g_Config.m_ClNameplates) { - // headline - Client.HSplitTop(30.0f, &Label, &Client); - UI()->DoLabelScaled(&Label, Localize("Client"), 20.0f, -1); - Client.Margin(5.0f, &Client); - Client.VSplitMid(&Left, &Right); - Left.VSplitRight(5.0f, &Left, 0); - Right.VMargin(5.0f, &Right); + Game.HSplitTop(Spacing, 0, &Game); + Game.HSplitTop(ButtonHeight, &Button, &Game); + Button.VSplitLeft(ButtonHeight, 0, &Button); + static int s_NameplatesAlways = 0; + if(DoButton_CheckBox(&s_NameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button)) + g_Config.m_ClNameplatesAlways ^= 1; - // auto demo settings - { - Left.HSplitTop(20.0f, &Button, &Left); - static int s_AutoDemoRecord = 0; - if(DoButton_CheckBox(&s_AutoDemoRecord, Localize("Automatically record demos"), g_Config.m_ClAutoDemoRecord, &Button)) - g_Config.m_ClAutoDemoRecord ^= 1; + Game.HSplitTop(Spacing, 0, &Game); + Game.HSplitTop(ButtonHeight, &Button, &Game); + Button.VSplitLeft(ButtonHeight, 0, &Button); + DoScrollbarOption(&g_Config.m_ClNameplatesSize, &g_Config.m_ClNameplatesSize, &Button, Localize("Size"), 100.0f, 0, 100); - Right.HSplitTop(20.0f, &Button, &Right); - static int s_AutoScreenshot = 0; - if(DoButton_CheckBox(&s_AutoScreenshot, Localize("Automatically take game over screenshot"), g_Config.m_ClAutoScreenshot, &Button)) - g_Config.m_ClAutoScreenshot ^= 1; - - Left.HSplitTop(10.0f, 0, &Left); - Left.VSplitLeft(20.0f, 0, &Left); - Left.HSplitTop(20.0f, &Label, &Left); - Button.VSplitRight(20.0f, &Button, 0); - char aBuf[64]; - if(g_Config.m_ClAutoDemoMax) - str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Max demos"), g_Config.m_ClAutoDemoMax); - else - str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max demos"), Localize("no limit")); - UI()->DoLabelScaled(&Label, aBuf, 13.0f, -1); - Left.HSplitTop(20.0f, &Button, 0); - Button.HMargin(2.0f, &Button); - g_Config.m_ClAutoDemoMax = static_cast(DoScrollbarH(&g_Config.m_ClAutoDemoMax, &Button, g_Config.m_ClAutoDemoMax/1000.0f)*1000.0f+0.1f); - - Right.HSplitTop(10.0f, 0, &Right); - Right.VSplitLeft(20.0f, 0, &Right); - Right.HSplitTop(20.0f, &Label, &Right); - Button.VSplitRight(20.0f, &Button, 0); - if(g_Config.m_ClAutoScreenshotMax) - str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Max Screenshots"), g_Config.m_ClAutoScreenshotMax); - else - str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max Screenshots"), Localize("no limit")); - UI()->DoLabelScaled(&Label, aBuf, 13.0f, -1); - Right.HSplitTop(20.0f, &Button, 0); - Button.HMargin(2.0f, &Button); - g_Config.m_ClAutoScreenshotMax = static_cast(DoScrollbarH(&g_Config.m_ClAutoScreenshotMax, &Button, g_Config.m_ClAutoScreenshotMax/1000.0f)*1000.0f+0.1f); - } + Game.HSplitTop(Spacing, 0, &Game); + Game.HSplitTop(ButtonHeight, &Button, &Game); + Button.VSplitLeft(ButtonHeight, 0, &Button); + static int s_NameplatesTeamcolors = 0; + if(DoButton_CheckBox(&s_NameplatesTeamcolors, Localize("Use team colors for name plates"), g_Config.m_ClNameplatesTeamcolors, &Button)) + g_Config.m_ClNameplatesTeamcolors ^= 1; } - // language selection - static int s_LanguageList = 0; - static int s_SelectedLanguage = 0; - static sorted_array s_Languages; - static float s_ScrollValue = 0; + // render client menu + Client.HSplitTop(ButtonHeight, &Label, &Client); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Client"), ButtonHeight*ms_FontmodHeight*0.8f, 0); - if(s_Languages.size() == 0) + Client.HSplitTop(Spacing, 0, &Client); + Client.HSplitTop(ButtonHeight, &Button, &Client); + static int s_AutoDemoRecord = 0; + if(DoButton_CheckBox(&s_AutoDemoRecord, Localize("Automatically record demos"), g_Config.m_ClAutoDemoRecord, &Button)) + g_Config.m_ClAutoDemoRecord ^= 1; + + if(g_Config.m_ClAutoDemoRecord) { - s_Languages.add(CLanguage("English", "", 826)); - LoadLanguageIndexfile(Storage(), Console(), &s_Languages); - for(int i = 0; i < s_Languages.size(); i++) - if(str_comp(s_Languages[i].m_FileName, g_Config.m_ClLanguagefile) == 0) - { - s_SelectedLanguage = i; - break; - } + Client.HSplitTop(Spacing, 0, &Client); + Client.HSplitTop(ButtonHeight, &Button, &Client); + Button.VSplitLeft(ButtonHeight, 0, &Button); + DoScrollbarOption(&g_Config.m_ClAutoDemoMax, &g_Config.m_ClAutoDemoMax, &Button, Localize("Max"), 100.0f, 0, 1000, true); } - int OldSelected = s_SelectedLanguage; + Client.HSplitTop(Spacing, 0, &Client); + Client.HSplitTop(ButtonHeight, &Button, &Client); + static int s_AutoScreenshot = 0; + if(DoButton_CheckBox(&s_AutoScreenshot, Localize("Automatically take game over screenshot"), g_Config.m_ClAutoScreenshot, &Button)) + g_Config.m_ClAutoScreenshot ^= 1; - UiDoListboxStart(&s_LanguageList , &Language, 24.0f, Localize("Language"), "", s_Languages.size(), 1, s_SelectedLanguage, s_ScrollValue); - - for(sorted_array::range r = s_Languages.all(); !r.empty(); r.pop_front()) + if(g_Config.m_ClAutoScreenshot) { - CListboxItem Item = UiDoListboxNextItem(&r.front()); - - if(Item.m_Visible) - { - CUIRect Rect; - Item.m_Rect.VSplitLeft(Item.m_Rect.h*2.0f, &Rect, &Item.m_Rect); - Rect.VMargin(6.0f, &Rect); - Rect.HMargin(3.0f, &Rect); - Graphics()->TextureSet(m_pClient->m_pCountryFlags->GetByCountryCode(r.front().m_CountryCode)->m_Texture); - Graphics()->QuadsBegin(); - IGraphics::CQuadItem QuadItem(Rect.x, Rect.y, Rect.w, Rect.h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - Item.m_Rect.HSplitTop(2.0f, 0, &Item.m_Rect); - UI()->DoLabelScaled(&Item.m_Rect, r.front().m_Name, 16.0f, -1); - } + Client.HSplitTop(Spacing, 0, &Client); + Client.HSplitTop(ButtonHeight, &Button, &Client); + Button.VSplitLeft(ButtonHeight, 0, &Button); + DoScrollbarOption(&g_Config.m_ClAutoScreenshotMax, &g_Config.m_ClAutoScreenshotMax, &Button, Localize("Max"), 100.0f, 0, 1000, true); } - s_SelectedLanguage = UiDoListboxEnd(&s_ScrollValue, 0); + MainView.HSplitTop(10.0f, 0, &MainView); - if(OldSelected != s_SelectedLanguage) + // render language selection + RenderLanguageSelection(MainView); + + // reset button + Spacing = 3.0f; + float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; + + BottomView.VSplitRight(ButtonWidth, 0, &BottomView); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + + BottomView.HSplitTop(25.0f, &BottomView, 0); + Button = BottomView; + static int s_ResetButton=0; + if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - str_copy(g_Config.m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(g_Config.m_ClLanguagefile)); - g_Localization.Load(s_Languages[s_SelectedLanguage].m_FileName, Storage(), Console()); + g_Config.m_ClMouseFollowfactor = 60; + g_Config.m_ClMouseMaxDistance = 1000; + g_Config.m_ClMouseDeadzone = 300; + g_Config.m_ClAutoswitchWeapons = 1; + g_Config.m_ClShowhud = 1; + g_Config.m_ClShowChatFriends = 0; + g_Config.m_ClNameplates = 1; + g_Config.m_ClNameplatesAlways = 1; + g_Config.m_ClNameplatesSize = 50; + g_Config.m_ClNameplatesTeamcolors = 1; + g_Config.m_ClAutoDemoRecord = 0; + g_Config.m_ClAutoDemoMax = 10; + g_Config.m_ClAutoScreenshot = 0; + g_Config.m_ClAutoScreenshotMax = 10; } } void CMenus::RenderSettingsPlayer(CUIRect MainView) { - CUIRect Button, Label; - MainView.HSplitTop(10.0f, 0, &MainView); + CUIRect Button, Left, Right, TopView, Label; - // player name - MainView.HSplitTop(20.0f, &Button, &MainView); - Button.VSplitLeft(80.0f, &Label, &Button); - Button.VSplitLeft(150.0f, &Button, 0); - char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "%s:", Localize("Name")); - UI()->DoLabelScaled(&Label, aBuf, 14.0, -1); + // render game menu backgrounds + float ButtonHeight = 20.0f; + float Spacing = 2.0f; + float BackgroundHeight = 2.0f*ButtonHeight+Spacing; + + MainView.HSplitTop(20.0f, 0, &MainView); + MainView.HSplitBottom(80.0f, &MainView, 0); // now we have the total rect for the settings + MainView.HSplitTop(BackgroundHeight, &TopView, &MainView); + RenderTools()->DrawUIRect(&TopView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + // render game menu + TopView.HSplitTop(ButtonHeight, &Label, &TopView); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Personal"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + // split menu + TopView.HSplitTop(Spacing, 0, &TopView); + TopView.VSplitMid(&Left, &Right); + Left.VSplitRight(1.5f, &Left, 0); + Right.VSplitLeft(1.5f, 0, &Right); + + // left menu + Left.HSplitTop(ButtonHeight, &Button, &Left); static float s_OffsetName = 0.0f; - DoEditBox(g_Config.m_PlayerName, &Button, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 14.0f, &s_OffsetName); + DoEditBoxOption(g_Config.m_PlayerName, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), &Button, Localize("Name"), 100.0f, &s_OffsetName); - // player clan - MainView.HSplitTop(5.0f, 0, &MainView); - MainView.HSplitTop(20.0f, &Button, &MainView); - Button.VSplitLeft(80.0f, &Label, &Button); - Button.VSplitLeft(150.0f, &Button, 0); - str_format(aBuf, sizeof(aBuf), "%s:", Localize("Clan")); - UI()->DoLabelScaled(&Label, aBuf, 14.0, -1); + // right menu + Right.HSplitTop(ButtonHeight, &Button, &Right); static float s_OffsetClan = 0.0f; - DoEditBox(g_Config.m_PlayerClan, &Button, g_Config.m_PlayerClan, sizeof(g_Config.m_PlayerClan), 14.0f, &s_OffsetClan); + DoEditBoxOption(g_Config.m_PlayerClan, g_Config.m_PlayerClan, sizeof(g_Config.m_PlayerClan), &Button, Localize("Clan"), 100.0f, &s_OffsetClan); // country flag selector - MainView.HSplitTop(20.0f, 0, &MainView); + MainView.HSplitTop(10.0f, 0, &MainView); static float s_ScrollValue = 0.0f; int OldSelected = -1; - UiDoListboxStart(&s_ScrollValue, &MainView, 50.0f, Localize("Country"), "", m_pClient->m_pCountryFlags->Num(), 6, OldSelected, s_ScrollValue); + UiDoListboxHeader(&MainView, Localize("Country"), 20.0f, 2.0f); + UiDoListboxStart(&s_ScrollValue, 40.0f, 0, m_pClient->m_pCountryFlags->Num(), 18, OldSelected, s_ScrollValue); for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i) { @@ -820,7 +847,16 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) IGraphics::CQuadItem QuadItem(Item.m_Rect.x, Item.m_Rect.y, Item.m_Rect.w, Item.m_Rect.h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, 0); + if(i == OldSelected) + { + TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); + TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); + UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, 0); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + } + else + UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, 0); } } @@ -831,35 +867,123 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) } } +void CMenus::RenderSettingsTeeBasic(CUIRect MainView) +{ + RenderSkinSelection(MainView); // yes thats all here ^^ +} + +void CMenus::RenderSettingsTeeCustom(CUIRect MainView) +{ + CUIRect Label, Button, Left, Right; + + // render skin preview background + float SpacingH = 2.0f; + float SpacingW = 3.0f; + float ButtonHeight = 20.0f; + float BoxSize = 297.0f; + float BackgroundHeight = (ButtonHeight+SpacingH)*3.0f+BoxSize; + + MainView.HSplitTop(BackgroundHeight, &MainView, 0); + RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + MainView.HSplitTop(ButtonHeight, &Label, &MainView); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Customize"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + // skin part selection + MainView.HSplitTop(SpacingH, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Label, &MainView); + RenderTools()->DrawUIRect(&Label, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + Label.VSplitLeft(Label.h, &Left, &Label); + Label.VSplitRight(Label.h, &Label, &Right); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Patterns"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + static int s_PatternButtonLeft = 0; + if(DoButton_Menu(&s_PatternButtonLeft, "<", 0, &Left, 5.0f, 0.0f, CUI::CORNER_L)) + { + m_TeePartSelected--; + if(m_TeePartSelected < 0) + m_TeePartSelected = NUM_SKINPARTS-1; + } + + static int s_PatternButtonRight = 0; + if(DoButton_Menu(&s_PatternButtonRight, ">", 0, &Right, 5.0f, 0.0f, CUI::CORNER_R)) + { + m_TeePartSelected++; + if(m_TeePartSelected >= NUM_SKINPARTS) + m_TeePartSelected = 0; + } + + MainView.HSplitTop(SpacingH, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Label, &MainView); + Label.y += 2.0f; + char aBuf[8]; + str_format(aBuf, sizeof(aBuf), "%d/%d", m_TeePartSelected+1, NUM_SKINPARTS); + UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, 0); + + MainView.HSplitTop(SpacingH, 0, &MainView); + MainView.VSplitMid(&Left, &Right); + Left.VSplitRight(SpacingW/2.0f, &Left, 0); + Right.VSplitLeft(SpacingW/2.0f, 0, &Right); + + // part selection + RenderSkinPartSelection(Left); + + // HSL picker + RenderHSLPicker(Right); +} + void CMenus::RenderSettingsTee(CUIRect MainView) { - CUIRect Button, Label, EditBox; - CUIRect YourSkin, Preview, CustomizeSkin, Left, Mid, SaveSkin, Selection, UCC, Picker; - MainView.VMargin(20.0f, &MainView); - MainView.HMargin(10.0f, &MainView); - MainView.VSplitLeft(420.0f, 0, &Selection); - MainView.HSplitTop(65.0f, &YourSkin, &CustomizeSkin); + static bool s_CustomSkinMenu = false; - // Preview : + CUIRect Button, Label, BottomView, Preview; + + // cut view + MainView.HSplitBottom(80.0f, &MainView, &BottomView); + BottomView.HSplitTop(20.f, 0, &BottomView); + + // render skin preview background + float SpacingH = 2.0f; + float SpacingW = 3.0f; + float ButtonHeight = 20.0f; + float SkinHeight = 45.0f; + float BackgroundHeight = ButtonHeight+SpacingH+SkinHeight; + if(!s_CustomSkinMenu) + BackgroundHeight = (ButtonHeight+SpacingH)*2.0f+SkinHeight; + + MainView.HSplitTop(20.0f, 0, &MainView); + MainView.HSplitTop(BackgroundHeight, &Preview, &MainView); + RenderTools()->DrawUIRect(&Preview, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + Preview.HSplitTop(ButtonHeight, &Label, &Preview); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Skin"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + // Preview { - YourSkin.VSplitLeft(80.0f, &YourSkin, &Button); - YourSkin.HSplitTop(18.0f, 0, &Label); - UI()->DoLabelScaled(&Label, Localize("Your skin:"), 14.0f, -1); + CUIRect Left, Right; + Preview.HSplitTop(SpacingH, 0, &Preview); + Preview.HSplitTop(SkinHeight, &Left, &Preview); - float tw = TextRender()->TextWidth(0, 14.0f, g_Config.m_PlayerSkin, -1); - Button.VSplitLeft(16.0f + 50.0f+tw, &Button, 0); - Button.HSplitTop(12.0f + 40.0f, &Button, 0); - static int s_SkinButton = 0; - if(DoButton_Menu(&s_SkinButton, "", 0, &Button)) - { - m_TeePartSelection = SELECTION_SKIN; - m_TeePartsColorSelection = NO_SELECTION; - } + // split the menu in 2 parts + Left.VSplitMid(&Left, &Right); + Left.VSplitRight(SpacingW/2.0f, &Left, 0); + Right.VSplitLeft(SpacingW/2.0f, 0, &Right); + + // handle left + RenderTools()->DrawUIRect(&Left, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + Left.VSplitMid(&Label, &Left); + Label.y += 14.0f; + UI()->DoLabelScaled(&Label, Localize("Normal:"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + RenderTools()->DrawUIRect(&Left, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - Button.VSplitLeft(24.0f, 0, &Preview); - Preview.HSplitTop(30.0f, 0, &Preview); CTeeRenderInfo OwnSkinInfo; - OwnSkinInfo.m_Size = 50.0f*UI()->Scale(); + OwnSkinInfo.m_Size = 40.0f; for(int p = 0; p < NUM_SKINPARTS; p++) { int SkinPart = m_pClient->m_pSkins->FindSkinPart(p, gs_apSkinVariables[p]); @@ -875,418 +999,135 @@ void CMenus::RenderSettingsTee(CUIRect MainView) OwnSkinInfo.m_aColors[p] = vec4(1.0f, 1.0f, 1.0f, 1.0f); } } - RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Preview.x, Preview.y)); + RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Left.x+Left.w/2.0f, Left.y+Left.h/2.0f+2.0f)); - Button.VSplitLeft(50.0f, 0, &Label); - Label.HSplitTop(18.0f, 0, &Label); - UI()->DoLabelScaled(&Label, g_Config.m_PlayerSkin, 14.0f, -1); + // handle right (team skins) + RenderTools()->DrawUIRect(&Right, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - if(m_TeePartSelection == NO_SELECTION) - { - // draw tee with red team color - Button.VSplitLeft(150.0f, 0, &Preview); - Preview.VSplitLeft(100.0f, &Label, &Preview); - Label.HSplitTop(18.0f, 0, &Label); - UI()->DoLabelScaled(&Label, Localize("Red team:"), 14.0f, -1); + Right.VSplitLeft(Right.w/3.0f+SpacingW/2.0f, &Label, &Right); + Label.y += 14.0f; + UI()->DoLabelScaled(&Label, Localize("Team:"), ButtonHeight*ms_FontmodHeight*0.8f, 0); - Preview.HSplitTop(30.0f, 0, &Preview); - for(int p = 0; p < NUM_SKINPARTS; p++) - { - int TeamColor = m_pClient->m_pSkins->GetTeamColor(*gs_apUCCVariables[p], *gs_apColorVariables[p], TEAM_RED, p); - OwnSkinInfo.m_aColors[p] = m_pClient->m_pSkins->GetColorV4(TeamColor, p==SKINPART_TATTOO); - } - RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Preview.x, Preview.y)); + Right.VSplitMid(&Left, &Right); + Left.VSplitRight(SpacingW/2.0f, &Left, 0); + Right.VSplitLeft(SpacingW/2.0f, 0, &Right); - // draw tee with blue team color - Button.VSplitLeft(300.0f, 0, &Preview); - Preview.VSplitLeft(100.0f, &Label, &Preview); - Label.HSplitTop(18.0f, 0, &Label); - UI()->DoLabelScaled(&Label, Localize("Blue team:"), 14.0f, -1); - - Preview.HSplitTop(30.0f, 0, &Preview); - for(int p = 0; p < NUM_SKINPARTS; p++) - { - int TeamColor = m_pClient->m_pSkins->GetTeamColor(*gs_apUCCVariables[p], *gs_apColorVariables[p], TEAM_BLUE, p); - OwnSkinInfo.m_aColors[p] = m_pClient->m_pSkins->GetColorV4(TeamColor, p==SKINPART_TATTOO); - } - RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Preview.x, Preview.y)); - } - } - - // Selection : - { - if(m_TeePartSelection == SELECTION_SKIN) - RenderSkinSelection(Selection); - else if(m_TeePartSelection != NO_SELECTION) - RenderSkinPartSelection(Selection); - } - - // Skin Customization : - { - CustomizeSkin.HSplitTop(20.0f, &Button, &Left); - static int s_CustomizeSkinButton = 0; - if(DoButton_CheckBox(&s_CustomizeSkinButton, Localize("Customize skin"), g_Config.m_ClCustomizeSkin, &Button)) - { - g_Config.m_ClCustomizeSkin ^= 1; - if(!g_Config.m_ClCustomizeSkin) - { - m_TeePartSelection = NO_SELECTION; - m_TeePartsColorSelection = NO_SELECTION; - } - } - } - - if(!g_Config.m_ClCustomizeSkin) - return; - - // Parts Customization : - { - Left.HSplitTop(10.0f, 0, &Left); - Left.VSplitLeft(15.0f, 0, &Left); - Left.HSplitTop(260.0f, &Left, &SaveSkin); - Left.VSplitLeft(180.0f, &Left, &Mid); - Mid.VSplitLeft(10.0f, 0, &Mid); - Mid.VSplitLeft(165.0f, &Mid, &UCC); - - const char *const apNames[6] = {Localize("Body:"), Localize("Tattoo:"), Localize("Decoration:"), - Localize("Hands:"), Localize("Feet:"), Localize("Eyes:")}; - CUIRect *const apColumns[6] = {&Left, &Left, &Left, - &Mid, &Mid, &Mid}; - static int const s_aSprites[6] = {SPRITE_TEE_BODY, SPRITE_TEE_TATTOO, SPRITE_TEE_DECORATION, - SPRITE_TEE_HAND, SPRITE_TEE_FOOT, SPRITE_TEE_EYES_NORMAL}; - static int s_aButtons[6]; + RenderTools()->DrawUIRect(&Left, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); for(int p = 0; p < NUM_SKINPARTS; p++) { - IGraphics::CTextureHandle Tex = g_pData->m_aImages[IMAGE_NO_SKINPART].m_Id; - int Sprite = -1; - if(gs_apSkinVariables[p][0]) - { - int SkinPart = m_pClient->m_pSkins->FindSkinPart(p, gs_apSkinVariables[p]); - const CSkins::CSkinPart *pSkinPart = m_pClient->m_pSkins->GetSkinPart(p, SkinPart); - Tex = pSkinPart->m_OrgTexture; - Sprite = s_aSprites[p]; - } - - CUIRect ColorSelection; - apColumns[p]->HSplitTop(80.0f, &ColorSelection, apColumns[p]); - ColorSelection.HMargin(5.0f, &ColorSelection); - if(m_TeePartsColorSelection & gs_aSelectionParts[p]) - RenderTools()->DrawUIRect(&ColorSelection, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - ColorSelection.HSplitTop(5.0f, 0, &ColorSelection); - ColorSelection.VSplitRight(70.0f, &Label, &Button); - Label.HSplitTop(20.0f, 0, &Label); - Label.VSplitLeft(5.0f, 0, &Label); - UI()->DoLabelScaled(&Label, apNames[p], 14.0f, -1); - Button.HSplitTop(60.0f, &Button, 0); - Button.VSplitLeft(60.0f, &Button, 0); - float ImageRatio = p==SKINPART_EYES?2.0f:1.0f; - if(DoButton_Customize(&s_aButtons[p], Tex, Sprite, &Button, ImageRatio)) - { - m_TeePartSelection = gs_aSelectionParts[p]; - m_TeePartsColorSelection = gs_aSelectionParts[p]; - } - if(UI()->DoColorSelectionLogic(&ColorSelection, &Button)) - { - static int s_InitialSelectedPart = -1; - int AddSelection = NO_SELECTION; - if(Input()->KeyPressed(KEY_RSHIFT) || Input()->KeyPressed(KEY_LSHIFT)) - { - if(s_InitialSelectedPart != -1) - { - int Min = p < s_InitialSelectedPart ? p : s_InitialSelectedPart; - int Max = p > s_InitialSelectedPart ? p : s_InitialSelectedPart; - for(int p2 = Min; p2 <= Max; p2++) - AddSelection |= gs_aSelectionParts[p2]; - } - } - else - { - AddSelection = gs_aSelectionParts[p]; - s_InitialSelectedPart = p; - } - if(Input()->KeyPressed(KEY_RCTRL) || Input()->KeyPressed(KEY_LCTRL)) - { - if(m_TeePartsColorSelection & gs_aSelectionParts[p]) - m_TeePartsColorSelection &= ~AddSelection; - else - m_TeePartsColorSelection |= AddSelection; - } - else - m_TeePartsColorSelection = AddSelection; - m_TeePartSelection = NO_SELECTION; - } + int TeamColor = m_pClient->m_pSkins->GetTeamColor(*gs_apUCCVariables[p], *gs_apColorVariables[p], TEAM_RED, p); + OwnSkinInfo.m_aColors[p] = m_pClient->m_pSkins->GetColorV4(TeamColor, p==SKINPART_TATTOO); } - } + RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Left.x+Left.w/2.0f, Left.y+Left.h/2.0f+2.0f)); - // Save Skin : - { - SaveSkin.HSplitTop(20.0f, &SaveSkin, 0); - SaveSkin.VSplitLeft(160.0f, &EditBox, &Button); - Button.VSplitLeft(10.0f, 0, &Button); - Button.VSplitLeft(80.0f, &Button, 0); - static float s_OffsetSkin = 0.0f; - static int s_EditBox; - DoEditBox(&s_EditBox, &EditBox, m_aSaveSkinName, sizeof(m_aSaveSkinName), 14.0f, &s_OffsetSkin); - static int s_SaveButton; - if(DoButton_Menu(&s_SaveButton, Localize("Save skin"), 0, &Button) || (UI()->LastActiveItem() == &s_EditBox && m_EnterPressed)) - { - if(m_aSaveSkinName[0]) - m_Popup = POPUP_SAVE_SKIN; - } - } + RenderTools()->DrawUIRect(&Right, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - if(m_TeePartsColorSelection == NO_SELECTION || m_TeePartSelection != NO_SELECTION) - return; - - bool None = true; - for(int p = 0; p < NUM_SKINPARTS; p++) - { - if((m_TeePartsColorSelection & gs_aSelectionParts[p]) && gs_apSkinVariables[p][0]) - None = false; - } - if(None) - return; - - int CheckedUCC = 0; - - // Use Custom Color : - { for(int p = 0; p < NUM_SKINPARTS; p++) { - if((m_TeePartsColorSelection & gs_aSelectionParts[p]) && *gs_apUCCVariables[p]) - CheckedUCC = 1; - } - - UCC.VSplitLeft(40.0f, 0, &UCC); - UCC.HSplitTop(5.0f, 0, &UCC); - UCC.HSplitTop(20.0f, &Button, &Picker); - static int s_UCCButton = 0; - if(DoButton_CheckBox(&s_UCCButton, Localize("Custom colors"), CheckedUCC, &Button)) - { - CheckedUCC ^= 1; - for(int p = 0; p < NUM_SKINPARTS; p++) - { - if(m_TeePartsColorSelection & gs_aSelectionParts[p]) - *gs_apUCCVariables[p] = CheckedUCC; - } + int TeamColor = m_pClient->m_pSkins->GetTeamColor(*gs_apUCCVariables[p], *gs_apColorVariables[p], TEAM_BLUE, p); + OwnSkinInfo.m_aColors[p] = m_pClient->m_pSkins->GetColorV4(TeamColor, p==SKINPART_TATTOO); } + RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Right.x+Right.w/2.0f, Right.y+Right.h/2.0f+2.0f)); } - if(!CheckedUCC) - return; - - // HSL Picker : + if(!s_CustomSkinMenu) { - Picker.HSplitTop(10.0f, 0, &Picker); - Picker.VSplitLeft(20.0f, 0, &Picker); - RenderHSLPicker(Picker); + Preview.HSplitTop(SpacingH, 0, &Preview); + RenderTools()->DrawUIRect(&Preview, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + Preview.y += 2.0f; + UI()->DoLabel(&Preview, g_Config.m_PlayerSkin, ButtonHeight*ms_FontmodHeight*0.8f, 0); + } + + MainView.HSplitTop(10.0f, 0, &MainView); + + if(s_CustomSkinMenu) + RenderSettingsTeeCustom(MainView); + else + RenderSettingsTeeBasic(MainView); + + // bottom button + float ButtonWidth = (BottomView.w/6.0f)-(SpacingW*5.0)/6.0f; + float BackgroundWidth = s_CustomSkinMenu ? ButtonWidth*2.0f+SpacingW : ButtonWidth; + + BottomView.VSplitRight(BackgroundWidth, 0, &BottomView); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + + BottomView.HSplitTop(25.0f, &BottomView, 0); + if(s_CustomSkinMenu) + { + BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); + static int s_CustomSkinSaveButton=0; + if(DoButton_Menu(&s_CustomSkinSaveButton, Localize("Save"), 0, &Button)) + m_Popup = POPUP_SAVE_SKIN; + BottomView.VSplitLeft(SpacingW, 0, &BottomView); + } + + BottomView.VSplitLeft(ButtonWidth, &Button, &BottomView); + static int s_CustomSwitchButton=0; + if(DoButton_Menu(&s_CustomSwitchButton, s_CustomSkinMenu ? Localize("Basic") : Localize("Custom"), 0, &Button)) + { + if(s_CustomSkinMenu) + s_CustomSkinMenu = false; + else + s_CustomSkinMenu = true; } } -typedef void (*pfnAssignFuncCallback)(CConfiguration *pConfig, int Value); - -typedef struct -{ - CLocConstString m_Name; - const char *m_pCommand; - int m_KeyId; -} CKeyInfo; - -static CKeyInfo gs_aKeys[] = -{ - { "Move left", "+left", 0}, // Localize - these strings are localized within CLocConstString - { "Move right", "+right", 0 }, - { "Jump", "+jump", 0 }, - { "Fire", "+fire", 0 }, - { "Hook", "+hook", 0 }, - { "Hammer", "+weapon1", 0 }, - { "Pistol", "+weapon2", 0 }, - { "Shotgun", "+weapon3", 0 }, - { "Grenade", "+weapon4", 0 }, - { "Laser", "+weapon5", 0 }, - { "Next weapon", "+nextweapon", 0 }, - { "Prev. weapon", "+prevweapon", 0 }, - { "Vote yes", "vote yes", 0 }, - { "Vote no", "vote no", 0 }, - { "Chat", "chat all", 0 }, - { "Team chat", "chat team", 0 }, - { "Show chat", "+show_chat", 0 }, - { "Emoticon", "+emote", 0 }, - { "Spectator mode", "+spectate", 0 }, - { "Spectate next", "spectate_next", 0 }, - { "Spectate previous", "spectate_previous", 0 }, - { "Console", "toggle_local_console", 0 }, - { "Remote console", "toggle_remote_console", 0 }, - { "Screenshot", "screenshot", 0 }, - { "Scoreboard", "+scoreboard", 0 }, - { "Respawn", "kill", 0 }, - { "Ready", "ready_change", 0 }, -}; - -/* This is for scripts/update_localization.py to work, don't remove! - Localize("Move left");Localize("Move right");Localize("Jump");Localize("Fire");Localize("Hook");Localize("Hammer"); - Localize("Pistol");Localize("Shotgun");Localize("Grenade");Localize("Laser");Localize("Next weapon");Localize("Prev. weapon"); - Localize("Vote yes");Localize("Vote no");Localize("Chat");Localize("Team chat");Localize("Show chat");Localize("Emoticon"); - Localize("Spectator mode");Localize("Spectate next");Localize("Spectate previous");Localize("Console");Localize("Remote console"); - Localize("Screenshot");Localize("Scoreboard");Localize("Respawn");Localize("Ready"); -*/ - -const int g_KeyCount = sizeof(gs_aKeys) / sizeof(CKeyInfo); - -void CMenus::UiDoGetButtons(int Start, int Stop, CUIRect View) -{ - for (int i = Start; i < Stop; i++) - { - CKeyInfo &Key = gs_aKeys[i]; - CUIRect Button, Label; - View.HSplitTop(20.0f, &Button, &View); - Button.VSplitLeft(135.0f, &Label, &Button); - - char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%s:", (const char *)Key.m_Name); - - UI()->DoLabelScaled(&Label, aBuf, 13.0f, -1); - int OldId = Key.m_KeyId; - int NewId = DoKeyReader((void *)&gs_aKeys[i].m_Name, &Button, OldId); - if(NewId != OldId) - { - if(OldId != 0 || NewId == 0) - m_pClient->m_pBinds->Bind(OldId, ""); - if(NewId != 0) - m_pClient->m_pBinds->Bind(NewId, gs_aKeys[i].m_pCommand); - } - View.HSplitTop(5.0f, 0, &View); - } -} +//typedef void (*pfnAssignFuncCallback)(CConfiguration *pConfig, int Value); void CMenus::RenderSettingsControls(CUIRect MainView) { - // this is kinda slow, but whatever - for(int i = 0; i < g_KeyCount; i++) - gs_aKeys[i].m_KeyId = 0; + MainView.HSplitTop(20.0f, 0, &MainView); - for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) - { - const char *pBind = m_pClient->m_pBinds->Get(KeyId); - if(!pBind[0]) - continue; + // cut view + CUIRect BottomView, Button; + MainView.HSplitBottom(80.0f, &MainView, &BottomView); + BottomView.HSplitTop(20.f, 0, &BottomView); - for(int i = 0; i < g_KeyCount; i++) - if(str_comp(pBind, gs_aKeys[i].m_pCommand) == 0) - { - gs_aKeys[i].m_KeyId = KeyId; - break; - } - } + float HeaderHeight = 20.0f; - CUIRect MovementSettings, WeaponSettings, VotingSettings, ChatSettings, MiscSettings, ResetButton; - MainView.VSplitMid(&MovementSettings, &VotingSettings); + static int s_MovementDropdown = 0; + float Split = DoDropdownMenu(&s_MovementDropdown, &MainView, Localize("Movement"), HeaderHeight, RenderSettingsControlsMovement); - // movement settings - { - MovementSettings.VMargin(5.0f, &MovementSettings); - MovementSettings.HSplitTop(MainView.h/3+32.0f, &MovementSettings, &WeaponSettings); - RenderTools()->DrawUIRect(&MovementSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - MovementSettings.Margin(10.0f, &MovementSettings); + MainView.HSplitTop(Split+10.0f, 0, &MainView); + static int s_WeaponDropdown = 0; + Split = DoDropdownMenu(&s_WeaponDropdown, &MainView, Localize("Weapon"), HeaderHeight, RenderSettingsControlsWeapon); - TextRender()->Text(0, MovementSettings.x, MovementSettings.y, 14.0f*UI()->Scale(), Localize("Movement"), -1); + MainView.HSplitTop(Split+10.0f, 0, &MainView); + static int s_VotingDropdown = 0; + Split = DoDropdownMenu(&s_VotingDropdown, &MainView, Localize("Voting"), HeaderHeight, RenderSettingsControlsVoting); - MovementSettings.HSplitTop(14.0f+7.0f, 0, &MovementSettings); + MainView.HSplitTop(Split+10.0f, 0, &MainView); + static int s_ChatDropdown = 0; + Split = DoDropdownMenu(&s_ChatDropdown, &MainView, Localize("Chat"), HeaderHeight, RenderSettingsControlsChat); - { - CUIRect Button, Label; - MovementSettings.HSplitTop(20.0f, &Button, &MovementSettings); - Button.VSplitLeft(135.0f, &Label, &Button); - UI()->DoLabel(&Label, Localize("Mouse sens."), 14.0f*UI()->Scale(), -1); - Button.HMargin(2.0f, &Button); - static int s_InpMousesense = 0; - g_Config.m_InpMousesens = (int)(DoScrollbarH(&s_InpMousesense, &Button, (g_Config.m_InpMousesens-5)/500.0f)*500.0f)+5; - //*key.key = ui_do_key_reader(key.key, &Button, *key.key); - MovementSettings.HSplitTop(10.0f, 0, &MovementSettings); - } + MainView.HSplitTop(Split+10.0f, 0, &MainView); + static int s_MiscDropdown = 0; + Split = DoDropdownMenu(&s_MiscDropdown, &MainView, Localize("Misc"), HeaderHeight, RenderSettingsControlsMisc); - UiDoGetButtons(0, 5, MovementSettings); + // reset button + float Spacing = 3.0f; + float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; - } - - // weapon settings - { - WeaponSettings.HSplitTop(10.0f, 0, &WeaponSettings); - WeaponSettings.HSplitTop(MainView.h/3+52.0f, &WeaponSettings, &ResetButton); - RenderTools()->DrawUIRect(&WeaponSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - WeaponSettings.Margin(10.0f, &WeaponSettings); - - TextRender()->Text(0, WeaponSettings.x, WeaponSettings.y, 14.0f*UI()->Scale(), Localize("Weapon"), -1); - - WeaponSettings.HSplitTop(14.0f+7.0f, 0, &WeaponSettings); - UiDoGetButtons(5, 12, WeaponSettings); - } - - // defaults - { - ResetButton.HSplitTop(10.0f, 0, &ResetButton); - RenderTools()->DrawUIRect(&ResetButton, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - ResetButton.HMargin(17.0f, &ResetButton); - ResetButton.VMargin(30.0f, &ResetButton); - ResetButton.HSplitTop(20.0f, &ResetButton, 0); - static int s_DefaultButton = 0; - if(DoButton_Menu((void*)&s_DefaultButton, Localize("Reset to defaults"), 0, &ResetButton)) - m_pClient->m_pBinds->SetDefaults(); - } - - // voting settings - { - VotingSettings.VMargin(5.0f, &VotingSettings); - VotingSettings.HSplitTop(MainView.h/3-73.0f, &VotingSettings, &ChatSettings); - RenderTools()->DrawUIRect(&VotingSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - VotingSettings.Margin(10.0f, &VotingSettings); - - TextRender()->Text(0, VotingSettings.x, VotingSettings.y, 14.0f*UI()->Scale(), Localize("Voting"), -1); - - VotingSettings.HSplitTop(14.0f+7.0f, 0, &VotingSettings); - UiDoGetButtons(12, 14, VotingSettings); - } - - // chat settings - { - ChatSettings.HSplitTop(10.0f, 0, &ChatSettings); - ChatSettings.HSplitTop(MainView.h/3-48.0f, &ChatSettings, &MiscSettings); - RenderTools()->DrawUIRect(&ChatSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - ChatSettings.Margin(10.0f, &ChatSettings); - - TextRender()->Text(0, ChatSettings.x, ChatSettings.y, 14.0f*UI()->Scale(), Localize("Chat"), -1); - - ChatSettings.HSplitTop(14.0f+7.0f, 0, &ChatSettings); - UiDoGetButtons(14, 17, ChatSettings); - } - - // misc settings - { - MiscSettings.HSplitTop(10.0f, 0, &MiscSettings); - RenderTools()->DrawUIRect(&MiscSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - MiscSettings.Margin(10.0f, &MiscSettings); - - TextRender()->Text(0, MiscSettings.x, MiscSettings.y, 14.0f*UI()->Scale(), Localize("Miscellaneous"), -1); - - MiscSettings.HSplitTop(14.0f+7.0f, 0, &MiscSettings); - UiDoGetButtons(17, 26, MiscSettings); - } + BottomView.VSplitRight(ButtonWidth, 0, &BottomView); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + BottomView.HSplitTop(25.0f, &BottomView, 0); + Button = BottomView; + static int s_ResetButton=0; + if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) + m_pClient->m_pBinds->SetDefaults(); } void CMenus::RenderSettingsGraphics(CUIRect MainView) { - CUIRect Button; char aBuf[128]; bool CheckSettings = false; - static const int MAX_RESOLUTIONS = 256; - static CVideoMode s_aModes[MAX_RESOLUTIONS]; - static int s_NumNodes = Graphics()->GetVideoModes(s_aModes, MAX_RESOLUTIONS); static int s_GfxScreenWidth = g_Config.m_GfxScreenWidth; static int s_GfxScreenHeight = g_Config.m_GfxScreenHeight; - static int s_GfxColorDepth = g_Config.m_GfxColorDepth; static int s_GfxBorderless = g_Config.m_GfxBorderless; static int s_GfxFullscreen = g_Config.m_GfxFullscreen; static int s_GfxVsync = g_Config.m_GfxVsync; @@ -1294,67 +1135,37 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) static int s_GfxTextureQuality = g_Config.m_GfxTextureQuality; static int s_GfxTextureCompression = g_Config.m_GfxTextureCompression; - CUIRect ModeList; - MainView.VSplitLeft(300.0f, &MainView, &ModeList); + CUIRect Label, Button, Screen, Texture, BottomView; - // draw allmodes switch - ModeList.HSplitTop(20, &Button, &ModeList); - static int s_GfxDisplayAllModes = 0; - if(DoButton_CheckBox(&s_GfxDisplayAllModes, Localize("Show only supported"), g_Config.m_GfxDisplayAllModes^1, &Button)) - { - g_Config.m_GfxDisplayAllModes ^= 1; - s_NumNodes = Graphics()->GetVideoModes(s_aModes, MAX_RESOLUTIONS); - } + // cut view + MainView.HSplitBottom(80.0f, &MainView, &BottomView); + BottomView.HSplitTop(20.f, 0, &BottomView); - // display mode list - static float s_ScrollValue = 0; - static int s_DisplayModeList = 0; - int OldSelected = -1; - int G = gcd(s_GfxScreenWidth, s_GfxScreenHeight); - str_format(aBuf, sizeof(aBuf), "%s: %dx%d %d bit (%d:%d)", Localize("Current"), s_GfxScreenWidth, s_GfxScreenHeight, s_GfxColorDepth, s_GfxScreenWidth/G, s_GfxScreenHeight/G); - UiDoListboxStart(&s_DisplayModeList , &ModeList, 24.0f, Localize("Display Modes"), aBuf, s_NumNodes, 1, OldSelected, s_ScrollValue); + // render screen menu background + int NumOptions = g_Config.m_GfxFullscreen ? 3 : 4; + float ButtonHeight = 20.0f; + float Spacing = 2.0f; + float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; - for(int i = 0; i < s_NumNodes; ++i) - { - const int Depth = s_aModes[i].m_Red+s_aModes[i].m_Green+s_aModes[i].m_Blue > 16 ? 24 : 16; - if(g_Config.m_GfxColorDepth == Depth && - g_Config.m_GfxScreenWidth == s_aModes[i].m_Width && - g_Config.m_GfxScreenHeight == s_aModes[i].m_Height) - { - OldSelected = i; - } + MainView.HSplitTop(20.0f, 0, &MainView); + MainView.HSplitTop(BackgroundHeight, &Screen, &MainView); + RenderTools()->DrawUIRect(&Screen, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - CListboxItem Item = UiDoListboxNextItem(&s_aModes[i], OldSelected == i); - if(Item.m_Visible) - { - int G = gcd(s_aModes[i].m_Width, s_aModes[i].m_Height); - str_format(aBuf, sizeof(aBuf), " %dx%d %d bit (%d:%d)", s_aModes[i].m_Width, s_aModes[i].m_Height, Depth, s_aModes[i].m_Width/G, s_aModes[i].m_Height/G); - UI()->DoLabelScaled(&Item.m_Rect, aBuf, 16.0f, -1); - } - } + // render textures menu background + NumOptions = 3; + BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; - const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0); - if(OldSelected != NewSelected) - { - const int Depth = s_aModes[NewSelected].m_Red+s_aModes[NewSelected].m_Green+s_aModes[NewSelected].m_Blue > 16 ? 24 : 16; - g_Config.m_GfxColorDepth = Depth; - g_Config.m_GfxScreenWidth = s_aModes[NewSelected].m_Width; - g_Config.m_GfxScreenHeight = s_aModes[NewSelected].m_Height; - CheckSettings = true; - } + MainView.HSplitTop(10.0f, 0, &MainView); + MainView.HSplitTop(BackgroundHeight, &Texture, &MainView); + RenderTools()->DrawUIRect(&Texture, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); - // switches - MainView.HSplitTop(20.0f, &Button, &MainView); - static int s_ButtonGfxBorderless = 0; - if(DoButton_CheckBox(&s_ButtonGfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button)) - { - g_Config.m_GfxBorderless ^= 1; - if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen) - g_Config.m_GfxFullscreen = 0; - CheckSettings = true; - } + // render screen menu + Screen.HSplitTop(ButtonHeight, &Label, &Screen); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Screen"), ButtonHeight*ms_FontmodHeight*0.8f, 0); - MainView.HSplitTop(20.0f, &Button, &MainView); + Screen.HSplitTop(Spacing, 0, &Screen); + Screen.HSplitTop(ButtonHeight, &Button, &Screen); static int s_ButtonGfxFullscreen = 0; if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button)) { @@ -1364,7 +1175,23 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) CheckSettings = true; } - MainView.HSplitTop(20.0f, &Button, &MainView); + if(!g_Config.m_GfxFullscreen) + { + Screen.HSplitTop(Spacing, 0, &Screen); + Screen.HSplitTop(ButtonHeight, &Button, &Screen); + Button.VSplitLeft(ButtonHeight, 0, &Button); + static int s_ButtonGfxBorderless = 0; + if(DoButton_CheckBox(&s_ButtonGfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button)) + { + g_Config.m_GfxBorderless ^= 1; + if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen) + g_Config.m_GfxFullscreen = 0; + CheckSettings = true; + } + } + + Screen.HSplitTop(Spacing, 0, &Screen); + Screen.HSplitTop(ButtonHeight, &Button, &Screen); static int s_ButtonGfxVsync = 0; if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), g_Config.m_GfxVsync, &Button)) { @@ -1372,16 +1199,42 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) CheckSettings = true; } - MainView.HSplitTop(20.0f, &Button, &MainView); - static int s_ButtonGfxFsaaSamples = 0; - if(DoButton_CheckBox_Number(&s_ButtonGfxFsaaSamples, Localize("FSAA samples"), g_Config.m_GfxFsaaSamples, &Button)) + // FSAA button { - g_Config.m_GfxFsaaSamples = (g_Config.m_GfxFsaaSamples+1)%17; - CheckSettings = true; + Screen.HSplitTop(Spacing, 0, &Screen); + Screen.HSplitTop(ButtonHeight, &Button, &Screen); + RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + CUIRect Text; + Button.VSplitLeft(ButtonHeight+5.0f, 0, &Button); + Button.VSplitLeft(100.0f, &Text, &Button); + + char aBuf[32]; + str_format(aBuf, sizeof(aBuf), "%s:", Localize("Anti Aliasing")); + Text.y += 2.0f; + UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, -1); + + Button.VSplitLeft(70.0f, &Button, 0); + str_format(aBuf, sizeof(aBuf), "%dx", g_Config.m_GfxFsaaSamples); + static int s_ButtonGfxFsaaSamples = 0; + if(DoButton_Menu(&s_ButtonGfxFsaaSamples, aBuf, 0, &Button)) + { + if(!g_Config.m_GfxFsaaSamples) + g_Config.m_GfxFsaaSamples = 2; + else if(g_Config.m_GfxFsaaSamples == 16) + g_Config.m_GfxFsaaSamples = 0; + else + g_Config.m_GfxFsaaSamples *= 2; + CheckSettings = true; + } } - MainView.HSplitTop(40.0f, &Button, &MainView); - MainView.HSplitTop(20.0f, &Button, &MainView); + // render texture menu + Texture.HSplitTop(ButtonHeight, &Label, &Texture); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Texture"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + Texture.HSplitTop(Spacing, 0, &Texture); + Texture.HSplitTop(ButtonHeight, &Button, &Texture); static int s_ButtonGfxTextureQuality = 0; if(DoButton_CheckBox(&s_ButtonGfxTextureQuality, Localize("Quality Textures"), g_Config.m_GfxTextureQuality, &Button)) { @@ -1389,7 +1242,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) CheckSettings = true; } - MainView.HSplitTop(20.0f, &Button, &MainView); + Texture.HSplitTop(Spacing, 0, &Texture); + Texture.HSplitTop(ButtonHeight, &Button, &Texture); static int s_ButtonGfxTextureCompression = 0; if(DoButton_CheckBox(&s_ButtonGfxTextureCompression, Localize("Texture Compression"), g_Config.m_GfxTextureCompression, &Button)) { @@ -1397,17 +1251,193 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) CheckSettings = true; } - MainView.HSplitTop(20.0f, &Button, &MainView); + Texture.HSplitTop(Spacing, 0, &Texture); + Texture.HSplitTop(ButtonHeight, &Button, &Texture); static int s_ButtonGfxHighDetail = 0; if(DoButton_CheckBox(&s_ButtonGfxHighDetail, Localize("High Detail"), g_Config.m_GfxHighDetail, &Button)) g_Config.m_GfxHighDetail ^= 1; + // render screen modes + MainView.HSplitTop(10.0f, 0, &MainView); + + // display mode list + { + // custom list header + NumOptions = 2; + + CUIRect Header, Button; + MainView.HSplitTop(ButtonHeight*(float)(NumOptions+1)+Spacing*(float)(NumOptions+1), &Header, 0); + RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 5.0f); + + // draw header + MainView.HSplitTop(ButtonHeight, &Header, &MainView); + Header.y += 2.0f; + UI()->DoLabel(&Header, Localize("Resolutions"), Header.h*ms_FontmodHeight*0.8f, 0); + + // supported modes button + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + static int s_GfxDisplayAllModes = 0; + if(DoButton_CheckBox(&s_GfxDisplayAllModes, Localize("Show only supported"), g_Config.m_GfxDisplayAllModes^1, &Button)) + { + g_Config.m_GfxDisplayAllModes ^= 1; + m_NumModes = Graphics()->GetVideoModes(m_aModes, MAX_RESOLUTIONS); + UpdateVideoFormats(); + + bool Found = false; + for(int i = 0; i < m_NumVideoFormats; i++) + { + int G = gcd(g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight); + if(m_aVideoFormats[i].m_WidthValue == g_Config.m_GfxScreenWidth/G && m_aVideoFormats[i].m_HeightValue == g_Config.m_GfxScreenHeight/G) + { + m_CurrentVideoFormat = i; + Found = true; + break; + } + + } + + if(!Found) + m_CurrentVideoFormat = 0; + + UpdatedFilteredVideoModes(); + } + + // format changer + { + MainView.HSplitTop(Spacing, 0, &MainView); + MainView.HSplitTop(ButtonHeight, &Button, &MainView); + RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + CUIRect Text, Value, Unit; + Button.VSplitLeft(Button.w/3.0f, &Text, &Button); + Button.VSplitMid(&Value, &Unit); + + char aBuf[32]; + str_format(aBuf, sizeof(aBuf), "%s:", Localize("Format")); + Text.y += 2.0f; + UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, 0); + + Unit.y += 2.0f; + if((float)m_aVideoFormats[m_CurrentVideoFormat].m_WidthValue/(float)m_aVideoFormats[m_CurrentVideoFormat].m_HeightValue >= 1.55f) + UI()->DoLabel(&Unit, Localize("Wide"), Unit.h*ms_FontmodHeight*0.8f, 0); + else + UI()->DoLabel(&Unit, Localize("Letterbox"), Unit.h*ms_FontmodHeight*0.8f, 0); + + str_format(aBuf, sizeof(aBuf), "%d:%d", m_aVideoFormats[m_CurrentVideoFormat].m_WidthValue, m_aVideoFormats[m_CurrentVideoFormat].m_HeightValue); + static int s_VideoFormatButton = 0; + if(DoButton_Menu(&s_VideoFormatButton, aBuf, 0, &Value)) + { + m_CurrentVideoFormat++; + if(m_CurrentVideoFormat == m_NumVideoFormats) + m_CurrentVideoFormat = 0; + + UpdatedFilteredVideoModes(); + } + } + + MainView.HSplitTop(Spacing, 0, &MainView); + + static float s_ScrollValue = 0; + static int s_DisplayModeList = 0; + int OldSelected = -1; + int G = gcd(s_GfxScreenWidth, s_GfxScreenHeight); + str_format(aBuf, sizeof(aBuf), "%s: %dx%d (%d:%d)", Localize("Current"), s_GfxScreenWidth, s_GfxScreenHeight, s_GfxScreenWidth/G, s_GfxScreenHeight/G); + UiDoListboxStart(&s_DisplayModeList, 20.0f, aBuf, m_lFilteredVideoModes.size(), 1, OldSelected, s_ScrollValue, &MainView); + + for(int i = 0; i < m_lFilteredVideoModes.size(); ++i) + { + if(g_Config.m_GfxScreenWidth == m_lFilteredVideoModes[i].m_Width && + g_Config.m_GfxScreenHeight == m_lFilteredVideoModes[i].m_Height) + { + OldSelected = i; + } + + CListboxItem Item = UiDoListboxNextItem(&m_lFilteredVideoModes[i], OldSelected == i); + if(Item.m_Visible) + { + int G = gcd(m_lFilteredVideoModes[i].m_Width, m_lFilteredVideoModes[i].m_Height); + str_format(aBuf, sizeof(aBuf), " %dx%d", m_lFilteredVideoModes[i].m_Width, m_lFilteredVideoModes[i].m_Height); + if(i == OldSelected) + { + TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f); + TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f); + Item.m_Rect.y += 2.0f; + UI()->DoLabelScaled(&Item.m_Rect, aBuf, Item.m_Rect.h*ms_FontmodHeight*0.8f, 0); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f); + } + else + { + Item.m_Rect.y += 2.0f; + UI()->DoLabelScaled(&Item.m_Rect, aBuf, Item.m_Rect.h*ms_FontmodHeight*0.8f, 0); + } + } + } + + const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0); + if(OldSelected != NewSelected) + { + g_Config.m_GfxScreenWidth = m_lFilteredVideoModes[NewSelected].m_Width; + g_Config.m_GfxScreenHeight = m_lFilteredVideoModes[NewSelected].m_Height; + CheckSettings = true; + } + } + + // reset button + Spacing = 3.0f; + float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; + + BottomView.VSplitRight(ButtonWidth, 0, &BottomView); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + + BottomView.HSplitTop(25.0f, &BottomView, 0); + Button = BottomView; + static int s_ResetButton=0; + if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) + { + g_Config.m_GfxScreenWidth = Graphics()->GetDesktopScreenWidth(); + g_Config.m_GfxScreenHeight = Graphics()->GetDesktopScreenHeight(); + g_Config.m_GfxBorderless = 0; + g_Config.m_GfxFullscreen = 1; + g_Config.m_GfxVsync = 1; + g_Config.m_GfxFsaaSamples = 0; + g_Config.m_GfxTextureQuality = 1; + g_Config.m_GfxTextureCompression = 0; + g_Config.m_GfxHighDetail = 1; + + if(g_Config.m_GfxDisplayAllModes) + { + g_Config.m_GfxDisplayAllModes = 0; + m_NumModes = Graphics()->GetVideoModes(m_aModes, MAX_RESOLUTIONS); + UpdateVideoFormats(); + + bool Found = false; + for(int i = 0; i < m_NumVideoFormats; i++) + { + int G = gcd(g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight); + if(m_aVideoFormats[i].m_WidthValue == g_Config.m_GfxScreenWidth/G && m_aVideoFormats[i].m_HeightValue == g_Config.m_GfxScreenHeight/G) + { + m_CurrentVideoFormat = i; + Found = true; + break; + } + + } + + if(!Found) + m_CurrentVideoFormat = 0; + + UpdatedFilteredVideoModes(); + } + + CheckSettings = true; + } + // check if the new settings require a restart if(CheckSettings) { if(s_GfxScreenWidth == g_Config.m_GfxScreenWidth && s_GfxScreenHeight == g_Config.m_GfxScreenHeight && - s_GfxColorDepth == g_Config.m_GfxColorDepth && s_GfxBorderless == g_Config.m_GfxBorderless && s_GfxFullscreen == g_Config.m_GfxFullscreen && s_GfxVsync == g_Config.m_GfxVsync && @@ -1422,12 +1452,38 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) void CMenus::RenderSettingsSound(CUIRect MainView) { - CUIRect Button; - MainView.VSplitMid(&MainView, 0); + CUIRect Label, Button, Sound, Detail, BottomView; + + // render sound menu background + int NumOptions = g_Config.m_SndEnable ? 3 : 1; + float ButtonHeight = 20.0f; + float Spacing = 2.0f; + float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing; + + MainView.HSplitTop(20.0f, 0, &MainView); + MainView.HSplitTop(BackgroundHeight, &Sound, &MainView); + RenderTools()->DrawUIRect(&Sound, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + // render detail menu background + if(g_Config.m_SndEnable) + { + BackgroundHeight = 2.0f*ButtonHeight+Spacing; + + MainView.HSplitTop(10.0f, 0, &MainView); + MainView.HSplitTop(BackgroundHeight, &Detail, &MainView); + RenderTools()->DrawUIRect(&Detail, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + } + static int s_SndEnable = g_Config.m_SndEnable; static int s_SndRate = g_Config.m_SndRate; - MainView.HSplitTop(20.0f, &Button, &MainView); + // render sound menu + Sound.HSplitTop(ButtonHeight, &Label, &Sound); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Sound"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + Sound.HSplitTop(Spacing, 0, &Sound); + Sound.HSplitTop(ButtonHeight, &Button, &Sound); static int s_ButtonSndEnable = 0; if(DoButton_CheckBox(&s_ButtonSndEnable, Localize("Use sounds"), g_Config.m_SndEnable, &Button)) { @@ -1442,64 +1498,110 @@ void CMenus::RenderSettingsSound(CUIRect MainView) m_NeedRestartSound = g_Config.m_SndEnable && (!s_SndEnable || s_SndRate != g_Config.m_SndRate); } - if(!g_Config.m_SndEnable) - return; - - MainView.HSplitTop(20.0f, &Button, &MainView); - static int s_ButtonSndMusic = 0; - if(DoButton_CheckBox(&s_ButtonSndMusic, Localize("Play background music"), g_Config.m_SndMusic, &Button)) + if(g_Config.m_SndEnable) { - g_Config.m_SndMusic ^= 1; - if(Client()->State() == IClient::STATE_OFFLINE) + Sound.HSplitTop(Spacing, 0, &Sound); + Sound.HSplitTop(ButtonHeight, &Button, &Sound); + Button.VSplitLeft(ButtonHeight, 0, &Button); + static int s_ButtonSndMusic = 0; + if(DoButton_CheckBox(&s_ButtonSndMusic, Localize("Play background music"), g_Config.m_SndMusic, &Button)) { - if(g_Config.m_SndMusic) - m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); - else - m_pClient->m_pSounds->Stop(SOUND_MENU); + g_Config.m_SndMusic ^= 1; + if(Client()->State() == IClient::STATE_OFFLINE) + { + if(g_Config.m_SndMusic) + m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); + else + m_pClient->m_pSounds->Stop(SOUND_MENU); + } } + + Sound.HSplitTop(Spacing, 0, &Sound); + Sound.HSplitTop(ButtonHeight, &Button, &Sound); + Button.VSplitLeft(ButtonHeight, 0, &Button); + static int s_ButtonSndNonactiveMute = 0; + if(DoButton_CheckBox(&s_ButtonSndNonactiveMute, Localize("Mute when not active"), g_Config.m_SndNonactiveMute, &Button)) + g_Config.m_SndNonactiveMute ^= 1; + + // render detail menu + Detail.HSplitTop(ButtonHeight, &Label, &Detail); + Label.y += 2.0f; + UI()->DoLabel(&Label, Localize("Detail"), ButtonHeight*ms_FontmodHeight*0.8f, 0); + + // split menu + CUIRect Left, Right; + Detail.HSplitTop(Spacing, 0, &Detail); + Detail.VSplitMid(&Left, &Right); + Left.VSplitRight(1.5f, &Left, 0); + Right.VSplitLeft(1.5f, 0, &Right); + + // sample rate thingy + { + Left.HSplitTop(ButtonHeight, &Button, &Left); + + RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + CUIRect Text, Value, Unit; + Button.VSplitLeft(Button.w/3.0f, &Text, &Button); + Button.VSplitMid(&Value, &Unit); + + char aBuf[32]; + str_format(aBuf, sizeof(aBuf), "%s:", Localize("Sample rate")); + Text.y += 2.0f; + UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, 0); + + Unit.y += 2.0f; + UI()->DoLabel(&Unit, "kHz", Unit.h*ms_FontmodHeight*0.8f, 0); + + if(g_Config.m_SndRate != 48000 && g_Config.m_SndRate != 44100) + g_Config.m_SndRate = 48000; + if(g_Config.m_SndRate == 48000) + str_copy(aBuf, "48.0", sizeof(aBuf)); + else + str_copy(aBuf, "44.1", sizeof(aBuf)); + static int s_SampleRateButton = 0; + if(DoButton_Menu(&s_SampleRateButton, aBuf, 0, &Value)) + { + if(g_Config.m_SndRate == 48000) + g_Config.m_SndRate = 44100; + else + g_Config.m_SndRate = 48000; + } + + m_NeedRestartSound = !s_SndEnable || s_SndRate != g_Config.m_SndRate; + } + + Right.HSplitTop(ButtonHeight, &Button, &Right); + DoScrollbarOption(&g_Config.m_SndVolume, &g_Config.m_SndVolume, &Button, Localize("Volume"), 110.0f, 0, 100); } - MainView.HSplitTop(20.0f, &Button, &MainView); - static int s_ButtonSndNonactiveMute = 0; - if(DoButton_CheckBox(&s_ButtonSndNonactiveMute, Localize("Mute when not active"), g_Config.m_SndNonactiveMute, &Button)) - g_Config.m_SndNonactiveMute ^= 1; + // reset button + MainView.HSplitBottom(60.0f, 0, &BottomView); - // sample rate box - { - char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_SndRate); - MainView.HSplitTop(20.0f, &Button, &MainView); - UI()->DoLabelScaled(&Button, Localize("Sample rate"), 14.0f, -1); - Button.VSplitLeft(190.0f, 0, &Button); - static float Offset = 0.0f; - DoEditBox(&g_Config.m_SndRate, &Button, aBuf, sizeof(aBuf), 14.0f, &Offset); - g_Config.m_SndRate = max(1, str_toint(aBuf)); - m_NeedRestartSound = !s_SndEnable || s_SndRate != g_Config.m_SndRate; - } + Spacing = 3.0f; + float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; - // volume slider + BottomView.VSplitRight(ButtonWidth, 0, &BottomView); + RenderTools()->DrawUIRect4(&BottomView, vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 5.0f); + + BottomView.HSplitTop(25.0f, &BottomView, 0); + Button = BottomView; + static int s_ResetButton=0; + if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button)) { - CUIRect Button, Label; - MainView.HSplitTop(5.0f, &Button, &MainView); - MainView.HSplitTop(20.0f, &Button, &MainView); - Button.VSplitLeft(190.0f, &Label, &Button); - Button.HMargin(2.0f, &Button); - UI()->DoLabelScaled(&Label, Localize("Sound volume"), 14.0f, -1); - g_Config.m_SndVolume = (int)(DoScrollbarH(&g_Config.m_SndVolume, &Button, g_Config.m_SndVolume/100.0f)*100.0f); - MainView.HSplitTop(20.0f, 0, &MainView); + g_Config.m_SndEnable = 1; + if(!g_Config.m_SndMusic) + { + g_Config.m_SndMusic = 1; + m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); + } + g_Config.m_SndNonactiveMute = 0; + g_Config.m_SndRate = 48000; + g_Config.m_SndVolume = 100; } } void CMenus::RenderSettings(CUIRect MainView) { - CUIRect RestartWarning; - MainView.HSplitBottom(15.0f, &MainView, &RestartWarning); - RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 10.0f); - - MainView.HSplitTop(10.0f, 0, &MainView); - - MainView.Margin(10.0f, &MainView); - // handle which page should be rendered if(g_Config.m_UiSettingsPage == SETTINGS_GENERAL) RenderSettingsGeneral(MainView); @@ -1514,7 +1616,21 @@ void CMenus::RenderSettings(CUIRect MainView) else if(g_Config.m_UiSettingsPage == SETTINGS_SOUND) RenderSettingsSound(MainView); + MainView.HSplitBottom(60.0f, 0, &MainView); + // reset warning if(m_NeedRestartGraphics || m_NeedRestartSound) - UI()->DoLabel(&RestartWarning, Localize("You must restart the game for all settings to take effect."), 15.0f, -1); + { + // background + CUIRect RestartWarning; + MainView.HSplitTop(25.0f, &RestartWarning, 0); + RestartWarning.VMargin(140.0f, &RestartWarning); + RenderTools()->DrawUIRect(&RestartWarning, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + // text + TextRender()->TextColor(0.973f, 0.863f, 0.207, 1.0f); + RestartWarning.y += 2.0f; + UI()->DoLabel(&RestartWarning, Localize("You must restart the game for all settings to take effect."), RestartWarning.h*ms_FontmodHeight*0.75f, 0); + TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); + } } diff --git a/src/game/client/components/menus_start.cpp b/src/game/client/components/menus_start.cpp index 08c098663..210c61206 100644 --- a/src/game/client/components/menus_start.cpp +++ b/src/game/client/components/menus_start.cpp @@ -15,57 +15,111 @@ void CMenus::RenderStartMenu(CUIRect MainView) { - CUIRect Menu; - MainView.VMargin(MainView.w/2-190.0f, &Menu); - Menu.HMargin(145.0f, &Menu); - RenderTools()->DrawUIRect(&Menu, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 10.0f); + CUIRect TopMenu, BottomMenu; + MainView.VMargin(MainView.w/2-190.0f, &TopMenu); + TopMenu.HSplitTop(365.0f, &TopMenu, &BottomMenu); + //TopMenu.HSplitBottom(145.0f, &TopMenu, 0); + RenderTools()->DrawUIRect4(&TopMenu, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 10.0f); - Menu.Margin(5.0f, &Menu); + TopMenu.HSplitTop(145.0f, 0, &TopMenu); CUIRect Button; - Menu.HSplitTop(40.0f, &Button, &Menu); - static int s_PlayButton = 0; - if(DoButton_MenuImage(&s_PlayButton, Localize("Play Game"), 0, &Button, "play_game", 10.0f, 0.5f)) - m_MenuPage = g_Config.m_UiBrowserPage; - - Menu.HSplitTop(5.0f, 0, &Menu); // little space - Menu.HSplitTop(40.0f, &Button, &Menu); - static int s_MapEditorButton = 0; - if(DoButton_MenuImage(&s_MapEditorButton, Localize("Map Editor"), 0, &Button, "editor", 10.0f, 0.5f)) - { - g_Config.m_ClEditor = 1; - Input()->MouseModeRelative(); - } - - Menu.HSplitTop(5.0f, 0, &Menu); // little space - Menu.HSplitTop(40.0f, &Button, &Menu); - static int s_DemoButton = 0; - if(DoButton_MenuImage(&s_DemoButton, Localize("Demos"), 0, &Button, "demos", 10.0f, 0.5f)) - { - m_MenuPage = PAGE_DEMOS; - DemolistPopulate(); - DemolistOnUpdate(false); - } - - Menu.HSplitTop(5.0f, 0, &Menu); // little space - Menu.HSplitTop(40.0f, &Button, &Menu); - static int s_LocalServerButton = 0; - if(DoButton_MenuImage(&s_LocalServerButton, Localize("Create Local Server"), 0, &Button, "local_server", 10.0f, 0.5f)) - { - } - - Menu.HSplitTop(5.0f, 0, &Menu); // little space - Menu.HSplitTop(40.0f, &Button, &Menu); + TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); static int s_SettingsButton = 0; - if(DoButton_MenuImage(&s_SettingsButton, Localize("Settings"), 0, &Button, "settings", 10.0f, 0.5f)) + if(g_Config.m_ClShowStartMenuImages) { - m_MenuPage = PAGE_SETTINGS; + if(DoButton_MenuImage(&s_SettingsButton, Localize("Settings"), 0, &Button, "settings", 10.0f, 0.5f)) + { + m_MenuPage = PAGE_SETTINGS; + } + } + else + { + if(DoButton_Menu(&s_SettingsButton, Localize("Settings"), 0, &Button, 10.0f, 0.5f)) + { + m_MenuPage = PAGE_SETTINGS; + } } - Menu.HSplitBottom(45.0f, &Menu, &Button); + /*TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space + TopMenu.HSplitBottom(40.0f, &TopMenu, &Bottom); + static int s_LocalServerButton = 0; + if(g_Config.m_ClShowStartMenuImages) + { + if(DoButton_MenuImage(&s_LocalServerButton, Localize("Local server"), 0, &Button, "local_server", 10.0f, 0.5f)) + { + } + } + else + { + if(DoButton_Menu(&s_LocalServerButton, Localize("Local server"), 0, &Button, 10.0f, 0.5f)) + { + } + }*/ + + TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space + TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); + static int s_DemoButton = 0; + if(g_Config.m_ClShowStartMenuImages) + { + if(DoButton_MenuImage(&s_DemoButton, Localize("Demos"), 0, &Button, "demos", 10.0f, 0.5f)) + { + m_MenuPage = PAGE_DEMOS; + DemolistPopulate(); + DemolistOnUpdate(false); + } + } + else + { + if(DoButton_Menu(&s_DemoButton, Localize("Demos"), 0, &Button, 10.0f, 0.5f)) + { + m_MenuPage = PAGE_DEMOS; + DemolistPopulate(); + DemolistOnUpdate(false); + } + } + + TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space + TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); + static int s_MapEditorButton = 0; + if(g_Config.m_ClShowStartMenuImages) + { + if(DoButton_MenuImage(&s_MapEditorButton, Localize("Editor"), 0, &Button, "editor", 10.0f, 0.5f)) + { + g_Config.m_ClEditor = 1; + Input()->MouseModeRelative(); + } + } + else + { + if(DoButton_Menu(&s_MapEditorButton, Localize("Editor"), 0, &Button, 10.0f, 0.5f)) + { + g_Config.m_ClEditor = 1; + Input()->MouseModeRelative(); + } + } + + TopMenu.HSplitBottom(5.0f, &TopMenu, 0); // little space + TopMenu.HSplitBottom(40.0f, &TopMenu, &Button); + static int s_PlayButton = 0; + if(g_Config.m_ClShowStartMenuImages) + { + if(DoButton_MenuImage(&s_PlayButton, Localize("Play"), 0, &Button, "play_game", 10.0f, 0.5f)) + m_MenuPage = g_Config.m_UiBrowserPage; + } + else + { + if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, 10.0f, 0.5f)) + m_MenuPage = g_Config.m_UiBrowserPage; + } + + BottomMenu.HSplitTop(90.0f, 0, &BottomMenu); + RenderTools()->DrawUIRect4(&BottomMenu, vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), CUI::CORNER_T, 10.0f); + + BottomMenu.HSplitTop(40.0f, &Button, &TopMenu); static int s_QuitButton = 0; - if(DoButton_Menu(&s_QuitButton, Localize("Quit Game"), 0, &Button, 15.0f, 0.5f)) + if(DoButton_Menu(&s_QuitButton, Localize("Quit"), 0, &Button, 10.0f, 0.5f)) m_Popup = POPUP_QUIT; // render version @@ -89,7 +143,7 @@ void CMenus::RenderLogo(CUIRect MainView) Graphics()->TextureSet(g_pData->m_aImages[IMAGE_BANNER].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,1); - IGraphics::CQuadItem QuadItem(MainView.w/2-140, 70, 280, 70); + IGraphics::CQuadItem QuadItem(MainView.w/2-140, 60, 280, 70); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp index c86edd885..2ee1ea55b 100644 --- a/src/game/client/render.cpp +++ b/src/game/client/render.cpp @@ -177,6 +177,152 @@ void CRenderTools::DrawRoundRectExt(float x, float y, float w, float h, float r, Graphics()->QuadsDrawTL(ArrayQ, NumItems); } +void CRenderTools::DrawRoundRectExt4(float x, float y, float w, float h, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, float r, int Corners) +{ + int Num = 8; + for(int i = 0; i < Num; i+=2) + { + float a1 = i/(float)Num * pi/2; + float a2 = (i+1)/(float)Num * pi/2; + float a3 = (i+2)/(float)Num * pi/2; + float Ca1 = cosf(a1); + float Ca2 = cosf(a2); + float Ca3 = cosf(a3); + float Sa1 = sinf(a1); + float Sa2 = sinf(a2); + float Sa3 = sinf(a3); + + if(Corners&1) // TL + { + Graphics()->SetColor(ColorTopLeft.r, ColorTopLeft.g, ColorTopLeft.b, ColorTopLeft.a); + IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem( + x+r, y+r, + x+(1-Ca1)*r, y+(1-Sa1)*r, + x+(1-Ca3)*r, y+(1-Sa3)*r, + x+(1-Ca2)*r, y+(1-Sa2)*r); + Graphics()->QuadsDrawFreeform(&ItemF, 1); + } + + if(Corners&2) // TR + { + Graphics()->SetColor(ColorTopRight.r, ColorTopRight.g, ColorTopRight.b, ColorTopRight.a); + IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem( + x+w-r, y+r, + x+w-r+Ca1*r, y+(1-Sa1)*r, + x+w-r+Ca3*r, y+(1-Sa3)*r, + x+w-r+Ca2*r, y+(1-Sa2)*r); + Graphics()->QuadsDrawFreeform(&ItemF, 1); + } + + if(Corners&4) // BL + { + Graphics()->SetColor(ColorBottomLeft.r, ColorBottomLeft.g, ColorBottomLeft.b, ColorBottomLeft.a); + IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem( + x+r, y+h-r, + x+(1-Ca1)*r, y+h-r+Sa1*r, + x+(1-Ca3)*r, y+h-r+Sa3*r, + x+(1-Ca2)*r, y+h-r+Sa2*r); + Graphics()->QuadsDrawFreeform(&ItemF, 1); + } + + if(Corners&8) // BR + { + Graphics()->SetColor(ColorBottomRight.r, ColorBottomRight.g, ColorBottomRight.b, ColorBottomRight.a); + IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem( + x+w-r, y+h-r, + x+w-r+Ca1*r, y+h-r+Sa1*r, + x+w-r+Ca3*r, y+h-r+Sa3*r, + x+w-r+Ca2*r, y+h-r+Sa2*r); + Graphics()->QuadsDrawFreeform(&ItemF, 1); + } + + if(Corners&16) // ITL + { + Graphics()->SetColor(ColorTopLeft.r, ColorTopLeft.g, ColorTopLeft.b, ColorTopLeft.a); + IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem( + x, y, + x+(1-Ca1)*r, y-r+Sa1*r, + x+(1-Ca3)*r, y-r+Sa3*r, + x+(1-Ca2)*r, y-r+Sa2*r); + Graphics()->QuadsDrawFreeform(&ItemF, 1); + } + + if(Corners&32) // ITR + { + Graphics()->SetColor(ColorTopRight.r, ColorTopRight.g, ColorTopRight.b, ColorTopRight.a); + IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem( + x+w, y, + x+w-r+Ca1*r, y-r+Sa1*r, + x+w-r+Ca3*r, y-r+Sa3*r, + x+w-r+Ca2*r, y-r+Sa2*r); + Graphics()->QuadsDrawFreeform(&ItemF, 1); + } + + if(Corners&64) // IBL + { + Graphics()->SetColor(ColorBottomLeft.r, ColorBottomLeft.g, ColorBottomLeft.b, ColorBottomLeft.a); + IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem( + x, y+h, + x+(1-Ca1)*r, y+h+(1-Sa1)*r, + x+(1-Ca3)*r, y+h+(1-Sa3)*r, + x+(1-Ca2)*r, y+h+(1-Sa2)*r); + Graphics()->QuadsDrawFreeform(&ItemF, 1); + } + + if(Corners&128) // IBR + { + Graphics()->SetColor(ColorBottomRight.r, ColorBottomRight.g, ColorBottomRight.b, ColorBottomRight.a); + IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem( + x+w, y+h, + x+w-r+Ca1*r, y+h+(1-Sa1)*r, + x+w-r+Ca3*r, y+h+(1-Sa3)*r, + x+w-r+Ca2*r, y+h+(1-Sa2)*r); + Graphics()->QuadsDrawFreeform(&ItemF, 1); + } + } + + Graphics()->SetColor4(ColorTopLeft, ColorTopRight, ColorBottomLeft, ColorBottomRight); + IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x+r, y+r, w-r*2, h-r*2); // center + Graphics()->QuadsDrawTL(&ItemQ, 1); + Graphics()->SetColor4(ColorTopLeft, ColorTopRight, ColorTopLeft, ColorTopRight); + ItemQ = IGraphics::CQuadItem(x+r, y, w-r*2, r); // top + Graphics()->QuadsDrawTL(&ItemQ, 1); + Graphics()->SetColor4(ColorBottomLeft, ColorBottomRight, ColorBottomLeft, ColorBottomRight); + ItemQ = IGraphics::CQuadItem(x+r, y+h-r, w-r*2, r); // bottom + Graphics()->QuadsDrawTL(&ItemQ, 1); + Graphics()->SetColor4(ColorTopLeft, ColorTopLeft, ColorBottomLeft, ColorBottomLeft); + ItemQ = IGraphics::CQuadItem(x, y+r, r, h-r*2); // left + Graphics()->QuadsDrawTL(&ItemQ, 1); + Graphics()->SetColor4(ColorTopRight, ColorTopRight, ColorBottomRight, ColorBottomRight); + ItemQ = IGraphics::CQuadItem(x+w-r, y+r, r, h-r*2); // right + Graphics()->QuadsDrawTL(&ItemQ, 1); + + if(!(Corners&1)) + { + Graphics()->SetColor(ColorTopLeft.r, ColorTopLeft.g, ColorTopLeft.b, ColorTopLeft.a); + IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x, y, r, r); // TL + Graphics()->QuadsDrawTL(&ItemQ, 1); + } + if(!(Corners&2)) + { + Graphics()->SetColor(ColorTopRight.r, ColorTopRight.g, ColorTopRight.b, ColorTopRight.a); + IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x+w, y, -r, r); // TR + Graphics()->QuadsDrawTL(&ItemQ, 1); + } + if(!(Corners&4)) + { + Graphics()->SetColor(ColorBottomLeft.r, ColorBottomLeft.g, ColorBottomLeft.b, ColorBottomLeft.a); + IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x, y+h, r, -r); // BL + Graphics()->QuadsDrawTL(&ItemQ, 1); + } + if(!(Corners&8)) + { + Graphics()->SetColor(ColorBottomRight.r, ColorBottomRight.g, ColorBottomRight.b, ColorBottomRight.a); + IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x+w, y+h, -r, -r); // BR + Graphics()->QuadsDrawTL(&ItemQ, 1); + } +} + void CRenderTools::DrawRoundRect(float x, float y, float w, float h, float r) { DrawRoundRectExt(x,y,w,h,r,0xf); @@ -193,6 +339,15 @@ void CRenderTools::DrawUIRect(const CUIRect *r, vec4 Color, int Corners, float R Graphics()->QuadsEnd(); } +void CRenderTools::DrawUIRect4(const CUIRect *r, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, int Corners, float Rounding) +{ + Graphics()->TextureClear(); + + Graphics()->QuadsBegin(); + DrawRoundRectExt4(r->x,r->y,r->w,r->h,ColorTopLeft,ColorTopRight,ColorBottomLeft,ColorBottomRight,Rounding*UI()->Scale(), Corners); + Graphics()->QuadsEnd(); +} + void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos) { vec2 Direction = Dir; diff --git a/src/game/client/render.h b/src/game/client/render.h index b50aab6fd..9c46c4ccd 100644 --- a/src/game/client/render.h +++ b/src/game/client/render.h @@ -58,8 +58,10 @@ public: // rects void DrawRoundRect(float x, float y, float w, float h, float r); void DrawRoundRectExt(float x, float y, float w, float h, float r, int Corners); + void DrawRoundRectExt4(float x, float y, float w, float h, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, float r, int Corners); void DrawUIRect(const CUIRect *pRect, vec4 Color, int Corners, float Rounding); + void DrawUIRect4(const CUIRect *pRect, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, int Corners, float Rounding); // larger rendering methods void RenderTilemapGenerateSkip(class CLayers *pLayers); diff --git a/src/game/variables.h b/src/game/variables.h index e1eca96cb..1ff3a00ef 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -61,7 +61,7 @@ MACRO_CONFIG_STR(PlayerSkinEyes, player_skin_eyes, 24, "standard", CFGFLAG_CLIEN //MACRO_CONFIG_INT(UiPage, ui_page, 6, 0, 10, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface page") MACRO_CONFIG_INT(UiBrowserPage, ui_browser_page, 6, 6, 8, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface serverbrowser page") -MACRO_CONFIG_INT(UiSettingsPage, ui_settings_page, 0, 0, 4, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface settings page") +MACRO_CONFIG_INT(UiSettingsPage, ui_settings_page, 0, 0, 5, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface settings page") //MACRO_CONFIG_INT(UiToolboxPage, ui_toolbox_page, 0, 0, 2, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toolbox page") MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address") MACRO_CONFIG_INT(UiMousesens, ui_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity for menus/editor") @@ -69,8 +69,10 @@ MACRO_CONFIG_INT(UiMousesens, ui_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG MACRO_CONFIG_INT(GfxNoclip, gfx_noclip, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable clipping") MACRO_CONFIG_STR(ClBackgroundMap, cl_background_map, 64, "menu_night", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Background map") -MACRO_CONFIG_INT(ClRotationRadius, cl_rotation_radius, 30, 1, 500, CFGFLAG_CLIENT|CFGFLAG_SAVE, "camera rotation radius") -MACRO_CONFIG_INT(ClRotationSpeed, cl_rotation_speed, 40, 1, 120, CFGFLAG_CLIENT|CFGFLAG_SAVE, "camera rotations in seconds") +MACRO_CONFIG_INT(ClRotationRadius, cl_rotation_radius, 30, 1, 500, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Camera rotation radius") +MACRO_CONFIG_INT(ClRotationSpeed, cl_rotation_speed, 40, 1, 120, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Camera rotations in seconds") + +MACRO_CONFIG_INT(ClShowStartMenuImages, cl_show_start_menu_images, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show start menu images") // server MACRO_CONFIG_INT(SvWarmup, sv_warmup, 0, -1, 1000, CFGFLAG_SERVER, "Number of seconds to do warmup before match starts (0 disables, -1 all players ready)")