hlsdk-xash3d/cl_dll/aghl/AgVGuiMapBrowser.cpp

606 lines
16 KiB
C++

#include<VGUI_HeaderPanel.h>
#include<VGUI_TablePanel.h>
#include<VGUI_LineBorder.h>
#include<VGUI_Label.h>
#include<VGUI_Button.h>
#include<VGUI_ActionSignal.h>
#include "VGUI_ScrollPanel.h"
#include "VGUI_TextImage.h"
#include "hud.h"
#include "cl_util.h"
#include "vgui_TeamFortressViewport.h"
#include "AgVGuiMapBrowser.h"
#include "parsemsg.h"
#include <keydefs.h>
static int g_iStartIndex = 0;
static AgString s_sMapList;
static bool s_bHaveAllMaps = true;
static AgStringSet s_setMaps;
static AgStringSet s_setLocalMaps;
extern cvar_t* g_pcl_show_local_maps;
const char* GetMap(unsigned int iRow)
{
if (iRow < s_setMaps.size())
{
AgStringSet::iterator itrMaps = s_setMaps.begin();
for (unsigned int i = 0; i < iRow && itrMaps != s_setMaps.end(); i++, itrMaps++)
{}
if (itrMaps != s_setMaps.end())
return (*itrMaps).c_str();
}
return NULL;
}
using namespace vgui;
namespace
{
class MapBrowserTablePanel;
class MapBrowserTablePanel_InputSignal : public InputSignal
{
MapBrowserTablePanel* m_pMapBrowser;
public:
MapBrowserTablePanel_InputSignal(MapBrowserTablePanel* pMapBrowser)
{
m_pMapBrowser = pMapBrowser;
}
virtual void cursorMoved(int x,int y,Panel* panel) {};
virtual void cursorEntered(Panel* panel){};
virtual void cursorExited(Panel* Panel) {};
virtual void mousePressed(MouseCode code,Panel* panel);
virtual void mouseDoublePressed(MouseCode code,Panel* panel);
virtual void mouseReleased(MouseCode code,Panel* panel) {};
virtual void mouseWheeled(int delta,Panel* panel) {};
virtual void keyPressed(KeyCode code,Panel* panel) {};
virtual void keyTyped(KeyCode code,Panel* panel) {};
virtual void keyReleased(KeyCode code,Panel* panel) {};
virtual void keyFocusTicked(Panel* panel) {};
};
#define CELL_HEIGHT YRES(15)
class MapBrowserTablePanel : public TablePanel
{
private:
Label *m_pLabel;
int m_nMouseOverRow;
public:
MapBrowserTablePanel( int x,int y,int wide,int tall,int columnCount) : TablePanel( x,y,wide,tall,columnCount)
{
m_pLabel = new Label( "", 0, 0 );
m_nMouseOverRow = 0;
setCellEditingEnabled(false);
}
public:
void setMouseOverRow( int row )
{
m_nMouseOverRow = row;
DoUpdateMap();
}
void DoChangeMap( void )
{
stopCellEditing();
DoCancel();
const char* pszMap = GetMap(m_nMouseOverRow + g_iStartIndex);
if (pszMap && strlen(pszMap))
{
char szCommand[256];
sprintf(szCommand,"agmap %s",pszMap);
ServerCmd(szCommand);
}
}
void DoChangeNextMap( void )
{
DoCancel();
const char* pszMap = GetMap(m_nMouseOverRow + g_iStartIndex);
if (pszMap && strlen(pszMap))
{
char szCommand[256];
sprintf(szCommand,"agnextmap %s",pszMap);
ServerCmd(szCommand);
}
}
void DoCancel( void )
{
ClientCmd( "togglemapbrowser\n" );
}
void DoPrev( void )
{
g_iStartIndex -= getRowCount();
if (g_iStartIndex < 0)
g_iStartIndex = 0;
DoUpdateMap();
}
void DoNext( void )
{
g_iStartIndex += getRowCount();
if (g_iStartIndex > (int)s_setMaps.size())
g_iStartIndex = 0;
DoUpdateMap();
}
void DoUpdateMap( void )
{
AgVGuiMapBrowser* pVGUI = (AgVGuiMapBrowser*)getParent();
pVGUI->UpdateMap(GetMap(m_nMouseOverRow + g_iStartIndex));
}
virtual int getRowCount()
{
int rowcount;
int height, width;
getSize( width, height );
height = max( 0, height );
rowcount = height / CELL_HEIGHT;
return rowcount;
}
virtual int getCellTall(int row)
{
return CELL_HEIGHT - 2;
}
virtual Panel* getCellRenderer(int column,int row,bool columnSelected,bool rowSelected,bool cellSelected)
{
const char* pszMap = GetMap(row + g_iStartIndex);
if ( row == m_nMouseOverRow )
{
m_pLabel->setFgColor( 255, 255, 255, 0 );
}
else
{
m_pLabel->setFgColor( 200, 240, 63, 100 );
if (pszMap && strlen(pszMap))
{
AgStringSet::iterator itrLocalMaps = s_setLocalMaps.find(pszMap);
if (itrLocalMaps == s_setLocalMaps.end())
m_pLabel->setFgColor( 200, 0, 0, 100 );
}
}
m_pLabel->setBgColor( 0, 0, 0, 200 );
m_pLabel->setContentAlignment( vgui::Label::a_west );
m_pLabel->setFont( Scheme::sf_primary2 );
if ( pszMap )
{
// Fill out with the correct data
switch ( column )
{
case 0:
{
m_pLabel->setText( pszMap );
}
break;
default:
break;
}
}
else
{
if ( !row && !column )
{
if ( !s_bHaveAllMaps )
{
m_pLabel->setText( "Please wait..." );
}
else
{
// m_pLabel->setText( "Press 'Refresh' to search for servers..." );
}
}
else
{
m_pLabel->setText( "" );
}
}
return m_pLabel;
}
virtual Panel* startCellEditing(int column,int row)
{
return null;
}
};
enum Action
{
Close, More, Previous, Change, ChangeNext,
};
class MapBrowserHandler : public ActionSignal
{
Action m_act;
MapBrowserTablePanel* m_pMapBrowser;
public:
MapBrowserHandler(Action act, MapBrowserTablePanel* pMapBrowser)
{
m_act = act;
m_pMapBrowser = pMapBrowser;
}
public:
virtual void actionPerformed(Panel* panel)
{
switch (m_act)
{
case Close:
gViewPort->ToggleMapBrowser();
break;
case More:
m_pMapBrowser->DoNext();
break;
case Change:
m_pMapBrowser->DoChangeMap();
break;
case ChangeNext:
m_pMapBrowser->DoChangeNextMap();
break;
default:
break;
}
}
};
void MapBrowserTablePanel_InputSignal::mousePressed(MouseCode code,Panel* panel)
{
int x, y;
int therow = 2;
if ( code != MOUSE_LEFT )
return;
panel->getApp()->getCursorPos(x,y);
panel->screenToLocal( x, y );
therow = y / (CELL_HEIGHT);
// Figure out which row it's on
m_pMapBrowser->setMouseOverRow( therow );
}
void MapBrowserTablePanel_InputSignal::mouseDoublePressed(MouseCode code,Panel* panel)
{
int x, y;
int therow = 2;
if ( code != MOUSE_LEFT )
return;
panel->getApp()->getCursorPos(x,y);
panel->screenToLocal( x, y );
therow = y / (CELL_HEIGHT-1);
// Figure out which row it's on
m_pMapBrowser->setMouseOverRow( therow );
m_pMapBrowser->DoChangeMap();
}
}
#define MAPBROWSER_TITLE_X XRES(16)
#define MAPBROWSER_TITLE_Y YRES(16)
#define MAPBROWSER_BUTTON_SIZE_X XRES(100)
#define MAPBROWSER_BUTTON_SIZE_Y YRES(24)
#define MAPBROWSER_BUTTON_SPACER_Y YRES(8)
#define MAPBROWSER_BUTTON_SPACER_X XRES(8)
#define TABLE_X XRES(8)
#define TABLE_Y YRES(60)
#define HEADER_SIZE_X XRES(100)
#define HEADER_SIZE_Y 0 //YRES(18)
#define NUM_COLUMNS 1
AgVGuiMapBrowser::AgVGuiMapBrowser(int x,int y,int wide,int tall) : Panel(x,y,wide,tall)
{
setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0)) );
// Get the scheme used for the Titles
CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
// schemes
SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
SchemeHandle_t hIRCText = pSchemes->getSchemeHandle( "Briefing Text" );
// color schemes
int r, g, b, a;
// Create the title
m_pLabel = new Label( "", MAPBROWSER_TITLE_X, MAPBROWSER_TITLE_Y );
m_pLabel->setParent( this );
m_pLabel->setFont( pSchemes->getFont(hTitleScheme) );
m_pLabel->setFont( Scheme::sf_primary1 );
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
m_pLabel->setFgColor( r, g, b, a );
// m_pLabel->setFgColor( Scheme::sc_primary1 );
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
m_pLabel->setBgColor( r, g, b, a );
m_pLabel->setContentAlignment( vgui::Label::a_west );
m_pLabel->setText("AG Map Browser");
int iXSize,iYSize;
getSize( iXSize,iYSize );
Label* pHeaderLabel = new Label("Maps");
pHeaderLabel->setContentAlignment( vgui::Label::a_west );
pHeaderLabel->setFgColor( Scheme::sc_primary1 );
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
pHeaderLabel->setBgColor( r, g, b, a );
pHeaderLabel->setFont( Scheme::sf_primary2 );
m_pHeaderPanel= new HeaderPanel(TABLE_X,TABLE_Y,HEADER_SIZE_X,HEADER_SIZE_Y);
m_pHeaderPanel->setParent(this);
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
m_pHeaderPanel->setFgColor( r, g, b, a );
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
m_pHeaderPanel->setBgColor( r, g, b, a );
m_pHeaderPanel->addSectionPanel(pHeaderLabel);
m_pHeaderPanel->setSliderPos( 0, HEADER_SIZE_X );
m_pTablePanel = new MapBrowserTablePanel( TABLE_X, TABLE_Y + HEADER_SIZE_Y, HEADER_SIZE_X, iYSize - (TABLE_Y + HEADER_SIZE_Y + MAPBROWSER_BUTTON_SIZE_Y*2 + MAPBROWSER_BUTTON_SPACER_Y), NUM_COLUMNS );
m_pTablePanel->setParent(this);
m_pTablePanel->setHeaderPanel(m_pHeaderPanel);
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
m_pTablePanel->setFgColor( r, g, b, a );
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
m_pTablePanel->setBgColor( r, g, b, a );
m_pTablePanel->addInputSignal(new MapBrowserTablePanel_InputSignal((MapBrowserTablePanel*)m_pTablePanel));
int bw = MAPBROWSER_BUTTON_SIZE_X;
int bh = MAPBROWSER_BUTTON_SIZE_Y;
int btny = iYSize - YRES(16) - BUTTON_SIZE_Y;//tall - MAPBROWSER_BUTTON_SIZE_Y - MAPBROWSER_BUTTON_SPACER_Y;
int btnx = TABLE_X;
CommandButton* pMore = new CommandButton("More",btnx, btny, bw, bh);
pMore->addActionSignal(new MapBrowserHandler(More,(MapBrowserTablePanel*)m_pTablePanel));
pMore->setParent(this);
btnx += MAPBROWSER_BUTTON_SPACER_X + MAPBROWSER_BUTTON_SIZE_X;
CommandButton* pChange = new CommandButton("Change Now",btnx, btny, bw, bh);
pChange->addActionSignal(new MapBrowserHandler(Change,(MapBrowserTablePanel*)m_pTablePanel));
pChange->setParent(this);
btnx += MAPBROWSER_BUTTON_SPACER_X + MAPBROWSER_BUTTON_SIZE_X;
CommandButton* pChangeNext = new CommandButton("Change Next",btnx, btny, bw, bh);
pChangeNext->addActionSignal(new MapBrowserHandler(ChangeNext,(MapBrowserTablePanel*)m_pTablePanel));
pChangeNext->setParent(this);
btnx += MAPBROWSER_BUTTON_SPACER_X + MAPBROWSER_BUTTON_SIZE_X;
CommandButton* pClose = new CommandButton("Close",btnx, btny, bw, bh);
pClose->addActionSignal(new MapBrowserHandler(Close,(MapBrowserTablePanel*)m_pTablePanel));
pClose->setParent(this);
// Create the Scroll panel
m_pTextScrollPanel = new CTFScrollPanel( TABLE_X + HEADER_SIZE_X + XRES(16), TABLE_Y + HEADER_SIZE_Y, iXSize - (TABLE_X + HEADER_SIZE_X + XRES(16)), iYSize - (TABLE_Y + HEADER_SIZE_Y + MAPBROWSER_BUTTON_SIZE_Y + MAPBROWSER_BUTTON_SPACER_Y + MAPBROWSER_TITLE_Y + YRES(8)));
m_pTextScrollPanel->setParent(this);
m_pTextScrollPanel->setScrollBarVisible(false, false);
m_pTextScrollPanel->setScrollBarAutoVisible(true, true);
// Create the text panel
m_pTextPanel = new TextPanel( "", 0,0, 64,64);
m_pTextPanel->setParent( m_pTextScrollPanel->getClient() );
// get the font and colors from the scheme
m_pTextPanel->setFont( pSchemes->getFont(hIRCText) );
pSchemes->getFgColor( hIRCText, r, g, b, a );
m_pTextPanel->setFgColor( r, g, b, a );
pSchemes->getBgColor( hIRCText, r, g, b, a );
m_pTextPanel->setBgColor( r, g, b, a );
m_pTextPanel->setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Map_Description_not_available"));
m_pTextScrollPanel->setScrollValue( 0, 0 );
}
void AgVGuiMapBrowser::paintBackground()
{
// Transparent black background
drawSetColor( 0,0,0, 100 );
drawFilledRect(0,0,_size[0],_size[1]);
}
void AgVGuiMapBrowser::UpdateMap(const char* pszMap)
{
char* pText = NULL;
if (pszMap)
{
char szMapFile[MAX_PATH];
sprintf(szMapFile,"maps/%s.txt",pszMap);
pText = (char*)gEngfuncs.COM_LoadFile(szMapFile, 5, NULL);
}
//force the scrollbars on so clientClip will take them in account after the validate
m_pTextScrollPanel->setScrollBarAutoVisible(false, false);
m_pTextScrollPanel->setScrollBarVisible(true, true);
m_pTextScrollPanel->validate();
if (pText)
m_pTextPanel->setText(pText);
else
m_pTextPanel->setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Map_Description_not_available"));
// Get the total size of the MOTD text and resize the text panel
int iScrollSizeX, iScrollSizeY;
// First, set the size so that the client's wdith is correct at least because the
// width is critical for getting the "wrapped" size right.
// You'll see a horizontal scroll bar if there is a single word that won't wrap in the
// specified width.
m_pTextPanel->getTextImage()->setSize(m_pTextScrollPanel->getClientClip()->getWide(), m_pTextScrollPanel->getClientClip()->getTall());
m_pTextPanel->getTextImage()->getTextSizeWrapped( iScrollSizeX, iScrollSizeY );
// Now resize the textpanel to fit the scrolled size
m_pTextPanel->setSize( iScrollSizeX , iScrollSizeY );
//turn the scrollbars back into automode
m_pTextScrollPanel->setScrollBarAutoVisible(true, true);
m_pTextScrollPanel->setScrollBarVisible(false, false);
m_pTextScrollPanel->setScrollValue( 0, 0 );
m_pTextScrollPanel->validate();
if (pText)
gEngfuncs.COM_FreeFile(pText);
}
int AgVGuiMapBrowser::MsgFunc_MapList( const char *pszName, int iSize, void *pbuf )
{
if (s_bHaveAllMaps)
s_sMapList = "";
BEGIN_READ( pbuf, iSize );
s_bHaveAllMaps = 0 == READ_BYTE();
s_sMapList += READ_STRING();
if (s_bHaveAllMaps)
{
s_setMaps.empty();
AgToLower(s_sMapList);
int iStart = 0;
int iEnd = 0;
do
{
iEnd = s_sMapList.find("#",iStart);
if (-1 != iEnd)
{
AgString sMap = s_sMapList.substr(iStart,iEnd-iStart);
AgTrim(sMap);
if (sMap.length())
{
s_setMaps.insert(sMap);
}
iStart = iEnd + 1;
}
}
while (-1 != iEnd);
s_setMaps.insert("boot_camp");
s_setMaps.insert("bounce");
s_setMaps.insert("datacore");
s_setMaps.insert("lambda_bunker");
s_setMaps.insert("snark_pit");
s_setMaps.insert("stalkyard");
s_setMaps.insert("subtransit");
s_setMaps.insert("undertow");
((MapBrowserTablePanel*)m_pTablePanel)->DoUpdateMap();
s_sMapList = "";
}
return 1;
}
void AgVGuiMapBrowser::GetMaps()
{
if (s_bHaveAllMaps && 0 == s_setMaps.size())
{
if (0 == s_setLocalMaps.size())
GetLocalMaps();
ServerCmd("maplist\n");
}
}
void AgVGuiMapBrowser::GetLocalMaps()
{
char szDirAG[MAX_PATH];
char szDirVALVE[MAX_PATH];
strcpy(szDirAG,AgGetDirectory());
strcat(szDirAG,"/maps");
strcpy(szDirVALVE,AgGetDirectoryValve());
strcat(szDirVALVE,"/maps");
AgStringSet setFiles;
AgStringSet::iterator itrFiles;
AgDirList(szDirAG,setFiles);
AgDirList(szDirVALVE,setFiles);
for (itrFiles = setFiles.begin() ;itrFiles != setFiles.end();++itrFiles)
{
AgString sFile = *itrFiles;
AgToLower(sFile);
if (!strstr(sFile.c_str(),".bsp"))
continue;
sFile = sFile.substr(0,sFile.length()-4);
AgTrim(sFile);
s_setLocalMaps.insert(sFile);
}
s_setLocalMaps.insert("boot_camp");
s_setLocalMaps.insert("bounce");
s_setLocalMaps.insert("datacore");
s_setLocalMaps.insert("lambda_bunker");
s_setLocalMaps.insert("snark_pit");
s_setLocalMaps.insert("stalkyard");
s_setLocalMaps.insert("subtransit");
s_setLocalMaps.insert("undertow");
}
int AgVGuiMapBrowser::KeyInput(int down, int keynum, const char *pszCurrentBinding)
{
if (!down)
return 1;
if (!isVisible())
return 1;
if (K_ESCAPE == keynum || pszCurrentBinding && 0 == _stricmp("togglemapbrowser",pszCurrentBinding))
{
gViewPort->ToggleMapBrowser();
return 0;
}
if (K_MWHEELUP == keynum)
{
((MapBrowserTablePanel*)m_pTablePanel)->DoPrev();
return 0;
}
if (K_MWHEELDOWN == keynum)
{
((MapBrowserTablePanel*)m_pTablePanel)->DoNext();
return 0;
}
return 1;
}