Rewrite backend for 2D drawing to be far more modular.

This commit is contained in:
UnknownShadow200 2015-09-28 17:10:27 +10:00
parent d3c85a8cc5
commit 63a42bbc68
19 changed files with 350 additions and 296 deletions

View File

@ -1,34 +0,0 @@
using System;
using System.Drawing;
using ClassicalSharp.GraphicsAPI;
namespace ClassicalSharp {
public struct DrawTextArgs {
public Color TextColour;
public string Text;
public bool UseShadow;
public Color ShadowColour;
public IGraphicsApi Graphics;
internal bool SkipPartsCheck;
public DrawTextArgs( IGraphicsApi graphics, string text, Color col, bool useShadow ) :
this( graphics, text, col, useShadow, Color.Black ) {
}
public DrawTextArgs( IGraphicsApi graphics, string text, bool useShadow ) :
this( graphics, text, Color.White, useShadow, Color.Black ) {
}
public DrawTextArgs( IGraphicsApi graphics, string text, Color col, bool useShadow, Color shadowCol ) {
Graphics = graphics;
Text = text;
TextColour = col;
UseShadow = useShadow;
ShadowColour = shadowCol;
SkipPartsCheck = false;
}
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Drawing;
namespace ClassicalSharp {
public struct DrawTextArgs {
public Color TextColour;
public string Text;
public bool UseShadow;
public Color ShadowColour;
internal bool SkipPartsCheck;
public DrawTextArgs( string text, Color col, bool useShadow ) :
this( text, col, useShadow, Color.Black ) { }
public DrawTextArgs( string text, bool useShadow ) :
this( text, Color.White, useShadow, Color.Black ) { }
public DrawTextArgs( string text, Color col, bool useShadow, Color shadowCol ) {
Text = text;
TextColour = col;
UseShadow = useShadow;
ShadowColour = shadowCol;
SkipPartsCheck = false;
}
}
}

View File

@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
namespace ClassicalSharp {
public sealed class GdiDrawer2D : IDrawer2D {
StringFormat format;
Bitmap measuringBmp;
Graphics measuringGraphics;
Dictionary<int, SolidBrush> brushCache = new Dictionary<int, SolidBrush>( 16 );
Graphics g;
public GdiDrawer2D( Game game ) {
graphics = game.Graphics;
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 ) {
Utils.LogWarning( "Previous IDrawer2D.SetBitmap() call was not properly disposed" );
g.Dispose();
}
g = Graphics.FromImage( bmp );
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.SmoothingMode = SmoothingMode.HighQuality;
}
public override void DrawText( Font font, ref DrawTextArgs args, float x, float y ) {
if( !args.SkipPartsCheck )
GetTextParts( args.Text );
Brush shadowBrush = GetOrCreateBrush( args.ShadowColour );
for( int i = 0; i < parts.Count; i++ ) {
TextPart part = parts[i];
Brush textBrush = GetOrCreateBrush( part.TextColour );
if( args.UseShadow )
g.DrawString( part.Text, font, shadowBrush, x + shadowOffset, y + shadowOffset, format );
g.DrawString( part.Text, font, textBrush, x, y, format );
x += g.MeasureString( part.Text, font, Int32.MaxValue, format ).Width;
}
}
public override void DrawRect( Color colour, int x, int y, int width, int height ) {
Brush brush = GetOrCreateBrush( colour );
g.FillRectangle( brush, x, y, width, height );
}
public override void DrawRectBounds( 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 override void DrawRoundedRect( Color colour, float x, float y, float width, float height ) {
GraphicsPath path = new GraphicsPath();
float x1 = x, y1 = y, x2 = x + width, y2 = y + height;
const float r = 3, dia = r * 2;
path.AddArc( x1, y1, dia, dia, 180, 90 );
path.AddLine( x1 + r, y1, x2 - r, y1 );
path.AddArc( x2 - dia, y1, dia, dia, 270, 90 );
path.AddLine( x2, y1 + r, x2, y2 - r );
path.AddArc( x2 - dia, y2 - dia, dia, dia, 0, 90 );
path.AddLine( x1 + r, y2, x2 - r, y2 );
path.AddArc( x1, y2 - dia, dia, dia, 90, 90 );
path.AddLine( x1, y1 + r, x1, y2 - r );
path.CloseAllFigures();
using( Brush brush = new SolidBrush( colour ) )
g.FillPath( brush, path );
path.Dispose();
}
public override void Dispose() {
g.Dispose();
g = null;
}
public override Size MeasureSize( string text, Font font, bool shadow ) {
GetTextParts( text );
SizeF total = SizeF.Empty;
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 && parts.Count > 0 ) {
total.Width += shadowOffset;
total.Height += shadowOffset;
}
return Size.Ceiling( total );
}
public override void DisposeInstance() {
measuringBmp.Dispose();
measuringGraphics.Dispose();
foreach( var pair in brushCache ) {
pair.Value.Dispose();
}
}
SolidBrush GetOrCreateBrush( Color color ) {
int key = color.ToArgb();
SolidBrush brush;
if( brushCache.TryGetValue( key, out brush ) ) {
return brush;
}
brush = new SolidBrush( color );
brushCache[key] = brush;
return brush;
}
}
}

View File

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using ClassicalSharp.GraphicsAPI;
namespace ClassicalSharp {
public abstract class IDrawer2D : IDisposable {
protected IGraphicsApi graphics;
protected const float shadowOffset = 1.3f;
/// <summary> Sets the underlying bitmap that drawing operations will be performed on. </summary>
public abstract void SetBitmap( Bitmap bmp );
public abstract void DrawText( Font font, ref DrawTextArgs args, float x, float y );
public abstract void DrawRect( Color colour, int x, int y, int width, int height );
public abstract void DrawRectBounds( Color colour, float lineWidth, int x, int y, int width, int height );
public abstract void DrawRoundedRect( Color colour, float x, float y, float width, float height );
/// <summary> Disposes of any resources used by this class that are associated with the underlying bitmap. </summary>
public abstract void Dispose();
public abstract Size MeasureSize( string text, Font font, bool shadow );
/// <summary> Disposes of all native resources used by this class. </summary>
/// <remarks> You will no longer be able to perform measuring or drawing calls after this. </remarks>
public abstract void DisposeInstance();
public Texture MakeTextTexture( Font font, int screenX, int screenY, ref DrawTextArgs args ) {
Size size = MeasureSize( args.Text, font, args.UseShadow );
if( parts.Count == 0 )
return new Texture( -1, screenX, screenY, 0, 0, 1, 1 );
using( Bitmap bmp = CreatePow2Bitmap( size ) ) {
SetBitmap( bmp );
args.SkipPartsCheck = true;
DrawText( font, ref args, 0, 0 );
Dispose();
return Make2DTexture( bmp, size, screenX, screenY );
}
}
public Texture Make2DTexture( Bitmap bmp, Size used, int screenX, int screenY ) {
int texId = graphics.CreateTexture( bmp );
return new Texture( texId, screenX, screenY, used.Width, used.Height,
(float)used.Width / bmp.Width, (float)used.Height / bmp.Height );
}
public static Bitmap CreatePow2Bitmap( Size size ) {
return new Bitmap( Utils.NextPowerOf2( size.Width ), Utils.NextPowerOf2( size.Height ) );
}
protected List<TextPart> parts = new List<TextPart>( 64 );
protected static Color white = Color.FromArgb( 255, 255, 255 );
protected struct TextPart {
public string Text;
public Color TextColour;
public TextPart( string text, Color col ) {
Text = text;
TextColour = col;
}
}
protected void GetTextParts( string value ) {
parts.Clear();
if( String.IsNullOrEmpty( value ) ) {
} else if( value.IndexOf( '&' ) == -1 ) {
parts.Add( new TextPart( value, white ) );
} else {
SplitText( value );
}
}
protected void SplitText( string value ) {
int code = 0xF;
for( int i = 0; i < value.Length; i++ ) {
int nextAnd = value.IndexOf( '&', i );
int partLength = nextAnd == -1 ? value.Length - i : nextAnd - i;
if( partLength > 0 ) {
string part = value.Substring( i, partLength );
Color col = Color.FromArgb(
191 * ( ( code >> 2 ) & 0x1 ) + 64 * ( code >> 3 ),
191 * ( ( code >> 1 ) & 0x1 ) + 64 * ( code >> 3 ),
191 * ( ( code >> 0 ) & 0x1 ) + 64 * ( code >> 3 ) );
parts.Add( new TextPart( part, col ) );
}
i += partLength + 1;
if( nextAnd >= 0 && nextAnd + 1 < value.Length ) {
try {
code = Utils.ParseHex( value[nextAnd + 1] );
} catch( FormatException ) {
code = 0xF;
i--; // include the character that isn't a colour code.
}
}
}
}
}
}

View File

@ -76,11 +76,12 @@ namespace ClassicalSharp {
public override void Init() { public override void Init() {
game.BlockPermissionsChanged += BlockPermissionsChanged; game.BlockPermissionsChanged += BlockPermissionsChanged;
Size size = new Size( blockSize, blockSize ); Size size = new Size( blockSize, blockSize );
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) { using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) { using( IDrawer2D drawer = game.Drawer2D ) {
Utils2D.DrawRectBounds( g, Color.White, blockSize / 8, 0, 0, blockSize, blockSize ); drawer.SetBitmap( bmp );
drawer.DrawRectBounds( Color.White, blockSize / 8, 0, 0, blockSize, blockSize );
selectedBlock = drawer.Make2DTexture( bmp, size, 0, 0 );
} }
selectedBlock = Utils2D.Make2DTexture( graphicsApi, bmp, size, 0, 0 );
} }
RecreateBlockTextures(); RecreateBlockTextures();
} }
@ -139,18 +140,19 @@ namespace ClassicalSharp {
UpdateBlockInfoString( block ); UpdateBlockInfoString( block );
string value = buffer.GetString(); string value = buffer.GetString();
Size size = Utils2D.MeasureSize( value, font, true ); Size size = game.Drawer2D.MeasureSize( value, font, true );
int x = startX + ( blockSize * blocksPerRow ) / 2 - size.Width / 2; int x = startX + ( blockSize * blocksPerRow ) / 2 - size.Width / 2;
int y = startY - size.Height; int y = startY - size.Height;
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) { using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) { using( IDrawer2D drawer = game.Drawer2D ) {
Utils2D.DrawRect( g, backColour, 0, 0, bmp.Width, bmp.Height ); drawer.SetBitmap( bmp );
DrawTextArgs args = new DrawTextArgs( graphicsApi, value, true ); drawer.DrawRect( backColour, 0, 0, bmp.Width, bmp.Height );
DrawTextArgs args = new DrawTextArgs( value, true );
args.SkipPartsCheck = true; args.SkipPartsCheck = true;
Utils2D.DrawText( g, font, ref args, 0, 0 ); drawer.DrawText( font, ref args, 0, 0 );
blockInfoTexture = drawer.Make2DTexture( bmp, size, x, y );
} }
blockInfoTexture = Utils2D.Make2DTexture( graphicsApi, bmp, size, x, y );
} }
} }

