2010-11-20 10:37:14 +00:00
|
|
|
/* (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. */
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2011-08-31 11:56:04 +00:00
|
|
|
#include <base/tl/string.h>
|
|
|
|
|
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>
|
|
|
|
|
2011-12-04 13:04:12 +00:00
|
|
|
#include "maplayers.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
|
|
|
}
|
|
|
|
|
2011-03-28 22:48:36 +00:00
|
|
|
int CMenus::DoButton_Sprite(const void *pID, int ImageID, int SpriteID, int Checked, const CUIRect *pRect, int Corners)
|
2010-07-27 20:25:36 +00:00
|
|
|
{
|
2011-04-13 18:37:12 +00:00
|
|
|
RenderTools()->DrawUIRect(pRect, Checked ? vec4(1.0f, 1.0f, 1.0f, 0.10f) : vec4(1.0f, 1.0f, 1.0f, 0.5f)*ButtonColorMul(pID), Corners, 5.0f);
|
2011-03-28 19:10:37 +00:00
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id);
|
2010-07-27 20:25:36 +00:00
|
|
|
Graphics()->QuadsBegin();
|
2011-03-28 22:48:36 +00:00
|
|
|
if(!Checked)
|
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.5f);
|
2011-02-12 10:40:36 +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();
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-07-27 20:25:36 +00:00
|
|
|
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();
|
2011-04-13 18:37:12 +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;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2014-01-15 14:08:00 +00:00
|
|
|
if(!m_MenuActive)
|
|
|
|
return;
|
|
|
|
|
|
|
|
TotalHeight = SeekBarHeight+ButtonbarHeight+NameBarHeight+Margins*3;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
MainView.HSplitBottom(TotalHeight, 0, &MainView);
|
2011-03-12 17:07:57 +00:00
|
|
|
MainView.VSplitLeft(50.0f, 0, &MainView);
|
|
|
|
MainView.VSplitRight(450.0f, &MainView, 0);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_T, 10.0f);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
MainView.Margin(5.0f, &MainView);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-09-06 19:36:39 +00:00
|
|
|
CUIRect SeekBar, ButtonBar, NameBar;
|
2011-04-13 18:37:12 +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;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2014-01-15 14:08:00 +00:00
|
|
|
MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
|
|
|
|
ButtonBar.HSplitTop(Margins, 0, &ButtonBar);
|
|
|
|
ButtonBar.HSplitBottom(NameBarHeight, &ButtonBar, &NameBar);
|
|
|
|
NameBar.HSplitTop(4.0f, 0, &NameBar);
|
2008-10-06 18:05:01 +00:00
|
|
|
|
|
|
|
// do seekbar
|
|
|
|
{
|
2011-02-12 10:40:36 +00:00
|
|
|
static int s_SeekBarID = 0;
|
|
|
|
void *id = &s_SeekBarID;
|
2010-05-29 07:25:38 +00:00
|
|
|
char aBuffer[128];
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2012-01-10 22:13:19 +00:00
|
|
|
// draw seek bar
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2012-01-10 22:13:19 +00:00
|
|
|
// draw filled bar
|
2010-05-29 07:25:38 +00:00
|
|
|
float Amount = CurrentTick/(float)TotalTicks;
|
|
|
|
CUIRect FilledBar = SeekBar;
|
|
|
|
FilledBar.w = 10.0f + (FilledBar.w-10.0f)*Amount;
|
|
|
|
RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2012-01-10 22:13:19 +00:00
|
|
|
// draw markers
|
|
|
|
for(int i = 0; i < pInfo->m_NumTimelineMarkers; i++)
|
|
|
|
{
|
|
|
|
float Ratio = (pInfo->m_aTimelineMarkers[i]-pInfo->m_FirstTick) / (float)TotalTicks;
|
|
|
|
Graphics()->TextureSet(-1);
|
|
|
|
Graphics()->QuadsBegin();
|
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
IGraphics::CQuadItem QuadItem(SeekBar.x + (SeekBar.w-10.0f)*Ratio, SeekBar.y, UI()->PixelSize(), SeekBar.h);
|
|
|
|
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw time
|
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
|
2011-04-13 18:37:12 +00:00
|
|
|
int Inside = UI()->MouseInside(&SeekBar);
|
|
|
|
|
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;
|
2014-01-22 16:14:47 +00:00
|
|
|
|
|
|
|
if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT))
|
|
|
|
{
|
|
|
|
Amount = PrevAmount + (Amount-PrevAmount) * 0.05f;
|
|
|
|
|
|
|
|
if(Amount > 0.0f && Amount < 1.0f && absolute(PrevAmount-Amount) >= 0.0001f)
|
|
|
|
{
|
2014-01-22 16:19:21 +00:00
|
|
|
//PrevAmount = Amount;
|
2014-01-22 16:14:47 +00:00
|
|
|
m_pClient->OnReset();
|
|
|
|
m_pClient->m_SuppressEvents = true;
|
|
|
|
DemoPlayer()->SetPos(Amount);
|
|
|
|
m_pClient->m_SuppressEvents = false;
|
|
|
|
m_pClient->m_pMapLayersBackGround->EnvelopeUpdate();
|
|
|
|
m_pClient->m_pMapLayersForeGround->EnvelopeUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2014-01-22 16:14:47 +00:00
|
|
|
if(Amount > 0.0f && Amount < 1.0f && absolute(PrevAmount-Amount) >= 0.001f)
|
|
|
|
{
|
|
|
|
PrevAmount = Amount;
|
|
|
|
m_pClient->OnReset();
|
|
|
|
m_pClient->m_SuppressEvents = true;
|
|
|
|
DemoPlayer()->SetPos(Amount);
|
|
|
|
m_pClient->m_SuppressEvents = false;
|
|
|
|
m_pClient->m_pMapLayersBackGround->EnvelopeUpdate();
|
|
|
|
m_pClient->m_pMapLayersForeGround->EnvelopeUpdate();
|
|
|
|
}
|
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);
|
2011-04-13 18:37:12 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Inside)
|
2009-10-27 14:38:53 +00:00
|
|
|
UI()->SetHotItem(id);
|
2011-04-13 18:37:12 +00:00
|
|
|
}
|
2010-09-03 20:30:46 +00:00
|
|
|
|
|
|
|
if(CurrentTick == TotalTicks)
|
|
|
|
{
|
2011-01-09 22:42:37 +00:00
|
|
|
m_pClient->OnReset();
|
|
|
|
DemoPlayer()->Pause();
|
|
|
|
DemoPlayer()->SetPos(0);
|
2010-09-03 20:30:46 +00:00
|
|
|
}
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2011-03-27 14:26:50 +00:00
|
|
|
bool IncreaseDemoSpeed = false, DecreaseDemoSpeed = false;
|
|
|
|
|
2014-01-15 14:08:00 +00:00
|
|
|
// do buttons
|
|
|
|
CUIRect Button;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2014-01-15 14:08:00 +00:00
|
|
|
// combined play and pause button
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
|
|
|
static int s_PlayPauseButton = 0;
|
|
|
|
if(!pInfo->m_Paused)
|
|
|
|
{
|
|
|
|
if(DoButton_Sprite(&s_PlayPauseButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_PAUSE, false, &Button, CUI::CORNER_ALL))
|
2011-04-13 18:37:12 +00:00
|
|
|
DemoPlayer()->Pause();
|
2014-01-15 14:08:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(DoButton_Sprite(&s_PlayPauseButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_PLAY, false, &Button, CUI::CORNER_ALL))
|
|
|
|
DemoPlayer()->Unpause();
|
|
|
|
}
|
|
|
|
|
|
|
|
// stop button
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2014-01-15 14:08:00 +00:00
|
|
|
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
|
|
|
static int s_ResetButton = 0;
|
|
|
|
if(DoButton_Sprite(&s_ResetButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_STOP, false, &Button, CUI::CORNER_ALL))
|
|
|
|
{
|
|
|
|
m_pClient->OnReset();
|
|
|
|
DemoPlayer()->Pause();
|
|
|
|
DemoPlayer()->SetPos(0);
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
2011-03-27 14:26:50 +00:00
|
|
|
|
2014-01-15 14:08:00 +00:00
|
|
|
// slowdown
|
|
|
|
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
|
|
|
static int s_SlowDownButton = 0;
|
|
|
|
if(DoButton_Sprite(&s_SlowDownButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_SLOWER, 0, &Button, CUI::CORNER_ALL) || Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
|
|
|
|
DecreaseDemoSpeed = true;
|
|
|
|
|
|
|
|
// fastforward
|
|
|
|
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
|
|
|
static int s_FastForwardButton = 0;
|
|
|
|
if(DoButton_Sprite(&s_FastForwardButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_FASTER, 0, &Button, CUI::CORNER_ALL))
|
|
|
|
IncreaseDemoSpeed = true;
|
|
|
|
|
|
|
|
// speed meter
|
|
|
|
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);
|
|
|
|
else
|
|
|
|
str_format(aBuffer, sizeof(aBuffer), "x%.2f", pInfo->m_Speed);
|
|
|
|
UI()->DoLabel(&ButtonBar, aBuffer, Button.h*0.7f, -1);
|
|
|
|
|
2014-08-13 14:35:15 +00:00
|
|
|
// slice begin button
|
|
|
|
ButtonBar.VSplitLeft(Margins*10, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
|
|
|
static int s_SliceBeginButton = 0;
|
|
|
|
if(DoButton_Sprite(&s_SliceBeginButton, IMAGE_DEMOBUTTONS2, SPRITE_DEMOBUTTON_SLICE_BEGIN, 0, &Button, CUI::CORNER_ALL))
|
|
|
|
Client()->DemoSliceBegin();
|
|
|
|
|
|
|
|
// slice end button
|
|
|
|
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
|
|
|
static int s_SliceEndButton = 0;
|
|
|
|
if(DoButton_Sprite(&s_SliceEndButton, IMAGE_DEMOBUTTONS2, SPRITE_DEMOBUTTON_SLICE_END, 0, &Button, CUI::CORNER_ALL))
|
|
|
|
Client()->DemoSliceEnd();
|
|
|
|
|
|
|
|
// slice save button
|
|
|
|
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
|
|
|
static int s_SliceSaveButton = 0;
|
|
|
|
if(DoButton_Sprite(&s_SliceSaveButton, IMAGE_FILEICONS, SPRITE_FILE_DEMO2, 0, &Button, CUI::CORNER_ALL))
|
|
|
|
Client()->DemoSlice();
|
|
|
|
|
2014-01-15 14:08:00 +00:00
|
|
|
// close button
|
|
|
|
ButtonBar.VSplitRight(ButtonbarHeight*3, &ButtonBar, &Button);
|
|
|
|
static int s_ExitButton = 0;
|
|
|
|
if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), 0, &Button))
|
|
|
|
Client()->Disconnect();
|
|
|
|
|
|
|
|
// demo name
|
|
|
|
char aDemoName[64] = {0};
|
|
|
|
DemoPlayer()->GetDemoName(aDemoName, sizeof(aDemoName));
|
|
|
|
char aBuf[128];
|
|
|
|
str_format(aBuf, sizeof(aBuf), Localize("Demofile: %s"), aDemoName);
|
|
|
|
CTextCursor Cursor;
|
|
|
|
TextRender()->SetCursor(&Cursor, NameBar.x, NameBar.y, Button.h*0.5f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
|
|
|
|
Cursor.m_LineWidth = MainView.w;
|
|
|
|
TextRender()->TextEx(&Cursor, aBuf, -1);
|
|
|
|
|
2011-03-27 14:26:50 +00:00
|
|
|
if(IncreaseDemoSpeed || Input()->KeyPresses(KEY_MOUSE_WHEEL_UP))
|
|
|
|
{
|
|
|
|
if(pInfo->m_Speed < 0.1f) DemoPlayer()->SetSpeed(0.1f);
|
|
|
|
else if(pInfo->m_Speed < 0.25f) DemoPlayer()->SetSpeed(0.25f);
|
|
|
|
else if(pInfo->m_Speed < 0.5f) DemoPlayer()->SetSpeed(0.5f);
|
|
|
|
else if(pInfo->m_Speed < 0.75f) DemoPlayer()->SetSpeed(0.75f);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
else if(DecreaseDemoSpeed || Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
|
|
|
|
{
|
|
|
|
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.75f) DemoPlayer()->SetSpeed(0.75f);
|
|
|
|
else if(pInfo->m_Speed > 0.5f) DemoPlayer()->SetSpeed(0.5f);
|
|
|
|
else if(pInfo->m_Speed > 0.25f) DemoPlayer()->SetSpeed(0.25f);
|
|
|
|
else if(pInfo->m_Speed > 0.1f) DemoPlayer()->SetSpeed(0.1f);
|
|
|
|
else DemoPlayer()->SetSpeed(0.05f);
|
|
|
|
}
|
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;
|
|
|
|
|
2011-03-16 20:31:55 +00:00
|
|
|
void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems,
|
2010-05-29 07:25:38 +00:00
|
|
|
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;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-10-06 18:05:01 +00:00
|
|
|
// draw header
|
2010-05-29 07:25:38 +00:00
|
|
|
View.HSplitTop(ms_ListheaderHeight, &Header, &View);
|
2011-04-13 18:37:12 +00:00
|
|
|
RenderTools()->DrawUIRect(&Header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f);
|
2010-05-29 07:25:38 +00:00
|
|
|
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);
|
2011-04-13 18:37:12 +00:00
|
|
|
RenderTools()->DrawUIRect(&Footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f);
|
2010-05-29 07:25:38 +00:00
|
|
|
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
|
2014-06-16 11:29:18 +00:00
|
|
|
#if defined(__ANDROID__)
|
|
|
|
View.VSplitRight(50, &View, &Scroll);
|
|
|
|
#else
|
2010-05-29 07:25:38 +00:00
|
|
|
View.VSplitRight(15, &View, &Scroll);
|
2014-06-16 11:29:18 +00:00
|
|
|
#endif
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2011-04-13 18:37:12 +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);
|
2011-04-13 18:37:12 +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)
|
|
|
|
{
|
2011-05-10 17:16:22 +00:00
|
|
|
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP) && UI()->MouseInside(&View))
|
2011-01-23 16:00:18 +00:00
|
|
|
gs_ListBoxScrollValue -= 3.0f/Num;
|
2011-05-10 17:16:22 +00:00
|
|
|
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN) && UI()->MouseInside(&View))
|
2011-01-23 16:00:18 +00:00
|
|
|
gs_ListBoxScrollValue += 3.0f/Num;
|
2011-04-13 18:37:12 +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;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Scroll.HMargin(5.0f, &Scroll);
|
2011-02-12 10:40:36 +00:00
|
|
|
gs_ListBoxScrollValue = DoScrollbarV(pID, &Scroll, gs_ListBoxScrollValue);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
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);
|
|
|
|
|
2010-12-14 00:20:47 +00:00
|
|
|
s_RowView.VSplitLeft(s_RowView.w/(gs_ListBoxItemsPerRow-gs_ListBoxItemIndex%gs_ListBoxItemsPerRow)/(UI()->Scale()), &Item.m_Rect, &s_RowView);
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
Item.m_Visible = 1;
|
2009-10-27 14:38:53 +00:00
|
|
|
//item.rect = row;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Item.m_HitRect = Item.m_Rect;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
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;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
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
|
|
|
{
|
2011-04-13 18:37:12 +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
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
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;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
gs_ListBoxItemIndex++;
|
|
|
|
return Item;
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
2011-03-16 20:31:55 +00:00
|
|
|
CMenus::CListboxItem CMenus::UiDoListboxNextItem(const 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
|
|
|
}
|
2011-04-13 18:37:12 +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;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// 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;
|
|
|
|
|
2011-05-04 23:56:31 +00:00
|
|
|
if(m_EnterPressed || (UI()->ActiveItem() == pId && Input()->MouseDoubleClick()))
|
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
|
2011-04-13 18:37:12 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
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
|
2010-10-25 19:23:05 +00:00
|
|
|
float Offset = (NewIndex/gs_ListBoxItemsPerRow-gs_ListBoxNewSelected/gs_ListBoxItemsPerRow)*gs_ListBoxRowHeight;
|
2010-09-29 23:13:12 +00:00
|
|
|
int Scroll = gs_ListBoxOriginalView.y > Item.m_Rect.y+Offset ? -1 :
|
|
|
|
gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h < Item.m_Rect.y+Item.m_Rect.h+Offset ? 1 : 0;
|
|
|
|
if(Scroll)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2010-09-29 23:13:12 +00:00
|
|
|
int NumViewable = (int)(gs_ListBoxOriginalView.h/gs_ListBoxRowHeight) + 1;
|
|
|
|
int ScrollNum = (gs_ListBoxNumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1;
|
|
|
|
if(Scroll < 0)
|
|
|
|
{
|
2010-10-25 19:23:05 +00:00
|
|
|
int Num = (gs_ListBoxOriginalView.y-Item.m_Rect.y-Offset+gs_ListBoxRowHeight-1.0f)/gs_ListBoxRowHeight;
|
2010-09-29 23:13:12 +00:00
|
|
|
gs_ListBoxScrollValue -= (1.0f/ScrollNum)*Num;
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else
|
2010-09-29 23:13:12 +00:00
|
|
|
{
|
|
|
|
int Num = (Item.m_Rect.y+Item.m_Rect.h+Offset-(gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h)+gs_ListBoxRowHeight-1.0f)/
|
2010-10-25 19:23:05 +00:00
|
|
|
gs_ListBoxRowHeight;
|
2010-09-29 23:13:12 +00:00
|
|
|
gs_ListBoxScrollValue += (1.0f/ScrollNum)*Num;
|
|
|
|
}
|
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;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
gs_ListBoxNewSelected = NewIndex;
|
|
|
|
}
|
2009-06-15 14:01:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +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);
|
2011-04-13 18:37:12 +00:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2011-02-21 10:23:30 +00:00
|
|
|
int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
2010-09-18 13:08:57 +00:00
|
|
|
CMenus *pSelf = (CMenus *)pUser;
|
2010-09-28 22:53:53 +00:00
|
|
|
int Length = str_length(pName);
|
|
|
|
if((pName[0] == '.' && (pName[1] == 0 ||
|
|
|
|
(pName[1] == '.' && pName[2] == 0 && !str_comp(pSelf->m_aCurrentDemoFolder, "demos")))) ||
|
|
|
|
(!IsDir && (Length < 5 || str_comp(pName+Length-5, ".demo"))))
|
2011-02-21 10:23:30 +00:00
|
|
|
return 0;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CDemoItem Item;
|
2010-09-28 22:53:53 +00:00
|
|
|
str_copy(Item.m_aFilename, pName, sizeof(Item.m_aFilename));
|
|
|
|
if(IsDir)
|
2010-10-09 11:27:21 +00:00
|
|
|
{
|
2010-09-28 22:53:53 +00:00
|
|
|
str_format(Item.m_aName, sizeof(Item.m_aName), "%s/", pName);
|
2010-10-09 11:27:21 +00:00
|
|
|
Item.m_Valid = false;
|
|
|
|
}
|
2010-09-28 22:53:53 +00:00
|
|
|
else
|
2010-10-09 11:27:21 +00:00
|
|
|
{
|
2010-11-21 11:33:13 +00:00
|
|
|
str_copy(Item.m_aName, pName, min(static_cast<int>(sizeof(Item.m_aName)), Length-4));
|
2010-11-20 13:45:09 +00:00
|
|
|
Item.m_InfosLoaded = false;
|
2010-10-09 11:27:21 +00:00
|
|
|
}
|
2010-09-28 22:53:53 +00:00
|
|
|
Item.m_IsDir = IsDir != 0;
|
2010-10-06 21:07:35 +00:00
|
|
|
Item.m_StorageType = StorageType;
|
2011-03-27 14:42:47 +00:00
|
|
|
pSelf->m_lDemos.add_unsorted(Item);
|
2011-02-21 10:23:30 +00:00
|
|
|
|
|
|
|
return 0;
|
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();
|
2010-10-07 22:13:05 +00:00
|
|
|
if(!str_comp(m_aCurrentDemoFolder, "demos"))
|
|
|
|
m_DemolistStorageType = IStorage::TYPE_ALL;
|
|
|
|
Storage()->ListDirectory(m_DemolistStorageType, m_aCurrentDemoFolder, DemolistFetchCallback, this);
|
2011-03-27 14:42:47 +00:00
|
|
|
m_lDemos.sort_range();
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
|
2010-09-28 22:53:53 +00:00
|
|
|
void CMenus::DemolistOnUpdate(bool Reset)
|
|
|
|
{
|
|
|
|
m_DemolistSelectedIndex = Reset ? m_lDemos.size() > 0 ? 0 : -1 :
|
|
|
|
m_DemolistSelectedIndex >= m_lDemos.size() ? m_lDemos.size()-1 : m_DemolistSelectedIndex;
|
|
|
|
m_DemolistSelectedIsDir = m_DemolistSelectedIndex < 0 ? false : m_lDemos[m_DemolistSelectedIndex].m_IsDir;
|
|
|
|
}
|
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-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-28 22:53:53 +00:00
|
|
|
DemolistOnUpdate(true);
|
2010-09-05 12:28:08 +00:00
|
|
|
s_Inited = 1;
|
2010-09-05 17:06:27 +00:00
|
|
|
}
|
|
|
|
|
2010-10-13 10:59:30 +00:00
|
|
|
char aFooterLabel[128] = {0};
|
|
|
|
if(m_DemolistSelectedIndex >= 0)
|
|
|
|
{
|
2010-11-20 13:45:09 +00:00
|
|
|
CDemoItem *Item = &m_lDemos[m_DemolistSelectedIndex];
|
|
|
|
if(str_comp(Item->m_aFilename, "..") == 0)
|
2010-10-13 10:59:30 +00:00
|
|
|
str_copy(aFooterLabel, Localize("Parent Folder"), sizeof(aFooterLabel));
|
|
|
|
else if(m_DemolistSelectedIsDir)
|
|
|
|
str_copy(aFooterLabel, Localize("Folder"), sizeof(aFooterLabel));
|
|
|
|
else
|
2010-11-20 13:45:09 +00:00
|
|
|
{
|
|
|
|
if(!Item->m_InfosLoaded)
|
|
|
|
{
|
|
|
|
char aBuffer[512];
|
|
|
|
str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_aCurrentDemoFolder, Item->m_aFilename);
|
2011-03-13 09:41:10 +00:00
|
|
|
Item->m_Valid = DemoPlayer()->GetDemoInfo(Storage(), aBuffer, Item->m_StorageType, &Item->m_Info);
|
2010-11-20 13:45:09 +00:00
|
|
|
Item->m_InfosLoaded = true;
|
|
|
|
}
|
|
|
|
if(!Item->m_Valid)
|
|
|
|
str_copy(aFooterLabel, Localize("Invalid Demo"), sizeof(aFooterLabel));
|
|
|
|
else
|
2011-03-13 09:41:10 +00:00
|
|
|
str_copy(aFooterLabel, Localize("Demo details"), sizeof(aFooterLabel));
|
2010-11-20 13:45:09 +00:00
|
|
|
}
|
2010-10-09 11:27:21 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +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);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-03-13 09:41:10 +00:00
|
|
|
CUIRect ButtonBar, RefreshRect, PlayRect, DeleteRect, RenameRect, FileIcon, ListBox;
|
2010-05-29 07:25:38 +00:00
|
|
|
MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar);
|
|
|
|
ButtonBar.HSplitTop(5.0f, 0, &ButtonBar);
|
2010-09-28 22:53:53 +00:00
|
|
|
ButtonBar.VSplitRight(130.0f, &ButtonBar, &PlayRect);
|
|
|
|
ButtonBar.VSplitLeft(130.0f, &RefreshRect, &ButtonBar);
|
2011-03-12 18:08:44 +00:00
|
|
|
ButtonBar.VSplitLeft(10.0f, 0, &ButtonBar);
|
2010-09-28 22:53:53 +00:00
|
|
|
ButtonBar.VSplitLeft(120.0f, &DeleteRect, &ButtonBar);
|
2011-03-12 18:08:44 +00:00
|
|
|
ButtonBar.VSplitLeft(10.0f, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(120.0f, &RenameRect, &ButtonBar);
|
2011-03-13 09:41:10 +00:00
|
|
|
MainView.HSplitBottom(140.0f, &ListBox, &MainView);
|
|
|
|
|
|
|
|
// render demo info
|
|
|
|
MainView.VMargin(5.0f, &MainView);
|
|
|
|
MainView.HSplitBottom(5.0f, &MainView, 0);
|
|
|
|
RenderTools()->DrawUIRect(&MainView, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f);
|
|
|
|
if(!m_DemolistSelectedIsDir && m_DemolistSelectedIndex >= 0 && m_lDemos[m_DemolistSelectedIndex].m_Valid)
|
|
|
|
{
|
|
|
|
CUIRect Left, Right, Labels;
|
|
|
|
MainView.Margin(20.0f, &MainView);
|
|
|
|
MainView.VSplitMid(&Labels, &MainView);
|
|
|
|
|
|
|
|
// left side
|
|
|
|
Labels.HSplitTop(20.0f, &Left, &Labels);
|
2011-04-03 21:33:43 +00:00
|
|
|
Left.VSplitLeft(150.0f, &Left, &Right);
|
2011-03-13 09:41:10 +00:00
|
|
|
UI()->DoLabelScaled(&Left, Localize("Created:"), 14.0f, -1);
|
|
|
|
UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aTimestamp, 14.0f, -1);
|
|
|
|
Labels.HSplitTop(5.0f, 0, &Labels);
|
|
|
|
Labels.HSplitTop(20.0f, &Left, &Labels);
|
2011-04-03 21:33:43 +00:00
|
|
|
Left.VSplitLeft(150.0f, &Left, &Right);
|
2011-03-13 09:41:10 +00:00
|
|
|
UI()->DoLabelScaled(&Left, Localize("Type:"), 14.0f, -1);
|
|
|
|
UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aType, 14.0f, -1);
|
|
|
|
Labels.HSplitTop(5.0f, 0, &Labels);
|
|
|
|
Labels.HSplitTop(20.0f, &Left, &Labels);
|
2011-04-03 21:33:43 +00:00
|
|
|
Left.VSplitLeft(150.0f, &Left, &Right);
|
2011-03-13 09:41:10 +00:00
|
|
|
UI()->DoLabelScaled(&Left, Localize("Length:"), 14.0f, -1);
|
2011-05-09 15:55:12 +00:00
|
|
|
int Length = ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[0]<<24)&0xFF000000) | ((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[1]<<16)&0xFF0000) |
|
|
|
|
((m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[2]<<8)&0xFF00) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aLength[3]&0xFF);
|
2011-03-13 09:41:10 +00:00
|
|
|
char aBuf[64];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "%d:%02d", Length/60, Length%60);
|
|
|
|
UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1);
|
|
|
|
Labels.HSplitTop(5.0f, 0, &Labels);
|
|
|
|
Labels.HSplitTop(20.0f, &Left, &Labels);
|
2011-04-03 21:33:43 +00:00
|
|
|
Left.VSplitLeft(150.0f, &Left, &Right);
|
2011-03-13 09:41:10 +00:00
|
|
|
UI()->DoLabelScaled(&Left, Localize("Version:"), 14.0f, -1);
|
|
|
|
str_format(aBuf, sizeof(aBuf), "%d", m_lDemos[m_DemolistSelectedIndex].m_Info.m_Version);
|
|
|
|
UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1);
|
|
|
|
|
|
|
|
// right side
|
|
|
|
Labels = MainView;
|
|
|
|
Labels.HSplitTop(20.0f, &Left, &Labels);
|
2011-04-03 21:33:43 +00:00
|
|
|
Left.VSplitLeft(150.0f, &Left, &Right);
|
2011-03-13 09:41:10 +00:00
|
|
|
UI()->DoLabelScaled(&Left, Localize("Map:"), 14.0f, -1);
|
|
|
|
UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapName, 14.0f, -1);
|
|
|
|
Labels.HSplitTop(5.0f, 0, &Labels);
|
|
|
|
Labels.HSplitTop(20.0f, &Left, &Labels);
|
|
|
|
Left.VSplitLeft(20.0f, 0, &Left);
|
2011-04-03 21:33:43 +00:00
|
|
|
Left.VSplitLeft(130.0f, &Left, &Right);
|
2011-03-13 09:41:10 +00:00
|
|
|
UI()->DoLabelScaled(&Left, Localize("Size:"), 14.0f, -1);
|
2011-05-09 15:55:12 +00:00
|
|
|
unsigned Size = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[1]<<16) |
|
2011-03-13 09:41:10 +00:00
|
|
|
(m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapSize[3]);
|
2014-07-08 18:35:27 +00:00
|
|
|
if(Size > 1024*1024)
|
|
|
|
str_format(aBuf, sizeof(aBuf), Localize("%.2f MiB"), float(Size)/(1024*1024));
|
|
|
|
else
|
|
|
|
str_format(aBuf, sizeof(aBuf), Localize("%.2f KiB"), float(Size)/1024);
|
2011-03-13 09:41:10 +00:00
|
|
|
UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1);
|
|
|
|
Labels.HSplitTop(5.0f, 0, &Labels);
|
|
|
|
Labels.HSplitTop(20.0f, &Left, &Labels);
|
|
|
|
Left.VSplitLeft(20.0f, 0, &Left);
|
2011-04-03 21:33:43 +00:00
|
|
|
Left.VSplitLeft(130.0f, &Left, &Right);
|
2011-03-13 09:41:10 +00:00
|
|
|
UI()->DoLabelScaled(&Left, Localize("Crc:"), 14.0f, -1);
|
|
|
|
unsigned Crc = (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[0]<<24) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[1]<<16) |
|
|
|
|
(m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[2]<<8) | (m_lDemos[m_DemolistSelectedIndex].m_Info.m_aMapCrc[3]);
|
|
|
|
str_format(aBuf, sizeof(aBuf), "%08x", Crc);
|
|
|
|
UI()->DoLabelScaled(&Right, aBuf, 14.0f, -1);
|
|
|
|
Labels.HSplitTop(5.0f, 0, &Labels);
|
|
|
|
Labels.HSplitTop(20.0f, &Left, &Labels);
|
2011-04-03 21:33:43 +00:00
|
|
|
Left.VSplitLeft(150.0f, &Left, &Right);
|
2011-03-13 09:41:10 +00:00
|
|
|
UI()->DoLabelScaled(&Left, Localize("Netversion:"), 14.0f, -1);
|
|
|
|
UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aNetversion, 14.0f, -1);
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_DemoListId = 0;
|
|
|
|
static float s_ScrollValue = 0;
|
2014-06-16 11:29:18 +00:00
|
|
|
#if defined(__ANDROID__)
|
|
|
|
UiDoListboxStart(&s_DemoListId, &ListBox, 50.0f, Localize("Demos"), aFooterLabel, m_lDemos.size(), 1, m_DemolistSelectedIndex, s_ScrollValue);
|
|
|
|
#else
|
2011-03-13 09:41:10 +00:00
|
|
|
UiDoListboxStart(&s_DemoListId, &ListBox, 17.0f, Localize("Demos"), aFooterLabel, m_lDemos.size(), 1, m_DemolistSelectedIndex, s_ScrollValue);
|
2014-06-16 11:29:18 +00:00
|
|
|
#endif
|
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)
|
2010-11-17 18:46:50 +00:00
|
|
|
{
|
|
|
|
Item.m_Rect.VSplitLeft(Item.m_Rect.h, &FileIcon, &Item.m_Rect);
|
|
|
|
Item.m_Rect.VSplitLeft(5.0f, 0, &Item.m_Rect);
|
|
|
|
DoButton_Icon(IMAGE_FILEICONS, r.front().m_IsDir?SPRITE_FILE_FOLDER:SPRITE_FILE_DEMO1, &FileIcon);
|
2010-05-29 07:25:38 +00:00
|
|
|
UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight, -1);
|
2010-11-17 18:46:50 +00:00
|
|
|
}
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
bool Activated = false;
|
2010-09-28 22:53:53 +00:00
|
|
|
m_DemolistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, &Activated);
|
|
|
|
DemolistOnUpdate(false);
|
2011-04-13 18:37:12 +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-09-28 22:53:53 +00:00
|
|
|
DemolistOnUpdate(false);
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
2010-10-09 11:27:21 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_PlayButton = 0;
|
2010-09-28 22:53:53 +00:00
|
|
|
if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir?Localize("Open"):Localize("Play"), 0, &PlayRect) || Activated)
|
2010-09-03 19:41:37 +00:00
|
|
|
{
|
2010-09-28 22:53:53 +00:00
|
|
|
if(m_DemolistSelectedIndex >= 0)
|
2009-06-15 13:16:33 +00:00
|
|
|
{
|
2010-09-28 22:53:53 +00:00
|
|
|
if(m_DemolistSelectedIsDir) // folder
|
2010-06-04 20:14:02 +00:00
|
|
|
{
|
2010-09-28 22:53:53 +00:00
|
|
|
if(str_comp(m_lDemos[m_DemolistSelectedIndex].m_aFilename, "..") == 0) // parent folder
|
|
|
|
fs_parent_dir(m_aCurrentDemoFolder);
|
|
|
|
else // sub folder
|
|
|
|
{
|
|
|
|
char aTemp[256];
|
|
|
|
str_copy(aTemp, m_aCurrentDemoFolder, sizeof(aTemp));
|
|
|
|
str_format(m_aCurrentDemoFolder, sizeof(m_aCurrentDemoFolder), "%s/%s", aTemp, m_lDemos[m_DemolistSelectedIndex].m_aFilename);
|
2010-10-07 22:13:05 +00:00
|
|
|
m_DemolistStorageType = m_lDemos[m_DemolistSelectedIndex].m_StorageType;
|
2010-09-28 22:53:53 +00:00
|
|
|
}
|
2010-06-04 20:14:02 +00:00
|
|
|
DemolistPopulate();
|
2010-09-28 22:53:53 +00:00
|
|
|
DemolistOnUpdate(true);
|
2010-06-04 20:14:02 +00:00
|
|
|
}
|
2010-09-28 22:53:53 +00:00
|
|
|
else // file
|
2010-06-04 20:14:02 +00:00
|
|
|
{
|
2010-09-28 22:53:53 +00:00
|
|
|
char aBuf[512];
|
2010-10-06 21:07:35 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "%s/%s", m_aCurrentDemoFolder, m_lDemos[m_DemolistSelectedIndex].m_aFilename);
|
|
|
|
const char *pError = Client()->DemoPlayer_Play(aBuf, m_lDemos[m_DemolistSelectedIndex].m_StorageType);
|
2010-06-04 20:14:02 +00:00
|
|
|
if(pError)
|
2010-11-20 22:46:49 +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
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-09-28 22:53:53 +00:00
|
|
|
if(!m_DemolistSelectedIsDir)
|
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-28 22:53:53 +00:00
|
|
|
if(m_DemolistSelectedIndex >= 0)
|
2010-09-08 00:27:48 +00:00
|
|
|
{
|
|
|
|
UI()->SetActiveItem(0);
|
2010-09-05 15:53:31 +00:00
|
|
|
m_Popup = POPUP_DELETE_DEMO;
|
2011-03-12 18:08:44 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int s_RenameButton = 0;
|
|
|
|
if(DoButton_Menu(&s_RenameButton, Localize("Rename"), 0, &RenameRect))
|
|
|
|
{
|
|
|
|
if(m_DemolistSelectedIndex >= 0)
|
|
|
|
{
|
|
|
|
UI()->SetActiveItem(0);
|
|
|
|
m_Popup = POPUP_RENAME_DEMO;
|
|
|
|
str_copy(m_aCurrentDemoFile, m_lDemos[m_DemolistSelectedIndex].m_aFilename, sizeof(m_aCurrentDemoFile));
|
|
|
|
return;
|
2010-09-08 00:27:48 +00:00
|
|
|
}
|
2010-09-03 18:05:22 +00:00
|
|
|
}
|
|
|
|
}
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|