mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-23 17:43:08 -05:00
Rewrite code to avoid usage of Dictionary
This commit is contained in:
parent
7303e8c2e4
commit
db4275f571
25 changed files with 300 additions and 361 deletions
|
@ -1,79 +0,0 @@
|
|||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
#if ANDROID
|
||||
using System;
|
||||
using ClassicalSharp.GraphicsAPI;
|
||||
using Android.Graphics;
|
||||
using Android.Graphics.Drawables;
|
||||
using System.Drawing;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
public sealed partial class CanvasDrawer2D {
|
||||
|
||||
Bitmap measuringBmp;
|
||||
Canvas measuringC;
|
||||
|
||||
public CanvasDrawer2D(IGraphicsApi graphics) {
|
||||
this.graphics = graphics;
|
||||
measuringBmp = Bitmap.CreateBitmap(1, 1, Bitmap.Config.Argb8888);
|
||||
measuringC = new Canvas(measuringBmp);
|
||||
}
|
||||
|
||||
protected override void DrawSysText(ref DrawTextArgs args, int x, int y) {
|
||||
if (!args.SkipPartsCheck)
|
||||
GetTextParts(args.Text);
|
||||
|
||||
float textX = x;
|
||||
Paint backBrush = GetOrCreateBrush(FastColour.Black);
|
||||
for (int i = 0; i < parts.Count; i++) {
|
||||
TextPart part = parts[i];
|
||||
Paint foreBrush = GetOrCreateBrush(part.Col);
|
||||
if (args.UseShadow)
|
||||
c.DrawText(part.Text, textX + Offset, y + Offset, backBrush);
|
||||
|
||||
c.DrawText(part.Text, textX, y, foreBrush);
|
||||
textX += foreBrush.MeasureText(part.Text);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawClippedText(ref DrawTextArgs args, int x, int y, float maxWidth, float maxHeight) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
FastBitmap bitmapWrapper = new FastBitmap();
|
||||
protected override void DrawBitmappedText(ref DrawTextArgs args, int x, int y) {
|
||||
using (bitmapWrapper) {
|
||||
bitmapWrapper.SetData(curBmp, true, false);
|
||||
DrawBitmapTextImpl(bitmapWrapper, ref args, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureSysSize(ref DrawTextArgs args) {
|
||||
GetTextParts(args.Text);
|
||||
if (parts.Count == 0)
|
||||
return Size.Empty;
|
||||
|
||||
SizeF total = SizeF.Empty;
|
||||
for (int i = 0; i < parts.Count; i++) {
|
||||
TextPart part = parts[i];
|
||||
Paint textBrush = GetOrCreateBrush(part.Col);
|
||||
total.Width += textBrush.MeasureText(part.Text);
|
||||
}
|
||||
total.Height = PtToPx(args.Font.Size);
|
||||
if (args.UseShadow) {
|
||||
total.Width += Offset; total.Height += Offset;
|
||||
}
|
||||
return Size.Ceiling(total);
|
||||
}
|
||||
|
||||
int PtToPx(int point) {
|
||||
return (int)Math.Ceiling((float)point / 72 * 96); // TODO: not sure if even right, non 96 dpi?
|
||||
}
|
||||
|
||||
void DisposeText() {
|
||||
measuringC.Dispose();
|
||||
measuringBmp.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -2,16 +2,24 @@
|
|||
#if ANDROID
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ClassicalSharp.GraphicsAPI;
|
||||
using System.Drawing;
|
||||
using Android.Graphics;
|
||||
using Android.Graphics.Drawables;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
public sealed partial class CanvasDrawer2D : IDrawer2D {
|
||||
public sealed class CanvasDrawer2D : IDrawer2D {
|
||||
|
||||
Dictionary<int, Paint> brushCache = new Dictionary<int, Paint>(16);
|
||||
Bitmap curBmp;
|
||||
Canvas c;
|
||||
Dictionary<int, Paint> brushCache = new Dictionary<int, Paint>(16);
|
||||
Bitmap curBmp, measuringBmp;
|
||||
Canvas c, measuringC;
|
||||
|
||||
public CanvasDrawer2D(IGraphicsApi graphics) {
|
||||
this.graphics = graphics;
|
||||
measuringBmp = Bitmap.CreateBitmap(1, 1, Bitmap.Config.Argb8888);
|
||||
measuringC = new Canvas(measuringBmp);
|
||||
}
|
||||
|
||||
public override void SetBitmap(Bitmap bmp) {
|
||||
if (c != null) {
|
||||
|
@ -78,6 +86,62 @@ namespace ClassicalSharp {
|
|||
brushCache[key] = brush;
|
||||
return brush;
|
||||
}
|
||||
|
||||
protected override void DrawSysText(ref DrawTextArgs args, int x, int y) {
|
||||
if (!args.SkipPartsCheck)
|
||||
GetTextParts(args.Text);
|
||||
|
||||
float textX = x;
|
||||
Paint backBrush = GetOrCreateBrush(FastColour.Black);
|
||||
for (int i = 0; i < parts.Count; i++) {
|
||||
TextPart part = parts[i];
|
||||
Paint foreBrush = GetOrCreateBrush(part.Col);
|
||||
if (args.UseShadow)
|
||||
c.DrawText(part.Text, textX + Offset, y + Offset, backBrush);
|
||||
|
||||
c.DrawText(part.Text, textX, y, foreBrush);
|
||||
textX += foreBrush.MeasureText(part.Text);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawClippedText(ref DrawTextArgs args, int x, int y, float maxWidth, float maxHeight) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
FastBitmap bitmapWrapper = new FastBitmap();
|
||||
protected override void DrawBitmappedText(ref DrawTextArgs args, int x, int y) {
|
||||
using (bitmapWrapper) {
|
||||
bitmapWrapper.SetData(curBmp, true, false);
|
||||
DrawBitmapTextImpl(bitmapWrapper, ref args, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureSysSize(ref DrawTextArgs args) {
|
||||
GetTextParts(args.Text);
|
||||
if (parts.Count == 0)
|
||||
return Size.Empty;
|
||||
|
||||
SizeF total = SizeF.Empty;
|
||||
for (int i = 0; i < parts.Count; i++) {
|
||||
TextPart part = parts[i];
|
||||
Paint textBrush = GetOrCreateBrush(part.Col);
|
||||
total.Width += textBrush.MeasureText(part.Text);
|
||||
}
|
||||
total.Height = PtToPx(args.Font.Size);
|
||||
if (args.UseShadow) {
|
||||
total.Width += Offset; total.Height += Offset;
|
||||
}
|
||||
return Size.Ceiling(total);
|
||||
}
|
||||
|
||||
int PtToPx(int point) {
|
||||
return (int)Math.Ceiling((float)point / 72 * 96); // TODO: not sure if even right, non 96 dpi?
|
||||
}
|
||||
|
||||
void DisposeText() {
|
||||
measuringC.Dispose();
|
||||
measuringBmp.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
/// <summary> Contains arguments for measuring or drawing text. </summary>
|
||||
public struct DrawTextArgs {
|
||||
|
||||
public string Text;
|
||||
public Font Font;
|
||||
public bool UseShadow;
|
||||
public bool SkipPartsCheck;
|
||||
|
||||
public DrawTextArgs(string text, Font font, bool useShadow) {
|
||||
Text = text;
|
||||
Font = font;
|
||||
UseShadow = useShadow;
|
||||
SkipPartsCheck = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
#if !ANDROID
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
#if !LAUNCHER
|
||||
using ClassicalSharp.GraphicsAPI;
|
||||
#endif
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
public sealed partial class GdiPlusDrawer2D {
|
||||
|
||||
StringFormat format;
|
||||
Bitmap measuringBmp;
|
||||
Graphics measuringGraphics;
|
||||
|
||||
#if !LAUNCHER
|
||||
public GdiPlusDrawer2D(IGraphicsApi graphics) {
|
||||
this.graphics = graphics;
|
||||
#else
|
||||
public GdiPlusDrawer2D() {
|
||||
#endif
|
||||
format = StringFormat.GenericTypographic;
|
||||
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
|
||||
format.Trimming = StringTrimming.None;
|
||||
//format.FormatFlags |= StringFormatFlags.NoWrap;
|
||||
//format.FormatFlags |= StringFormatFlags.NoClip;
|
||||
|
||||
measuringBmp = new Bitmap(1, 1);
|
||||
measuringGraphics = Graphics.FromImage(measuringBmp);
|
||||
measuringGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||
}
|
||||
|
||||
protected override void DrawSysText(ref DrawTextArgs args, int x, int y) {
|
||||
if (!args.SkipPartsCheck)
|
||||
GetTextParts(args.Text);
|
||||
|
||||
float textX = x;
|
||||
Brush backBrush = GetOrCreateBrush(FastColour.Black);
|
||||
for (int i = 0; i < parts.Count; i++) {
|
||||
TextPart part = parts[i];
|
||||
Brush foreBrush = GetOrCreateBrush(part.Col);
|
||||
if (args.UseShadow)
|
||||
g.DrawString(part.Text, args.Font, backBrush, textX + Offset, y + Offset, format);
|
||||
|
||||
g.DrawString(part.Text, args.Font, foreBrush, textX, y, format);
|
||||
textX += g.MeasureString(part.Text, args.Font, Int32.MaxValue, format).Width;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawClippedText(ref DrawTextArgs args, int x, int y, float maxWidth, float maxHeight) {
|
||||
if (!args.SkipPartsCheck)
|
||||
GetTextParts(args.Text);
|
||||
|
||||
Brush shadowBrush = GetOrCreateBrush(FastColour.Black);
|
||||
StringFormatFlags flags = format.FormatFlags;
|
||||
format.FormatFlags |= StringFormatFlags.NoWrap;
|
||||
format.Trimming = StringTrimming.EllipsisCharacter;
|
||||
float textX = x;
|
||||
|
||||
for (int i = 0; i < parts.Count; i++) {
|
||||
TextPart part = parts[i];
|
||||
Brush textBrush = GetOrCreateBrush(part.Col);
|
||||
RectangleF rect = new RectangleF(textX + Offset, y + Offset, maxWidth, maxHeight);
|
||||
if (args.UseShadow)
|
||||
g.DrawString(part.Text, args.Font, shadowBrush, rect, format);
|
||||
|
||||
rect = new RectangleF(textX, y, maxWidth, maxHeight);
|
||||
g.DrawString(part.Text, args.Font, textBrush, rect, format);
|
||||
textX += g.MeasureString(part.Text, args.Font, Int32.MaxValue, format).Width;
|
||||
}
|
||||
format.Trimming = StringTrimming.None;
|
||||
format.FormatFlags = flags;
|
||||
}
|
||||
|
||||
FastBitmap bitmapWrapper = new FastBitmap();
|
||||
protected override void DrawBitmappedText(ref DrawTextArgs args, int x, int y) {
|
||||
using (bitmapWrapper) {
|
||||
bitmapWrapper.SetData(curBmp, true, false);
|
||||
DrawBitmapTextImpl(bitmapWrapper, ref args, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureSysSize(ref DrawTextArgs args) {
|
||||
GetTextParts(args.Text);
|
||||
int count = parts.Count;
|
||||
if (count == 0) return Size.Empty;
|
||||
|
||||
float width = 0, height = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
SizeF size = measuringGraphics.MeasureString(parts[i].Text, args.Font, Int32.MaxValue, format);
|
||||
height = Math.Max(height, size.Height);
|
||||
width += size.Width;
|
||||
}
|
||||
|
||||
if (args.UseShadow) { width += Offset; height += Offset; }
|
||||
return new Size((int)Math.Ceiling(width), (int)Math.Ceiling(height));
|
||||
}
|
||||
|
||||
void DisposeText() {
|
||||
measuringGraphics.Dispose();
|
||||
measuringBmp.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -5,14 +5,36 @@ using System.Collections.Generic;
|
|||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Text;
|
||||
#if !LAUNCHER
|
||||
using ClassicalSharp.GraphicsAPI;
|
||||
#endif
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
public sealed partial class GdiPlusDrawer2D : IDrawer2D {
|
||||
public sealed class GdiPlusDrawer2D : IDrawer2D {
|
||||
|
||||
Dictionary<int, SolidBrush> brushCache = new Dictionary<int, SolidBrush>(16);
|
||||
Graphics g;
|
||||
Bitmap curBmp;
|
||||
struct CachedBrush { public int ARGB; public SolidBrush Brush; }
|
||||
List<CachedBrush> brushes = new List<CachedBrush>(16);
|
||||
Graphics g, measuringGraphics;
|
||||
Bitmap curBmp, measuringBmp;
|
||||
StringFormat format;
|
||||
|
||||
#if !LAUNCHER
|
||||
public GdiPlusDrawer2D(IGraphicsApi graphics) {
|
||||
this.graphics = graphics;
|
||||
#else
|
||||
public GdiPlusDrawer2D() {
|
||||
#endif
|
||||
format = StringFormat.GenericTypographic;
|
||||
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
|
||||
format.Trimming = StringTrimming.None;
|
||||
//format.FormatFlags |= StringFormatFlags.NoWrap;
|
||||
//format.FormatFlags |= StringFormatFlags.NoClip;
|
||||
|
||||
measuringBmp = new Bitmap(1, 1);
|
||||
measuringGraphics = Graphics.FromImage(measuringBmp);
|
||||
measuringGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||
}
|
||||
|
||||
public override void SetBitmap(Bitmap bmp) {
|
||||
if (g != null) {
|
||||
|
@ -64,8 +86,8 @@ namespace ClassicalSharp {
|
|||
}
|
||||
|
||||
public override void DisposeInstance() {
|
||||
foreach (KeyValuePair<int, SolidBrush> pair in brushCache) {
|
||||
pair.Value.Dispose();
|
||||
for (int i = 0; i < brushes.Count; i++) {
|
||||
brushes[i].Brush.Dispose();
|
||||
}
|
||||
|
||||
DisposeText();
|
||||
|
@ -73,14 +95,85 @@ namespace ClassicalSharp {
|
|||
}
|
||||
|
||||
SolidBrush GetOrCreateBrush(FastColour col) {
|
||||
int key = col.ToArgb();
|
||||
SolidBrush brush;
|
||||
if (brushCache.TryGetValue(key, out brush))
|
||||
return brush;
|
||||
int argb = col.ToArgb();
|
||||
for (int i = 0; i < brushes.Count; i++) {
|
||||
if (brushes[i].ARGB == argb) return brushes[i].Brush;
|
||||
}
|
||||
|
||||
brush = new SolidBrush(col);
|
||||
brushCache[key] = brush;
|
||||
return brush;
|
||||
CachedBrush b; b.ARGB = argb; b.Brush = new SolidBrush(col);
|
||||
brushes.Add(b);
|
||||
return b.Brush;
|
||||
}
|
||||
|
||||
protected override void DrawSysText(ref DrawTextArgs args, int x, int y) {
|
||||
if (!args.SkipPartsCheck)
|
||||
GetTextParts(args.Text);
|
||||
|
||||
float textX = x;
|
||||
Brush backBrush = GetOrCreateBrush(FastColour.Black);
|
||||
for (int i = 0; i < parts.Count; i++) {
|
||||
TextPart part = parts[i];
|
||||
Brush foreBrush = GetOrCreateBrush(part.Col);
|
||||
if (args.UseShadow)
|
||||
g.DrawString(part.Text, args.Font, backBrush, textX + Offset, y + Offset, format);
|
||||
|
||||
g.DrawString(part.Text, args.Font, foreBrush, textX, y, format);
|
||||
textX += g.MeasureString(part.Text, args.Font, Int32.MaxValue, format).Width;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawClippedText(ref DrawTextArgs args, int x, int y, float maxWidth, float maxHeight) {
|
||||
if (!args.SkipPartsCheck)
|
||||
GetTextParts(args.Text);
|
||||
|
||||
Brush shadowBrush = GetOrCreateBrush(FastColour.Black);
|
||||
StringFormatFlags flags = format.FormatFlags;
|
||||
format.FormatFlags |= StringFormatFlags.NoWrap;
|
||||
format.Trimming = StringTrimming.EllipsisCharacter;
|
||||
float textX = x;
|
||||
|
||||
for (int i = 0; i < parts.Count; i++) {
|
||||
TextPart part = parts[i];
|
||||
Brush textBrush = GetOrCreateBrush(part.Col);
|
||||
RectangleF rect = new RectangleF(textX + Offset, y + Offset, maxWidth, maxHeight);
|
||||
if (args.UseShadow)
|
||||
g.DrawString(part.Text, args.Font, shadowBrush, rect, format);
|
||||
|
||||
rect = new RectangleF(textX, y, maxWidth, maxHeight);
|
||||
g.DrawString(part.Text, args.Font, textBrush, rect, format);
|
||||
textX += g.MeasureString(part.Text, args.Font, Int32.MaxValue, format).Width;
|
||||
}
|
||||
format.Trimming = StringTrimming.None;
|
||||
format.FormatFlags = flags;
|
||||
}
|
||||
|
||||
FastBitmap bitmapWrapper = new FastBitmap();
|
||||
protected override void DrawBitmappedText(ref DrawTextArgs args, int x, int y) {
|
||||
using (bitmapWrapper) {
|
||||
bitmapWrapper.SetData(curBmp, true, false);
|
||||
DrawBitmapTextImpl(bitmapWrapper, ref args, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureSysSize(ref DrawTextArgs args) {
|
||||
GetTextParts(args.Text);
|
||||
int count = parts.Count;
|
||||
if (count == 0) return Size.Empty;
|
||||
|
||||
float width = 0, height = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
SizeF size = measuringGraphics.MeasureString(parts[i].Text, args.Font, Int32.MaxValue, format);
|
||||
height = Math.Max(height, size.Height);
|
||||
width += size.Width;
|
||||
}
|
||||
|
||||
if (args.UseShadow) { width += Offset; height += Offset; }
|
||||
return new Size((int)Math.Ceiling(width), (int)Math.Ceiling(height));
|
||||
}
|
||||
|
||||
void DisposeText() {
|
||||
measuringGraphics.Dispose();
|
||||
measuringBmp.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,20 @@ using Android.Graphics;
|
|||
#endif
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
/// <summary> Contains arguments for measuring or drawing text. </summary>
|
||||
public struct DrawTextArgs {
|
||||
public string Text;
|
||||
public Font Font;
|
||||
public bool UseShadow, SkipPartsCheck;
|
||||
|
||||
public DrawTextArgs(string text, Font font, bool useShadow) {
|
||||
Text = text;
|
||||
Font = font;
|
||||
UseShadow = useShadow;
|
||||
SkipPartsCheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Class responsible for performing drawing operations on bitmaps
|
||||
/// and for converting bitmaps into graphics api textures. </summary>
|
||||
|
|
|
@ -142,13 +142,20 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
}
|
||||
|
||||
public void SetBlockTo(BlockID block) {
|
||||
selIndex = Array.IndexOf<BlockID>(blocksTable, block);
|
||||
selIndex = IndexOfBlock(block);
|
||||
scrollY = (selIndex / blocksPerRow) - (maxRows - 1);
|
||||
ClampScrollY();
|
||||
MoveCursorToSelected();
|
||||
RecreateBlockInfoTexture();
|
||||
}
|
||||
|
||||
int IndexOfBlock(BlockID block) {
|
||||
for (int i = 0; i < blocksTable.Length; i++) {
|
||||
if (blocksTable[i] == block) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MoveCursorToSelected() {
|
||||
if (selIndex == -1) return;
|
||||
game.DesktopCursorPos = GetMouseCoords(selIndex);
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
|
||||
void DefaultButtonClick(Game game, Widget widget, MouseButton btn, int x, int y) {
|
||||
if (btn != MouseButton.Left) return;
|
||||
int index = Array.IndexOf<Widget>(widgets, targetWidget);
|
||||
int index = IndexOfWidget(targetWidget);
|
||||
string defValue = defaultValues[index];
|
||||
|
||||
input.Clear();
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
}
|
||||
|
||||
void HandleFontChange() {
|
||||
int selIndex = Array.IndexOf<Widget>(widgets, selectedWidget);
|
||||
int selIndex = IndexOfWidget(selectedWidget);
|
||||
game.Events.RaiseChatFontChanged();
|
||||
base.Dispose();
|
||||
base.Init();
|
||||
|
|
|
@ -168,7 +168,7 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
|
||||
void DefaultButtonClick(Game game, Widget widget, MouseButton btn, int x, int y) {
|
||||
if (btn != MouseButton.Left) return;
|
||||
int index = Array.IndexOf<Widget>(widgets, targetWidget);
|
||||
int index = IndexOfWidget(targetWidget);
|
||||
string defValue = defaultValues[index];
|
||||
|
||||
input.Clear();
|
||||
|
|
|
@ -90,19 +90,19 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
int index = 0;
|
||||
if (btn == MouseButton.Right && (curWidget == null || curWidget == widget)) {
|
||||
curWidget = (ButtonWidget)widget;
|
||||
index = Array.IndexOf<Widget>(widgets, curWidget) - 2;
|
||||
index = IndexOfWidget(curWidget) - 2;
|
||||
KeyBind mapping = Get(index, left, right);
|
||||
HandlesKeyDown(game.Input.Keys.GetDefault(mapping));
|
||||
}
|
||||
if (btn != MouseButton.Left) return;
|
||||
|
||||
if (curWidget != null) {
|
||||
index = Array.IndexOf<Widget>(widgets, curWidget) - 2;
|
||||
index = IndexOfWidget(curWidget) - 2;
|
||||
curWidget.SetText(ButtonText(index));
|
||||
curWidget = null;
|
||||
}
|
||||
|
||||
index = Array.IndexOf<Widget>(widgets, widget) - 2;
|
||||
index = IndexOfWidget(widget) - 2;
|
||||
string text = ButtonText(index);
|
||||
curWidget = (ButtonWidget)widget;
|
||||
curWidget.SetText("> " + text + " <");
|
||||
|
@ -119,7 +119,7 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
if (key == Key.Escape) {
|
||||
game.Gui.SetNewScreen(null);
|
||||
} else if (curWidget != null) {
|
||||
int index = Array.IndexOf<Widget>(widgets, curWidget) - 2;
|
||||
int index = IndexOfWidget(curWidget) - 2;
|
||||
KeyBind mapping = Get(index, left, right);
|
||||
game.Input.Keys[mapping] = key;
|
||||
curWidget.SetText(ButtonText(index));
|
||||
|
|
|
@ -149,7 +149,7 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
bool canShow = input == null && selectedWidget != null && descriptions != null;
|
||||
if (!canShow) return;
|
||||
|
||||
int index = Array.IndexOf<Widget>(widgets, selectedWidget);
|
||||
int index = IndexOfWidget(selectedWidget);
|
||||
if (index < 0 || index >= descriptions.Length) return;
|
||||
string[] desc = descriptions[index];
|
||||
if (desc == null) return;
|
||||
|
@ -186,7 +186,7 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
if (button == null) return;
|
||||
DisposeExtendedHelp();
|
||||
|
||||
int index = Array.IndexOf<Widget>(widgets, button);
|
||||
int index = IndexOfWidget(button);
|
||||
MenuInputValidator validator = validators[index];
|
||||
if (validator is BooleanValidator) {
|
||||
string value = button.GetValue(game);
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
if (descWidget != null) descWidget.Dispose();
|
||||
if (button == null) return;
|
||||
|
||||
string text = descriptions[Array.IndexOf<Widget>(widgets, button)];
|
||||
string text = descriptions[IndexOfWidget(button)];
|
||||
MakeDescWidget(text);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,13 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
protected Font titleFont, regularFont;
|
||||
protected FastColour backCol = new FastColour(60, 60, 60, 160);
|
||||
|
||||
protected int IndexOfWidget(Widget w) {
|
||||
for (int i = 0; i < widgets.Length; i++) {
|
||||
if (widgets[i] == w) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected void RenderMenuBounds() {
|
||||
gfx.Draw2DQuad(0, 0, game.Width, game.Height, backCol);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
|
||||
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;
|
||||
bool always = IndexOfWidget(w) >= alwaysIndex;
|
||||
|
||||
if (yesClick != null) yesClick(this, always);
|
||||
Dispose();
|
||||
|
@ -75,7 +75,7 @@ namespace ClassicalSharp.Gui.Screens {
|
|||
|
||||
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;
|
||||
bool always = IndexOfWidget(w) >= alwaysIndex;
|
||||
|
||||
if (confirmNo && !confirmingMode) {
|
||||
confirmingMode = true;
|
||||
|
|
|
@ -78,12 +78,9 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="2D\Drawing\CanvasDrawer2D.cs" />
|
||||
<Compile Include="2D\Drawing\CanvasDrawer2D.Text.cs" />
|
||||
<Compile Include="2D\Drawing\GdiPlusDrawer2D.Text.cs" />
|
||||
<Compile Include="2D\Drawing\IDrawer2D.TextMC.cs" />
|
||||
<Compile Include="2D\GuiElement.cs" />
|
||||
<Compile Include="2D\IsometricBlockDrawer.cs" />
|
||||
<Compile Include="2D\Drawing\DrawTextArgs.cs" />
|
||||
<Compile Include="2D\Drawing\GdiPlusDrawer2D.cs" />
|
||||
<Compile Include="2D\Drawing\IDrawer2D.cs" />
|
||||
<Compile Include="2D\Screens\ChatScreen.cs" />
|
||||
|
|
|
@ -119,7 +119,7 @@ namespace ClassicalSharp.Entities {
|
|||
fetchedSkin = true;
|
||||
}
|
||||
|
||||
DownloadedItem item;
|
||||
Request item;
|
||||
if (!game.AsyncDownloader.TryGetItem(SkinName, out item)) return;
|
||||
if (item == null || item.Data == null) { SetSkinAll(true); return; }
|
||||
|
||||
|
|
|
@ -112,21 +112,24 @@ namespace ClassicalSharp.Map {
|
|||
NbtList list = new NbtList();
|
||||
list.ChildTagId = (NbtTagType)reader.ReadByte();
|
||||
list.ChildrenValues = new object[ReadInt32()];
|
||||
for (int i = 0; i < list.ChildrenValues.Length; i++)
|
||||
for (int i = 0; i < list.ChildrenValues.Length; i++) {
|
||||
list.ChildrenValues[i] = ReadTag((byte)list.ChildTagId, false).Value;
|
||||
}
|
||||
tag.Value = list; break;
|
||||
|
||||
case NbtTagType.Compound:
|
||||
Dictionary<string, NbtTag> children = new Dictionary<string, NbtTag>();
|
||||
NbtTag child;
|
||||
while ((child = ReadTag(reader.ReadByte(), true)).TagId != NbtTagType.Invalid)
|
||||
while ((child = ReadTag(reader.ReadByte(), true)).TagId != NbtTagType.Invalid) {
|
||||
children[child.Name] = child;
|
||||
}
|
||||
tag.Value = children; break;
|
||||
|
||||
case NbtTagType.Int32Array:
|
||||
int[] array = new int[ReadInt32()];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
array[i] = ReadInt32();
|
||||
}
|
||||
tag.Value = array; break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace ClassicalSharp {
|
|||
|
||||
protected void WarningScreenTick(Overlay warning) {
|
||||
string identifier = warning.Metadata;
|
||||
DownloadedItem item;
|
||||
Request item;
|
||||
if (!game.AsyncDownloader.TryGetItem(identifier, out item) || item.Data == null) return;
|
||||
|
||||
long contentLength = (long)item.Data;
|
||||
|
@ -130,7 +130,7 @@ namespace ClassicalSharp {
|
|||
}
|
||||
|
||||
protected void CheckAsyncResources() {
|
||||
DownloadedItem item;
|
||||
Request item;
|
||||
if (game.AsyncDownloader.TryGetItem("terrain", out item)) {
|
||||
TexturePack.ExtractTerrainPng(game, item);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace ClassicalSharp.Network.Protocols {
|
|||
internal bool sendWomId = false, sentWomId = false;
|
||||
|
||||
public override void Tick() {
|
||||
DownloadedItem item;
|
||||
Request item;
|
||||
game.AsyncDownloader.TryGetItem(womEnvIdentifier, out item);
|
||||
if (item != null && item.Data != null) {
|
||||
ParseWomConfig((string)item.Data);
|
||||
|
|
|
@ -22,10 +22,10 @@ namespace ClassicalSharp.Network {
|
|||
|
||||
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
|
||||
Thread worker;
|
||||
readonly object requestLocker = new object();
|
||||
List<Request> requests = new List<Request>();
|
||||
readonly object downloadedLocker = new object();
|
||||
Dictionary<string, DownloadedItem> downloaded = new Dictionary<string, DownloadedItem>();
|
||||
readonly object pendingLocker = new object();
|
||||
List<Request> pending = new List<Request>();
|
||||
readonly object processedLocker = new object();
|
||||
List<Request> processed = new List<Request>();
|
||||
string skinServer = null;
|
||||
readonly IDrawer2D drawer;
|
||||
|
||||
|
@ -38,8 +38,8 @@ namespace ClassicalSharp.Network {
|
|||
public void Init(Game game) { Init(game.skinServer); }
|
||||
public void Ready(Game game) { }
|
||||
public void Reset(Game game) {
|
||||
lock (requestLocker)
|
||||
requests.Clear();
|
||||
lock (pendingLocker)
|
||||
pending.Clear();
|
||||
handle.Set();
|
||||
}
|
||||
|
||||
|
@ -113,12 +113,12 @@ namespace ClassicalSharp.Network {
|
|||
|
||||
void AddRequest(string url, bool priority, string identifier,
|
||||
RequestType type, DateTime lastModified, string etag) {
|
||||
lock (requestLocker) {
|
||||
lock (pendingLocker) {
|
||||
Request request = new Request(url, identifier, type, lastModified, etag);
|
||||
if (priority) {
|
||||
requests.Insert(0, request);
|
||||
pending.Insert(0, request);
|
||||
} else {
|
||||
requests.Add(request);
|
||||
pending.Add(request);
|
||||
}
|
||||
}
|
||||
handle.Set();
|
||||
|
@ -129,8 +129,8 @@ namespace ClassicalSharp.Network {
|
|||
/// Note that this will *block** the calling thread as the method waits until the asynchronous
|
||||
/// thread has exited the for loop. </summary>
|
||||
public void Dispose() {
|
||||
lock (requestLocker) {
|
||||
requests.Insert(0, null);
|
||||
lock (pendingLocker) {
|
||||
pending.Insert(0, null);
|
||||
}
|
||||
|
||||
handle.Set();
|
||||
|
@ -142,26 +142,14 @@ namespace ClassicalSharp.Network {
|
|||
/// <summary> Removes older entries that were downloaded a certain time ago
|
||||
/// but were never removed from the downloaded queue. </summary>
|
||||
public void PurgeOldEntriesTask(ScheduledTask task) {
|
||||
const int seconds = 10;
|
||||
lock (downloadedLocker) {
|
||||
lock (processedLocker) {
|
||||
DateTime now = DateTime.UtcNow;
|
||||
List<string> itemsToRemove = new List<string>(downloaded.Count);
|
||||
|
||||
foreach (var item in downloaded) {
|
||||
DateTime timestamp = item.Value.TimeDownloaded;
|
||||
if ((now - timestamp).TotalSeconds > seconds) {
|
||||
itemsToRemove.Add(item.Key);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < itemsToRemove.Count; i++) {
|
||||
string key = itemsToRemove[i];
|
||||
DownloadedItem item;
|
||||
downloaded.TryGetValue(key, out item);
|
||||
downloaded.Remove(key);
|
||||
Bitmap bmp = item.Data as Bitmap;
|
||||
if (bmp != null)
|
||||
bmp.Dispose();
|
||||
for (int i = processed.Count - 1; i >= 0; i--) {
|
||||
Request item = processed[i];
|
||||
if ((now - item.TimeDownloaded).TotalSeconds < 10) continue;
|
||||
|
||||
item.Dispose();
|
||||
processed.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,13 +159,12 @@ namespace ClassicalSharp.Network {
|
|||
/// If it does, it removes the item from the queue and outputs it. </summary>
|
||||
/// <remarks> If the asynchronous thread failed to download the item, this method
|
||||
/// will return 'true' and 'item' will be set. However, the contents of the 'item' object will be null.</remarks>
|
||||
public bool TryGetItem(string identifier, out DownloadedItem item) {
|
||||
public bool TryGetItem(string identifier, out Request item) {
|
||||
bool success = false;
|
||||
lock (downloadedLocker) {
|
||||
success = downloaded.TryGetValue(identifier, out item);
|
||||
if (success) {
|
||||
downloaded.Remove(identifier);
|
||||
}
|
||||
lock (processedLocker) {
|
||||
int i = FindRequest(identifier, out item);
|
||||
success = i >= 0;
|
||||
if (success) processed.RemoveAt(i);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
@ -185,14 +172,14 @@ namespace ClassicalSharp.Network {
|
|||
void DownloadThreadWorker() {
|
||||
while (true) {
|
||||
Request request = null;
|
||||
lock (requestLocker) {
|
||||
if (requests.Count > 0) {
|
||||
request = requests[0];
|
||||
requests.RemoveAt(0);
|
||||
if (request == null)
|
||||
return;
|
||||
lock (pendingLocker) {
|
||||
if (pending.Count > 0) {
|
||||
request = pending[0];
|
||||
pending.RemoveAt(0);
|
||||
if (request == null) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (request != null) {
|
||||
CurrentItem = request;
|
||||
CurrentItemProgress = -2;
|
||||
|
@ -206,21 +193,30 @@ namespace ClassicalSharp.Network {
|
|||
}
|
||||
}
|
||||
|
||||
int FindRequest(string identifer, out Request item) {
|
||||
item = null;
|
||||
for (int i = 0; i < processed.Count; i++) {
|
||||
if (processed[i].Identifier != identifer) continue;
|
||||
item = processed[i];
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ProcessRequest(Request request) {
|
||||
string url = request.Url;
|
||||
Utils.LogDebug("Downloading {0} from: {1}", request.Type, url);
|
||||
object value = null;
|
||||
HttpStatusCode status = HttpStatusCode.OK;
|
||||
string etag = null;
|
||||
DateTime lastModified = DateTime.MinValue;
|
||||
request.Data = null;
|
||||
|
||||
try {
|
||||
HttpWebRequest req = MakeRequest(request);
|
||||
using (HttpWebResponse response = (HttpWebResponse)req.GetResponse()) {
|
||||
etag = response.Headers[HttpResponseHeader.ETag];
|
||||
if (response.Headers[HttpResponseHeader.LastModified] != null)
|
||||
lastModified = response.LastModified;
|
||||
value = DownloadContent(request, response);
|
||||
request.ETag = response.Headers[HttpResponseHeader.ETag];
|
||||
if (response.Headers[HttpResponseHeader.LastModified] != null) {
|
||||
request.LastModified = response.LastModified;
|
||||
}
|
||||
request.Data = DownloadContent(request, response);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (!(ex is WebException || ex is ArgumentException || ex is UriFormatException || ex is IOException)) throw;
|
||||
|
@ -239,24 +235,24 @@ namespace ClassicalSharp.Network {
|
|||
Utils.LogDebug("Failed to download from: " + url);
|
||||
}
|
||||
}
|
||||
value = CheckIsValidImage(value, url);
|
||||
|
||||
lock (downloadedLocker) {
|
||||
DownloadedItem oldItem;
|
||||
DownloadedItem newItem = new DownloadedItem(value, request.TimeAdded, url,
|
||||
status, etag, lastModified);
|
||||
|
||||
request.Data = CheckIsValidImage(request.Data, url);
|
||||
request.TimeDownloaded = DateTime.UtcNow;
|
||||
|
||||
lock (processedLocker) {
|
||||
Request older;
|
||||
int index = FindRequest(request.Identifier, out older);
|
||||
|
||||
if (downloaded.TryGetValue(request.Identifier, out oldItem)) {
|
||||
if (oldItem.TimeAdded > newItem.TimeAdded) {
|
||||
DownloadedItem old = oldItem;
|
||||
oldItem = newItem;
|
||||
newItem = old;
|
||||
if (index >= 0) {
|
||||
if (older.TimeAdded > request.TimeAdded) {
|
||||
Request tmp = older; older = request; request = tmp;
|
||||
}
|
||||
|
||||
Bitmap oldBmp = oldItem.Data as Bitmap;
|
||||
if (oldBmp != null) oldBmp.Dispose();
|
||||
|
||||
older.Dispose();
|
||||
processed[index] = request;
|
||||
} else {
|
||||
processed.Add(request);
|
||||
}
|
||||
downloaded[request.Identifier] = newItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,25 +327,25 @@ namespace ClassicalSharp.Network {
|
|||
public sealed class Request {
|
||||
|
||||
/// <summary> Full url to GET from. </summary>
|
||||
public string Url;
|
||||
|
||||
public string Url;
|
||||
/// <summary> Unique identifier for this request. </summary>
|
||||
public string Identifier;
|
||||
|
||||
public string Identifier;
|
||||
/// <summary> Type of data to return for this request. </summary>
|
||||
public RequestType Type;
|
||||
|
||||
/// <summary> Point in time this request was added to the fetch queue. </summary>
|
||||
public DateTime TimeAdded;
|
||||
/// <summary> Point in time the item was fully downloaded. </summary>
|
||||
public DateTime TimeDownloaded;
|
||||
/// <summary> Contents that were downloaded. </summary>
|
||||
public object Data;
|
||||
|
||||
/// <summary> Point in time the item most recently cached. (if at all) </summary>
|
||||
public DateTime LastModified;
|
||||
|
||||
public DateTime LastModified;
|
||||
/// <summary> ETag of the item most recently cached. (if any) </summary>
|
||||
public string ETag;
|
||||
|
||||
public Request(string url, string identifier, RequestType type,
|
||||
DateTime lastModified, string etag) {
|
||||
public Request(string url, string identifier, RequestType type, DateTime lastModified, string etag) {
|
||||
Url = url;
|
||||
Identifier = identifier;
|
||||
Type = type;
|
||||
|
@ -357,38 +353,10 @@ namespace ClassicalSharp.Network {
|
|||
LastModified = lastModified;
|
||||
ETag = etag;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Represents an item that was asynchronously downloaded. </summary>
|
||||
public class DownloadedItem {
|
||||
|
||||
/// <summary> Contents that were downloaded. </summary>
|
||||
public object Data;
|
||||
|
||||
/// <summary> Point in time the item was originally added to the download queue. </summary>
|
||||
public DateTime TimeAdded;
|
||||
|
||||
/// <summary> Point in time the item was fully downloaded. </summary>
|
||||
public DateTime TimeDownloaded;
|
||||
|
||||
/// <summary> Full URL this item was downloaded from. </summary>
|
||||
public string Url;
|
||||
|
||||
/// <summary> Unique identifier assigned by the server to this item. </summary>
|
||||
public string ETag;
|
||||
|
||||
/// <summary> Time the server indicates this item was last modified. </summary>
|
||||
public DateTime LastModified;
|
||||
|
||||
public DownloadedItem(object data, DateTime timeAdded,
|
||||
string url, HttpStatusCode code,
|
||||
string etag, DateTime lastModified) {
|
||||
Data = data;
|
||||
TimeAdded = timeAdded;
|
||||
TimeDownloaded = DateTime.UtcNow;
|
||||
Url = url;
|
||||
ETag = etag;
|
||||
LastModified = lastModified;
|
||||
public void Dispose() {
|
||||
Bitmap bmp = Data as Bitmap;
|
||||
if (bmp != null) bmp.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,7 +62,7 @@ namespace ClassicalSharp.Textures {
|
|||
}
|
||||
|
||||
|
||||
internal static void ExtractTerrainPng(Game game, DownloadedItem item) {
|
||||
internal static void ExtractTerrainPng(Game game, Request item) {
|
||||
if (item.Data == null) return;
|
||||
game.World.TextureUrl = item.Url;
|
||||
game.Events.RaiseTexturePackChanged();
|
||||
|
@ -101,7 +101,7 @@ namespace ClassicalSharp.Textures {
|
|||
ms.Dispose();
|
||||
}
|
||||
|
||||
internal static void ExtractTexturePack(Game game, DownloadedItem item) {
|
||||
internal static void ExtractTexturePack(Game game, Request item) {
|
||||
if (item.Data == null) return;
|
||||
game.World.TextureUrl = item.Url;
|
||||
byte[] data = (byte[])item.Data;
|
||||
|
|
|
@ -57,15 +57,9 @@
|
|||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\ClassicalSharp\2D\Drawing\DrawTextArgs.cs">
|
||||
<Link>Shared\DrawTextArgs.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\ClassicalSharp\2D\Drawing\GdiPlusDrawer2D.cs">
|
||||
<Link>Shared\GdiPlusDrawer2D.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\ClassicalSharp\2D\Drawing\GdiPlusDrawer2D.Text.cs">
|
||||
<Link>Shared\GdiPlusDrawer2D.Text.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\ClassicalSharp\2D\Drawing\IDrawer2D.cs">
|
||||
<Link>Shared\IDrawer2D.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace Launcher.Patcher {
|
|||
}
|
||||
|
||||
bool Download(string identifier, ref byte[] data, Action<string> setStatus) {
|
||||
DownloadedItem item;
|
||||
Request item;
|
||||
if (downloader.TryGetItem(identifier, out item)) {
|
||||
FilesToDownload.RemoveAt(0);
|
||||
Console.WriteLine("got resource " + identifier);
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace Launcher.Patcher {
|
|||
public bool CheckDownloaded(ResourceFetcher fetcher, Action<string> setStatus) {
|
||||
if (Done) return true;
|
||||
for (int i = 0; i < identifiers.Length; i++) {
|
||||
DownloadedItem item;
|
||||
Request item;
|
||||
if (fetcher.downloader.TryGetItem(identifiers[i], out item)) {
|
||||
fetcher.FilesToDownload.RemoveAt(0);
|
||||
Console.WriteLine("got sound " + identifiers[i]);
|
||||
|
|
Loading…
Add table
Reference in a new issue