View File

@ -122,8 +122,8 @@ namespace ClassicalSharp {
void UpdateAnnouncement( string text ) { void UpdateAnnouncement( string text ) {
announcementDisplayTime = DateTime.UtcNow; announcementDisplayTime = DateTime.UtcNow;
DrawTextArgs args = new DrawTextArgs( graphicsApi, text, true ); DrawTextArgs args = new DrawTextArgs( text, true );
announcementTex = Utils2D.MakeTextTexture( announcementFont, 0, 0, ref args ); announcementTex = game.Drawer2D.MakeTextTexture( announcementFont, 0, 0, ref args );
announcementTex.X1 = game.Width / 2 - announcementTex.Width / 2; announcementTex.X1 = game.Width / 2 - announcementTex.Width / 2;
announcementTex.Y1 = game.Height / 4 - announcementTex.Height / 2; announcementTex.Y1 = game.Height / 4 - announcementTex.Height / 2;
} }

View File

@ -36,11 +36,12 @@ namespace ClassicalSharp {
progX = game.Width / 2f - progWidth / 2f; progX = game.Width / 2f - progWidth / 2f;
Size size = new Size( progWidth, progHeight ); Size size = new Size( progWidth, progHeight );
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) { using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) { using( IDrawer2D drawer = game.Drawer2D ) {
Utils2D.DrawRectBounds( g, Color.White, 5f, 0, 0, progWidth, progHeight ); drawer.SetBitmap( bmp );
drawer.DrawRectBounds( Color.White, 5f, 0, 0, progWidth, progHeight );
progressBoxTexture = drawer.Make2DTexture( bmp, size, (int)progX, (int)progY );
} }
progressBoxTexture = Utils2D.Make2DTexture( graphicsApi, bmp, size, (int)progX, (int)progY );
} }
game.MapLoading += MapLoading; game.MapLoading += MapLoading;
} }

