diff --git a/data/menu_buttons.png b/data/menu_buttons.png new file mode 100644 index 000000000..fb9e3e3c4 Binary files /dev/null and b/data/menu_buttons.png differ diff --git a/datasrc/content.py b/datasrc/content.py index a626cef08..241c1f1c8 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -233,6 +233,7 @@ 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") container.images.Add(image_null) container.images.Add(image_game) @@ -251,6 +252,7 @@ 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.pickups.Add(Pickup("health")) container.pickups.Add(Pickup("armor")) @@ -274,6 +276,7 @@ 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) container.spritesets.Add(set_particles) container.spritesets.Add(set_game) @@ -290,6 +293,7 @@ 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.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 +450,9 @@ 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)) + 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 881862c9b..cca761b22 100644 --- a/src/engine/client/graphics.cpp +++ b/src/engine/client/graphics.cpp @@ -799,6 +799,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 a4a08d0b7..6c62139d4 100644 --- a/src/engine/client/graphics.h +++ b/src/engine/client/graphics.h @@ -148,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 e96949304..36fb37df0 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -734,7 +734,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 65cff4980..aecdaef9f 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -296,7 +296,7 @@ public: INITFLAG_BORDERLESS = 8, }; - 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; @@ -439,6 +439,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 84b649020..fd81674ca 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -52,6 +52,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 @@ -138,6 +140,9 @@ public: 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/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 71f8c379d..91f922be8 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 @@ -274,15 +273,19 @@ int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const c 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); + 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()->DrawUIRect(&c, vec4(1.0f , 1.0f, 1.0f, 1.0f), CUI::CORNER_ALL, 3.0f); + RenderTools()->SelectSprite(SPRITE_CHECKBOX_ACTIVE); else - RenderTools()->DrawUIRect(&c, vec4(1.0f , 1.0f, 1.0f, 0.25f+(*pFade/Seconds)*0.125f), CUI::CORNER_ALL, 3.0f); + 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); @@ -712,6 +715,134 @@ void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHe gs_ListBoxView.y -= gs_ListBoxScrollValue*Num*Row.h; } +void CMenus::UiDoListboxStartVideo(const void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems, + int ItemsPerRow, int SelectedIndex, float ScrollValue, float ButtonHeight, float Spaceing) +{ + CUIRect Scroll, Row, Left, Right; + CUIRect View = *pRect; + CUIRect Header, Footer; + + // background + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + + // draw header + View.HSplitTop(ms_ListheaderHeight, &Header, &View); + UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight, 0); + + // supported modes button + View.HSplitTop(Spaceing, 0, &View); + View.HSplitTop(ButtonHeight, &Left, &View); + Left.VSplitMid(&Left, &Right); + Left.VSplitRight(1.5f, &Left, 0); + Right.VSplitLeft(1.5f, 0, &Right); + static int s_GfxDisplayAllModes = 0; + if(DoButton_CheckBox(&s_GfxDisplayAllModes, Localize("Show only supported"), g_Config.m_GfxDisplayAllModes^1, &Left)) + { + 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 + { + RenderTools()->DrawUIRect(&Right, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f); + CUIRect Text, Value, Unit; + Right.VSplitLeft(Right.w/3.0f, &Text, &Right); + Right.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(); + } + } + + // draw footers + View.HSplitBottom(ms_ListheaderHeight, &View, &Footer); + Footer.VSplitLeft(10.0f, 0, &Footer); + UI()->DoLabel(&Footer, pBottomText, Footer.h*ms_FontmodHeight, 0); + + // list background + View.HSplitTop(Spaceing, 0, &View); + RenderTools()->DrawUIRect(&View, vec4(0.0f, 0.0f, 0.0f, 0.25f), 0, 0.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; @@ -1235,8 +1366,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_NumFilteredVideoModes = 0; + 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_aFilteredVideoModes[m_NumFilteredVideoModes++] = 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); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index b6ff7c5c7..787469de9 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -100,6 +101,8 @@ class CMenus : public CComponent 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 UiDoListboxStartVideo(const void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems, + int ItemsPerRow, int SelectedIndex, float ScrollValue, float ButtonHeight, float Spaceing); CListboxItem UiDoListboxNextItem(const void *pID, bool Selected = false); CListboxItem UiDoListboxNextRow(); int UiDoListboxEnd(float *pScrollValue, bool *pItemActivated); @@ -378,6 +381,28 @@ 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]; + CVideoMode m_aFilteredVideoModes[MAX_RESOLUTIONS]; + int m_NumVideoFormats; + int m_CurrentVideoFormat; + int m_NumFilteredVideoModes; + void UpdateVideoFormats(); + void UpdatedFilteredVideoModes(); + // found in menus.cpp int Render(); //void render_background(); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index d2875bb38..d472991c5 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -581,7 +581,11 @@ void CMenus::RenderLanguageSelection(CUIRect MainView) void CMenus::RenderSettingsGeneral(CUIRect MainView) { - CUIRect Label, Button, Game, Client, Language, BottomView; + CUIRect Label, Button, Game, Client, BottomView; + + // 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; @@ -707,12 +711,9 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) MainView.HSplitTop(10.0f, 0, &MainView); // render language selection - MainView.HSplitTop(115.0f, &Language, &MainView); - RenderLanguageSelection(Language); + RenderLanguageSelection(MainView); // reset button - MainView.HSplitBottom(60.0f, 0, &BottomView); - float Spacing = 3.0f; float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f; @@ -1258,13 +1259,9 @@ void CMenus::RenderSettingsControls(CUIRect MainView) 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; @@ -1275,67 +1272,36 @@ 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 Spaceing = 2.0f; + float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spaceing; - 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*Spaceing; - 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); + UI()->DoLabel(&Label, Localize("Screen"), ButtonHeight*ms_FontmodHeight, 0); - MainView.HSplitTop(20.0f, &Button, &MainView); + Screen.HSplitTop(Spaceing, 0, &Screen); + Screen.HSplitTop(ButtonHeight, &Button, &Screen); static int s_ButtonGfxFullscreen = 0; if(DoButton_CheckBox(&s_ButtonGfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button)) { @@ -1345,7 +1311,23 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) CheckSettings = true; } - MainView.HSplitTop(20.0f, &Button, &MainView); + if(!g_Config.m_GfxFullscreen) + { + Screen.HSplitTop(Spaceing, 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(Spaceing, 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)) { @@ -1353,16 +1335,41 @@ 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(Spaceing, 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); + UI()->DoLabel(&Label, Localize("Texture"), ButtonHeight*ms_FontmodHeight, 0); + + Texture.HSplitTop(Spaceing, 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)) { @@ -1370,7 +1377,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) CheckSettings = true; } - MainView.HSplitTop(20.0f, &Button, &MainView); + Texture.HSplitTop(Spaceing, 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)) { @@ -1378,11 +1386,105 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) CheckSettings = true; } - MainView.HSplitTop(20.0f, &Button, &MainView); + Texture.HSplitTop(Spaceing, 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 + { + 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); + UiDoListboxStartVideo(&s_DisplayModeList , &MainView, 24.0f, Localize("Display Modes"), aBuf, m_NumFilteredVideoModes, 1, OldSelected, s_ScrollValue, ButtonHeight, Spaceing); // ugly + + for(int i = 0; i < m_NumFilteredVideoModes; ++i) + { + const int Depth = m_aFilteredVideoModes[i].m_Red+m_aFilteredVideoModes[i].m_Green+m_aFilteredVideoModes[i].m_Blue > 16 ? 24 : 16; + if(g_Config.m_GfxColorDepth == Depth && + g_Config.m_GfxScreenWidth == m_aFilteredVideoModes[i].m_Width && + g_Config.m_GfxScreenHeight == m_aFilteredVideoModes[i].m_Height) + { + OldSelected = i; + } + + CListboxItem Item = UiDoListboxNextItem(&m_aFilteredVideoModes[i], OldSelected == i); + if(Item.m_Visible) + { + int G = gcd(m_aFilteredVideoModes[i].m_Width, m_aFilteredVideoModes[i].m_Height); + str_format(aBuf, sizeof(aBuf), " %dx%d %d bit", m_aFilteredVideoModes[i].m_Width, m_aFilteredVideoModes[i].m_Height, Depth); + UI()->DoLabelScaled(&Item.m_Rect, aBuf, 16.0f, 0); + } + } + + const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0); + if(OldSelected != NewSelected) + { + const int Depth = m_aFilteredVideoModes[NewSelected].m_Red+m_aFilteredVideoModes[NewSelected].m_Green+m_aFilteredVideoModes[NewSelected].m_Blue > 16 ? 24 : 16; + g_Config.m_GfxColorDepth = Depth; + g_Config.m_GfxScreenWidth = m_aFilteredVideoModes[NewSelected].m_Width; + g_Config.m_GfxScreenHeight = m_aFilteredVideoModes[NewSelected].m_Height; + CheckSettings = true; + } + } + + // reset button + float 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_GfxColorDepth = 24; + 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) { @@ -1405,7 +1507,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView) { CUIRect Label, Button, Sound, Detail, BottomView; - // render sound menu backgrounds + // render sound menu background int NumOptions = g_Config.m_SndEnable ? 3 : 1; float ButtonHeight = 20.0f; float Spaceing = 2.0f;