789 lines
24 KiB
ActionScript
789 lines
24 KiB
ActionScript
/*
|
|
Copyright (c) 2013 yvt
|
|
|
|
This file is part of OpenSpades.
|
|
|
|
OpenSpades is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
OpenSpades is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include "Flags.as"
|
|
|
|
namespace spades {
|
|
|
|
|
|
class MainScreenUI {
|
|
private Renderer@ renderer;
|
|
private AudioDevice@ audioDevice;
|
|
private Font@ font;
|
|
MainScreenHelper@ helper;
|
|
|
|
spades::ui::UIManager@ manager;
|
|
|
|
MainScreenMainMenu@ mainMenu;
|
|
|
|
bool shouldExit = false;
|
|
|
|
private float time = -1.f;
|
|
|
|
MainScreenUI(Renderer@ renderer, AudioDevice@ audioDevice, Font@ font, MainScreenHelper@ helper) {
|
|
@this.renderer = renderer;
|
|
@this.audioDevice = audioDevice;
|
|
@this.font = font;
|
|
@this.helper = helper;
|
|
|
|
SetupRenderer();
|
|
|
|
@manager = spades::ui::UIManager(renderer, audioDevice);
|
|
@manager.RootElement.Font = font;
|
|
|
|
@mainMenu = MainScreenMainMenu(this);
|
|
mainMenu.Bounds = manager.RootElement.Bounds;
|
|
manager.RootElement.AddChild(mainMenu);
|
|
|
|
}
|
|
|
|
void SetupRenderer() {
|
|
// load map
|
|
@renderer.GameMap = GameMap("Maps/Title.vxl");
|
|
renderer.FogColor = Vector3(0.1f, 0.10f, 0.1f);
|
|
renderer.FogDistance = 128.f;
|
|
time = -1.f;
|
|
|
|
// returned from the client game, so reload the server list.
|
|
if(mainMenu !is null)
|
|
mainMenu.LoadServerList();
|
|
|
|
if(manager !is null)
|
|
manager.KeyPanic();
|
|
}
|
|
|
|
void MouseEvent(float x, float y) {
|
|
manager.MouseEvent(x, y);
|
|
}
|
|
|
|
void WheelEvent(float x, float y) {
|
|
manager.WheelEvent(x, y);
|
|
}
|
|
|
|
void KeyEvent(string key, bool down) {
|
|
manager.KeyEvent(key, down);
|
|
}
|
|
|
|
void TextInputEvent(string text) {
|
|
manager.TextInputEvent(text);
|
|
}
|
|
|
|
void TextEditingEvent(string text, int start, int len) {
|
|
manager.TextEditingEvent(text, start, len);
|
|
}
|
|
|
|
bool AcceptsTextInput() {
|
|
return manager.AcceptsTextInput;
|
|
}
|
|
|
|
AABB2 GetTextInputRect() {
|
|
return manager.TextInputRect;
|
|
}
|
|
|
|
private SceneDefinition SetupCamera(SceneDefinition sceneDef,
|
|
Vector3 eye, Vector3 at, Vector3 up, float fov) {
|
|
Vector3 dir = (at - eye).Normalized;
|
|
Vector3 side = Cross(dir, up).Normalized;
|
|
up = -Cross(dir, side);
|
|
sceneDef.viewOrigin = eye;
|
|
sceneDef.viewAxisX = side;
|
|
sceneDef.viewAxisY = up;
|
|
sceneDef.viewAxisZ = dir;
|
|
sceneDef.fovY = fov * 3.141592654f / 180.f;
|
|
sceneDef.fovX = atan(tan(sceneDef.fovY * 0.5f) * renderer.ScreenWidth / renderer.ScreenHeight) * 2.f;
|
|
return sceneDef;
|
|
}
|
|
|
|
void RunFrame(float dt) {
|
|
if(time < 0.f) {
|
|
time = 0.f;
|
|
}
|
|
|
|
SceneDefinition sceneDef;
|
|
float cameraX = time;
|
|
cameraX -= floor(cameraX / 512.f) * 512.f;
|
|
cameraX = 512.f - cameraX;
|
|
sceneDef = SetupCamera(sceneDef,
|
|
Vector3(cameraX, 256.f, 12.f), Vector3(cameraX + .1f, 257.f, 12.5f), Vector3(0.f, 0.f, -1.f),
|
|
30.f);
|
|
sceneDef.zNear = 0.1f;
|
|
sceneDef.zFar = 222.f;
|
|
sceneDef.time = int(time * 1000.f);
|
|
sceneDef.viewportWidth = int(renderer.ScreenWidth);
|
|
sceneDef.viewportHeight = int(renderer.ScreenHeight);
|
|
sceneDef.denyCameraBlur = true;
|
|
sceneDef.depthOfFieldNearRange = 100.f;
|
|
sceneDef.skipWorld = false;
|
|
|
|
// fade the map
|
|
float fade = Clamp((time - 1.f) / 2.2f, 0.f, 1.f);
|
|
sceneDef.globalBlur = Clamp((1.f - (time - 1.f) / 2.5f), 0.f, 1.f);
|
|
if(!mainMenu.IsEnabled) {
|
|
sceneDef.globalBlur = Max(sceneDef.globalBlur, 0.5f);
|
|
}
|
|
|
|
renderer.StartScene(sceneDef);
|
|
renderer.EndScene();
|
|
|
|
// fade the map (draw)
|
|
if(fade < 1.f) {
|
|
renderer.ColorNP = Vector4(0.f, 0.f, 0.f, 1.f - fade);
|
|
renderer.DrawImage(renderer.RegisterImage("Gfx/White.tga"),
|
|
AABB2(0.f, 0.f, renderer.ScreenWidth, renderer.ScreenHeight));
|
|
}
|
|
|
|
// draw title logo
|
|
Image@ img = renderer.RegisterImage("Gfx/Title/Logo.png");
|
|
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 1.f);
|
|
renderer.DrawImage(img, Vector2((renderer.ScreenWidth - img.Width) * 0.5f, 64.f));
|
|
|
|
manager.RunFrame(dt);
|
|
manager.Render();
|
|
|
|
renderer.FrameDone();
|
|
renderer.Flip();
|
|
time += Min(dt, 0.05f);
|
|
}
|
|
|
|
void Closing() {
|
|
shouldExit = true;
|
|
}
|
|
|
|
bool WantsToBeClosed() {
|
|
return shouldExit;
|
|
}
|
|
}
|
|
|
|
class ServerListItem: spades::ui::ButtonBase {
|
|
MainScreenServerItem@ item;
|
|
FlagIconRenderer@ flagIconRenderer;
|
|
ServerListItem(spades::ui::UIManager@ manager, MainScreenServerItem@ item){
|
|
super(manager);
|
|
@this.item = item;
|
|
@flagIconRenderer = FlagIconRenderer(manager.Renderer);
|
|
}
|
|
void Render() {
|
|
Renderer@ renderer = Manager.Renderer;
|
|
Vector2 pos = ScreenPosition;
|
|
Vector2 size = Size;
|
|
Image@ img = renderer.RegisterImage("Gfx/White.tga");
|
|
if(Pressed && Hover) {
|
|
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.3f);
|
|
} else if(Hover) {
|
|
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.15f);
|
|
} else {
|
|
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.0f);
|
|
}
|
|
renderer.DrawImage(img, AABB2(pos.x, pos.y, size.x, size.y));
|
|
|
|
Font.Draw(item.Name, ScreenPosition + Vector2(4.f, 2.f), 1.f, Vector4(1,1,1,1));
|
|
string playersStr = ToString(item.NumPlayers) + "/" + ToString(item.MaxPlayers);
|
|
Vector4 col(1,1,1,1);
|
|
if(item.NumPlayers >= item.MaxPlayers) col = Vector4(1,0.7f,0.7f,1);
|
|
else if(item.NumPlayers >= item.MaxPlayers * 3 / 4) col = Vector4(1,1,0.7f,1);
|
|
else if(item.NumPlayers == 0) col = Vector4(0.7f,0.7f,1,1);
|
|
Font.Draw(playersStr, ScreenPosition + Vector2(340.f-Font.Measure(playersStr).x * 0.5f, 2.f), 1.f, col);
|
|
Font.Draw(item.MapName, ScreenPosition + Vector2(400.f, 2.f), 1.f, Vector4(1,1,1,1));
|
|
Font.Draw(item.GameMode, ScreenPosition + Vector2(550.f, 2.f), 1.f, Vector4(1,1,1,1));
|
|
Font.Draw(item.Protocol, ScreenPosition + Vector2(630.f, 2.f), 1.f, Vector4(1,1,1,1));
|
|
if(not flagIconRenderer.DrawIcon(item.Country, ScreenPosition + Vector2(700.f, size.y * 0.5f))) {
|
|
Font.Draw(item.Country, ScreenPosition + Vector2(680.f, 2.f), 1.f, Vector4(1,1,1,1));
|
|
}
|
|
}
|
|
}
|
|
|
|
funcdef void ServerListItemEventHandler(ServerListModel@ sender, MainScreenServerItem@ item);
|
|
|
|
class ServerListModel: spades::ui::ListViewModel {
|
|
spades::ui::UIManager@ manager;
|
|
MainScreenServerItem@[]@ list;
|
|
|
|
ServerListItemEventHandler@ ItemActivated;
|
|
|
|
ServerListModel(spades::ui::UIManager@ manager, MainScreenServerItem@[]@ list) {
|
|
@this.manager = manager;
|
|
@this.list = list;
|
|
}
|
|
int NumRows {
|
|
get { return int(list.length); }
|
|
}
|
|
private void ItemClicked(spades::ui::UIElement@ sender){
|
|
ServerListItem@ item = cast<ServerListItem>(sender);
|
|
if(ItemActivated !is null) {
|
|
ItemActivated(this, item.item);
|
|
}
|
|
}
|
|
spades::ui::UIElement@ CreateElement(int row) {
|
|
ServerListItem i(manager, list[row]);
|
|
@i.Activated = spades::ui::EventHandler(this.ItemClicked);
|
|
return i;
|
|
}
|
|
void RecycleElement(spades::ui::UIElement@ elem) {}
|
|
}
|
|
|
|
|
|
class ServerListHeader: spades::ui::ButtonBase {
|
|
string Text;
|
|
ServerListHeader(spades::ui::UIManager@ manager){
|
|
super(manager);
|
|
}
|
|
void OnActivated() {
|
|
ButtonBase::OnActivated();
|
|
}
|
|
void Render() {
|
|
Renderer@ renderer = Manager.Renderer;
|
|
Vector2 pos = ScreenPosition;
|
|
Vector2 size = Size;
|
|
Image@ img = renderer.RegisterImage("Gfx/White.tga");
|
|
if(Pressed && Hover) {
|
|
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.3f);
|
|
} else if(Hover) {
|
|
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.15f);
|
|
} else {
|
|
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 0.0f);
|
|
}
|
|
renderer.DrawImage(img, AABB2(pos.x - 2.f, pos.y, size.x, size.y));
|
|
|
|
Font.Draw(Text, ScreenPosition + Vector2(0.f, 2.f), 1.f, Vector4(1,1,1,1));
|
|
}
|
|
}
|
|
|
|
|
|
class RefreshButton: spades::ui::SimpleButton {
|
|
RefreshButton(spades::ui::UIManager@ manager){
|
|
super(manager);
|
|
}
|
|
void Render() {
|
|
SimpleButton::Render();
|
|
|
|
Renderer@ renderer = Manager.Renderer;
|
|
Vector2 pos = ScreenPosition;
|
|
Vector2 size = Size;
|
|
Image@ img = renderer.RegisterImage("Gfx/UI/Refresh.png");
|
|
renderer.DrawImage(img, pos + (size - Vector2(16.f, 16.f)) * 0.5f);
|
|
}
|
|
}
|
|
|
|
class ProtocolButton: spades::ui::SimpleButton {
|
|
ProtocolButton(spades::ui::UIManager@ manager){
|
|
super(manager);
|
|
Toggle = true;
|
|
}
|
|
}
|
|
|
|
uint8 ToLower(uint8 c) {
|
|
if(c >= uint8(0x41) and c <= uint8(0x5a)) {
|
|
return uint8(c - 0x41 + 0x61);
|
|
} else {
|
|
return c;
|
|
}
|
|
}
|
|
bool StringContainsCaseInsensitive(string text, string pattern) {
|
|
for(int i = text.length - 1; i >= 0; i--)
|
|
text[i] = ToLower(text[i]);
|
|
for(int i = pattern.length - 1; i >= 0; i--)
|
|
pattern[i] = ToLower(pattern[i]);
|
|
return text.findFirst(pattern) >= 0;
|
|
}
|
|
|
|
class MainScreenMainMenu: spades::ui::UIElement {
|
|
|
|
MainScreenUI@ ui;
|
|
MainScreenHelper@ helper;
|
|
spades::ui::Field@ addressField;
|
|
|
|
spades::ui::Button@ protocol3Button;
|
|
spades::ui::Button@ protocol4Button;
|
|
|
|
spades::ui::Button@ filterProtocol3Button;
|
|
spades::ui::Button@ filterProtocol4Button;
|
|
spades::ui::Button@ filterEmptyButton;
|
|
spades::ui::Button@ filterFullButton;
|
|
spades::ui::Field@ filterField;
|
|
|
|
spades::ui::ListView@ serverList;
|
|
MainScreenServerListLoadingView@ loadingView;
|
|
MainScreenServerListErrorView@ errorView;
|
|
bool loading = false, loaded = false;
|
|
|
|
private ConfigItem cg_protocolVersion("cg_protocolVersion");
|
|
private ConfigItem cg_lastQuickConnectHost("cg_lastQuickConnectHost");
|
|
private ConfigItem cg_serverlistSort("cg_serverlistSort", "16385");
|
|
|
|
MainScreenMainMenu(MainScreenUI@ ui) {
|
|
super(ui.manager);
|
|
@this.ui = ui;
|
|
@this.helper = ui.helper;
|
|
|
|
float contentsWidth = 750.f;
|
|
float contentsLeft = (Manager.Renderer.ScreenWidth - contentsWidth) * 0.5f;
|
|
float footerPos = Manager.Renderer.ScreenHeight - 50.f;
|
|
{
|
|
spades::ui::Button button(Manager);
|
|
button.Caption = _Tr("MainScreen", "Connect");
|
|
button.Bounds = AABB2(contentsLeft + contentsWidth - 150.f, 200.f, 150.f, 30.f);
|
|
button.Activated = EventHandler(this.OnConnectPressed);
|
|
AddChild(button);
|
|
}
|
|
{
|
|
@addressField = spades::ui::Field(Manager);
|
|
addressField.Bounds = AABB2(contentsLeft, 200, contentsWidth - 240.f, 30.f);
|
|
addressField.Placeholder = _Tr("MainScreen", "Quick Connect");
|
|
addressField.Text = cg_lastQuickConnectHost.StringValue;
|
|
addressField.Changed = spades::ui::EventHandler(this.OnAddressChanged);
|
|
AddChild(addressField);
|
|
}
|
|
{
|
|
@protocol3Button = ProtocolButton(Manager);
|
|
protocol3Button.Bounds = AABB2(contentsLeft + contentsWidth - 240.f + 6.f, 200,
|
|
40.f, 30.f);
|
|
protocol3Button.Caption = _Tr("MainScreen", "0.75");
|
|
protocol3Button.Activated = spades::ui::EventHandler(this.OnProtocol3Pressed);
|
|
protocol3Button.Toggle = true;
|
|
protocol3Button.Toggled = cg_protocolVersion.IntValue == 3;
|
|
AddChild(protocol3Button);
|
|
}
|
|
{
|
|
@protocol4Button = ProtocolButton(Manager);
|
|
protocol4Button.Bounds = AABB2(contentsLeft + contentsWidth - 200.f + 6.f, 200,
|
|
40.f, 30.f);
|
|
protocol4Button.Caption = _Tr("MainScreen", "0.76");
|
|
protocol4Button.Activated = spades::ui::EventHandler(this.OnProtocol4Pressed);
|
|
protocol4Button.Toggle = true;
|
|
protocol4Button.Toggled = cg_protocolVersion.IntValue == 4;
|
|
AddChild(protocol4Button);
|
|
}
|
|
{
|
|
spades::ui::Button button(Manager);
|
|
button.Caption = _Tr("MainScreen", "Quit");
|
|
button.Bounds = AABB2(contentsLeft + contentsWidth - 100.f, footerPos, 100.f, 30.f);
|
|
button.Activated = EventHandler(this.OnQuitPressed);
|
|
AddChild(button);
|
|
}
|
|
{
|
|
spades::ui::Button button(Manager);
|
|
button.Caption = _Tr("MainScreen", "Credits");
|
|
button.Bounds = AABB2(contentsLeft + contentsWidth - 202.f, footerPos, 100.f, 30.f);
|
|
button.Activated = EventHandler(this.OnCreditsPressed);
|
|
AddChild(button);
|
|
}
|
|
{
|
|
spades::ui::Button button(Manager);
|
|
button.Caption = _Tr("MainScreen", "Setup");
|
|
button.Bounds = AABB2(contentsLeft + contentsWidth - 304.f, footerPos, 100.f, 30.f);
|
|
button.Activated = EventHandler(this.OnSetupPressed);
|
|
AddChild(button);
|
|
}
|
|
{
|
|
RefreshButton button(Manager);
|
|
button.Bounds = AABB2(contentsLeft + contentsWidth - 364.f, footerPos, 30.f, 30.f);
|
|
button.Activated = EventHandler(this.OnRefreshServerListPressed);
|
|
AddChild(button);
|
|
}
|
|
{
|
|
spades::ui::Label label(Manager);
|
|
label.Text = _Tr("MainScreen", "Filter");
|
|
label.Bounds = AABB2(contentsLeft, footerPos, 50.f, 30.f);
|
|
label.Alignment = Vector2(0.f, 0.5f);
|
|
AddChild(label);
|
|
}
|
|
{
|
|
@filterProtocol3Button = ProtocolButton(Manager);
|
|
filterProtocol3Button.Bounds = AABB2(contentsLeft + 50.f, footerPos,
|
|
40.f, 30.f);
|
|
filterProtocol3Button.Caption = _Tr("MainScreen", "0.75");
|
|
filterProtocol3Button.Activated = spades::ui::EventHandler(this.OnFilterProtocol3Pressed);
|
|
filterProtocol3Button.Toggle = true;
|
|
AddChild(filterProtocol3Button);
|
|
}
|
|
{
|
|
@filterProtocol4Button = ProtocolButton(Manager);
|
|
filterProtocol4Button.Bounds = AABB2(contentsLeft + 90.f, footerPos,
|
|
40.f, 30.f);
|
|
filterProtocol4Button.Caption = _Tr("MainScreen", "0.76");
|
|
filterProtocol4Button.Activated = spades::ui::EventHandler(this.OnFilterProtocol4Pressed);
|
|
filterProtocol4Button.Toggle = true;
|
|
AddChild(filterProtocol4Button);
|
|
}
|
|
{
|
|
@filterEmptyButton = ProtocolButton(Manager);
|
|
filterEmptyButton.Bounds = AABB2(contentsLeft + 135.f, footerPos,
|
|
50.f, 30.f);
|
|
filterEmptyButton.Caption = _Tr("MainScreen", "Empty");
|
|
filterEmptyButton.Activated = spades::ui::EventHandler(this.OnFilterEmptyPressed);
|
|
filterEmptyButton.Toggle = true;
|
|
AddChild(filterEmptyButton);
|
|
}
|
|
{
|
|
@filterFullButton = ProtocolButton(Manager);
|
|
filterFullButton.Bounds = AABB2(contentsLeft + 185.f, footerPos,
|
|
70.f, 30.f);
|
|
filterFullButton.Caption = _Tr("MainScreen", "Not Full");
|
|
filterFullButton.Activated = spades::ui::EventHandler(this.OnFilterFullPressed);
|
|
filterFullButton.Toggle = true;
|
|
AddChild(filterFullButton);
|
|
}
|
|
{
|
|
@filterField = spades::ui::Field(Manager);
|
|
filterField.Bounds = AABB2(contentsLeft + 260.f, footerPos, 120.f, 30.f);
|
|
filterField.Placeholder = _Tr("MainScreen", "Filter");
|
|
filterField.Changed = spades::ui::EventHandler(this.OnFilterTextChanged);
|
|
AddChild(filterField);
|
|
}
|
|
{
|
|
@serverList = spades::ui::ListView(Manager);
|
|
serverList.Bounds = AABB2(contentsLeft, 270.f, contentsWidth, footerPos - 280.f);
|
|
AddChild(serverList);
|
|
}
|
|
{
|
|
ServerListHeader header(Manager);
|
|
header.Bounds = AABB2(contentsLeft + 2.f, 240.f, 300.f - 2.f, 30.f);
|
|
header.Text = _Tr("MainScreen", "Server Name");
|
|
header.Activated = spades::ui::EventHandler(this.SortServerListByName);
|
|
AddChild(header);
|
|
}
|
|
{
|
|
ServerListHeader header(Manager);
|
|
header.Bounds = AABB2(contentsLeft + 300.f, 240.f, 100.f, 30.f);
|
|
header.Text = _Tr("MainScreen", "Players");
|
|
header.Activated = spades::ui::EventHandler(this.SortServerListByNumPlayers);
|
|
AddChild(header);
|
|
}
|
|
{
|
|
ServerListHeader header(Manager);
|
|
header.Bounds = AABB2(contentsLeft + 400.f, 240.f, 150.f, 30.f);
|
|
header.Text = _Tr("MainScreen", "Map Name");
|
|
header.Activated = spades::ui::EventHandler(this.SortServerListByMapName);
|
|
AddChild(header);
|
|
}
|
|
{
|
|
ServerListHeader header(Manager);
|
|
header.Bounds = AABB2(contentsLeft + 550.f, 240.f, 80.f, 30.f);
|
|
header.Text = _Tr("MainScreen", "Game Mode");
|
|
header.Activated = spades::ui::EventHandler(this.SortServerListByGameMode);
|
|
AddChild(header);
|
|
}
|
|
{
|
|
ServerListHeader header(Manager);
|
|
header.Bounds = AABB2(contentsLeft + 630.f, 240.f, 50.f, 30.f);
|
|
header.Text = _Tr("MainScreen", "Ver.");
|
|
header.Activated = spades::ui::EventHandler(this.SortServerListByProtocol);
|
|
AddChild(header);
|
|
}
|
|
{
|
|
ServerListHeader header(Manager);
|
|
header.Bounds = AABB2(contentsLeft + 680.f, 240.f, 50.f, 30.f);
|
|
header.Text = _Tr("MainScreen", "Loc.");
|
|
header.Activated = spades::ui::EventHandler(this.SortServerListByCountry);
|
|
AddChild(header);
|
|
}
|
|
{
|
|
@loadingView = MainScreenServerListLoadingView(Manager);
|
|
loadingView.Bounds = AABB2(contentsLeft, 240.f, contentsWidth, 100.f);
|
|
loadingView.Visible = false;
|
|
AddChild(loadingView);
|
|
}
|
|
{
|
|
@errorView = MainScreenServerListErrorView(Manager);
|
|
errorView.Bounds = AABB2(contentsLeft, 240.f, contentsWidth, 100.f);
|
|
errorView.Visible = false;
|
|
AddChild(errorView);
|
|
}
|
|
LoadServerList();
|
|
}
|
|
|
|
void LoadServerList() {
|
|
if(loading) {
|
|
return;
|
|
}
|
|
loaded = false;
|
|
loading = true;
|
|
@serverList.Model = spades::ui::ListViewModel(); // empty
|
|
errorView.Visible = false;
|
|
loadingView.Visible = true;
|
|
helper.StartQuery();
|
|
}
|
|
|
|
void ServerListItemActivated(ServerListModel@ sender, MainScreenServerItem@ item) {
|
|
addressField.Text = item.Address;
|
|
cg_lastQuickConnectHost = addressField.Text;
|
|
if(item.Protocol == "0.75") {
|
|
SetProtocolVersion(3);
|
|
}else if(item.Protocol == "0.76") {
|
|
SetProtocolVersion(4);
|
|
}
|
|
addressField.SelectAll();
|
|
}
|
|
|
|
private void SortServerListByPing(spades::ui::UIElement@ sender) {
|
|
SortServerList(0);
|
|
}
|
|
private void SortServerListByNumPlayers(spades::ui::UIElement@ sender) {
|
|
SortServerList(1);
|
|
}
|
|
private void SortServerListByName(spades::ui::UIElement@ sender) {
|
|
SortServerList(2);
|
|
}
|
|
private void SortServerListByMapName(spades::ui::UIElement@ sender) {
|
|
SortServerList(3);
|
|
}
|
|
private void SortServerListByGameMode(spades::ui::UIElement@ sender) {
|
|
SortServerList(4);
|
|
}
|
|
private void SortServerListByProtocol(spades::ui::UIElement@ sender) {
|
|
SortServerList(5);
|
|
}
|
|
private void SortServerListByCountry(spades::ui::UIElement@ sender) {
|
|
SortServerList(6);
|
|
}
|
|
|
|
private void SortServerList(int keyId) {
|
|
int sort = cg_serverlistSort.IntValue;
|
|
if(int(sort & 0xfff) == keyId) {
|
|
sort ^= int(0x4000);
|
|
} else {
|
|
sort = keyId;
|
|
}
|
|
cg_serverlistSort = sort;
|
|
UpdateServerList();
|
|
}
|
|
|
|
private void UpdateServerList() {
|
|
string key = "";
|
|
switch(cg_serverlistSort.IntValue & 0xfff) {
|
|
case 0: key = "Ping"; break;
|
|
case 1: key = "NumPlayers"; break;
|
|
case 2: key = "Name"; break;
|
|
case 3: key = "MapName"; break;
|
|
case 4: key = "GameMode"; break;
|
|
case 5: key = "Protocol"; break;
|
|
case 6: key = "Country"; break;
|
|
}
|
|
MainScreenServerItem@[]@ list = helper.GetServerList(key,
|
|
(cg_serverlistSort.IntValue & 0x4000) != 0);
|
|
if((list is null) or (loading)){
|
|
@serverList.Model = spades::ui::ListViewModel(); // empty
|
|
return;
|
|
}
|
|
|
|
// filter the server list
|
|
bool filterProtocol3 = filterProtocol3Button.Toggled;
|
|
bool filterProtocol4 = filterProtocol4Button.Toggled;
|
|
bool filterEmpty = filterEmptyButton.Toggled;
|
|
bool filterFull = filterFullButton.Toggled;
|
|
string filterText = filterField.Text;
|
|
MainScreenServerItem@[]@ list2 = array<spades::MainScreenServerItem@>();
|
|
for(int i = 0, count = list.length; i < count; i++) {
|
|
MainScreenServerItem@ item = list[i];
|
|
if(filterProtocol3 and (item.Protocol != "0.75")) {
|
|
continue;
|
|
}
|
|
if(filterProtocol4 and (item.Protocol != "0.76")) {
|
|
continue;
|
|
}
|
|
if(filterEmpty and (item.NumPlayers > 0)) {
|
|
continue;
|
|
}
|
|
if(filterFull and (item.NumPlayers >= item.MaxPlayers)) {
|
|
continue;
|
|
}
|
|
if(filterText.length > 0) {
|
|
if(not (StringContainsCaseInsensitive(item.Name, filterText) or
|
|
StringContainsCaseInsensitive(item.MapName, filterText) or
|
|
StringContainsCaseInsensitive(item.GameMode, filterText))) {
|
|
continue;
|
|
}
|
|
}
|
|
list2.insertLast(item);
|
|
}
|
|
|
|
ServerListModel model(Manager, list2);
|
|
@serverList.Model = model;
|
|
@model.ItemActivated = ServerListItemEventHandler(this.ServerListItemActivated);
|
|
serverList.ScrollToTop();
|
|
}
|
|
|
|
private void CheckServerList() {
|
|
if(helper.PollServerListState()) {
|
|
MainScreenServerItem@[]@ list = helper.GetServerList("", false);
|
|
if(list is null or list.length == 0) {
|
|
// failed.
|
|
// FIXME: show error message?
|
|
loaded = false; loading = false;
|
|
errorView.Visible = true;
|
|
loadingView.Visible = false;
|
|
@serverList.Model = spades::ui::ListViewModel(); // empty
|
|
return;
|
|
}
|
|
loading = false;
|
|
loaded = true;
|
|
errorView.Visible = false;
|
|
loadingView.Visible = false;
|
|
UpdateServerList();
|
|
}
|
|
}
|
|
|
|
private void OnAddressChanged(spades::ui::UIElement@ sender) {
|
|
cg_lastQuickConnectHost = addressField.Text;
|
|
}
|
|
|
|
private void SetProtocolVersion(int ver) {
|
|
protocol3Button.Toggled = (ver == 3);
|
|
protocol4Button.Toggled = (ver == 4);
|
|
cg_protocolVersion = ver;
|
|
}
|
|
|
|
private void OnProtocol3Pressed(spades::ui::UIElement@ sender) {
|
|
SetProtocolVersion(3);
|
|
}
|
|
|
|
private void OnProtocol4Pressed(spades::ui::UIElement@ sender) {
|
|
SetProtocolVersion(4);
|
|
}
|
|
|
|
private void OnFilterProtocol3Pressed(spades::ui::UIElement@ sender) {
|
|
filterProtocol4Button.Toggled = false;
|
|
UpdateServerList();
|
|
}
|
|
private void OnFilterProtocol4Pressed(spades::ui::UIElement@ sender) {
|
|
filterProtocol3Button.Toggled = false;
|
|
UpdateServerList();
|
|
}
|
|
private void OnFilterFullPressed(spades::ui::UIElement@ sender) {
|
|
filterEmptyButton.Toggled = false;
|
|
UpdateServerList();
|
|
}
|
|
private void OnFilterEmptyPressed(spades::ui::UIElement@ sender) {
|
|
filterFullButton.Toggled = false;
|
|
UpdateServerList();
|
|
}
|
|
private void OnFilterTextChanged(spades::ui::UIElement@ sender) {
|
|
UpdateServerList();
|
|
}
|
|
|
|
private void OnRefreshServerListPressed(spades::ui::UIElement@ sender) {
|
|
LoadServerList();
|
|
}
|
|
|
|
private void OnQuitPressed(spades::ui::UIElement@ sender) {
|
|
ui.shouldExit = true;
|
|
}
|
|
|
|
private void OnCreditsPressed(spades::ui::UIElement@ sender) {
|
|
AlertScreen al(this, ui.helper.Credits, Min(500.f, Manager.Renderer.ScreenHeight - 100.f));
|
|
al.Run();
|
|
}
|
|
|
|
private void OnSetupPressed(spades::ui::UIElement@ sender) {
|
|
PreferenceView al(this, PreferenceViewOptions());
|
|
al.Run();
|
|
}
|
|
|
|
private void Connect() {
|
|
string msg = helper.ConnectServer();
|
|
if(msg.length > 0) {
|
|
// failde to initialize client.
|
|
AlertScreen al(this, msg);
|
|
al.Run();
|
|
}
|
|
}
|
|
|
|
private void OnConnectPressed(spades::ui::UIElement@ sender) {
|
|
Connect();
|
|
}
|
|
|
|
void HotKey(string key) {
|
|
if(IsEnabled and key == "Enter") {
|
|
Connect();
|
|
} else if(IsEnabled and key == "Escape") {
|
|
ui.shouldExit = true;
|
|
} else {
|
|
UIElement::HotKey(key);
|
|
}
|
|
}
|
|
|
|
void Render() {
|
|
CheckServerList();
|
|
UIElement::Render();
|
|
|
|
// check for client error message.
|
|
if(IsEnabled) {
|
|
string msg = helper.GetPendingErrorMessage();
|
|
if(msg.length > 0) {
|
|
// try to maek the "disconnected" message more friendly.
|
|
if(msg.findFirst("Disconnected:") >= 0) {
|
|
int ind1 = msg.findFirst("Disconnected:");
|
|
int ind2 = msg.findFirst("\n", ind1);
|
|
if(ind2 < 0) ind2 = msg.length;
|
|
ind1 += "Disconnected:".length;
|
|
msg = msg.substr(ind1, ind2 - ind1);
|
|
msg = _Tr("MainScreen", "You were disconnected from the server because of the following reason:\n\n{0}", msg);
|
|
}
|
|
|
|
// failed to connect.
|
|
AlertScreen al(this, msg);
|
|
al.Run();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class MainScreenServerListLoadingView: spades::ui::UIElement {
|
|
MainScreenServerListLoadingView(spades::ui::UIManager@ manager) {
|
|
super(manager);
|
|
}
|
|
void Render() {
|
|
Renderer@ renderer = Manager.Renderer;
|
|
Vector2 pos = ScreenPosition;
|
|
Vector2 size = Size;
|
|
Font@ font = this.Font;
|
|
string text = _Tr("MainScreen", "Loading...");
|
|
Vector2 txtSize = font.Measure(text);
|
|
Vector2 txtPos;
|
|
txtPos = pos + (size - txtSize) * 0.5f;
|
|
|
|
font.Draw(text, txtPos, 1.f, Vector4(1,1,1,0.8));
|
|
}
|
|
}
|
|
|
|
class MainScreenServerListErrorView: spades::ui::UIElement {
|
|
MainScreenServerListErrorView(spades::ui::UIManager@ manager) {
|
|
super(manager);
|
|
}
|
|
void Render() {
|
|
Renderer@ renderer = Manager.Renderer;
|
|
Vector2 pos = ScreenPosition;
|
|
Vector2 size = Size;
|
|
Font@ font = this.Font;
|
|
string text = _Tr("MainScreen", "Failed to fetch the server list.");
|
|
Vector2 txtSize = font.Measure(text);
|
|
Vector2 txtPos;
|
|
txtPos = pos + (size - txtSize) * 0.5f;
|
|
|
|
font.Draw(text, txtPos, 1.f, Vector4(1,1,1,0.8));
|
|
}
|
|
}
|
|
|
|
MainScreenUI@ CreateMainScreenUI(Renderer@ renderer, AudioDevice@ audioDevice,
|
|
Font@ font, MainScreenHelper@ helper) {
|
|
return MainScreenUI(renderer, audioDevice, font, helper);
|
|
}
|
|
}
|