View File

@ -1,188 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using ClassicalSharp.GraphicsAPI;
namespace ClassicalSharp {
public static class Utils2D {
public static StringFormat format;
static Bitmap measuringBmp;
static Graphics measuringGraphics;
static Dictionary<int, SolidBrush> brushCache = new Dictionary<int, SolidBrush>( 16 );
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 );
measuringGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
}
static SolidBrush GetOrCreateBrush( Color color ) {
int key = color.ToArgb();
SolidBrush brush;
if( brushCache.TryGetValue( key, out brush ) ) {
return brush;
}
brush = new SolidBrush( color );
brushCache[key] = brush;
return brush;
}
public static Bitmap CreatePow2Bitmap( Size size ) {
return new Bitmap( Utils.NextPowerOf2( size.Width ), Utils.NextPowerOf2( size.Height ) );
}
const float shadowOffset = 1.3f;
public static Size MeasureSize( string text, Font font, bool shadow ) {
GetTextParts( text );
SizeF total = SizeF.Empty;
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 && parts.Count > 0 ) {
total.Width += shadowOffset;
total.Height += shadowOffset;
}
return Size.Ceiling( total );
}
public static void DrawText( Graphics g, Font font, ref DrawTextArgs args, float x, float y ) {
if( !args.SkipPartsCheck )
GetTextParts( args.Text );
DrawTextNoCheck( g, font, ref args, x, y );
}
static void DrawTextNoCheck( Graphics g, Font font, ref DrawTextArgs args, float x, float y ) {
g.TextRenderingHint = TextRenderingHint.AntiAlias;
Brush shadowBrush = GetOrCreateBrush( args.ShadowColour );
for( int i = 0; i < parts.Count; i++ ) {
TextPart part = parts[i];
Brush textBrush = GetOrCreateBrush( part.TextColour );
if( args.UseShadow ) {
g.DrawString( part.Text, font, shadowBrush, x + shadowOffset, y + shadowOffset, format );
}
g.DrawString( part.Text, font, textBrush, x, y, format );
x += g.MeasureString( part.Text, font, Int32.MaxValue, format ).Width;
}
}
public static void DrawRect( Graphics g, Color colour, int x, int y, int width, int height ) {
Brush brush = GetOrCreateBrush( colour );
g.FillRectangle( brush, x, y, 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 DrawRoundedRect( Graphics g, Color colour, float x, float y, float width, float height ) {
GraphicsPath path = new GraphicsPath();
float x1 = x, y1 = y, x2 = x + width, y2 = y + height;
const float r = 3, dia = r * 2;
path.AddArc( x1, y1, dia, dia, 180, 90 );
path.AddLine( x1 + r, y1, x2 - r, y1 );
path.AddArc( x2 - dia, y1, dia, dia, 270, 90 );
path.AddLine( x2, y1 + r, x2, y2 - r );
path.AddArc( x2 - dia, y2 - dia, dia, dia, 0, 90 );
path.AddLine( x1 + r, y2, x2 - r, y2 );
path.AddArc( x1, y2 - dia, dia, dia, 90, 90 );
path.AddLine( x1, y1 + r, x1, y2 - r );
path.CloseAllFigures();
using( Brush brush = new SolidBrush( colour ) )
g.FillPath( brush, path );
path.Dispose();
}
public static Texture MakeTextTexture( Font font, int x1, int y1, ref DrawTextArgs args ) {
Size size = MeasureSize( args.Text, font, args.UseShadow );
if( parts.Count == 0 )
return new Texture( -1, x1, y1, 0, 0, 1, 1 );
using( Bitmap bmp = CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
DrawTextNoCheck( g, font, ref args, 0, 0 );
}
return Make2DTexture( args.Graphics, bmp, size, x1, y1 );
}
}
public static Texture Make2DTexture( IGraphicsApi graphics, Bitmap bmp, Size used, int x1, int y1 ) {
int texId = graphics.CreateTexture( bmp );
return new Texture( texId, x1, y1, used.Width, used.Height,
(float)used.Width / bmp.Width, (float)used.Height / bmp.Height );
}
public static void Dispose() {
measuringBmp.Dispose();
measuringGraphics.Dispose();
foreach( var pair in brushCache ) {
pair.Value.Dispose();
}
}
static List<TextPart> parts = new List<TextPart>( 64 );
static Color white = Color.FromArgb( 255, 255, 255 );
struct TextPart {
public string Text;
public Color TextColour;
public TextPart( string text, Color col ) {
Text = text;
TextColour = col;
}
}
static void GetTextParts( string value ) {
parts.Clear();
if( String.IsNullOrEmpty( value ) ) {
} else if( value.IndexOf( '&' ) == -1 ) {
parts.Add( new TextPart( value, white ) );
} else {
SplitText( value );
}
}
static void SplitText( string value ) {
int code = 0xF;
for( int i = 0; i < value.Length; i++ ) {
int nextAnd = value.IndexOf( '&', i );
int partLength = nextAnd == -1 ? value.Length - i : nextAnd - i;
if( partLength > 0 ) {
string part = value.Substring( i, partLength );
Color col = Color.FromArgb(
191 * ( ( code >> 2 ) & 0x1 ) + 64 * ( code >> 3 ),
191 * ( ( code >> 1 ) & 0x1 ) + 64 * ( code >> 3 ),
191 * ( ( code >> 0 ) & 0x1 ) + 64 * ( code >> 3 ) );
parts.Add( new TextPart( part, col ) );
}
i += partLength + 1;
if( nextAnd >= 0 && nextAnd + 1 < value.Length ) {
try {
code = Utils.ParseHex( value[nextAnd + 1] );
} catch( FormatException ) {
code = 0xF;
i--; // include the character that isn't a colour code.
}
}
}
}
}
}

