ddnet/src/game/client/components/menus.cpp
GreYFoXGTi 2151883b43 Merge branch 'master' of http://github.com/oy/teeworlds
Conflicts:
	src/game/gamecore.cpp
	src/game/server/entities/character.cpp
	src/game/server/entities/laser.cpp
	src/game/server/entities/pickup.cpp
	src/game/server/entities/projectile.cpp
	src/game/server/entity.h
	src/game/server/gamecontext.cpp
	src/game/server/player.cpp
	src/game/variables.h
2011-01-20 16:10:32 +02:00

1397 lines
38 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* (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 <math.h>
#include <base/system.h>
#include <base/math.h>
#include <base/vmath.h>
#include "menus.h"
#include "skins.h"
#include <engine/graphics.h>
#include <engine/textrender.h>
#include <engine/serverbrowser.h>
#include <engine/keys.h>
#include <engine/storage.h>
#include <engine/shared/config.h>
#include <game/version.h>
#include <game/generated/protocol.h>
#include <game/generated/client_data.h>
#include <game/client/gameclient.h>
#include <game/client/lineinput.h>
#include <game/localization.h>
#include <mastersrv/mastersrv.h>
vec4 CMenus::ms_GuiColor;
vec4 CMenus::ms_ColorTabbarInactiveOutgame;
vec4 CMenus::ms_ColorTabbarActiveOutgame;
vec4 CMenus::ms_ColorTabbarInactive;
vec4 CMenus::ms_ColorTabbarActive;
vec4 CMenus::ms_ColorTabbarInactiveIngame;
vec4 CMenus::ms_ColorTabbarActiveIngame;
float CMenus::ms_ButtonHeight = 25.0f;
float CMenus::ms_ListheaderHeight = 17.0f;
float CMenus::ms_FontmodHeight = 0.8f;
IInput::CEvent CMenus::m_aInputEvents[MAX_INPUTEVENTS];
int CMenus::m_NumInputEvents;
CMenus::CMenus()
{
m_Popup = POPUP_NONE;
m_ActivePage = PAGE_INTERNET;
m_GamePage = PAGE_GAME;
m_NeedRestartGraphics = false;
m_NeedRestartSound = false;
m_NeedSendinfo = false;
m_MenuActive = true;
m_UseMouseButtons = true;
m_EscapePressed = false;
m_EnterPressed = false;
m_DeletePressed = false;
m_NumInputEvents = 0;
m_LastInput = time_get();
str_copy(m_aCurrentDemoFolder, "demos", sizeof(m_aCurrentDemoFolder));
m_aCallvoteReason[0] = 0;
}
vec4 CMenus::ButtonColorMul(const void *pID)
{
if(UI()->ActiveItem() == pID)
return vec4(1,1,1,0.5f);
else if(UI()->HotItem() == pID)
return vec4(1,1,1,1.5f);
return vec4(1,1,1,1);
}
int CMenus::DoButton_Icon(int ImageId, int SpriteId, const CUIRect *pRect)
{
Graphics()->TextureSet(g_pData->m_aImages[ImageId].m_Id);
Graphics()->QuadsBegin();
RenderTools()->SelectSprite(SpriteId);
IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
return 0;
}
int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f);
UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0);
return UI()->DoButtonLogic(pID, pText, Checked, pRect);
}
void CMenus::DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f);
UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0);
}
int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners)
{
if(Checked)
RenderTools()->DrawUIRect(pRect, ms_ColorTabbarActive, Corners, 10.0f);
else
RenderTools()->DrawUIRect(pRect, ms_ColorTabbarInactive, Corners, 10.0f);
UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0);
return UI()->DoButtonLogic(pID, pText, Checked, pRect);
}
int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
//void CMenus::ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
{
if(Checked)
RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f), CUI::CORNER_T, 5.0f);
CUIRect t;
pRect->VSplitLeft(5.0f, 0, &t);
UI()->DoLabel(&t, pText, pRect->h*ms_FontmodHeight, -1);
return UI()->DoButtonLogic(pID, pText, Checked, pRect);
}
int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect)
//void CMenus::ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra)
{
CUIRect c = *pRect;
CUIRect t = *pRect;
c.w = c.h;
t.x += c.w;
t.w -= c.w;
t.VSplitLeft(5.0f, 0, &t);
c.Margin(2.0f, &c);
RenderTools()->DrawUIRect(&c, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 3.0f);
c.y += 2;
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);
}
int CMenus::DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
return DoButton_CheckBox_Common(pID, pText, Checked?"X":"", pRect);
}
int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
char aBuf[16];
str_format(aBuf, sizeof(aBuf), "%d", Checked);
return DoButton_CheckBox_Common(pID, pText, aBuf, pRect);
}
int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners)
{
int Inside = UI()->MouseInside(pRect);
bool ReturnValue = false;
bool UpdateOffset = false;
static int s_AtIndex = 0;
static bool s_DoScroll = false;
static float s_ScrollStart = 0.0f;
FontSize *= UI()->Scale();
if(UI()->LastActiveItem() == pID)
{
int Len = str_length(pStr);
if(Len == 0)
s_AtIndex = 0;
if(Inside && UI()->MouseButton(0))
{
s_DoScroll = true;
s_ScrollStart = UI()->MouseX();
int MxRel = (int)(UI()->MouseX() - pRect->x);
for(int i = 1; i <= Len; i++)
{
if(TextRender()->TextWidth(0, FontSize, pStr, i) - *Offset + 10 > MxRel)
{
s_AtIndex = i - 1;
break;
}
if(i == Len)
s_AtIndex = Len;
}
}
else if(!UI()->MouseButton(0))
s_DoScroll = false;
else if(s_DoScroll)
{
// do scrolling
if(UI()->MouseX() < pRect->x && s_ScrollStart-UI()->MouseX() > 10.0f)
{
s_AtIndex = max(0, s_AtIndex-1);
s_ScrollStart = UI()->MouseX();
UpdateOffset = true;
}
else if(UI()->MouseX() > pRect->x+pRect->w && UI()->MouseX()-s_ScrollStart > 10.0f)
{
s_AtIndex = min(Len, s_AtIndex+1);
s_ScrollStart = UI()->MouseX();
UpdateOffset = true;
}
}
for(int i = 0; i < m_NumInputEvents; i++)
{
Len = str_length(pStr);
ReturnValue |= CLineInput::Manipulate(m_aInputEvents[i], pStr, StrSize, &Len, &s_AtIndex);
}
}
bool JustGotActive = false;
if(UI()->ActiveItem() == pID)
{
if(!UI()->MouseButton(0))
{
s_DoScroll = false;
UI()->SetActiveItem(0);
}
}
else if(UI()->HotItem() == pID)
{
if(UI()->MouseButton(0))
{
if (UI()->LastActiveItem() != pID)
JustGotActive = true;
UI()->SetActiveItem(pID);
}
}
if(Inside)
UI()->SetHotItem(pID);
CUIRect Textbox = *pRect;
RenderTools()->DrawUIRect(&Textbox, vec4(1, 1, 1, 0.5f), Corners, 3.0f);
Textbox.VMargin(2.0f, &Textbox);
Textbox.HMargin(2.0f, &Textbox);
const char *pDisplayStr = pStr;
char aStars[128];
if(Hidden)
{
unsigned s = str_length(pStr);
if(s >= sizeof(aStars))
s = sizeof(aStars)-1;
for(unsigned int i = 0; i < s; ++i)
aStars[i] = '*';
aStars[s] = 0;
pDisplayStr = aStars;
}
// check if the text has to be moved
if(UI()->LastActiveItem() == pID && !JustGotActive && (UpdateOffset || m_NumInputEvents))
{
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex);
if(w-*Offset > Textbox.w)
{
// move to the left
float wt = TextRender()->TextWidth(0, FontSize, pDisplayStr, -1);
do
{
*Offset += min(wt-*Offset-Textbox.w, Textbox.w/3);
}
while(w-*Offset > Textbox.w);
}
else if(w-*Offset < 0.0f)
{
// move to the right
do
{
*Offset = max(0.0f, *Offset-Textbox.w/3);
}
while(w-*Offset < 0.0f);
}
}
UI()->ClipEnable(pRect);
Textbox.x -= *Offset;
UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1);
// render the cursor
if(UI()->LastActiveItem() == pID && !JustGotActive)
{
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex);
Textbox = *pRect;
Textbox.VSplitLeft(2.0f, 0, &Textbox);
Textbox.x += (w-*Offset-TextRender()->TextWidth(0, FontSize, "|", -1)/2);
if((2*time_get()/time_freq()) % 2) // make it blink
UI()->DoLabel(&Textbox, "|", FontSize, -1);
}
UI()->ClipDisable();
return ReturnValue;
}
float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
{
CUIRect Handle;
static float OffsetY;
pRect->HSplitTop(33, &Handle, 0);
Handle.y += (pRect->h-Handle.h)*Current;
// logic
float ReturnValue = Current;
int Inside = UI()->MouseInside(&Handle);
if(UI()->ActiveItem() == pID)
{
if(!UI()->MouseButton(0))
UI()->SetActiveItem(0);
float Min = pRect->y;
float Max = pRect->h-Handle.h;
float Cur = UI()->MouseY()-OffsetY;
ReturnValue = (Cur-Min)/Max;
if(ReturnValue < 0.0f) ReturnValue = 0.0f;
if(ReturnValue > 1.0f) ReturnValue = 1.0f;
}
else if(UI()->HotItem() == pID)
{
if(UI()->MouseButton(0))
{
UI()->SetActiveItem(pID);
OffsetY = UI()->MouseY()-Handle.y;
}
}
if(Inside)
UI()->SetHotItem(pID);
// render
CUIRect Rail;
pRect->VMargin(5.0f, &Rail);
RenderTools()->DrawUIRect(&Rail, vec4(1,1,1,0.25f), 0, 0.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 = Handle;
Slider.Margin(5.0f, &Slider);
RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f);
return ReturnValue;
}
float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current)
{
CUIRect Handle;
static float OffsetX;
pRect->VSplitLeft(33, &Handle, 0);
Handle.x += (pRect->w-Handle.w)*Current;
// logic
float ReturnValue = Current;
int Inside = UI()->MouseInside(&Handle);
if(UI()->ActiveItem() == pID)
{
if(!UI()->MouseButton(0))
UI()->SetActiveItem(0);
float Min = pRect->x;
float Max = pRect->w-Handle.w;
float Cur = UI()->MouseX()-OffsetX;
ReturnValue = (Cur-Min)/Max;
if(ReturnValue < 0.0f) ReturnValue = 0.0f;
if(ReturnValue > 1.0f) ReturnValue = 1.0f;
}
else if(UI()->HotItem() == pID)
{
if(UI()->MouseButton(0))
{
UI()->SetActiveItem(pID);
OffsetX = UI()->MouseX()-Handle.x;
}
}
if(Inside)
UI()->SetHotItem(pID);
// render
CUIRect Rail;
pRect->HMargin(5.0f, &Rail);
RenderTools()->DrawUIRect(&Rail, vec4(1,1,1,0.25f), 0, 0.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 = Handle;
Slider.Margin(5.0f, &Slider);
RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f);
return ReturnValue;
}
int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key)
{
// process
static void *pGrabbedID = 0;
static bool MouseReleased = true;
static int ButtonUsed = 0;
int Inside = UI()->MouseInside(pRect);
int NewKey = Key;
if(!UI()->MouseButton(0) && !UI()->MouseButton(1) && pGrabbedID == pID)
MouseReleased = true;
if(UI()->ActiveItem() == pID)
{
if(m_Binder.m_GotKey)
{
// abort with escape key
if(m_Binder.m_Key.m_Key != KEY_ESCAPE)
NewKey = m_Binder.m_Key.m_Key;
m_Binder.m_GotKey = false;
UI()->SetActiveItem(0);
MouseReleased = false;
pGrabbedID = pID;
}
if(ButtonUsed == 1 && !UI()->MouseButton(1))
{
if(Inside)
NewKey = 0;
UI()->SetActiveItem(0);
}
}
else if(UI()->HotItem() == pID)
{
if(MouseReleased)
{
if(UI()->MouseButton(0))
{
m_Binder.m_TakeKey = true;
m_Binder.m_GotKey = false;
UI()->SetActiveItem(pID);
ButtonUsed = 0;
}
if(UI()->MouseButton(1))
{
UI()->SetActiveItem(pID);
ButtonUsed = 1;
}
}
}
if(Inside)
UI()->SetHotItem(pID);
// draw
if (UI()->ActiveItem() == pID && ButtonUsed == 0)
DoButton_KeySelect(pID, "???", 0, pRect);
else
{
if(Key == 0)
DoButton_KeySelect(pID, "", 0, pRect);
else
DoButton_KeySelect(pID, Input()->KeyName(Key), 0, pRect);
}
return NewKey;
}
int CMenus::RenderMenubar(CUIRect r)
{
CUIRect Box = r;
CUIRect Button;
m_ActivePage = g_Config.m_UiPage;
int NewPage = -1;
if(Client()->State() != IClient::STATE_OFFLINE)
m_ActivePage = m_GamePage;
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);
}
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))
{
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))
{
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))
{
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))
{
DemolistPopulate();
NewPage = PAGE_DEMOS;
}
}
else
{
// online menus
Box.VSplitLeft(90.0f, &Button, &Box);
static int s_GameButton=0;
if(DoButton_MenuTab(&s_GameButton, Localize("Game"), m_ActivePage==PAGE_GAME, &Button, CUI::CORNER_T))
NewPage = PAGE_GAME;
Box.VSplitLeft(4.0f, 0, &Box);
Box.VSplitLeft(140.0f, &Button, &Box);
static int s_ServerInfoButton=0;
if(DoButton_MenuTab(&s_ServerInfoButton, Localize("Server info"), m_ActivePage==PAGE_SERVER_INFO, &Button, CUI::CORNER_T))
NewPage = PAGE_SERVER_INFO;
Box.VSplitLeft(4.0f, 0, &Box);
Box.VSplitLeft(140.0f, &Button, &Box);
static int s_CallVoteButton=0;
if(DoButton_MenuTab(&s_CallVoteButton, Localize("Call vote"), m_ActivePage==PAGE_CALLVOTE, &Button, CUI::CORNER_T))
NewPage = PAGE_CALLVOTE;
Box.VSplitLeft(4.0f, 0, &Box);
Box.VSplitLeft(min(100.0f, Box.x - 80.0f - 10.0f - 80.0f - 4.0f), &Button, &Box);
static int s_BrowserButton=0;
if (DoButton_MenuTab(&s_BrowserButton, Localize("Browser"), m_ActivePage==PAGE_BROWSER, &Button, CUI::CORNER_T))
NewPage = PAGE_BROWSER;
Box.VSplitLeft(30.0f, 0, &Box);
}
/*
box.VSplitRight(110.0f, &box, &button);
static int system_button=0;
if (UI()->DoButton(&system_button, "System", g_Config.m_UiPage==PAGE_SYSTEM, &button))
g_Config.m_UiPage = PAGE_SYSTEM;
box.VSplitRight(30.0f, &box, 0);
*/
Box.VSplitRight(90.0f, &Box, &Button);
static int s_QuitButton=0;
if(DoButton_MenuTab(&s_QuitButton, Localize("Quit"), 0, &Button, CUI::CORNER_T))
m_Popup = POPUP_QUIT;
Box.VSplitRight(10.0f, &Box, &Button);
Box.VSplitRight(130.0f, &Box, &Button);
static int s_SettingsButton=0;
if(DoButton_MenuTab(&s_SettingsButton, Localize("Settings"), m_ActivePage==PAGE_SETTINGS, &Button, CUI::CORNER_T))
NewPage = PAGE_SETTINGS;
if(NewPage != -1)
{
if(Client()->State() == IClient::STATE_OFFLINE)
g_Config.m_UiPage = NewPage;
else
m_GamePage = NewPage;
}
return 0;
}
void CMenus::RenderLoading(float Percent)
{
static int64 LastLoadRender = 0;
// make sure that we don't render for each little thing we load
// because that will slow down loading if we have vsync
if(time_get()-LastLoadRender < time_freq()/60)
return;
LastLoadRender = time_get();
// need up date this here to get correct
vec3 Rgb = HslToRgb(vec3(g_Config.m_UiColorHue/255.0f, g_Config.m_UiColorSat/255.0f, g_Config.m_UiColorLht/255.0f));
ms_GuiColor = vec4(Rgb.r, Rgb.g, Rgb.b, g_Config.m_UiColorAlpha/255.0f);
CUIRect Screen = *UI()->Screen();
Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
RenderBackground();
float tw;
float w = 700;
float h = 200;
float x = Screen.w/2-w/2;
float y = Screen.h/2-h/2;
Graphics()->BlendNormal();
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
Graphics()->SetColor(0,0,0,0.50f);
RenderTools()->DrawRoundRect(x, y, w, h, 40.0f);
Graphics()->QuadsEnd();
const char *pCaption = Localize("Loading DDRace Client");
tw = TextRender()->TextWidth(0, 48.0f, pCaption, -1);
CUIRect r;
r.x = x;
r.y = y+20;
r.w = w;
r.h = h;
UI()->DoLabel(&r, pCaption, 48.0f, 0, -1);
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
Graphics()->SetColor(1,1,1,0.75f);
RenderTools()->DrawRoundRect(x+40, y+h-75, (w-80)*Percent, 25, 5.0f);
Graphics()->QuadsEnd();
Graphics()->Swap();
}
void CMenus::RenderNews(CUIRect MainView)
{
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
}
void CMenus::OnInit()
{
/*
array<string> my_strings;
array<string>::range r2;
my_strings.add("4");
my_strings.add("6");
my_strings.add("1");
my_strings.add("3");
my_strings.add("7");
my_strings.add("5");
my_strings.add("2");
for(array<string>::range r = my_strings.all(); !r.empty(); r.pop_front())
dbg_msg("", "%s", r.front().cstr());
sort(my_strings.all());
dbg_msg("", "after:");
for(array<string>::range r = my_strings.all(); !r.empty(); r.pop_front())
dbg_msg("", "%s", r.front().cstr());
array<int> myarray;
myarray.add(4);
myarray.add(6);
myarray.add(1);
myarray.add(3);
myarray.add(7);
myarray.add(5);
myarray.add(2);
for(array<int>::range r = myarray.all(); !r.empty(); r.pop_front())
dbg_msg("", "%d", r.front());
sort(myarray.all());
sort_verify(myarray.all());
dbg_msg("", "after:");
for(array<int>::range r = myarray.all(); !r.empty(); r.pop_front())
dbg_msg("", "%d", r.front());
exit(-1);
// */
if(g_Config.m_ClShowWelcome)
m_Popup = POPUP_LANGUAGE;
g_Config.m_ClShowWelcome = 0;
Console()->Chain("add_favorite", ConchainServerbrowserUpdate, this);
}
void CMenus::PopupMessage(const char *pTopic, const char *pBody, const char *pButton)
{
// reset active item
UI()->SetActiveItem(0);
str_copy(m_aMessageTopic, pTopic, sizeof(m_aMessageTopic));
str_copy(m_aMessageBody, pBody, sizeof(m_aMessageBody));
str_copy(m_aMessageButton, pButton, sizeof(m_aMessageButton));
m_Popup = POPUP_MESSAGE;
}
int CMenus::Render()
{
CUIRect Screen = *UI()->Screen();
Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
static bool s_First = true;
if(s_First)
{
if(g_Config.m_UiPage == PAGE_INTERNET)
ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
else if(g_Config.m_UiPage == PAGE_LAN)
ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN);
else if(g_Config.m_UiPage == PAGE_FAVORITES)
ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
s_First = false;
}
if(Client()->State() == IClient::STATE_ONLINE)
{
ms_ColorTabbarInactive = ms_ColorTabbarInactiveIngame;
ms_ColorTabbarActive = ms_ColorTabbarActiveIngame;
}
else
{
RenderBackground();
ms_ColorTabbarInactive = ms_ColorTabbarInactiveOutgame;
ms_ColorTabbarActive = ms_ColorTabbarActiveOutgame;
}
CUIRect TabBar;
CUIRect MainView;
// some margin around the screen
Screen.Margin(10.0f, &Screen);
static bool s_SoundCheck = false;
if(!s_SoundCheck && m_Popup == POPUP_NONE)
{
if(Client()->SoundInitFailed())
m_Popup = POPUP_SOUNDERROR;
s_SoundCheck = true;
}
if(m_Popup == POPUP_NONE)
{
// do tab bar
Screen.HSplitTop(24.0f, &TabBar, &MainView);
TabBar.VMargin(20.0f, &TabBar);
RenderMenubar(TabBar);
// news is not implemented yet
if(g_Config.m_UiPage <= PAGE_NEWS || g_Config.m_UiPage > PAGE_SETTINGS || (Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiPage >= PAGE_GAME && g_Config.m_UiPage <= PAGE_CALLVOTE))
{
ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
g_Config.m_UiPage = PAGE_INTERNET;
}
// render current page
if(Client()->State() != IClient::STATE_OFFLINE)
{
if(m_GamePage == PAGE_GAME)
RenderGame(MainView);
else if(m_GamePage == PAGE_SERVER_INFO)
RenderServerInfo(MainView);
else if(m_GamePage == PAGE_CALLVOTE)
RenderServerControl(MainView);
else if(m_GamePage == PAGE_BROWSER)
RenderInGameBrowser(MainView);
else if(m_GamePage == PAGE_SETTINGS)
RenderSettings(MainView);
}
else if(g_Config.m_UiPage == PAGE_NEWS)
RenderNews(MainView);
else if(g_Config.m_UiPage == PAGE_INTERNET)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_LAN)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_DEMOS)
RenderDemoList(MainView);
else if(g_Config.m_UiPage == PAGE_FAVORITES)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_SETTINGS)
RenderSettings(MainView);
}
else
{
// make sure that other windows doesn't do anything funnay!
//UI()->SetHotItem(0);
//UI()->SetActiveItem(0);
char aBuf[128];
const char *pTitle = "";
const char *pExtraText = "";
const char *pButtonText = "";
int ExtraAlign = 0;
if(m_Popup == POPUP_MESSAGE)
{
pTitle = m_aMessageTopic;
pExtraText = m_aMessageBody;
pButtonText = m_aMessageButton;
}
else if(m_Popup == POPUP_CONNECTING)
{
pTitle = Localize("Connecting to");
pExtraText = g_Config.m_UiServerAddress; // TODO: query the client about the address
pButtonText = Localize("Abort");
if(Client()->MapDownloadTotalsize() > 0)
{
pTitle = Localize("Downloading map");
pExtraText = "";
}
}
else if(m_Popup == POPUP_DISCONNECTED)
{
pTitle = Localize("Disconnected");
pExtraText = Client()->ErrorString();
pButtonText = Localize("Ok");
ExtraAlign = -1;
}
else if(m_Popup == POPUP_PURE)
{
pTitle = Localize("Disconnected");
pExtraText = Localize("The server is running a non-standard tuning on a pure game type.");
pButtonText = Localize("Ok");
ExtraAlign = -1;
}
else if(m_Popup == POPUP_DELETE_DEMO)
{
pTitle = Localize("Delete demo");
pExtraText = Localize("Are you sure that you want to delete the demo?");
ExtraAlign = -1;
}
else if(m_Popup == POPUP_SOUNDERROR)
{
pTitle = Localize("Sound error");
pExtraText = Localize("The audio device couldn't be initialised.");
pButtonText = Localize("Ok");
ExtraAlign = -1;
}
else if(m_Popup == POPUP_PASSWORD)
{
pTitle = Localize("Password incorrect");
pExtraText = "";
pButtonText = Localize("Try again");
}
else if(m_Popup == POPUP_QUIT)
{
pTitle = Localize("Quit");
pExtraText = Localize("Are you sure that you want to quit?");
}
else if(m_Popup == POPUP_FIRST_LAUNCH)
{
pTitle = Localize("Welcome to Teeworlds");
pExtraText = Localize("As this is the first time you launch the game, please enter your nick name below. It's recommended that you check the settings to adjust them to your liking before joining a server.");
pButtonText = Localize("Ok");
ExtraAlign = -1;
}
CUIRect Box, Part;
Box = Screen;
Box.VMargin(150.0f/UI()->Scale(), &Box);
Box.HMargin(150.0f/UI()->Scale(), &Box);
// render the box
RenderTools()->DrawUIRect(&Box, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 15.0f);
Box.HSplitTop(20.f/UI()->Scale(), &Part, &Box);
Box.HSplitTop(24.f/UI()->Scale(), &Part, &Box);
UI()->DoLabelScaled(&Part, pTitle, 24.f, 0);
Box.HSplitTop(20.f/UI()->Scale(), &Part, &Box);
Box.HSplitTop(24.f/UI()->Scale(), &Part, &Box);
Part.VMargin(20.f/UI()->Scale(), &Part);
if(ExtraAlign == -1)
UI()->DoLabelScaled(&Part, pExtraText, 20.f, -1, (int)Part.w);
else
UI()->DoLabelScaled(&Part, pExtraText, 20.f, 0, -1);
if(m_Popup == POPUP_QUIT)
{
CUIRect Yes, No;
Box.HSplitBottom(20.f, &Box, &Part);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VMargin(80.0f, &Part);
Part.VSplitMid(&No, &Yes);
Yes.VMargin(20.0f, &Yes);
No.VMargin(20.0f, &No);
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)
Client()->Quit();
}
else if(m_Popup == POPUP_PASSWORD)
{
CUIRect Label, TextBox, TryAgain, Abort;
Box.HSplitBottom(20.f, &Box, &Part);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VMargin(80.0f, &Part);
Part.VSplitMid(&Abort, &TryAgain);
TryAgain.VMargin(20.0f, &TryAgain);
Abort.VMargin(20.0f, &Abort);
static int s_ButtonAbort = 0;
if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &Abort) || m_EscapePressed)
m_Popup = POPUP_NONE;
static int s_ButtonTryAgain = 0;
if(DoButton_Menu(&s_ButtonTryAgain, Localize("Try again"), 0, &TryAgain) || m_EnterPressed)
{
Client()->Connect(g_Config.m_UiServerAddress);
}
Box.HSplitBottom(60.f, &Box, &Part);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VSplitLeft(60.0f, 0, &Label);
Label.VSplitLeft(100.0f, 0, &TextBox);
TextBox.VSplitLeft(20.0f, 0, &TextBox);
TextBox.VSplitRight(60.0f, &TextBox, 0);
UI()->DoLabel(&Label, Localize("Password"), 18.0f, -1);
static float Offset = 0.0f;
DoEditBox(&g_Config.m_Password, &TextBox, g_Config.m_Password, sizeof(g_Config.m_Password), 12.0f, &Offset, true);
}
else if(m_Popup == POPUP_CONNECTING)
{
Box = Screen;
Box.VMargin(150.0f, &Box);
Box.HMargin(150.0f, &Box);
Box.HSplitBottom(20.f, &Box, &Part);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VMargin(120.0f, &Part);
static int s_Button = 0;
if(DoButton_Menu(&s_Button, pButtonText, 0, &Part) || m_EscapePressed || m_EnterPressed)
{
Client()->Disconnect();
m_Popup = POPUP_NONE;
}
if(Client()->MapDownloadTotalsize() > 0)
{
int64 Now = time_get();
if(Now-m_DownloadLastCheckTime >= time_freq())
{
if(m_DownloadLastCheckSize > Client()->MapDownloadAmount())
{
// map downloaded restarted
m_DownloadLastCheckSize = 0;
}
// update download speed
float Diff = (Client()->MapDownloadAmount()-m_DownloadLastCheckSize)/1024.0f;
m_DownloadSpeed = (m_DownloadSpeed*(1.0f-(1.0f/m_DownloadSpeed))) + (Diff*(1.0f/m_DownloadSpeed));
m_DownloadLastCheckTime = Now;
m_DownloadLastCheckSize = Client()->MapDownloadAmount();
}
Box.HSplitTop(64.f, 0, &Box);
Box.HSplitTop(24.f, &Part, &Box);
str_format(aBuf, sizeof(aBuf), "%d/%d KiB (%.1f KiB/s)", Client()->MapDownloadAmount()/1024, Client()->MapDownloadTotalsize()/1024, m_DownloadSpeed);
UI()->DoLabel(&Part, aBuf, 20.f, 0, -1);
// time left
const char *pTimeLeftString;
int TimeLeft = (Client()->MapDownloadTotalsize()-Client()->MapDownloadAmount())/(m_DownloadSpeed*1024)+1;
if(TimeLeft >= 60)
{
TimeLeft /= 60;
pTimeLeftString = TimeLeft == 1 ? Localize("%i minute left") : Localize("%i minutes left");
}
else
pTimeLeftString = TimeLeft == 1 ? Localize("%i second left") : Localize("%i seconds left");
Box.HSplitTop(20.f, 0, &Box);
Box.HSplitTop(24.f, &Part, &Box);
str_format(aBuf, sizeof(aBuf), pTimeLeftString, TimeLeft);
UI()->DoLabel(&Part, aBuf, 20.f, 0, -1);
// progress bar
Box.HSplitTop(20.f, 0, &Box);
Box.HSplitTop(24.f, &Part, &Box);
Part.VMargin(40.0f, &Part);
RenderTools()->DrawUIRect(&Part, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
Part.w = max(10.0f, (Part.w*Client()->MapDownloadAmount())/Client()->MapDownloadTotalsize());
RenderTools()->DrawUIRect(&Part, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 5.0f);
}
}
else if(m_Popup == POPUP_LANGUAGE)
{
Box = Screen;
Box.VMargin(150.0f, &Box);
Box.HMargin(150.0f, &Box);
Box.HSplitTop(20.f, &Part, &Box);
Box.HSplitBottom(20.f, &Box, &Part);
Box.HSplitBottom(24.f, &Box, &Part);
Box.HSplitBottom(20.f, &Box, 0);
Box.VMargin(20.0f, &Box);
RenderLanguageSelection(Box);
Part.VMargin(120.0f, &Part);
static int s_Button = 0;
if(DoButton_Menu(&s_Button, Localize("Ok"), 0, &Part) || m_EscapePressed || m_EnterPressed)
m_Popup = POPUP_FIRST_LAUNCH;
}
else if(m_Popup == POPUP_DELETE_DEMO)
{
CUIRect Yes, No;
Box.HSplitBottom(20.f, &Box, &Part);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VMargin(80.0f, &Part);
Part.VSplitMid(&No, &Yes);
Yes.VMargin(20.0f, &Yes);
No.VMargin(20.0f, &No);
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)
{
m_Popup = POPUP_NONE;
// delete demo
if(m_DemolistSelectedIndex >= 0 && !m_DemolistSelectedIsDir)
{
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename);
if(Storage()->RemoveFile(aBuf, m_lDemos[m_DemolistSelectedIndex].m_StorageType))
{
DemolistPopulate();
DemolistOnUpdate(false);
}
else
PopupMessage(Localize("Error"), Localize("Unable to delete the demo"), Localize("Ok"));
}
}
}
else if(m_Popup == POPUP_FIRST_LAUNCH)
{
CUIRect Label, TextBox;
Box.HSplitBottom(20.f, &Box, &Part);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VMargin(80.0f, &Part);
static int s_EnterButton = 0;
if(DoButton_Menu(&s_EnterButton, Localize("Enter"), 0, &Part) || m_EnterPressed)
m_Popup = POPUP_NONE;
Box.HSplitBottom(40.f, &Box, &Part);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VSplitLeft(60.0f, 0, &Label);
Label.VSplitLeft(100.0f, 0, &TextBox);
TextBox.VSplitLeft(20.0f, 0, &TextBox);
TextBox.VSplitRight(60.0f, &TextBox, 0);
UI()->DoLabel(&Label, Localize("Nickname"), 18.0f, -1);
static float Offset = 0.0f;
DoEditBox(&g_Config.m_PlayerName, &TextBox, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 12.0f, &Offset);
}
else
{
Box.HSplitBottom(20.f, &Box, &Part);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VMargin(120.0f, &Part);
static int s_Button = 0;
if(DoButton_Menu(&s_Button, pButtonText, 0, &Part) || m_EscapePressed || m_EnterPressed)
m_Popup = POPUP_NONE;
}
}
return 0;
}
void CMenus::SetActive(bool Active)
{
m_MenuActive = Active;
if(!m_MenuActive)
{
if(m_NeedSendinfo)
{
m_pClient->SendInfo(false);
m_NeedSendinfo = false;
}
if(Client()->State() == IClient::STATE_ONLINE)
{
m_pClient->OnRelease();
}
}
else if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
m_pClient->OnRelease();
}
}
void CMenus::OnReset()
{
}
bool CMenus::OnMouseMove(float x, float y)
{
m_LastInput = time_get();
if(!m_MenuActive)
return false;
m_MousePos.x += x;
m_MousePos.y += y;
if(m_MousePos.x < 0) m_MousePos.x = 0;
if(m_MousePos.y < 0) m_MousePos.y = 0;
if(m_MousePos.x > Graphics()->ScreenWidth()) m_MousePos.x = Graphics()->ScreenWidth();
if(m_MousePos.y > Graphics()->ScreenHeight()) m_MousePos.y = Graphics()->ScreenHeight();
return true;
}
bool CMenus::OnInput(IInput::CEvent e)
{
m_LastInput = time_get();
// special handle esc and enter for popup purposes
if(e.m_Flags&IInput::FLAG_PRESS)
{
if(e.m_Key == KEY_ESCAPE)
{
m_EscapePressed = true;
SetActive(!IsActive());
return true;
}
}
if(IsActive())
{
if(e.m_Flags&IInput::FLAG_PRESS)
{
// special for popups
if(e.m_Key == KEY_RETURN || e.m_Key == KEY_KP_ENTER)
m_EnterPressed = true;
else if(e.m_Key == KEY_DELETE)
m_DeletePressed = true;
}
if(m_NumInputEvents < MAX_INPUTEVENTS)
m_aInputEvents[m_NumInputEvents++] = e;
return true;
}
return false;
}
void CMenus::OnStateChange(int NewState, int OldState)
{
// reset active item
UI()->SetActiveItem(0);
if(NewState == IClient::STATE_OFFLINE)
{
m_Popup = POPUP_NONE;
if(Client()->ErrorString() && Client()->ErrorString()[0] != 0)
{
if(str_find(Client()->ErrorString(), "password"))
{
m_Popup = POPUP_PASSWORD;
UI()->SetHotItem(&g_Config.m_Password);
UI()->SetActiveItem(&g_Config.m_Password);
}
else
m_Popup = POPUP_DISCONNECTED;
}
}
else if(NewState == IClient::STATE_LOADING)
{
m_Popup = POPUP_CONNECTING;
m_DownloadLastCheckTime = time_get();
m_DownloadLastCheckSize = 0;
m_DownloadSpeed = 1.0f;
//client_serverinfo_request();
}
else if(NewState == IClient::STATE_CONNECTING)
m_Popup = POPUP_CONNECTING;
else if (NewState == IClient::STATE_ONLINE || NewState == IClient::STATE_DEMOPLAYBACK)
{
m_Popup = POPUP_NONE;
SetActive(false);
}
}
extern "C" void font_debug_render();
void CMenus::OnRender()
{
/*
// text rendering test stuff
render_background();
CTextCursor cursor;
TextRender()->SetCursor(&cursor, 10, 10, 20, TEXTFLAG_RENDER);
TextRender()->TextEx(&cursor, "ãˆã<CB86>†ã<E280A0>“ã<E2809C><C3A3> - ガイド", -1);
TextRender()->SetCursor(&cursor, 10, 30, 15, TEXTFLAG_RENDER);
TextRender()->TextEx(&cursor, "ãˆã<CB86>†ã<E280A0>“ã<E2809C><C3A3> - ガイド", -1);
//Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
Graphics()->QuadsDrawTL(60, 60, 5000, 5000);
Graphics()->QuadsEnd();
return;*/
if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
SetActive(true);
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
CUIRect Screen = *UI()->Screen();
Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
RenderDemoPlayer(Screen);
}
if(Client()->State() == IClient::STATE_ONLINE && m_pClient->m_ServerMode == m_pClient->SERVERMODE_PUREMOD)
{
Client()->Disconnect();
SetActive(true);
m_Popup = POPUP_PURE;
}
if(!IsActive())
{
m_EscapePressed = false;
m_EnterPressed = false;
m_DeletePressed = false;
m_NumInputEvents = 0;
return;
}
// update colors
vec3 Rgb = HslToRgb(vec3(g_Config.m_UiColorHue/255.0f, g_Config.m_UiColorSat/255.0f, g_Config.m_UiColorLht/255.0f));
ms_GuiColor = vec4(Rgb.r, Rgb.g, Rgb.b, g_Config.m_UiColorAlpha/255.0f);
ms_ColorTabbarInactiveOutgame = vec4(0,0,0,0.25f);
ms_ColorTabbarActiveOutgame = vec4(0,0,0,0.5f);
float ColorIngameScaleI = 0.5f;
float ColorIngameAcaleA = 0.2f;
ms_ColorTabbarInactiveIngame = vec4(
ms_GuiColor.r*ColorIngameScaleI,
ms_GuiColor.g*ColorIngameScaleI,
ms_GuiColor.b*ColorIngameScaleI,
ms_GuiColor.a*0.8f);
ms_ColorTabbarActiveIngame = vec4(
ms_GuiColor.r*ColorIngameAcaleA,
ms_GuiColor.g*ColorIngameAcaleA,
ms_GuiColor.b*ColorIngameAcaleA,
ms_GuiColor.a);
// update the ui
CUIRect *pScreen = UI()->Screen();
float mx = (m_MousePos.x/(float)Graphics()->ScreenWidth())*pScreen->w;
float my = (m_MousePos.y/(float)Graphics()->ScreenHeight())*pScreen->h;
int Buttons = 0;
if(m_UseMouseButtons)
{
if(Input()->KeyPressed(KEY_MOUSE_1)) Buttons |= 1;
if(Input()->KeyPressed(KEY_MOUSE_2)) Buttons |= 2;
if(Input()->KeyPressed(KEY_MOUSE_3)) Buttons |= 4;
}
UI()->Update(mx,my,mx*3.0f,my*3.0f,Buttons);
// render
if(Client()->State() != IClient::STATE_DEMOPLAYBACK)
Render();
// render cursor
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id);
Graphics()->QuadsBegin();
Graphics()->SetColor(1,1,1,1);
IGraphics::CQuadItem QuadItem(mx, my, 24, 24);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
// render debug information
if(g_Config.m_Debug)
{
CUIRect Screen = *UI()->Screen();
Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "%p %p %p", UI()->HotItem(), UI()->ActiveItem(), UI()->LastActiveItem());
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, 10, 10, 10, TEXTFLAG_RENDER);
TextRender()->TextEx(&Cursor, aBuf, -1);
}
m_EscapePressed = false;
m_EnterPressed = false;
m_DeletePressed = false;
m_NumInputEvents = 0;
}
static int gs_TextureBlob = -1;
void CMenus::RenderBackground()
{
//Graphics()->Clear(1,1,1);
//render_sunrays(0,0);
if(gs_TextureBlob == -1)
gs_TextureBlob = Graphics()->LoadTexture("blob.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0);
float sw = 300*Graphics()->ScreenAspect();
float sh = 300;
Graphics()->MapScreen(0, 0, sw, sh);
// render background color
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
//vec4 bottom(gui_color.r*0.3f, gui_color.g*0.3f, gui_color.b*0.3f, 1.0f);
//vec4 bottom(0, 0, 0, 1.0f);
vec4 Bottom(ms_GuiColor.r, ms_GuiColor.g, ms_GuiColor.b, 1.0f);
vec4 Top(ms_GuiColor.r, ms_GuiColor.g, ms_GuiColor.b, 1.0f);
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex(0, Top.r, Top.g, Top.b, Top.a),
IGraphics::CColorVertex(1, Top.r, Top.g, Top.b, Top.a),
IGraphics::CColorVertex(2, Bottom.r, Bottom.g, Bottom.b, Bottom.a),
IGraphics::CColorVertex(3, Bottom.r, Bottom.g, Bottom.b, Bottom.a)};
Graphics()->SetColorVertex(Array, 4);
IGraphics::CQuadItem QuadItem(0, 0, sw, sh);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
// render the tiles
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
float Size = 15.0f;
float OffsetTime = fmod(Client()->LocalTime()*0.15f, 2.0f);
for(int y = -2; y < (int)(sw/Size); y++)
for(int x = -2; x < (int)(sh/Size); x++)
{
Graphics()->SetColor(0,0,0,0.045f);
IGraphics::CQuadItem QuadItem((x-OffsetTime)*Size*2+(y&1)*Size, (y+OffsetTime)*Size, Size, Size);
Graphics()->QuadsDrawTL(&QuadItem, 1);
}
Graphics()->QuadsEnd();
// render border fade
Graphics()->TextureSet(gs_TextureBlob);
Graphics()->QuadsBegin();
Graphics()->SetColor(0,0,0,0.5f);
QuadItem = IGraphics::CQuadItem(-100, -100, sw+200, sh+200);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
// restore screen
{CUIRect Screen = *UI()->Screen();
Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);}
}