2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <base/math.h>
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/demo.h>
|
|
|
|
#include <engine/keys.h>
|
2010-07-27 20:25:36 +00:00
|
|
|
#include <engine/graphics.h>
|
2010-09-06 19:36:39 +00:00
|
|
|
#include <engine/textrender.h>
|
2010-09-03 18:05:22 +00:00
|
|
|
#include <engine/storage.h>
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/client/render.h>
|
|
|
|
#include <game/client/gameclient.h>
|
|
|
|
#include <game/localization.h>
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/client/ui.h>
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-07-27 20:25:36 +00:00
|
|
|
#include <game/generated/client_data.h>
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "menus.h"
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int CMenus::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawUIRect(pRect, vec4(1,1,1, Checked ? 0.10f : 0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f);
|
2009-10-27 14:38:53 +00:00
|
|
|
UI()->DoLabel(pRect, pText, 14.0f, 0);
|
|
|
|
return UI()->DoButtonLogic(pID, pText, Checked, pRect);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
2010-08-16 02:12:03 +00:00
|
|
|
int CMenus::DoButton_DemoPlayer_Sprite(const void *pID, int SpriteId, int Checked, const CUIRect *pRect)
|
2010-07-27 20:25:36 +00:00
|
|
|
{
|
|
|
|
RenderTools()->DrawUIRect(pRect, vec4(1,1,1, Checked ? 0.10f : 0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f);
|
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_DEMOBUTTONS].m_Id);
|
|
|
|
Graphics()->QuadsBegin();
|
2010-08-16 02:12:03 +00:00
|
|
|
RenderTools()->SelectSprite(SpriteId);
|
2010-07-27 20:25:36 +00:00
|
|
|
IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h);
|
|
|
|
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
|
|
|
|
return UI()->DoButtonLogic(pID, "", Checked, pRect);
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CMenus::RenderDemoPlayer(CUIRect MainView)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
const float SeekBarHeight = 15.0f;
|
|
|
|
const float ButtonbarHeight = 20.0f;
|
2010-09-06 19:36:39 +00:00
|
|
|
const float NameBarHeight = 20.0f;
|
2010-05-29 07:25:38 +00:00
|
|
|
const float Margins = 5.0f;
|
|
|
|
float TotalHeight;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_MenuActive)
|
2010-09-06 19:36:39 +00:00
|
|
|
TotalHeight = SeekBarHeight+ButtonbarHeight+NameBarHeight+Margins*3;
|
2008-10-06 18:05:01 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
TotalHeight = SeekBarHeight+Margins*2;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
MainView.HSplitBottom(TotalHeight, 0, &MainView);
|
|
|
|
MainView.VSplitLeft(250.0f, 0, &MainView);
|
|
|
|
MainView.VSplitRight(250.0f, &MainView, 0);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_T, 10.0f);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
MainView.Margin(5.0f, &MainView);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-09-06 19:36:39 +00:00
|
|
|
CUIRect SeekBar, ButtonBar, NameBar;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-09-03 20:30:46 +00:00
|
|
|
int CurrentTick = pInfo->m_CurrentTick - pInfo->m_FirstTick;
|
|
|
|
int TotalTicks = pInfo->m_LastTick - pInfo->m_FirstTick;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_MenuActive)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
|
|
|
|
ButtonBar.HSplitTop(Margins, 0, &ButtonBar);
|
2010-09-06 19:36:39 +00:00
|
|
|
ButtonBar.HSplitBottom(NameBarHeight, &ButtonBar, &NameBar);
|
2010-09-07 17:31:20 +00:00
|
|
|
NameBar.HSplitTop(4.0f, 0, &NameBar);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
SeekBar = MainView;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// do seekbar
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_SeekBarId = 0;
|
|
|
|
void *id = &s_SeekBarId;
|
|
|
|
char aBuffer[128];
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
float Amount = CurrentTick/(float)TotalTicks;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CUIRect FilledBar = SeekBar;
|
|
|
|
FilledBar.w = 10.0f + (FilledBar.w-10.0f)*Amount;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
str_format(aBuffer, sizeof(aBuffer), "%d:%02d / %d:%02d",
|
|
|
|
CurrentTick/SERVER_TICK_SPEED/60, (CurrentTick/SERVER_TICK_SPEED)%60,
|
|
|
|
TotalTicks/SERVER_TICK_SPEED/60, (TotalTicks/SERVER_TICK_SPEED)%60);
|
|
|
|
UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h*0.70f, 0);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// do the logic
|
2010-05-29 07:25:38 +00:00
|
|
|
int Inside = UI()->MouseInside(&SeekBar);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
if(UI()->ActiveItem() == id)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2009-10-27 14:38:53 +00:00
|
|
|
if(!UI()->MouseButton(0))
|
|
|
|
UI()->SetActiveItem(0);
|
2008-10-06 18:05:01 +00:00
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
static float PrevAmount = 0.0f;
|
|
|
|
float Amount = (UI()->MouseX()-SeekBar.x)/(float)SeekBar.w;
|
|
|
|
if(Amount > 0 && Amount < 1.0f && PrevAmount != Amount)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
PrevAmount = Amount;
|
|
|
|
m_pClient->OnReset();
|
|
|
|
m_pClient->m_SuppressEvents = true;
|
|
|
|
DemoPlayer()->SetPos(Amount);
|
|
|
|
m_pClient->m_SuppressEvents = false;
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-10-27 14:38:53 +00:00
|
|
|
else if(UI()->HotItem() == id)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2009-10-27 14:38:53 +00:00
|
|
|
if(UI()->MouseButton(0))
|
|
|
|
UI()->SetActiveItem(id);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Inside)
|
2009-10-27 14:38:53 +00:00
|
|
|
UI()->SetHotItem(id);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
2010-09-03 20:30:46 +00:00
|
|
|
|
|
|
|
if(CurrentTick == TotalTicks)
|
|
|
|
{
|
|
|
|
DemoPlayer()->Pause();
|
|
|
|
DemoPlayer()->SetPos(0);
|
|
|
|
}
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_MenuActive)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
|
|
|
// do buttons
|
2010-05-29 07:25:38 +00:00
|
|
|
CUIRect Button;
|
2010-07-27 20:25:36 +00:00
|
|
|
|
|
|
|
// combined play and pause button
|
2010-05-29 07:25:38 +00:00
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
2010-07-27 20:25:36 +00:00
|
|
|
static int s_PlayPauseButton = 0;
|
|
|
|
if(!pInfo->m_Paused)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2010-07-27 20:25:36 +00:00
|
|
|
if(DoButton_DemoPlayer_Sprite(&s_PlayPauseButton, SPRITE_DEMOBUTTON_PAUSE, pInfo->m_Paused, &Button))
|
2010-05-29 07:25:38 +00:00
|
|
|
DemoPlayer()->Pause();
|
|
|
|
}
|
2010-07-27 20:25:36 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if(DoButton_DemoPlayer_Sprite(&s_PlayPauseButton, SPRITE_DEMOBUTTON_PLAY, !pInfo->m_Paused, &Button))
|
2010-08-16 02:12:03 +00:00
|
|
|
DemoPlayer()->Unpause();
|
2010-07-27 20:25:36 +00:00
|
|
|
}
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-09-03 20:30:46 +00:00
|
|
|
// stop button
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
2010-07-27 20:25:36 +00:00
|
|
|
static int s_ResetButton = 0;
|
2010-09-03 20:30:46 +00:00
|
|
|
if(DoButton_DemoPlayer_Sprite(&s_ResetButton, SPRITE_DEMOBUTTON_STOP, false, &Button))
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-09-03 20:30:46 +00:00
|
|
|
DemoPlayer()->Pause();
|
2010-07-27 20:25:36 +00:00
|
|
|
DemoPlayer()->SetPos(0);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// slowdown
|
2010-05-29 07:25:38 +00:00
|
|
|
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
|
|
|
static int s_SlowDownButton = 0;
|
2010-07-27 20:25:36 +00:00
|
|
|
if(DoButton_DemoPlayer_Sprite(&s_SlowDownButton, SPRITE_DEMOBUTTON_SLOWER, 0, &Button))
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pInfo->m_Speed > 4.0f) DemoPlayer()->SetSpeed(4.0f);
|
|
|
|
else if(pInfo->m_Speed > 2.0f) DemoPlayer()->SetSpeed(2.0f);
|
|
|
|
else if(pInfo->m_Speed > 1.0f) DemoPlayer()->SetSpeed(1.0f);
|
|
|
|
else if(pInfo->m_Speed > 0.5f) DemoPlayer()->SetSpeed(0.5f);
|
|
|
|
else DemoPlayer()->SetSpeed(0.05f);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// fastforward
|
2010-05-29 07:25:38 +00:00
|
|
|
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
|
|
|
static int s_FastForwardButton = 0;
|
2010-07-27 20:25:36 +00:00
|
|
|
if(DoButton_DemoPlayer_Sprite(&s_FastForwardButton, SPRITE_DEMOBUTTON_FASTER, 0, &Button))
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pInfo->m_Speed < 0.5f) DemoPlayer()->SetSpeed(0.5f);
|
|
|
|
else if(pInfo->m_Speed < 1.0f) DemoPlayer()->SetSpeed(1.0f);
|
|
|
|
else if(pInfo->m_Speed < 2.0f) DemoPlayer()->SetSpeed(2.0f);
|
|
|
|
else if(pInfo->m_Speed < 4.0f) DemoPlayer()->SetSpeed(4.0f);
|
|
|
|
else DemoPlayer()->SetSpeed(8.0f);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// speed meter
|
2010-05-29 07:25:38 +00:00
|
|
|
ButtonBar.VSplitLeft(Margins*3, 0, &ButtonBar);
|
|
|
|
char aBuffer[64];
|
|
|
|
if(pInfo->m_Speed >= 1.0f)
|
|
|
|
str_format(aBuffer, sizeof(aBuffer), "x%.0f", pInfo->m_Speed);
|
2008-10-06 18:05:01 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
str_format(aBuffer, sizeof(aBuffer), "x%.1f", pInfo->m_Speed);
|
|
|
|
UI()->DoLabel(&ButtonBar, aBuffer, Button.h*0.7f, -1);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2009-06-15 07:34:25 +00:00
|
|
|
// close button
|
2010-05-29 07:25:38 +00:00
|
|
|
ButtonBar.VSplitRight(ButtonbarHeight*3, &ButtonBar, &Button);
|
|
|
|
static int s_ExitButton = 0;
|
|
|
|
if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), 0, &Button))
|
|
|
|
Client()->Disconnect();
|
2010-09-06 19:36:39 +00:00
|
|
|
|
|
|
|
// demo name
|
|
|
|
char aBuf[128];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "Demofile: %s", DemoPlayer()->GetDemoName());
|
|
|
|
CTextCursor Cursor;
|
2010-09-07 17:31:20 +00:00
|
|
|
TextRender()->SetCursor(&Cursor, NameBar.x, NameBar.y, Button.h*0.5f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
|
|
|
|
Cursor.m_LineWidth = MainView.w;
|
2010-09-06 19:36:39 +00:00
|
|
|
TextRender()->TextEx(&Cursor, aBuf, -1);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
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(void *pId, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems,
|
|
|
|
int ItemsPerRow, int SelectedIndex, float ScrollValue)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CUIRect Scroll, Row;
|
|
|
|
CUIRect View = *pRect;
|
|
|
|
CUIRect Header, Footer;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// draw header
|
2010-05-29 07:25:38 +00:00
|
|
|
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);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// draw footers
|
2010-05-29 07:25:38 +00:00
|
|
|
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);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// background
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.15f), 0, 0);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// prepare the scroll
|
2010-05-29 07:25:38 +00:00
|
|
|
View.VSplitRight(15, &View, &Scroll);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// setup the variables
|
2010-05-29 07:25:38 +00:00
|
|
|
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;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// do the scrollbar
|
2010-05-29 07:25:38 +00:00
|
|
|
View.HSplitTop(gs_ListBoxRowHeight, &Row, 0);
|
2009-06-15 10:12:16 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
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))
|
|
|
|
gs_ListBoxScrollValue -= 1.0f/Num;
|
|
|
|
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
|
|
|
|
gs_ListBoxScrollValue += 1.0f/Num;
|
2009-06-15 10:12:16 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
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);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// the list
|
2010-05-29 07:25:38 +00:00
|
|
|
gs_ListBoxView = gs_ListBoxOriginalView;
|
|
|
|
gs_ListBoxView.VMargin(5.0f, &gs_ListBoxView);
|
|
|
|
UI()->ClipEnable(&gs_ListBoxView);
|
|
|
|
gs_ListBoxView.y -= gs_ListBoxScrollValue*Num*Row.h;
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CMenus::CListboxItem CMenus::UiDoListboxNextRow()
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
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), &Item.m_Rect, &s_RowView);
|
|
|
|
|
|
|
|
Item.m_Visible = 1;
|
2009-10-27 14:38:53 +00:00
|
|
|
//item.rect = row;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Item.m_HitRect = Item.m_Rect;
|
2009-10-27 14:38:53 +00:00
|
|
|
|
|
|
|
//CUIRect select_hit_box = item.rect;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(gs_ListBoxSelectedIndex == gs_ListBoxItemIndex)
|
|
|
|
Item.m_Selected = 1;
|
2009-10-27 14:38:53 +00:00
|
|
|
|
|
|
|
// make sure that only those in view can be selected
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Item.m_Rect.y+Item.m_Rect.h > gs_ListBoxOriginalView.y)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Item.m_HitRect.y < Item.m_HitRect.y) // clip the selection
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Item.m_HitRect.h -= gs_ListBoxOriginalView.y-Item.m_HitRect.y;
|
|
|
|
Item.m_HitRect.y = gs_ListBoxOriginalView.y;
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
Item.m_Visible = 0;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
// check if we need to do more
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Item.m_Rect.y > gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h)
|
|
|
|
Item.m_Visible = 0;
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
gs_ListBoxItemIndex++;
|
|
|
|
return Item;
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CMenus::CListboxItem CMenus::UiDoListboxNextItem(void *pId, bool Selected)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int ThisItemIndex = gs_ListBoxItemIndex;
|
|
|
|
if(Selected)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(gs_ListBoxSelectedIndex == gs_ListBoxNewSelected)
|
|
|
|
gs_ListBoxNewSelected = ThisItemIndex;
|
|
|
|
gs_ListBoxSelectedIndex = ThisItemIndex;
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CListboxItem Item = UiDoListboxNextRow();
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
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)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!gs_ListBoxDoneEvents)
|
2009-06-15 14:01:36 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
gs_ListBoxDoneEvents = 1;
|
|
|
|
|
|
|
|
if(m_EnterPressed || (Input()->MouseDoubleClick() && UI()->ActiveItem() == pId))
|
2009-06-15 14:01:36 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
gs_ListBoxItemActivated = true;
|
2010-09-03 17:39:20 +00:00
|
|
|
UI()->SetActiveItem(0);
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for(int i = 0; i < m_NumInputEvents; i++)
|
2009-06-15 14:01:36 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
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
|
|
|
|
int NumViewable = (int)(gs_ListBoxOriginalView.h/gs_ListBoxRowHeight) + 1;
|
|
|
|
int ScrollNum = (gs_ListBoxNumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1;
|
|
|
|
if(ScrollNum > 0 && NewIndex/gs_ListBoxItemsPerRow-gs_ListBoxSelectedIndex/gs_ListBoxItemsPerRow)
|
|
|
|
{
|
|
|
|
// TODO: make the scrolling better
|
|
|
|
if(NewIndex - gs_ListBoxSelectedIndex > 0)
|
|
|
|
gs_ListBoxScrollValue += 1.0f/ScrollNum;
|
|
|
|
else
|
|
|
|
gs_ListBoxScrollValue -= 1.0f/ScrollNum;
|
|
|
|
if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f;
|
|
|
|
if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
gs_ListBoxNewSelected = NewIndex;
|
|
|
|
}
|
2009-06-15 14:01:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-06 18:05:01 +00:00
|
|
|
//selected_index = i;
|
2010-05-29 07:25:38 +00:00
|
|
|
CUIRect r = Item.m_Rect;
|
2009-10-27 14:38:53 +00:00
|
|
|
r.Margin(1.5f, &r);
|
|
|
|
RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
return Item;
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int CMenus::UiDoListboxEnd(float *pScrollValue, bool *pItemActivated)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2009-10-27 14:38:53 +00:00
|
|
|
UI()->ClipDisable();
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pScrollValue)
|
|
|
|
*pScrollValue = gs_ListBoxScrollValue;
|
|
|
|
if(pItemActivated)
|
|
|
|
*pItemActivated = gs_ListBoxItemActivated;
|
|
|
|
return gs_ListBoxNewSelected;
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct FETCH_CALLBACKINFO
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CMenus *m_pSelf;
|
|
|
|
const char *m_pPrefix;
|
2008-10-06 18:05:01 +00:00
|
|
|
};
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CMenus::DemolistFetchCallback(const char *pName, int IsDir, void *pUser)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-06-07 09:27:16 +00:00
|
|
|
if(pName[0] == '.')
|
2008-10-06 18:05:01 +00:00
|
|
|
return;
|
2010-06-07 09:27:16 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
FETCH_CALLBACKINFO *pInfo = (FETCH_CALLBACKINFO *)pUser;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CDemoItem Item;
|
|
|
|
str_format(Item.m_aFilename, sizeof(Item.m_aFilename), "%s/%s", pInfo->m_pPrefix, pName);
|
|
|
|
str_copy(Item.m_aName, pName, sizeof(Item.m_aName));
|
|
|
|
pInfo->m_pSelf->m_lDemos.add(Item);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CMenus::DemolistPopulate()
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_lDemos.clear();
|
2009-06-15 10:12:16 +00:00
|
|
|
|
2010-06-04 20:14:02 +00:00
|
|
|
|
2010-09-03 19:41:37 +00:00
|
|
|
if(str_comp(m_aCurrentDemoFolder, "demos") != 0) //add parent folder
|
2010-06-04 20:14:02 +00:00
|
|
|
{
|
|
|
|
CDemoItem Item;
|
|
|
|
str_copy(Item.m_aName, "..", sizeof(Item.m_aName));
|
|
|
|
str_copy(Item.m_aFilename, "..", sizeof(Item.m_aFilename));
|
|
|
|
m_lDemos.add(Item);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
char aBuf[512];
|
2010-06-04 20:14:02 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "%s/%s", Client()->UserDirectory(), m_aCurrentDemoFolder);
|
|
|
|
|
2010-09-03 19:41:37 +00:00
|
|
|
FETCH_CALLBACKINFO Info = {this, aBuf};
|
2010-05-29 07:25:38 +00:00
|
|
|
fs_listdir(aBuf, DemolistFetchCallback, &Info);
|
2010-06-04 20:14:02 +00:00
|
|
|
Info.m_pPrefix = m_aCurrentDemoFolder;
|
|
|
|
fs_listdir(m_aCurrentDemoFolder, DemolistFetchCallback, &Info);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CMenus::RenderDemoList(CUIRect MainView)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-09-05 12:28:08 +00:00
|
|
|
static int s_SelectedItem = -1;
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_Inited = 0;
|
|
|
|
if(!s_Inited)
|
2010-09-05 12:28:08 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
DemolistPopulate();
|
2010-09-05 12:28:08 +00:00
|
|
|
s_Inited = 1;
|
|
|
|
if(m_lDemos.size() > 0)
|
|
|
|
s_SelectedItem = 0;
|
|
|
|
}
|
2010-09-05 15:53:31 +00:00
|
|
|
|
2010-09-05 17:06:27 +00:00
|
|
|
bool IsDir = false;
|
|
|
|
if(s_SelectedItem >= 0 && s_SelectedItem < m_lDemos.size())
|
|
|
|
{
|
|
|
|
if(str_comp(m_lDemos[s_SelectedItem].m_aName, "..") == 0 || fs_is_dir(m_lDemos[s_SelectedItem].m_aFilename))
|
|
|
|
IsDir = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// delete demo
|
|
|
|
if(m_DemolistDelEntry)
|
|
|
|
{
|
|
|
|
if(s_SelectedItem >= 0 && s_SelectedItem < m_lDemos.size() && !IsDir)
|
|
|
|
{
|
|
|
|
Storage()->RemoveFile(m_lDemos[s_SelectedItem].m_aFilename);
|
|
|
|
DemolistPopulate();
|
|
|
|
s_SelectedItem = s_SelectedItem-1 < 0 ? m_lDemos.size() > 0 ? 0 : -1 : s_SelectedItem-1;
|
|
|
|
}
|
|
|
|
m_DemolistDelEntry = false;
|
2010-09-05 15:53:31 +00:00
|
|
|
}
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// render background
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
|
|
|
|
MainView.Margin(10.0f, &MainView);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CUIRect ButtonBar;
|
|
|
|
MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar);
|
|
|
|
ButtonBar.HSplitTop(5.0f, 0, &ButtonBar);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_DemoListId = 0;
|
|
|
|
static float s_ScrollValue = 0;
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
UiDoListboxStart(&s_DemoListId, &MainView, 17.0f, Localize("Demos"), "", m_lDemos.size(), 1, s_SelectedItem, s_ScrollValue);
|
2009-06-15 10:12:16 +00:00
|
|
|
//for(int i = 0; i < num_demos; i++)
|
2010-05-29 07:25:38 +00:00
|
|
|
for(sorted_array<CDemoItem>::range r = m_lDemos.all(); !r.empty(); r.pop_front())
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CListboxItem Item = UiDoListboxNextItem((void*)(&r.front()));
|
|
|
|
if(Item.m_Visible)
|
|
|
|
UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight, -1);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
bool Activated = false;
|
|
|
|
s_SelectedItem = UiDoListboxEnd(&s_ScrollValue, &Activated);
|
2008-11-17 16:46:21 +00:00
|
|
|
|
2010-09-03 18:05:22 +00:00
|
|
|
CUIRect RefreshRect, PlayRect, DeleteRect;
|
|
|
|
ButtonBar.VSplitRight(130.0f, &ButtonBar, &PlayRect);
|
|
|
|
ButtonBar.VSplitLeft(130.0f, &RefreshRect, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(10.0f, &DeleteRect, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(120.0f, &DeleteRect, &ButtonBar);
|
2008-11-17 16:46:21 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_RefreshButton = 0;
|
|
|
|
if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect))
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
DemolistPopulate();
|
|
|
|
}
|
2010-06-04 20:14:02 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_PlayButton = 0;
|
2010-06-10 20:26:39 +00:00
|
|
|
char aTitleButton[10];
|
2010-06-04 20:14:02 +00:00
|
|
|
if(IsDir)
|
2010-06-10 20:26:39 +00:00
|
|
|
str_copy(aTitleButton, Localize("Open"), sizeof(aTitleButton));
|
2010-06-04 20:14:02 +00:00
|
|
|
else
|
2010-06-10 20:26:39 +00:00
|
|
|
str_copy(aTitleButton, Localize("Play"), sizeof(aTitleButton));
|
|
|
|
|
|
|
|
if(DoButton_Menu(&s_PlayButton, aTitleButton, 0, &PlayRect) || Activated)
|
2010-09-03 19:41:37 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(s_SelectedItem >= 0 && s_SelectedItem < m_lDemos.size())
|
2009-06-15 13:16:33 +00:00
|
|
|
{
|
2010-09-03 19:41:37 +00:00
|
|
|
if(str_comp(m_lDemos[s_SelectedItem].m_aName, "..") == 0) //parent folder
|
2010-06-04 20:14:02 +00:00
|
|
|
{
|
|
|
|
DemoSetParentDirectory();
|
|
|
|
DemolistPopulate();
|
2010-09-05 12:28:08 +00:00
|
|
|
s_SelectedItem = m_lDemos.size() > 0 ? 0 : -1;
|
2010-06-04 20:14:02 +00:00
|
|
|
}
|
2010-09-03 19:41:37 +00:00
|
|
|
else if(IsDir) //folder
|
2010-06-04 20:14:02 +00:00
|
|
|
{
|
2010-09-03 19:41:37 +00:00
|
|
|
char aTemp[256];
|
|
|
|
str_copy(aTemp, m_aCurrentDemoFolder, sizeof(aTemp));
|
|
|
|
str_format(m_aCurrentDemoFolder, sizeof(m_aCurrentDemoFolder), "%s/%s", aTemp, m_lDemos[s_SelectedItem].m_aName);
|
2010-06-04 20:14:02 +00:00
|
|
|
DemolistPopulate();
|
2010-09-05 12:28:08 +00:00
|
|
|
s_SelectedItem = m_lDemos.size() > 0 ? 0 : -1;
|
2010-06-04 20:14:02 +00:00
|
|
|
}
|
2010-09-03 19:41:37 +00:00
|
|
|
else //file
|
2010-06-04 20:14:02 +00:00
|
|
|
{
|
|
|
|
const char *pError = Client()->DemoPlayer_Play(m_lDemos[s_SelectedItem].m_aFilename);
|
|
|
|
if(pError)
|
2010-08-08 22:35:37 +00:00
|
|
|
PopupMessage(Localize("Error"), str_comp(pError, "error loading demo") ? pError : Localize("error loading demo"), Localize("Ok"));
|
2010-09-08 00:27:48 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
UI()->SetActiveItem(0);
|
|
|
|
return;
|
|
|
|
}
|
2010-06-04 20:14:02 +00:00
|
|
|
}
|
2009-06-15 13:16:33 +00:00
|
|
|
}
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
2008-11-17 16:46:21 +00:00
|
|
|
|
2010-09-05 15:53:31 +00:00
|
|
|
if(!IsDir)
|
2010-09-03 18:05:22 +00:00
|
|
|
{
|
2010-09-05 15:53:31 +00:00
|
|
|
static int s_DeleteButton = 0;
|
|
|
|
if(DoButton_Menu(&s_DeleteButton, Localize("Delete"), 0, &DeleteRect) || m_DeletePressed)
|
2010-09-03 18:05:22 +00:00
|
|
|
{
|
2010-09-05 15:53:31 +00:00
|
|
|
if(s_SelectedItem >= 0 && s_SelectedItem < m_lDemos.size())
|
2010-09-08 00:27:48 +00:00
|
|
|
{
|
|
|
|
UI()->SetActiveItem(0);
|
2010-09-05 15:53:31 +00:00
|
|
|
m_Popup = POPUP_DELETE_DEMO;
|
2010-09-08 00:27:48 +00:00
|
|
|
}
|
2010-09-03 18:05:22 +00:00
|
|
|
}
|
|
|
|
}
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
2010-06-04 20:14:02 +00:00
|
|
|
void CMenus::DemoSetParentDirectory()
|
|
|
|
{
|
|
|
|
int Stop = 0;
|
2010-09-03 19:41:37 +00:00
|
|
|
for(int i = 0; i < 256; i++)
|
2010-06-04 20:14:02 +00:00
|
|
|
{
|
|
|
|
if(m_aCurrentDemoFolder[i] == '/')
|
|
|
|
Stop = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
//keeps chars which are before the last '/' and remove chars which are after
|
2010-09-03 19:41:37 +00:00
|
|
|
for(int i = 0; i < 256; i++)
|
2010-06-04 20:14:02 +00:00
|
|
|
{
|
|
|
|
if(i >= Stop)
|
2010-09-03 19:41:37 +00:00
|
|
|
m_aCurrentDemoFolder[i] = '\0';
|
2010-06-04 20:14:02 +00:00
|
|
|
}
|
|
|
|
}
|