View File

@ -28,11 +28,12 @@ namespace ClassicalSharp {
int y = game.Height - blockSize; int y = game.Height - blockSize;
Size size = new Size( 32, 32 ); Size size = new Size( 32, 32 );
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) { using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) { using( IDrawer2D drawer = game.Drawer2D ) {
Utils2D.DrawRectBounds( g, Color.White, blockSize / 8, 0, 0, blockSize, blockSize ); drawer.SetBitmap( bmp );
drawer.DrawRectBounds( Color.White, blockSize / 8, 0, 0, blockSize, blockSize );
selectedBlock = drawer.Make2DTexture( bmp, size, 0, y );
} }
selectedBlock = Utils2D.Make2DTexture( graphicsApi, bmp, size, 0, y );
} }
int x = game.Width / 2 - ( blockSize * barTextures.Length ) / 2; int x = game.Width / 2 - ( blockSize * barTextures.Length ) / 2;

View File

@ -32,7 +32,7 @@ namespace ClassicalSharp {
readonly Font font; readonly Font font;
public override void Init() { public override void Init() {
defaultHeight = Utils2D.MeasureSize( "I", font, true ).Height; defaultHeight = game.Drawer2D.MeasureSize( "I", font, true ).Height;
Height = defaultHeight; Height = defaultHeight;
} }
@ -81,8 +81,7 @@ namespace ClassicalSharp {
public bool Active; public bool Active;
void MakeTexture( string text ) { void MakeTexture( string text ) {
DrawTextArgs args = new DrawTextArgs( graphicsApi, text, true ); Size size = game.Drawer2D.MeasureSize( text, font, true );
Size size = Utils2D.MeasureSize( text, font, true );
int xOffset = Math.Max( size.Width, DesiredMaxWidth ) - size.Width; int xOffset = Math.Max( size.Width, DesiredMaxWidth ) - size.Width;
size.Width = Math.Max( size.Width, DesiredMaxWidth ); size.Width = Math.Max( size.Width, DesiredMaxWidth );
int yOffset = Math.Max( size.Height, DesiredMaxHeight ) - size.Height; int yOffset = Math.Max( size.Height, DesiredMaxHeight ) - size.Height;
@ -91,15 +90,17 @@ namespace ClassicalSharp {
const int borderSize = 3; // 1 px for base border, 2 px for shadow, 1 px for offset text const int borderSize = 3; // 1 px for base border, 2 px for shadow, 1 px for offset text
size.Width += borderSize; size.Height += borderSize; size.Width += borderSize; size.Height += borderSize;
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) { using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) { using( IDrawer2D drawer = game.Drawer2D ) {
drawer.SetBitmap( bmp );
drawer.DrawRoundedRect( shadowCol, 1.3f, 1.3f, baseSize.Width, baseSize.Height );
drawer.DrawRoundedRect( boxCol, 0, 0, baseSize.Width, baseSize.Height );
DrawTextArgs args = new DrawTextArgs( text, true );
args.SkipPartsCheck = true; args.SkipPartsCheck = true;
g.SmoothingMode = SmoothingMode.HighQuality; drawer.DrawText( font, ref args, 1 + xOffset / 2, 1 + yOffset / 2 );
Utils2D.DrawRoundedRect( g, shadowCol, 1.3f, 1.3f, baseSize.Width, baseSize.Height ); texture = drawer.Make2DTexture( bmp, size, 0, 0 );
Utils2D.DrawRoundedRect( g, boxCol, 0, 0, baseSize.Width, baseSize.Height );
Utils2D.DrawText( g, font, ref args, 1 + xOffset / 2, 1 + yOffset / 2 );
} }
texture = Utils2D.Make2DTexture( graphicsApi, bmp, size, 0, 0 );
} }
} }
} }

