Refactor most 2D operations, further reduce memory allocations.

This commit is contained in:
UnknownShadow200 2015-05-09 18:37:20 +10:00
parent df8719e4ba
commit 989870e623
20 changed files with 217 additions and 267 deletions

View File

@ -6,8 +6,6 @@ namespace ClassicalSharp {
public class DrawTextArgs {
public float XOffset, YOffset;
public Color TextColour;
public string Text;
@ -16,22 +14,15 @@ namespace ClassicalSharp {
public IGraphicsApi Graphics;
public DrawTextArgs( IGraphicsApi graphics, string text, Color col, bool useShadow ) :
this( graphics, text, col, useShadow, Color.Black, 0f, 0f ) {
this( graphics, text, col, useShadow, Color.Black ) {
}
public DrawTextArgs( IGraphicsApi graphics, string text, Color col, bool useShadow, Color shadowCol ) :
this( graphics, text, col, useShadow, shadowCol, 0f, 0f ) {
}
public DrawTextArgs( IGraphicsApi graphics, string text, Color col,
bool useShadow, Color shadowCol, float x, float y ) {
public DrawTextArgs( IGraphicsApi graphics, string text, Color col, bool useShadow, Color shadowCol ) {
Graphics = graphics;
Text = text;
TextColour = col;
UseShadow = useShadow;
ShadowColour = shadowCol;
XOffset = x;
YOffset = y;
}
}
}

View File

@ -8,6 +8,7 @@ namespace ClassicalSharp {
public class BlockSelectScreen : Screen {
public BlockSelectScreen( Game window ) : base( window ) {
font = new Font( "Arial", 13 );
}
class BlockDrawInfo {
@ -26,6 +27,7 @@ namespace ClassicalSharp {
const int blocksPerRow = 10;
int rows;
int startX, startY;
readonly Font font;
public override void Render( double delta ) {
GraphicsApi.Texturing = true;
@ -49,6 +51,7 @@ namespace ClassicalSharp {
}
public override void Dispose() {
font.Dispose();
GraphicsApi.DeleteTexture( ref selectedBlock );
GraphicsApi.DeleteTexture( ref blockInfoTexture );
Window.BlockPermissionsChanged -= BlockPermissionsChanged;
@ -107,14 +110,14 @@ namespace ClassicalSharp {
Block block = blocksTable[selectedIndex].BlockId;
string text = GetBlockInfo( block );
List<DrawTextArgs> parts = Utils.SplitText( GraphicsApi, text, true );
Size size = Utils2D.MeasureSize( parts, "Arial", 13, true );
Size size = Utils2D.MeasureSize( parts, font, true );
int x = startX + ( blockSize * blocksPerRow ) / 2 - size.Width / 2;
int y = startY - size.Height;
using( Bitmap bmp = new Bitmap( size.Width, size.Height ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
Utils2D.DrawRect( g, backColour, bmp.Width, bmp.Height );
Utils2D.DrawText( g, parts, "Arial", 13 );
Utils2D.DrawRect( g, backColour, 0, 0, bmp.Width, bmp.Height );
Utils2D.DrawText( g, parts, font, 0, 0 );
}
blockInfoTexture = Utils2D.Make2DTexture( GraphicsApi, bmp, x, y );
}
@ -166,14 +169,14 @@ namespace ClassicalSharp {
public override bool HandlesMouseMove( int mouseX, int mouseY ) {
selectedIndex = -1;
if( Utils2D.Contains( startX, startY, blocksPerRow * blockSize, rows * blockSize, mouseX, mouseY ) ) {
if( Contains( startX, startY, blocksPerRow * blockSize, rows * blockSize, mouseX, mouseY ) ) {
for( int i = 0; i < blocksTable.Length; i++ ) {
int col = i % blocksPerRow;
int row = i / blocksPerRow;
int x = startX + blockSize * col;
int y = startY + blockSize * row;
if( Utils2D.Contains( x, y, blockSize, blockSize, mouseX, mouseY ) ) {
if( Contains( x, y, blockSize, blockSize, mouseX, mouseY ) ) {
selectedIndex = i;
break;
}
@ -198,5 +201,9 @@ namespace ClassicalSharp {
}
return true;
}
static bool Contains( int recX, int recY, int width, int height, int x, int y ) {
return x >= recX && y >= recY && x < recX + width && y < recY + height;
}
}
}

View File

@ -43,20 +43,25 @@ namespace ClassicalSharp {
}
}
Font chatFont, chatBoldFont, historyFont, announcementFont;
public override void Init() {
int fontSize = Window.ChatFontSize;
textInput = new TextInputWidget( Window, fontSize );
chatFont = new Font( "Arial", Window.ChatFontSize );
chatBoldFont = new Font( "Arial", Window.ChatFontSize, FontStyle.Bold );
announcementFont = new Font( "Arial", 14 );
historyFont = new Font( "Arial", 12, FontStyle.Italic );
textInput = new TextInputWidget( Window, chatFont, chatBoldFont );
textInput.ChatInputYOffset = ChatInputYOffset;
status = new TextGroupWidget( Window, 3, fontSize );
status = new TextGroupWidget( Window, 3, chatFont );
status.VerticalDocking = Docking.LeftOrTop;
status.HorizontalDocking = Docking.BottomOrRight;
status.Init();
bottomRight = new TextGroupWidget( Window, 3, fontSize );
bottomRight = new TextGroupWidget( Window, 3, chatFont );
bottomRight.VerticalDocking = Docking.BottomOrRight;
bottomRight.HorizontalDocking = Docking.BottomOrRight;
bottomRight.YOffset = ChatInputYOffset;
bottomRight.Init();
normalChat = new TextGroupWidget( Window, chatLines, fontSize );
normalChat = new TextGroupWidget( Window, chatLines, chatFont );
normalChat.XOffset = 10;
normalChat.YOffset = ChatLogYOffset;
normalChat.HorizontalDocking = Docking.LeftOrTop;
@ -94,6 +99,11 @@ namespace ClassicalSharp {
if( !String.IsNullOrEmpty( textInput.chatInputText ) ) {
Window.chatInInputBuffer = textInput.chatInputText;
}
chatFont.Dispose();
chatBoldFont.Dispose();
historyFont.Dispose();
announcementFont.Dispose();
normalChat.Dispose();
textInput.Dispose();
status.Dispose();
@ -133,10 +143,10 @@ namespace ClassicalSharp {
announcementDisplayTime = DateTime.UtcNow;
if( !String.IsNullOrEmpty( text ) ) {
List<DrawTextArgs> parts = Utils.SplitText( GraphicsApi, text, true );
Size size = Utils2D.MeasureSize( Utils.StripColours( text ), "Arial", 14, true );
Size size = Utils2D.MeasureSize( Utils.StripColours( text ), announcementFont, true );
int x = Window.Width / 2 - size.Width / 2;
int y = Window.Height / 4 - size.Height / 2;
announcementTexture = Utils2D.MakeTextTexture( parts, "Arial", 14, size, x, y );
announcementTexture = Utils2D.MakeTextTexture( parts, announcementFont, size, x, y );
} else {
announcementTexture = new Texture( -1, 0, 0, 0, 0, 0, 0 );
}
@ -215,14 +225,14 @@ namespace ClassicalSharp {
void MakePageNumberTexture() {
GraphicsApi.DeleteTexture( ref pageTexture );
string text = "Page " + pageNumber + " of " + pagesCount;
Size size = Utils2D.MeasureSize( text, "Arial", 12, FontStyle.Italic, false );
Size size = Utils2D.MeasureSize( text, historyFont, false );
int y = normalChat.CalcUsedY() - size.Height;
using( Bitmap bmp = new Bitmap( size.Width, size.Height ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
Utils2D.DrawRect( g, backColour, bmp.Width, bmp.Height );
Utils2D.DrawRect( g, backColour, 0, 0, bmp.Width, bmp.Height );
DrawTextArgs args = new DrawTextArgs( GraphicsApi, text, Color.Yellow, false );
Utils2D.DrawText( g, "Arial", 12, FontStyle.Italic, args );
Utils2D.DrawText( g, historyFont, args, 0, 0 );
}
pageTexture = Utils2D.Make2DTexture( GraphicsApi, bmp, 10, y );
}

View File

@ -7,9 +7,12 @@ namespace ClassicalSharp {
public class ErrorScreen : Screen {
string title, message;
readonly Font titleFont, messageFont;
public ErrorScreen( Game window, string title, string message ) : base( window ) {
this.title = title;
this.message = message;
titleFont = new Font( "Arial", 16, FontStyle.Bold );
messageFont = new Font( "Arial", 14, FontStyle.Regular );
}
Texture titleTexture, messageTexture;
@ -21,21 +24,23 @@ namespace ClassicalSharp {
public override void Init() {
GraphicsApi.ClearColour( new FastColour( 65, 31, 31 ) );
titleTexture = ModifyText( 30, title, 16, FontStyle.Bold );
messageTexture = ModifyText( -10, message, 14, FontStyle.Regular );
titleTexture = ModifyText( 30, title, titleFont );
messageTexture = ModifyText( -10, message, messageFont );
}
public override void Dispose() {
titleFont.Dispose();
messageFont.Dispose();
GraphicsApi.DeleteTexture( ref titleTexture );
GraphicsApi.DeleteTexture( ref messageTexture );
}
Texture ModifyText( int yOffset, string text, int fontSize, FontStyle style ) {
Texture ModifyText( int yOffset, string text, Font font ) {
List<DrawTextArgs> parts = Utils.SplitText( GraphicsApi, text, true );
Size size = Utils2D.MeasureSize( Utils.StripColours( text ), "Arial", fontSize, style, true );
Size size = Utils2D.MeasureSize( Utils.StripColours( text ), font, true );
int x = Window.Width / 2 - size.Width / 2;
int y = Window.Height / 2 - yOffset;
return Utils2D.MakeTextTexture( parts, "Arial", fontSize, style, size, x, y );
return Utils2D.MakeTextTexture( parts, font, size, x, y );
}
public override void OnResize( int oldWidth, int oldHeight, int width, int height ) {

View File

@ -1,10 +1,13 @@
using System;
using System.Drawing;
namespace ClassicalSharp {
public class FpsScreen : Screen {
readonly Font font;
public FpsScreen( Game window ) : base( window ) {
font = new Font( "Arial", 13 );
}
TextWidget fpsTextWidget;
@ -36,12 +39,13 @@ namespace ClassicalSharp {
}
public override void Init() {
fpsTextWidget = new TextWidget( Window, 13 );
fpsTextWidget = new TextWidget( Window, font );
fpsTextWidget.Init();
fpsTextWidget.SetText( "FPS: no data yet" );
}
public override void Dispose() {
font.Dispose();
fpsTextWidget.Dispose();
}
}

View File

@ -4,10 +4,12 @@ using System.Drawing;
namespace ClassicalSharp {
public class LoadingMapScreen : Screen {
readonly Font font;
public LoadingMapScreen( Game window, string name, string motd ) : base( window ) {
serverName = name;
serverMotd = motd;
font = new Font( "Arial", 14 );
}
string serverName, serverMotd;
@ -32,7 +34,7 @@ namespace ClassicalSharp {
progX = Window.Width / 2f - progWidth / 2f;
using( Bitmap bmp = new Bitmap( progWidth, progHeight ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
Utils2D.DrawRectBounds( g, Color.White, 5f, progWidth, progHeight );
Utils2D.DrawRectBounds( g, Color.White, 5f, 0, 0, progWidth, progHeight );
}
progressBoxTexture = Utils2D.Make2DTexture( GraphicsApi, bmp, 0, 0 );
}
@ -46,6 +48,7 @@ namespace ClassicalSharp {
}
public override void Dispose() {
font.Dispose();
messageWidget.Dispose();
titleWidget.Dispose();
GraphicsApi.DeleteTexture( ref progressBoxTexture );
@ -53,7 +56,7 @@ namespace ClassicalSharp {
}
TextWidget CreateTextWidget( int yOffset, string text ) {
TextWidget widget = new TextWidget( Window, 14 );
TextWidget widget = new TextWidget( Window, font );
widget.Init();
widget.HorizontalDocking = Docking.Centre;
widget.YOffset = yOffset;

View File

@ -1,4 +1,5 @@
using System;
using System.Drawing;
using OpenTK.Input;
namespace ClassicalSharp {
@ -11,6 +12,7 @@ namespace ClassicalSharp {
ChatScreen chat;
BlockHotbarWidget hotbar;
Widget playerList;
Font playerFont;
public override void Render( double delta ) {
chat.Render( delta );
@ -26,6 +28,7 @@ namespace ClassicalSharp {
}
public override void Dispose() {
playerFont.Dispose();
chat.Dispose();
hotbar.Dispose();
if( playerList != null ) {
@ -42,6 +45,7 @@ namespace ClassicalSharp {
}
public override void Init() {
playerFont = new Font( "Arial", 12 );
chat = new ChatScreen( Window );
chat.Window = Window;
const int blockSize = 32;
@ -64,9 +68,9 @@ namespace ClassicalSharp {
if( key == Window.Keys[KeyMapping.PlayerList] ) {
if( playerList == null ) {
if( Window.Network.UsingExtPlayerList ) {
playerList = new ExtPlayerListWidget( Window );
playerList = new ExtPlayerListWidget( Window, playerFont );
} else {
playerList = new PlayerListWidget( Window );
playerList = new PlayerListWidget( Window, playerFont );
}
playerList.Init();
}

View File

@ -27,11 +27,15 @@ namespace ClassicalSharp {
}
}
Font titleFont, keyStatusFont, textFont;
public override void Init() {
controlsWidget = CreateTextWidget( 0, 30, "&eControls list", Docking.Centre, Docking.LeftOrTop, 16, FontStyle.Bold );
keyStatusWidget = CreateTextWidget( 0, -80, "", Docking.Centre, Docking.BottomOrRight, 13, FontStyle.Italic );
gameWidget = CreateTextWidget( 0, -50, "&eBack to game", Docking.Centre, Docking.BottomOrRight, 16, FontStyle.Bold );
exitWidget = CreateTextWidget( 0, -10, "&eExit", Docking.Centre, Docking.BottomOrRight, 16, FontStyle.Bold );
titleFont = new Font( "Arial", 16, FontStyle.Bold );
keyStatusFont = new Font( "Arial", 13, FontStyle.Italic );
textFont = new Font( "Arial", 14, FontStyle.Bold );
controlsWidget = CreateTextWidget( 0, 30, "&eControls list", Docking.Centre, Docking.LeftOrTop, titleFont );
keyStatusWidget = CreateTextWidget( 0, -80, "", Docking.Centre, Docking.BottomOrRight, keyStatusFont );
gameWidget = CreateTextWidget( 0, -50, "&eBack to game", Docking.Centre, Docking.BottomOrRight, titleFont );
exitWidget = CreateTextWidget( 0, -10, "&eExit", Docking.Centre, Docking.BottomOrRight, titleFont );
KeyMapping[] mappingsLeft = { KeyMapping.Forward, KeyMapping.Back, KeyMapping.Left, KeyMapping.Right,
KeyMapping.Jump, KeyMapping.Respawn, KeyMapping.SetSpawn, KeyMapping.OpenChat, KeyMapping.SendChat,
@ -54,7 +58,7 @@ namespace ClassicalSharp {
keysLeft = new KeyMapWidget[mappings.Length];
for( int i = 0; i < keysLeft.Length; i++ ) {
string text = descriptions[i] + ": " + Window.Keys[mappings[i]];
TextWidget widget = CreateTextWidget( 0, startY, text, Docking.LeftOrTop, Docking.LeftOrTop, 14, FontStyle.Bold );
TextWidget widget = CreateTextWidget( 0, startY, text, Docking.LeftOrTop, Docking.LeftOrTop, textFont );
widget.XOffset = 10;
widget.MoveTo( widget.X + widget.XOffset, widget.Y );
keysLeft[i] = new KeyMapWidget( widget, mappings[i], descriptions[i] );
@ -68,7 +72,7 @@ namespace ClassicalSharp {
keysRight = new KeyMapWidget[mappings.Length];
for( int i = 0; i < keysRight.Length; i++ ) {
string text = descriptions[i] + ": " + Window.Keys[mappings[i]];
TextWidget widget = CreateTextWidget( 0, startY, text, Docking.LeftOrTop, Docking.LeftOrTop, 14, FontStyle.Bold );
TextWidget widget = CreateTextWidget( 0, startY, text, Docking.LeftOrTop, Docking.LeftOrTop, textFont );
widget.XOffset = leftEnd + 30;
widget.MoveTo( widget.X + widget.XOffset, widget.Y );
keysRight[i] = new KeyMapWidget( widget, mappings[i], descriptions[i] );
@ -77,6 +81,9 @@ namespace ClassicalSharp {
}
public override void Dispose() {
textFont.Dispose();
titleFont.Dispose();
keyStatusFont.Dispose();
gameWidget.Dispose();
controlsWidget.Dispose();
exitWidget.Dispose();
@ -88,9 +95,8 @@ namespace ClassicalSharp {
}
}
TextWidget CreateTextWidget( int x, int y, string text, Docking horizontal, Docking vertical, int fontSize, FontStyle style ) {
TextWidget widget = new TextWidget( Window, fontSize );
widget.Style = style;
TextWidget CreateTextWidget( int x, int y, string text, Docking horizontal, Docking vertical, Font font ) {
TextWidget widget = new TextWidget( Window, font );
widget.Init();
widget.HorizontalDocking = horizontal;
widget.VerticalDocking = vertical;

63
2D/Texture.cs Normal file
View File

@ -0,0 +1,63 @@
using System;
using ClassicalSharp.GraphicsAPI;
namespace ClassicalSharp {
public struct Texture {
public int ID;
public int X1, Y1;
public int Width, Height;
public float U1, V1;
// Normally just used for graphics cards that don't support non power of two textures.
public float U2, V2;
public Texture( int id, int x, int y, int width, int height, float u2, float v2 )
: this( id, x, y, width, height, 0, u2, 0, v2 ) {
}
public Texture( int id, int x, int y, int width, int height, TextureRectangle rec )
: this( id, x, y, width, height, rec.U1, rec.U2, rec.V1, rec.V2 ) {
}
public Texture( int id, int x, int y, int width, int height, float u1, float u2, float v1, float v2 ) {
ID = id;
X1 = x;
Y1 = y;
Width = width;
Height = height;
U1 = u1;
V1 = v1;
U2 = u2;
V2 = v2;
}
public bool IsValid {
get { return ID > 0; }
}
public void Render( IGraphicsApi graphics ) {
graphics.Texturing = true;
graphics.Bind2DTexture( ID );
graphics.Draw2DTexture( ref this );
graphics.Texturing = false;
}
public void RenderNoBind( IGraphicsApi graphics ) {
graphics.Draw2DTexture( ref this );
}
public int X2 {
get { return X1 + Width; }
//set { X1 = value - Width; }
}
public int Y2 {
get { return Y1 + Height; }
//set { Y1 = value - Height; }
}
public override string ToString() {
return ID + String.Format( "({0}, {1} -> {2},{3}", X1, Y1, Width, Height );
}
}
}

View File

@ -1,64 +1,42 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using ClassicalSharp.GraphicsAPI;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using ClassicalSharp.GraphicsAPI;
namespace ClassicalSharp {
public static class Utils2D {
public static StringFormat format;
static Bitmap measuringBmp;
static Graphics measuringGraphics;
static Utils2D() {
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 );
}
const float shadowOffset = 1.3f;
public static Size MeasureSize( string text, string fontName, float fontSize, bool shadow ) {
using( Font font = new Font( fontName, fontSize ) ) {
return MeasureSize( text, font, shadow );
}
}
public static Size MeasureSize( string text, string fontName, float fontSize, FontStyle style, bool shadow ) {
using( Font font = new Font( fontName, fontSize, style ) ) {
return MeasureSize( text, font, shadow );
}
}
const float shadowOffset = 1.3f;
public static Size MeasureSize( string text, Font font, bool shadow ) {
using( Bitmap measuringBmp = new Bitmap( 1, 1 ) ) {
using( Graphics g = Graphics.FromImage( measuringBmp ) ) {
SizeF size = g.MeasureString( text, font, Int32.MaxValue, format );
if( shadow ) {
size.Width += shadowOffset;
size.Height += shadowOffset;
}
return Size.Ceiling( size );
}
}
}
public static Size MeasureSize( List<DrawTextArgs> parts, string fontName, float fontSize, bool shadow ) {
using( Font font = new Font( fontName, fontSize ) ) {
return MeasureSize( parts, font, shadow );
SizeF size = measuringGraphics.MeasureString( text, font, Int32.MaxValue, format );
if( shadow ) {
size.Width += shadowOffset;
size.Height += shadowOffset;
}
return Size.Ceiling( size );
}
public static Size MeasureSize( List<DrawTextArgs> parts, Font font, bool shadow ) {
SizeF total = SizeF.Empty;
using( Bitmap measuringBmp = new Bitmap( 1, 1 ) ) {
using( Graphics g = Graphics.FromImage( measuringBmp ) ) {
for( int i = 0; i < parts.Count; i++ ) {
SizeF size = g.MeasureString( parts[i].Text, font, Int32.MaxValue, format );
total.Height = Math.Max( total.Height, size.Height );
total.Width += size.Width;
}
}
for( int i = 0; i < parts.Count; i++ ) {
SizeF size = measuringGraphics.MeasureString( parts[i].Text, font, Int32.MaxValue, format );
total.Height = Math.Max( total.Height, size.Height );
total.Width += size.Width;
}
if( shadow ) {
total.Width += shadowOffset;
@ -67,21 +45,7 @@ namespace ClassicalSharp {
return Size.Ceiling( total );
}
public static void DrawText( Graphics g, string fontName, float fontSize, DrawTextArgs args ) {
using( Font font = new Font( fontName, fontSize ) ) {
DrawText( g, font, args );
}
}
public static void DrawText( Graphics g, string fontName, float fontSize, FontStyle style, DrawTextArgs args ) {
using( Font font = new Font( fontName, fontSize, style ) ) {
DrawText( g, font, args );
}
}
public static void DrawText( Graphics g, Font font, DrawTextArgs args ) {
float x = args.XOffset, y = args.YOffset;
public static void DrawText( Graphics g, Font font, DrawTextArgs args, float x, float y ) {
using( Brush textBrush = new SolidBrush( args.TextColour ),
shadowBrush = new SolidBrush( args.ShadowColour ) ) {
g.TextRenderingHint = TextRenderingHint.AntiAlias;
@ -92,28 +56,10 @@ namespace ClassicalSharp {
}
}
public static void DrawText( Graphics g, List<DrawTextArgs> parts, string fontName, float fontSize ) {
using( Font font = new Font( fontName, fontSize ) ) {
DrawText( g, parts, font );
}
}
public static void DrawText( Graphics g, List<DrawTextArgs> parts, string fontName, float fontSize, float x, float y ) {
using( Font font = new Font( fontName, fontSize ) ) {
DrawText( g, parts, font, x, y );
}
}
public static void DrawText( Graphics g, List<DrawTextArgs> parts, Font font ) {
DrawText( g, parts, font, 0, 0 );
}
public static void DrawText( Graphics g, List<DrawTextArgs> parts, Font font, float x, float y ) {
for( int i = 0; i < parts.Count; i++ ) {
DrawTextArgs part = parts[i];
part.XOffset = x;
part.YOffset = y;
DrawText( g, font, part );
DrawText( g, font, part, x, y );
SizeF partSize = g.MeasureString( part.Text, font, Int32.MaxValue, format );
x += partSize.Width;
}
@ -125,60 +71,27 @@ namespace ClassicalSharp {
}
}
public static void DrawRect( Graphics g, Color colour, int width, int height ) {
DrawRect( g, colour, 0, 0, width, height );
}
public static void DrawRectBounds( Graphics g, Color colour, float lineWidth, int x, int y, int width, int height ) {
using( Pen pen = new Pen( colour, lineWidth ) ) {
g.DrawRectangle( pen, x, y, width, height );
}
}
public static void DrawRectBounds( Graphics g, Color colour, float lineWidth, int width, int height ) {
DrawRectBounds( g, colour, lineWidth, 0, 0, width, height );
}
public static Texture MakeTextTexture( string fontName, float fontSize, int x1, int y1, DrawTextArgs args ) {
using( Font font = new Font( fontName, fontSize ) ) {
return MakeTextTexture( font, x1, y1, args );
}
}
public static Texture MakeTextTexture( string fontName, float fontSize, FontStyle style, int x1, int y1, DrawTextArgs args ) {
using( Font font = new Font( fontName, fontSize, style ) ) {
return MakeTextTexture( font, x1, y1, args );
}
}
public static Texture MakeTextTexture( Font font, int x1, int y1, DrawTextArgs args ) {
Size size = MeasureSize( args.Text, font, args.UseShadow );
using( Bitmap bmp = new Bitmap( size.Width, size.Height ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
DrawText( g, font, args );
DrawText( g, font, args, 0, 0 );
}
return Make2DTexture( args.Graphics, bmp, x1, y1 );
}
}
public static Texture MakeTextTexture( List<DrawTextArgs> parts, string fontName, float fontSize, Size size, int x1, int y1 ) {
using( Font font = new Font( fontName, fontSize ) ) {
return MakeTextTexture( parts, font, size, x1, y1 );
}
}
public static Texture MakeTextTexture( List<DrawTextArgs> parts, string fontName, float fontSize, FontStyle style, Size size, int x1, int y1 ) {
using( Font font = new Font( fontName, fontSize, style ) ) {
return MakeTextTexture( parts, font, size, x1, y1 );
}
}
public static Texture MakeTextTexture( List<DrawTextArgs> parts, Font font, Size size, int x1, int y1 ) {
if( parts.Count == 0 ) return new Texture( -1, x1, y1, 0, 0, 1, 1 );
using( Bitmap bmp = new Bitmap( size.Width, size.Height ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
DrawText( g, parts, font );
DrawText( g, parts, font, 0, 0 );
}
return Make2DTexture( parts[0].Graphics, bmp, x1, y1 );
}
@ -197,10 +110,6 @@ namespace ClassicalSharp {
}
}
public static bool Contains( int recX, int recY, int width, int height, int x, int y ) {
return x >= recX && y >= recY && x < recX + width && y < recY + height;
}
public static Bitmap ResizeToPower2( Bitmap bmp ) {
int adjWidth = Utils.NextPowerOf2( bmp.Width );
int adjHeight = Utils.NextPowerOf2( bmp.Height );
@ -211,62 +120,4 @@ namespace ClassicalSharp {
return adjBmp;
}
}
public struct Texture {
public int ID;
public int X1, Y1;
public int Width, Height;
public float U1, V1;
// Normally just used for graphics cards that don't support non power of two textures.
public float U2, V2;
public Texture( int id, int x, int y, int width, int height, float u2, float v2 )
: this( id, x, y, width, height, 0, u2, 0, v2 ) {
}
public Texture( int id, int x, int y, int width, int height, TextureRectangle rec )
: this( id, x, y, width, height, rec.U1, rec.U2, rec.V1, rec.V2 ) {
}
public Texture( int id, int x, int y, int width, int height, float u1, float u2, float v1, float v2 ) {
ID = id;
X1 = x;
Y1 = y;
Width = width;
Height = height;
U1 = u1;
V1 = v1;
U2 = u2;
V2 = v2;
}
public bool IsValid {
get { return ID > 0; }
}
public void Render( IGraphicsApi graphics ) {
graphics.Texturing = true;
graphics.Bind2DTexture( ID );
graphics.Draw2DTexture( ref this );
graphics.Texturing = false;
}
public void RenderNoBind( IGraphicsApi graphics ) {
graphics.Draw2DTexture( ref this );
}
public int X2 {
get { return X1 + Width; }
//set { X1 = value - Width; }
}
public int Y2 {
get { return Y1 + Height; }
//set { Y1 = value - Height; }
}
public override string ToString() {
return ID + String.Format( "({0}, {1} -> {2},{3}", X1, Y1, Width, Height );
}
}
}

View File

@ -7,9 +7,11 @@ namespace ClassicalSharp {
public class ExtPlayerListWidget : Widget {
public ExtPlayerListWidget( Game window ) : base( window ) {
readonly Font font;
public ExtPlayerListWidget( Game window, Font font ) : base( window ) {
HorizontalDocking = Docking.Centre;
VerticalDocking = Docking.Centre;
this.font = font;
}
const int namesPerColumn = 20;
@ -30,14 +32,14 @@ namespace ClassicalSharp {
public byte NameId;
public PlayerInfo( IGraphicsApi graphics, CpeListInfo p ) {
public PlayerInfo( IGraphicsApi graphics, CpeListInfo p, Font font ) {
Name = p.ListName;
NameId = p.NameId;
GroupName = p.GroupName;
GroupRank = p.GroupRank;
List<DrawTextArgs> parts = Utils.SplitText( graphics, Name, true );
Size size = Utils2D.MeasureSize( Utils.StripColours( Name ), "Arial", 12, true );
Texture = Utils2D.MakeTextTexture( parts, "Arial", 12, size, 0, 0 );
Size size = Utils2D.MeasureSize( Utils.StripColours( Name ), font, true );
Texture = Utils2D.MakeTextTexture( parts, font, size, 0, 0 );
}
public override string ToString() {
@ -95,7 +97,7 @@ namespace ClassicalSharp {
PlayerInfo pInfo = info[i];
if( pInfo.NameId == e.Id ) {
GraphicsApi.DeleteTexture( ref pInfo.Texture );
info[i] = new PlayerInfo( GraphicsApi, Window.CpePlayersList[e.Id] );
info[i] = new PlayerInfo( GraphicsApi, Window.CpePlayersList[e.Id], font );
SortPlayerInfo();
break;
}
@ -117,7 +119,7 @@ namespace ClassicalSharp {
void PlayerListInfoAdded( object sender, IdEventArgs e ) {
CpeListInfo player = Window.CpePlayersList[e.Id];
info.Add( new PlayerInfo( GraphicsApi, player ) );
info.Add( new PlayerInfo( GraphicsApi, player, font ) );
rows = (int)Math.Ceiling( (double)info.Count / namesPerColumn );
SortPlayerInfo();
}
@ -126,7 +128,7 @@ namespace ClassicalSharp {
for( int i = 0; i < Window.CpePlayersList.Length; i++ ) {
CpeListInfo player = Window.CpePlayersList[i];
if( player != null ) {
info.Add( new PlayerInfo( GraphicsApi, player ) );
info.Add( new PlayerInfo( GraphicsApi, player, font ) );
}
}
}

View File

@ -7,9 +7,11 @@ namespace ClassicalSharp {
public sealed class PlayerListWidget : Widget {
public PlayerListWidget( Game window ) : base( window ) {
readonly Font font;
public PlayerListWidget( Game window, Font font ) : base( window ) {
HorizontalDocking = Docking.Centre;
VerticalDocking = Docking.Centre;
this.font = font;
}
const int namesPerColumn = 20;
@ -26,12 +28,12 @@ namespace ClassicalSharp {
public byte PlayerId;
public PlayerInfo( IGraphicsApi graphics, Player p ) {
public PlayerInfo( IGraphicsApi graphics, Player p, Font font ) {
Name = p.DisplayName;
PlayerId = p.ID;
List<DrawTextArgs> parts = Utils.SplitText( graphics, Name, true );
Size size = Utils2D.MeasureSize( Utils.StripColours( Name ), "Arial", 12, true );
Texture = Utils2D.MakeTextTexture( parts, "Arial", 12, size, 0, 0 );
Size size = Utils2D.MeasureSize( Utils.StripColours( Name ), font, true );
Texture = Utils2D.MakeTextTexture( parts, font, size, 0, 0 );
}
}
@ -65,7 +67,7 @@ namespace ClassicalSharp {
void PlayerSpawned( object sender, IdEventArgs e ) {
Player player = Window.NetPlayers[e.Id];
info.Add( new PlayerInfo( GraphicsApi, player ) );
info.Add( new PlayerInfo( GraphicsApi, player, font ) );
rows = (int)Math.Ceiling( (double)info.Count / namesPerColumn );
SortPlayerInfo();
}
@ -88,7 +90,7 @@ namespace ClassicalSharp {
PlayerInfo pInfo = info[i];
if( pInfo.PlayerId == e.Id ) {
GraphicsApi.DeleteTexture( ref pInfo.Texture );
info[i] = new PlayerInfo( GraphicsApi, Window.NetPlayers[e.Id] );
info[i] = new PlayerInfo( GraphicsApi, Window.NetPlayers[e.Id], font );
SortPlayerInfo();
break;
}
@ -99,11 +101,11 @@ namespace ClassicalSharp {
for( int i = 0; i < Window.NetPlayers.Length; i++ ) {
Player player = Window.NetPlayers[i];
if( player != null ) {
info.Add( new PlayerInfo( GraphicsApi, player ) );
info.Add( new PlayerInfo( GraphicsApi, player, font ) );
}
}
Player localPlayer = Window.LocalPlayer;
info.Add( new PlayerInfo( GraphicsApi, localPlayer ) );
info.Add( new PlayerInfo( GraphicsApi, localPlayer, font ) );
}
void SortPlayerInfo() {

View File

@ -6,21 +6,21 @@ namespace ClassicalSharp {
public sealed class TextGroupWidget : Widget {
public TextGroupWidget( Game window, int elementsCount, int fontSize ) : base( window ) {
public TextGroupWidget( Game window, int elementsCount, Font font ) : base( window ) {
ElementsCount = elementsCount;
this.fontSize = fontSize;
this.font = font;
}
Texture[] textures;
string[] textCache;
int ElementsCount, defaultHeight;
public int XOffset = 0, YOffset = 0;
readonly int fontSize;
readonly Font font;
public override void Init() {
textures = new Texture[ElementsCount];
textCache = new string[ElementsCount];
defaultHeight = Utils2D.MeasureSize( "I", "Arial", fontSize, true ).Height;
defaultHeight = Utils2D.MeasureSize( "I", font, true ).Height;
for( int i = 0; i < textures.Length; i++ ) {
textures[i].Height = defaultHeight;
}
@ -33,13 +33,13 @@ namespace ClassicalSharp {
Size size = new Size( 0, defaultHeight );
if( !String.IsNullOrEmpty( text ) ) {
parts = Utils.SplitText( GraphicsApi, text, true );
size = Utils2D.MeasureSize( Utils.StripColours( text ), "Arial", fontSize, true );
size = Utils2D.MeasureSize( Utils.StripColours( text ), font, true );
}
int x = HorizontalDocking == Docking.LeftOrTop ? XOffset : Window.Width - size.Width - XOffset;
int y = CalcY( index, size.Height );
if( !String.IsNullOrEmpty( text ) ) {
textures[index] = Utils2D.MakeTextTexture( parts, "Arial", fontSize, size, x, y );
textures[index] = Utils2D.MakeTextTexture( parts, font, size, x, y );
} else {
textures[index] = new Texture( -1, 0, 0, 0, defaultHeight, 0, 0 );
}

View File

@ -7,7 +7,7 @@ namespace ClassicalSharp {
public sealed class TextInputWidget : Widget {
public TextInputWidget( Game window, int fontSize ) : base( window ) {
public TextInputWidget( Game window, Font font, Font boldFont ) : base( window ) {
HorizontalDocking = Docking.LeftOrTop;
VerticalDocking = Docking.BottomOrRight;
handlers[0] = new InputHandler( BackspaceKey, Key.BackSpace, 10 );
@ -17,7 +17,8 @@ namespace ClassicalSharp {
handlers[4] = new InputHandler( UpKey, Key.Up, 5 );
handlers[5] = new InputHandler( DownKey, Key.Down, 5 );
typingLogPos = Window.ChatInputLog.Count; // Index of newest entry + 1.
this.fontSize = fontSize;
this.font = font;
this.boldFont = boldFont;
}
Texture chatInputTexture, chatCaretTexture;
@ -26,7 +27,7 @@ namespace ClassicalSharp {
int typingLogPos = 0;
public int ChatInputYOffset;
public string chatInputText = "";
readonly int fontSize;
readonly Font font, boldFont;
public override void Render( double delta ) {
chatInputTexture.Render( GraphicsApi );
@ -37,20 +38,20 @@ namespace ClassicalSharp {
public override void Init() {
X = 10;
DrawTextArgs caretArgs = new DrawTextArgs( GraphicsApi, "_", Color.White, false );
chatCaretTexture = Utils2D.MakeTextTexture( "Arial", fontSize, FontStyle.Bold, 0, 0, caretArgs );
chatCaretTexture = Utils2D.MakeTextTexture( boldFont, 0, 0, caretArgs );
if( chatInputText.Length == 0 ) {
caretPos = -1;
}
Size size = Utils2D.MeasureSize( chatInputText, "Arial", fontSize, false );
Size size = Utils2D.MeasureSize( chatInputText, font, false );
if( caretPos == -1 ) {
chatCaretTexture.X1 = 10 + size.Width;
size.Width += chatCaretTexture.Width;
} else {
Size trimmedSize = Utils2D.MeasureSize( chatInputText.Substring( 0, caretPos ), "Arial", fontSize, false );
Size trimmedSize = Utils2D.MeasureSize( chatInputText.Substring( 0, caretPos ), font, false );
chatCaretTexture.X1 = 10 + trimmedSize.Width;
Size charSize = Utils2D.MeasureSize( chatInputText.Substring( caretPos, 1 ), "Arial", fontSize, false );
Size charSize = Utils2D.MeasureSize( chatInputText.Substring( caretPos, 1 ), font, false );
chatCaretTexture.Width = charSize.Width;
}
size.Height = Math.Max( size.Height, chatCaretTexture.Height );
@ -58,9 +59,9 @@ namespace ClassicalSharp {
int y = Window.Height - ChatInputYOffset - size.Height / 2;
using( Bitmap bmp = new Bitmap( size.Width, size.Height ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
Utils2D.DrawRect( g, backColour, bmp.Width, bmp.Height );
Utils2D.DrawRect( g, backColour, 0, 0, bmp.Width, bmp.Height );
DrawTextArgs args = new DrawTextArgs( GraphicsApi, chatInputText, Color.White, false );
Utils2D.DrawText( g, "Arial", fontSize, args );
Utils2D.DrawText( g, font, args, 0, 0 );
}
chatInputTexture = Utils2D.Make2DTexture( GraphicsApi, bmp, 10, y );
}

View File

@ -6,19 +6,18 @@ namespace ClassicalSharp {
public sealed class TextWidget : Widget {
public TextWidget( Game window, int fontSize ) : base( window ) {
this.fontSize = fontSize;
public TextWidget( Game window, Font font ) : base( window ) {
this.font = font;
}
Texture texture;
string textCache = null;
public int XOffset = 0, YOffset = 0;
public FontStyle Style = FontStyle.Regular;
int defaultHeight;
readonly int fontSize;
readonly Font font;
public override void Init() {
defaultHeight = Utils2D.MeasureSize( "I", "Arial", fontSize, Style, true ).Height;
defaultHeight = Utils2D.MeasureSize( "I", font, true ).Height;
texture.Height = defaultHeight;
UpdateDimensions();
}
@ -35,11 +34,11 @@ namespace ClassicalSharp {
List<DrawTextArgs> parts = null;
Size size = new Size( 0, defaultHeight );
parts = Utils.SplitText( GraphicsApi, text, true );
size = Utils2D.MeasureSize( Utils.StripColours( text ), "Arial", fontSize, Style, true );
size = Utils2D.MeasureSize( Utils.StripColours( text ), font, true );
X = CalcAdjOffset( XOffset, Window.Width, size.Width, HorizontalDocking );
Y = CalcAdjOffset( YOffset, Window.Height, size.Height, VerticalDocking );
texture = Utils2D.MakeTextTexture( parts, "Arial", fontSize, Style, size, X, Y );
texture = Utils2D.MakeTextTexture( parts, font, size, X, Y );
UpdateDimensions();
}

View File

@ -80,6 +80,7 @@
<Compile Include="2D\Screens\NormalScreen.cs" />
<Compile Include="2D\Screens\PauseScreen.cs" />
<Compile Include="2D\Screens\Screen.cs" />
<Compile Include="2D\Texture.cs" />
<Compile Include="2D\Utils2D.cs" />
<Compile Include="2D\Widgets\BlockHotbarWidget.cs" />
<Compile Include="2D\Widgets\ExtPlayerListWidget.cs" />

View File

@ -71,6 +71,7 @@ namespace ClassicalSharp {
public override void Tick( double delta ) {
if( Window.Map.IsNotLoaded ) return;
Window.Title = ( GC.GetTotalMemory( false ) / 1024.0 / 1024.0 ).ToString(); // TODO: temp debug statement
float xMoving = 0, zMoving = 0;
lastPos = Position = nextPos;

Binary file not shown.

View File

@ -1,6 +1,4 @@
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
</configuration>
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
</configuration>

View File

@ -22,12 +22,14 @@ namespace ClassicalSharp.Renderers {
Window = window;
Graphics = window.Graphics;
List<DrawTextArgs> parts = Utils.SplitText( Graphics, player.DisplayName, true );
Size size = Utils2D.MeasureSize( Utils.StripColours( player.DisplayName ), "Arial", 14, true );
nameTexture = Utils2D.MakeTextTexture( parts, "Arial", 14, size, 0, 0 );
nameWidth = size.Width;
nameHeight = size.Height;
nameTextureId = nameTexture.ID;
using( Font font = new Font( "Arial", 14 ) ) {
List<DrawTextArgs> parts = Utils.SplitText( Graphics, player.DisplayName, true );
Size size = Utils2D.MeasureSize( Utils.StripColours( player.DisplayName ), font, true );
nameTexture = Utils2D.MakeTextTexture( parts, font, size, 0, 0 );
nameWidth = size.Width;
nameHeight = size.Height;
nameTextureId = nameTexture.ID;
}
}
public void Dispose() {