Refactor overlays

This commit is contained in:
UnknownShadow200 2017-08-20 17:13:35 +10:00
parent 117c4b680a
commit dfc5380757
17 changed files with 255 additions and 240 deletions

View File

@ -423,32 +423,32 @@ namespace ClassicalSharp.Gui.Screens {
string url = Utils.StripColours(text);
if (Utils.IsUrlPrefix(url, 0)) {
WarningScreen warning = new WarningScreen(game, false, false);
warning.Metadata = url;
warning.SetHandlers(OpenUrl, AppendUrl, null);
WarningOverlay overlay = new WarningOverlay(game, false, false);
overlay.Metadata = url;
overlay.SetHandlers(OpenUrl, AppendUrl);
overlay.lines[0] = "&eAre you sure you want to open this link?";
warning.SetTextData(
"&eAre you sure you want to open this link?",
url, "Be careful - links from strangers may be websites that",
" have viruses, or things you may not want to open/see.");
game.Gui.ShowWarning(warning);
overlay.lines[1] = url;
overlay.lines[2] = "Be careful - links from strangers may be websites that";
overlay.lines[3] = " have viruses, or things you may not want to open/see.";
game.Gui.ShowOverlay(overlay);
} else if (game.ClickableChat) {
input.Append(text);
}
return true;
}
void OpenUrl(WarningScreen screen, bool always) {
void OpenUrl(Overlay urlOverlay, bool always) {
try {
Process.Start((string)screen.Metadata);
Process.Start((string)urlOverlay.Metadata);
} catch (Exception ex) {
ErrorHandler.LogError("ChatScreen.OpenUrl", ex);
}
}
void AppendUrl(WarningScreen screen, bool always) {
void AppendUrl(Overlay urlOverlay, bool always) {
if (!game.ClickableChat) return;
input.Append((string)screen.Metadata);
input.Append((string)urlOverlay.Metadata);
}
void ScrollHistory() {

View File

@ -128,11 +128,7 @@ namespace ClassicalSharp.Gui.Screens {
return secsLeft == 0 ? "Reconnect" : "Reconnect in " + secsLeft;
}
protected override void ContextLost() {
if (widgets == null) return;
for (int i = 0; i < widgets.Length; i++)
widgets[i].Dispose();
}
protected override void ContextLost() { DisposeWidgets(widgets); }
protected override void ContextRecreated() {
if (gfx.LostContext) return;

View File

@ -31,8 +31,7 @@ namespace ClassicalSharp.Gui.Screens {
}
protected override void ContextLost() {
for (int i = 0; i < buttons.Length; i++)
buttons[i].Dispose();
DisposeWidgets(buttons);
title.Dispose();
}

View File

@ -46,14 +46,7 @@ namespace ClassicalSharp.Gui.Screens {
gfx.ContextRecreated -= ContextRecreated;
}
protected override void ContextLost() {
if (widgets == null) return;
for (int i = 0; i < widgets.Length; i++) {
if (widgets[i] == null) continue;
widgets[i].Dispose();
}
}
protected override void ContextLost() { DisposeWidgets(widgets); }
public override void OnResize(int width, int height) {
for (int i = 0; i < widgets.Length; i++) {

View File

@ -0,0 +1,89 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Drawing;
using ClassicalSharp.Gui.Widgets;
using OpenTK.Input;
namespace ClassicalSharp.Gui.Screens {
public abstract class Overlay : MenuScreen {
public Action<Overlay> OnRenderFrame;
protected TextWidget[] labels;
public string[] lines = new string[4];
public Overlay(Game game) : base(game) { }
public override void Init() {
base.Init();
titleFont = new Font(game.FontName, 16, FontStyle.Bold);
regularFont = new Font(game.FontName, 16);
backCol.A = 210;
if (game.Graphics.LostContext) return;
MakeButtons();
RedrawText();
}
public override void Render(double delta) {
RenderMenuBounds();
gfx.Texturing = true;
RenderMenuWidgets(delta);
for (int i = 0; i < labels.Length; i++)
labels[i].Render(delta);
gfx.Texturing = false;
if (OnRenderFrame != null) OnRenderFrame(this);
}
public override void OnResize(int width, int height) {
base.OnResize(width, height);
for (int i = 0; i < labels.Length; i++)
labels[i].CalculatePosition();
}
protected override void ContextLost() {
base.ContextLost();
DisposeWidgets(labels);
}
protected override void ContextRecreated() {
MakeButtons();
RedrawText();
}
protected void CloseOverlay() {
if (game.Gui.overlays.Count > 0)
game.Gui.overlays.RemoveAt(0);
if (game.Gui.overlays.Count == 0)
game.CursorVisible = game.realVisible;
}
public abstract void RedrawText();
public abstract void MakeButtons();
protected void SetTextWidgets(string[] lines) {
if (labels != null) {
for (int i = 0; i < labels.Length; i++)
labels[i].Dispose();
}
int count = 0;
for (int i = 0; i < lines.Length; i++) {
if (lines[i] != null) count++;
}
labels = new TextWidget[count];
labels[0] = TextWidget.Create(game, lines[0], titleFont)
.SetLocation(Anchor.Centre, Anchor.Centre, 0, -120);
if (count == 1) return;
for (int i = 1; i < lines.Length; i++) {
labels[i] = TextWidget.Create(game,lines[i], regularFont)
.SetLocation(Anchor.Centre, Anchor.Centre, 0, -70 + 20 * i);
labels[i].Colour = new FastColour(224, 224, 224);
}
}
}
}

View File

@ -0,0 +1,98 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Drawing;
using ClassicalSharp.Gui.Widgets;
using OpenTK.Input;
namespace ClassicalSharp.Gui.Screens {
public delegate void WarningClickHandler(WarningOverlay screen, bool isAlways);
public sealed class WarningOverlay : Overlay {
public WarningOverlay(Game game, bool showAlways, bool confirmNo) : base(game) {
this.confirmNo = confirmNo;
this.showAlways = showAlways;
}
public void SetHandlers(WarningClickHandler yesClick,
WarningClickHandler noClick) {
this.yesClick = yesClick;
this.noClick = noClick;
}
bool confirmNo, confirmingMode, showAlways;
int alwaysIndex = 100;
public override void RedrawText() {
if (confirmingMode) {
SetTextWidgets(new string[] {
"&eYou might be missing out.",
"Texture packs can play a vital role in the look and feel of maps.",
"", "Sure you don't want to download the texture pack?"});
} else {
SetTextWidgets(lines);
}
}
public override void MakeButtons() {
DisposeWidgets(widgets);
alwaysIndex = 100;
if (confirmingMode) {
widgets = new ButtonWidget[2];
widgets[0] = ButtonWidget.Create(game, 160, "I'm sure", titleFont, OnNoClick)
.SetLocation(Anchor.Centre, Anchor.Centre, -110, 30);
widgets[1] = ButtonWidget.Create(game, 160, "Go back", titleFont, GoBackClick)
.SetLocation(Anchor.Centre, Anchor.Centre, 110, 30);
return;
}
widgets = new ButtonWidget[showAlways ? 4 : 2];
widgets[0] = ButtonWidget.Create(game, 160, "Yes", titleFont, OnYesClick)
.SetLocation(Anchor.Centre, Anchor.Centre, -110, 30);
widgets[1] = ButtonWidget.Create(game, 160, "No", titleFont, OnNoClick)
.SetLocation(Anchor.Centre, Anchor.Centre, 110, 30);
if (!showAlways) return;
alwaysIndex = 2;
widgets[2] = ButtonWidget.Create(game, 160, "Always yes", titleFont, OnYesClick)
.SetLocation(Anchor.Centre, Anchor.Centre, -110, 85);
widgets[3] = ButtonWidget.Create(game, 160, "Always no", titleFont, OnNoClick)
.SetLocation(Anchor.Centre, Anchor.Centre, 110, 85);
}
WarningClickHandler yesClick, noClick;
void OnYesClick(Game g, Widget w, MouseButton btn, int x, int y) {
if (btn != MouseButton.Left) return;
bool always = Array.IndexOf<Widget>(widgets, w) >= alwaysIndex;
if (yesClick != null) yesClick(this, always);
Dispose();
CloseOverlay();
}
void OnNoClick(Game g, Widget w, MouseButton btn, int x, int y) {
if (btn != MouseButton.Left) return;
bool always = Array.IndexOf<Widget>(widgets, w) >= alwaysIndex;
if (confirmNo && !confirmingMode) {
confirmingMode = true;
ContextRecreated();
return;
}
if (noClick != null) noClick(this, always);
Dispose();
CloseOverlay();
}
void GoBackClick(Game g, Widget w, MouseButton btn, int x, int y) {
if (btn != MouseButton.Left) return;
confirmingMode = false;
ContextRecreated();
}
}
}

View File

@ -38,5 +38,13 @@ namespace ClassicalSharp.Gui.Screens {
protected abstract void ContextLost();
protected abstract void ContextRecreated();
protected static void DisposeWidgets<T>(T[] widgets) where T : Widget {
if (widgets == null) return;
for (int i = 0; i < widgets.Length; i++) {
widgets[i].Dispose();
}
}
}
}

View File

@ -1,174 +0,0 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Drawing;
using ClassicalSharp.Gui.Widgets;
using OpenTK.Input;
namespace ClassicalSharp.Gui.Screens {
public delegate void WarningClickHandler(WarningScreen screen, bool isAlways);
public sealed class WarningScreen : MenuScreen {
public WarningScreen(Game game, bool showAlways, bool confirmNo) : base(game) {
this.confirmNo = confirmNo;
this.showAlways = showAlways;
}
public void SetHandlers(WarningClickHandler yesClick,
WarningClickHandler noClick,
Action<WarningScreen> renderFrame) {
this.yesClick = yesClick;
this.noClick = noClick;
this.renderFrame = renderFrame;
}
public void SetTextData(string title, params string[] body) {
this.title = title;
this.body = body;
}
string title;
string[] body;
bool confirmNo, confirmingMode, showAlways;
int alwaysIndex = 100;
public override void Init() {
base.Init();
titleFont = new Font(game.FontName, 16, FontStyle.Bold);
regularFont = new Font(game.FontName, 16);
backCol.A = 210;
if (game.Graphics.LostContext) return;
InitStandardButtons();
RedrawText();
}
public void RedrawText() {
if (confirmingMode) {
SetTextImpl("&eYou might be missing out.",
"Texture packs can play a vital role in the look and feel of maps.",
"", "Sure you don't want to download the texture pack?");
} else {
SetTextImpl(title, body);
}
}
void SetTextImpl(string title, params string[] body) {
if (labels != null) {
for (int i = 0; i < labels.Length; i++)
labels[i].Dispose();
}
labels = new TextWidget[body.Length + 1];
labels[0] = TextWidget.Create(game, title, titleFont)
.SetLocation(Anchor.Centre, Anchor.Centre, 0, -120);
for (int i = 0; i < body.Length; i++) {
labels[i + 1] = TextWidget.Create(game, body[i], regularFont)
.SetLocation(Anchor.Centre, Anchor.Centre, 0, -70 + 20 * i);
labels[i + 1].Colour = new FastColour(224, 224, 224);
}
}
TextWidget[] labels;
void CloseScreen() {
if (game.Gui.overlays.Count > 0)
game.Gui.overlays.RemoveAt(0);
if (game.Gui.overlays.Count == 0)
game.CursorVisible = game.realVisible;
}
public override void Render(double delta) {
RenderMenuBounds();
gfx.Texturing = true;
RenderMenuWidgets(delta);
for (int i = 0; i < labels.Length; i++)
labels[i].Render(delta);
gfx.Texturing = false;
if (renderFrame != null)
renderFrame(this);
}
public override void OnResize(int width, int height) {
base.OnResize(width, height);
for (int i = 0; i < labels.Length; i++)
labels[i].CalculatePosition();
}
protected override void ContextLost() {
base.ContextLost();
if (labels == null) return;
for (int i = 0; i < labels.Length; i++)
labels[i].Dispose();
}
protected override void ContextRecreated() {
InitStandardButtons();
RedrawText();
}
void InitStandardButtons() {
base.ContextLost();
alwaysIndex = 100;
if (confirmingMode) {
widgets = new ButtonWidget[2];
widgets[0] = ButtonWidget.Create(game, 160, "I'm sure", titleFont, OnNoClick)
.SetLocation(Anchor.Centre, Anchor.Centre, -110, 30);
widgets[1] = ButtonWidget.Create(game, 160, "Go back", titleFont, GoBackClick)
.SetLocation(Anchor.Centre, Anchor.Centre, 110, 30);
return;
}
widgets = new ButtonWidget[showAlways ? 4 : 2];
widgets[0] = ButtonWidget.Create(game, 160, "Yes", titleFont, OnYesClick)
.SetLocation(Anchor.Centre, Anchor.Centre, -110, 30);
widgets[1] = ButtonWidget.Create(game, 160, "No", titleFont, OnNoClick)
.SetLocation(Anchor.Centre, Anchor.Centre, 110, 30);
if (!showAlways) return;
alwaysIndex = 2;
widgets[2] = ButtonWidget.Create(game, 160, "Always yes", titleFont, OnYesClick)
.SetLocation(Anchor.Centre, Anchor.Centre, -110, 85);
widgets[3] = ButtonWidget.Create(game, 160, "Always no", titleFont, OnNoClick)
.SetLocation(Anchor.Centre, Anchor.Centre, 110, 85);
}
WarningClickHandler yesClick, noClick;
Action<WarningScreen> renderFrame;
void OnYesClick(Game g, Widget w, MouseButton btn, int x, int y) {
if (btn != MouseButton.Left) return;
bool always = Array.IndexOf<Widget>(widgets, w) >= alwaysIndex;
if (yesClick != null) yesClick(this, always);
Dispose();
CloseScreen();
}
void OnNoClick(Game g, Widget w, MouseButton btn, int x, int y) {
if (btn != MouseButton.Left) return;
bool always = Array.IndexOf<Widget>(widgets, w) >= alwaysIndex;
if (confirmNo && !confirmingMode) {
confirmingMode = true;
ContextRecreated();
return;
}
if (noClick != null) noClick(this, always);
Dispose();
CloseScreen();
}
void GoBackClick(Game g, Widget w, MouseButton btn, int x, int y) {
if (btn != MouseButton.Left) return;
confirmingMode = false;
ContextRecreated();
}
}
}

View File

@ -90,6 +90,8 @@
<Compile Include="2D\Screens\ClickableScreen.cs" />
<Compile Include="2D\Screens\DeathScreen.cs" />
<Compile Include="2D\Screens\DisconnectScreen.cs" />
<Compile Include="2D\Screens\Overlays\Overlay.cs" />
<Compile Include="2D\Screens\Overlays\WarningOverlay.cs" />
<Compile Include="2D\Screens\StatusScreen.cs" />
<Compile Include="2D\Screens\Inventory\InventoryScreen.cs" />
<Compile Include="2D\Screens\Inventory\InventoryScreen.Input.cs" />
@ -117,7 +119,6 @@
<Compile Include="2D\Screens\Menu\TexturePackScreen.cs" />
<Compile Include="2D\Screens\HudScreen.cs" />
<Compile Include="2D\Screens\Screen.cs" />
<Compile Include="2D\Screens\WarningScreen.cs" />
<Compile Include="2D\Texture.cs" />
<Compile Include="2D\Utils\FastBitmap.cs" />
<Compile Include="2D\Utils\FastColour.cs" />
@ -333,6 +334,7 @@
<ItemGroup>
<Folder Include="2D\Drawing" />
<Folder Include="2D\Screens\Inventory" />
<Folder Include="2D\Screens\Overlays" />
<Folder Include="2D\Utils" />
<Folder Include="2D\Screens" />
<Folder Include="2D\Screens\Menu" />

View File

@ -131,6 +131,7 @@ namespace ClassicalSharp.Entities {
/// <remarks> Parses hack flags specified in the motd and/or name of the server. </remarks>
/// <remarks> Recognises +/-hax, +/-fly, +/-noclip, +/-speed, +/-respawn, +/-ophax, and horspeed=xyz </remarks>
public void UpdateHacksState() {
return;
SetAllHacks(true);
if (HacksFlags == null) return;

View File

@ -16,7 +16,7 @@ namespace ClassicalSharp {
StatusScreen fpsScreen;
internal HudScreen hudScreen;
internal Screen activeScreen;
internal List<WarningScreen> overlays = new List<WarningScreen>();
internal List<Overlay> overlays = new List<Overlay>();
public GuiInterface(Game game) {
fpsScreen = game.AddComponent(new StatusScreen(game));
@ -61,10 +61,9 @@ namespace ClassicalSharp {
activeScreen.Dispose();
gfx.DeleteTexture(ref GuiTex);
gfx.DeleteTexture(ref GuiClassicTex);
gfx.DeleteTexture(ref IconsTex);
gfx.DeleteTexture(ref IconsTex);
for (int i = 0; i < overlays.Count; i++)
overlays[i].Dispose();
Reset(game);
}
void TextureChanged(object sender, TextureEventArgs e) {
@ -98,13 +97,13 @@ namespace ClassicalSharp {
public void RefreshHud() { hudScreen.Recreate(); }
public void ShowWarning(WarningScreen screen) {
public void ShowOverlay(Overlay overlay) {
bool cursorVis = game.CursorVisible;
if (overlays.Count == 0) game.CursorVisible = true;
overlays.Add(screen);
overlays.Add(overlay);
if (overlays.Count == 1) game.CursorVisible = cursorVis;
// Save cursor visibility state
screen.Init();
overlay.Init();
}

View File

@ -36,30 +36,29 @@ namespace ClassicalSharp {
}
internal void MakeWarning(Game game, string plugin) {
WarningScreen warning = new WarningScreen(game, true, false);
WarningOverlay warning = new WarningOverlay(game, true, false);
warning.Metadata = plugin;
warning.SetHandlers(Accept, Deny, null);
warning.SetHandlers(Accept, Deny);
warning.SetTextData(
"&eAre you sure you want to load plugin " + plugin + " ?",
"Be careful - plugins from strangers may have viruses",
" or other malicious behaviour.");
game.Gui.ShowWarning(warning);
warning.lines[0] = "&eAre you sure you want to load plugin " + plugin + " ?";
warning.lines[1] = "Be careful - plugins from strangers may have viruses";
warning.lines[2] = " or other malicious behaviour.";
game.Gui.ShowOverlay(warning);
}
void Accept(WarningScreen warning, bool always) {
string plugin = (string)warning.Metadata;
void Accept(Overlay overlay, bool always) {
string plugin = (string)overlay.Metadata;
if (always && !accepted.HasEntry(plugin)) {
accepted.AddEntry(plugin);
}
string dir = Path.Combine(Program.AppDirectory, "plugins");
Load(Path.Combine(dir, plugin + ".dll"), true);
string dir = Path.Combine(Program.AppDirectory, "plugins");
Load(Path.Combine(dir, plugin + ".dll"), true);
}
void Deny(WarningScreen warning, bool always) {
string plugin = (string)warning.Metadata;
void Deny(Overlay overlay, bool always) {
string plugin = (string)overlay.Metadata;
if (always && !denied.HasEntry(plugin)) {
denied.AddEntry(plugin);
}

View File

@ -68,7 +68,7 @@ namespace ClassicalSharp.Network {
public static string[] ClientExtensions = {
"ClickDistance", "CustomBlocks", "HeldBlock", "EmoteFix", "TextHotKey", "ExtPlayerList",
"EnvColors", "SelectionCuboid", "BlockPermissions", "ChangeModel", "EnvMapAppearance",
"EnvWeatherType", "HackControl", "MessageTypes", "PlayerClick", "FullCP437",
"EnvWeatherType", "MessageTypes", "PlayerClick", "FullCP437",
"LongerMessages", "BlockDefinitions", "BlockDefinitionsExt", "BulkBlockUpdate", "TextColors",
"EnvMapAspect", "EntityProperty", "ExtEntityPositions", "TwoWayPing", "InventoryOrder",
};

View File

@ -59,8 +59,8 @@ namespace ClassicalSharp {
protected Game game;
protected void WarningScreenTick(WarningScreen screen) {
string identifier = (string)screen.Metadata;
protected void WarningScreenTick(Overlay warning) {
string identifier = (string)warning.Metadata;
DownloadedItem item;
if (!game.AsyncDownloader.TryGetItem(identifier, out item) || item.Data == null) return;
@ -73,10 +73,8 @@ namespace ClassicalSharp {
if (url.StartsWith("https://")) address = url.Substring(8);
if (url.StartsWith("http://")) address = url.Substring(7);
screen.SetTextData("Do you want to download the server's texture pack?",
"Texture pack url:", address,
"Download size: " + contentLengthMB.ToString("F3") + " MB");
screen.RedrawText();
warning.lines[3] = "Download size: " + contentLengthMB.ToString("F3") + " MB";
warning.RedrawText();
}
protected internal void RetrieveTexturePack(string url) {
@ -86,30 +84,31 @@ namespace ClassicalSharp {
if (url.StartsWith("https://")) address = url.Substring(8);
if (url.StartsWith("http://")) address = url.Substring(7);
WarningScreen warning = new WarningScreen(game, true, true);
WarningOverlay warning = new WarningOverlay(game, true, true);
warning.Metadata = "CL_" + url;
warning.SetHandlers(DownloadTexturePack, SkipTexturePack, WarningScreenTick);
warning.SetHandlers(DownloadTexturePack, SkipTexturePack);
warning.OnRenderFrame = WarningScreenTick;
warning.lines[0] = "Do you want to download the server's texture pack?";
warning.SetTextData(
"Do you want to download the server's texture pack?",
"Texture pack url:", address,
"Download size: Determining...");
game.Gui.ShowWarning(warning);
warning.lines[1] = "Texture pack url:";
warning.lines[2] = address;
warning.lines[3] = "Download size: Determining...";
game.Gui.ShowOverlay(warning);
} else {
DownloadTexturePack(url);
}
}
void DownloadTexturePack(WarningScreen screen, bool always) {
string url = ((string)screen.Metadata).Substring(3);
void DownloadTexturePack(Overlay texPackOverlay, bool always) {
string url = ((string)texPackOverlay.Metadata).Substring(3);
DownloadTexturePack(url);
if (always && !game.AcceptedUrls.HasEntry(url)) {
game.AcceptedUrls.AddEntry(url);
}
}
void SkipTexturePack(WarningScreen screen, bool always) {
string url = ((string)screen.Metadata).Substring(3);
void SkipTexturePack(Overlay texPackOverlay, bool always) {
string url = ((string)texPackOverlay.Metadata).Substring(3);
if (always && !game.DeniedUrls.HasEntry(url)) {
game.DeniedUrls.AddEntry(url);
}

View File

@ -225,6 +225,7 @@
<ClInclude Include="Respawn.h" />
<ClInclude Include="SelectionBox.h" />
<ClInclude Include="SkyboxRenderer.h" />
<ClInclude Include="stb_image.h" />
<ClInclude Include="Stream.h" />
<ClInclude Include="GameStructs.h" />
<ClInclude Include="StringConvert.h" />

View File

@ -396,6 +396,9 @@
<ClInclude Include="TerrainAtlas.h">
<Filter>Header Files\TexturePack</Filter>
</ClInclude>
<ClInclude Include="stb_image.h">
<Filter>Header Files\TexturePack</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Noise.c">

View File

@ -3,6 +3,8 @@
#include "Platform.h"
#include "Window.h"
#include "GraphicsAPI.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
int main(int argc, char* argv[]) {
ErrorHandler_Init();