View File

@ -106,8 +106,8 @@ namespace ClassicalSharp {
} }
void AddPlayerInfo( CpeListInfo player, int index ) { void AddPlayerInfo( CpeListInfo player, int index ) {
DrawTextArgs args = new DrawTextArgs( graphicsApi, player.ListName, true ); DrawTextArgs args = new DrawTextArgs(player.ListName, true );
Texture tex = Utils2D.MakeTextTexture( font, 0, 0, ref args ); Texture tex = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
if( index < 0 ) { if( index < 0 ) {
info[namesCount] = new PlayerInfo( player ); info[namesCount] = new PlayerInfo( player );
textures[namesCount] = tex; textures[namesCount] = tex;

View File

@ -48,31 +48,32 @@ namespace ClassicalSharp {
} }
public override void Init() { public override void Init() {
DrawTextArgs caretArgs = new DrawTextArgs( graphicsApi, "_", Color.White, false ); DrawTextArgs caretArgs = new DrawTextArgs( "_", Color.White, false );
chatCaretTexture = Utils2D.MakeTextTexture( boldFont, 0, 0, ref caretArgs ); chatCaretTexture = game.Drawer2D.MakeTextTexture( boldFont, 0, 0, ref caretArgs );
SetText( chatInputText.GetString() ); SetText( chatInputText.GetString() );
} }
public void SetText( string value ) { public void SetText( string value ) {
chatInputText.Append( 0, value ); chatInputText.Append( 0, value );
Size textSize = Utils2D.MeasureSize( value, font, false ); Size textSize = game.Drawer2D.MeasureSize( value, font, false );
Size size = new Size( Math.Max( textSize.Width, DesiredMaxWidth ), Size size = new Size( Math.Max( textSize.Width, DesiredMaxWidth ),
Math.Max( textSize.Height, DesiredMaxHeight ) ); Math.Max( textSize.Height, DesiredMaxHeight ) );
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) { using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) { using( IDrawer2D drawer = game.Drawer2D ) {
Utils2D.DrawRect( g, backColour, 0, 0, size.Width, size.Height ); drawer.SetBitmap( bmp );
DrawTextArgs args = new DrawTextArgs( graphicsApi, value, Color.White, false ); drawer.DrawRect( backColour, 0, 0, size.Width, size.Height );
DrawTextArgs args = new DrawTextArgs( value, Color.White, false );
args.SkipPartsCheck = true; args.SkipPartsCheck = true;
Utils2D.DrawText( g, font, ref args, 0, 0 ); drawer.DrawText( font, ref args, 0, 0 );
string range = Validator.Range; string range = Validator.Range;
Size hintSize = Utils2D.MeasureSize( range, hintFont, true ); Size hintSize = drawer.MeasureSize( range, hintFont, true );
args = new DrawTextArgs( graphicsApi, range, Color.White, false ); args = new DrawTextArgs( range, Color.White, false );
args.SkipPartsCheck = true; args.SkipPartsCheck = true;
Utils2D.DrawText( g, hintFont, ref args, size.Width - hintSize.Width, 0 ); drawer.DrawText( hintFont, ref args, size.Width - hintSize.Width, 0 );
chatInputTexture = drawer.Make2DTexture( bmp, size, 0, 0 );
} }
chatInputTexture = Utils2D.Make2DTexture( graphicsApi, bmp, size, 0, 0 );
} }
X = CalcOffset( game.Width, size.Width, XOffset, HorizontalDocking ); X = CalcOffset( game.Width, size.Width, XOffset, HorizontalDocking );

View File

@ -50,8 +50,8 @@ namespace ClassicalSharp {
} }
void AddPlayerInfo( Player player ) { void AddPlayerInfo( Player player ) {
DrawTextArgs args = new DrawTextArgs( graphicsApi, player.DisplayName, true ); DrawTextArgs args = new DrawTextArgs( player.DisplayName, true );
Texture tex = Utils2D.MakeTextTexture( font, 0, 0, ref args ); Texture tex = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
info[namesCount] = new PlayerInfo( player ); info[namesCount] = new PlayerInfo( player );
textures[namesCount] = tex; textures[namesCount] = tex;
namesCount++; namesCount++;

View File

@ -18,7 +18,7 @@ namespace ClassicalSharp {
public override void Init() { public override void Init() {
textures = new Texture[ElementsCount]; textures = new Texture[ElementsCount];
defaultHeight = Utils2D.MeasureSize( "I", font, true ).Height; defaultHeight = game.Drawer2D.MeasureSize( "I", font, true ).Height;
for( int i = 0; i < textures.Length; i++ ) { for( int i = 0; i < textures.Length; i++ ) {
textures[i].Height = defaultHeight; textures[i].Height = defaultHeight;
} }
@ -29,8 +29,8 @@ namespace ClassicalSharp {
graphicsApi.DeleteTexture( ref textures[index] ); graphicsApi.DeleteTexture( ref textures[index] );
if( !String.IsNullOrEmpty( text ) ) { if( !String.IsNullOrEmpty( text ) ) {
DrawTextArgs args = new DrawTextArgs( graphicsApi, text, true ); DrawTextArgs args = new DrawTextArgs( text, true );
Texture tex = Utils2D.MakeTextTexture( font, 0, 0, ref args ); Texture tex = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
tex.X1 = CalcOffset( game.Width, tex.Width, XOffset, HorizontalDocking ); tex.X1 = CalcOffset( game.Width, tex.Width, XOffset, HorizontalDocking );
tex.Y1 = CalcY( index, tex.Height ); tex.Y1 = CalcY( index, tex.Height );
textures[index] = tex; textures[index] = tex;

View File

@ -31,14 +31,14 @@ namespace ClassicalSharp {
public override void Init() { public override void Init() {
X = 10; X = 10;
DrawTextArgs caretArgs = new DrawTextArgs( graphicsApi, "_", Color.White, false ); DrawTextArgs caretArgs = new DrawTextArgs( "_", Color.White, false );
chatCaretTexture = Utils2D.MakeTextTexture( boldFont, 0, 0, ref caretArgs ); chatCaretTexture = game.Drawer2D.MakeTextTexture( boldFont, 0, 0, ref caretArgs );
string value = chatInputText.GetString(); string value = chatInputText.GetString();
if( chatInputText.Empty ) { if( chatInputText.Empty ) {
caretPos = -1; caretPos = -1;
} }
Size size = Utils2D.MeasureSize( value, font, false ); Size size = game.Drawer2D.MeasureSize( value, font, false );
if( caretPos == -1 ) { if( caretPos == -1 ) {
chatCaretTexture.X1 = 10 + size.Width; chatCaretTexture.X1 = 10 + size.Width;
@ -46,10 +46,10 @@ namespace ClassicalSharp {
DrawString( size, value, true ); DrawString( size, value, true );
} else { } else {
string subString = chatInputText.GetSubstring( caretPos ); string subString = chatInputText.GetSubstring( caretPos );
Size trimmedSize = Utils2D.MeasureSize( subString, font, false ); Size trimmedSize = game.Drawer2D.MeasureSize( subString, font, false );
chatCaretTexture.X1 = 10 + trimmedSize.Width; chatCaretTexture.X1 = 10 + trimmedSize.Width;
Size charSize = Utils2D.MeasureSize( new String( value[caretPos], 1 ), font, false ); Size charSize = game.Drawer2D.MeasureSize( new String( value[caretPos], 1 ), font, false );
chatCaretTexture.Width = charSize.Width; chatCaretTexture.Width = charSize.Width;
DrawString( size, value, false ); DrawString( size, value, false );
} }
@ -59,14 +59,15 @@ namespace ClassicalSharp {
size.Height = Math.Max( size.Height, chatCaretTexture.Height ); size.Height = Math.Max( size.Height, chatCaretTexture.Height );
int y = game.Height - ChatInputYOffset - size.Height / 2; int y = game.Height - ChatInputYOffset - size.Height / 2;
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) { using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) { using( IDrawer2D drawer = game.Drawer2D ) {
Utils2D.DrawRect( g, backColour, 0, 0, bmp.Width, bmp.Height ); drawer.SetBitmap( bmp );
DrawTextArgs args = new DrawTextArgs( graphicsApi, value, Color.White, false ); drawer.DrawRect( backColour, 0, 0, bmp.Width, bmp.Height );
DrawTextArgs args = new DrawTextArgs( value, Color.White, false );
args.SkipPartsCheck = skipCheck; args.SkipPartsCheck = skipCheck;
Utils2D.DrawText( g, font, ref args, 0, 0 ); drawer.DrawText( font, ref args, 0, 0 );
chatInputTexture = drawer.Make2DTexture( bmp, size, 10, y );
} }
chatInputTexture = Utils2D.Make2DTexture( graphicsApi, bmp, size, 10, y );
} }
chatCaretTexture.Y1 = chatInputTexture.Y1; chatCaretTexture.Y1 = chatInputTexture.Y1;

View File

@ -27,7 +27,7 @@ namespace ClassicalSharp {
readonly Font font; readonly Font font;
public override void Init() { public override void Init() {
defaultHeight = Utils2D.MeasureSize( "I", font, true ).Height; defaultHeight = game.Drawer2D.MeasureSize( "I", font, true ).Height;
Height = defaultHeight; Height = defaultHeight;
} }
@ -37,8 +37,8 @@ namespace ClassicalSharp {
texture = new Texture(); texture = new Texture();
Height = defaultHeight; Height = defaultHeight;
} else { } else {
DrawTextArgs args = new DrawTextArgs( graphicsApi, text, true ); DrawTextArgs args = new DrawTextArgs( text, true );
texture = Utils2D.MakeTextTexture( font, 0, 0, ref args ); texture = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
X = texture.X1 = CalcOffset( game.Width, texture.Width, XOffset, HorizontalDocking ); X = texture.X1 = CalcOffset( game.Width, texture.Width, XOffset, HorizontalDocking );
Y = texture.Y1 = CalcOffset( game.Height, texture.Height, YOffset, VerticalDocking ); Y = texture.Y1 = CalcOffset( game.Height, texture.Height, YOffset, VerticalDocking );
Height = texture.Height; Height = texture.Height;

View File

@ -65,7 +65,9 @@
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="2D\DrawTextArgs.cs" /> <Compile Include="2D\Drawing\DrawTextArgs.cs" />
<Compile Include="2D\Drawing\GdiDrawer2D.cs" />
<Compile Include="2D\Drawing\IDrawer2D.cs" />
<Compile Include="2D\Screens\BlockSelectScreen.cs" /> <Compile Include="2D\Screens\BlockSelectScreen.cs" />
<Compile Include="2D\Screens\ChatScreen.cs" /> <Compile Include="2D\Screens\ChatScreen.cs" />
<Compile Include="2D\Screens\ErrorScreen.cs" /> <Compile Include="2D\Screens\ErrorScreen.cs" />
@ -81,7 +83,6 @@
<Compile Include="2D\Screens\NormalScreen.cs" /> <Compile Include="2D\Screens\NormalScreen.cs" />
<Compile Include="2D\Screens\Screen.cs" /> <Compile Include="2D\Screens\Screen.cs" />
<Compile Include="2D\Texture.cs" /> <Compile Include="2D\Texture.cs" />
<Compile Include="2D\Utils2D.cs" />
<Compile Include="2D\Widgets\BlockHotbarWidget.cs" /> <Compile Include="2D\Widgets\BlockHotbarWidget.cs" />
<Compile Include="2D\Widgets\ExtPlayerListWidget.cs" /> <Compile Include="2D\Widgets\ExtPlayerListWidget.cs" />
<Compile Include="2D\Widgets\Menu\MenuInputValidator.cs" /> <Compile Include="2D\Widgets\Menu\MenuInputValidator.cs" />
@ -197,6 +198,7 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="2D\Drawing" />
<Folder Include="2D\Screens" /> <Folder Include="2D\Screens" />
<Folder Include="2D\Screens\Menu" /> <Folder Include="2D\Screens\Menu" />
<Folder Include="2D\Widgets" /> <Folder Include="2D\Widgets" />

View File

@ -21,8 +21,8 @@ namespace ClassicalSharp {
api = game.Graphics; api = game.Graphics;
using( Font font = new Font( "Arial", 14 ) ) { using( Font font = new Font( "Arial", 14 ) ) {
DrawTextArgs args = new DrawTextArgs( api, DisplayName, true ); DrawTextArgs args = new DrawTextArgs( DisplayName, true );
nameTex = Utils2D.MakeTextTexture( font, 0, 0, ref args ); nameTex = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
} }
} }

View File

@ -39,6 +39,7 @@ namespace ClassicalSharp {
public EnvRenderer EnvRenderer; public EnvRenderer EnvRenderer;
public WeatherRenderer WeatherRenderer; public WeatherRenderer WeatherRenderer;
public Inventory Inventory; public Inventory Inventory;
public IDrawer2D Drawer2D;
public CommandManager CommandManager; public CommandManager CommandManager;
public SelectionManager SelectionManager; public SelectionManager SelectionManager;
@ -98,6 +99,7 @@ namespace ClassicalSharp {
Utils.LogWarning( "Unable to load options.txt" ); Utils.LogWarning( "Unable to load options.txt" );
} }
Keys = new KeyMap(); Keys = new KeyMap();
Drawer2D = new GdiDrawer2D( this );
ViewDistance = Options.GetInt( "viewdist", 16, 8192, 512 ); ViewDistance = Options.GetInt( "viewdist", 16, 8192, 512 );
defaultIb = Graphics.MakeDefaultIb(); defaultIb = Graphics.MakeDefaultIb();
ModelCache = new ModelCache( this ); ModelCache = new ModelCache( this );
@ -346,7 +348,7 @@ namespace ClassicalSharp {
} }
Graphics.DeleteIb( defaultIb ); Graphics.DeleteIb( defaultIb );
Graphics.Dispose(); Graphics.Dispose();
Utils2D.Dispose(); Drawer2D.DisposeInstance();
Animations.Dispose(); Animations.Dispose();
Graphics.DeleteTexture( ref CloudsTextureId ); Graphics.DeleteTexture( ref CloudsTextureId );
Graphics.DeleteTexture( ref RainTextureId ); Graphics.DeleteTexture( ref RainTextureId );