mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 18:15:28 -04:00
Rewrite backend for 2D drawing to be far more modular.
This commit is contained in:
parent
d3c85a8cc5
commit
63a42bbc68
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
29
ClassicalSharp/2D/Drawing/DrawTextArgs.cs
Normal file
29
ClassicalSharp/2D/Drawing/DrawTextArgs.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
127
ClassicalSharp/2D/Drawing/GdiDrawer2D.cs
Normal file
127
ClassicalSharp/2D/Drawing/GdiDrawer2D.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
109
ClassicalSharp/2D/Drawing/IDrawer2D.cs
Normal file
109
ClassicalSharp/2D/Drawing/IDrawer2D.cs
Normal 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.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -76,11 +76,12 @@ namespace ClassicalSharp {
|
||||
public override void Init() {
|
||||
game.BlockPermissionsChanged += BlockPermissionsChanged;
|
||||
Size size = new Size( blockSize, blockSize );
|
||||
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) {
|
||||
using( Graphics g = Graphics.FromImage( bmp ) ) {
|
||||
Utils2D.DrawRectBounds( g, Color.White, blockSize / 8, 0, 0, blockSize, blockSize );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
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();
|
||||
}
|
||||
@ -139,18 +140,19 @@ namespace ClassicalSharp {
|
||||
UpdateBlockInfoString( block );
|
||||
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 y = startY - size.Height;
|
||||
|
||||
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) {
|
||||
using( Graphics g = Graphics.FromImage( bmp ) ) {
|
||||
Utils2D.DrawRect( g, backColour, 0, 0, bmp.Width, bmp.Height );
|
||||
DrawTextArgs args = new DrawTextArgs( graphicsApi, value, true );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRect( backColour, 0, 0, bmp.Width, bmp.Height );
|
||||
DrawTextArgs args = new DrawTextArgs( value, true );
|
||||
args.SkipPartsCheck = true;
|
||||
Utils2D.DrawText( g, font, ref args, 0, 0 );
|
||||
}
|
||||
blockInfoTexture = Utils2D.Make2DTexture( graphicsApi, bmp, size, x, y );
|
||||
drawer.DrawText( font, ref args, 0, 0 );
|
||||
blockInfoTexture = drawer.Make2DTexture( bmp, size, x, y );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,8 +122,8 @@ namespace ClassicalSharp {
|
||||
|
||||
void UpdateAnnouncement( string text ) {
|
||||
announcementDisplayTime = DateTime.UtcNow;
|
||||
DrawTextArgs args = new DrawTextArgs( graphicsApi, text, true );
|
||||
announcementTex = Utils2D.MakeTextTexture( announcementFont, 0, 0, ref args );
|
||||
DrawTextArgs args = new DrawTextArgs( text, true );
|
||||
announcementTex = game.Drawer2D.MakeTextTexture( announcementFont, 0, 0, ref args );
|
||||
announcementTex.X1 = game.Width / 2 - announcementTex.Width / 2;
|
||||
announcementTex.Y1 = game.Height / 4 - announcementTex.Height / 2;
|
||||
}
|
||||
|
@ -36,11 +36,12 @@ namespace ClassicalSharp {
|
||||
progX = game.Width / 2f - progWidth / 2f;
|
||||
|
||||
Size size = new Size( progWidth, progHeight );
|
||||
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) {
|
||||
using( Graphics g = Graphics.FromImage( bmp ) ) {
|
||||
Utils2D.DrawRectBounds( g, Color.White, 5f, 0, 0, progWidth, progHeight );
|
||||
}
|
||||
progressBoxTexture = Utils2D.Make2DTexture( graphicsApi, bmp, size, (int)progX, (int)progY );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRectBounds( Color.White, 5f, 0, 0, progWidth, progHeight );
|
||||
progressBoxTexture = drawer.Make2DTexture( bmp, size, (int)progX, (int)progY );
|
||||
}
|
||||
}
|
||||
game.MapLoading += MapLoading;
|
||||
}
|
||||
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -28,11 +28,12 @@ namespace ClassicalSharp {
|
||||
int y = game.Height - blockSize;
|
||||
|
||||
Size size = new Size( 32, 32 );
|
||||
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) {
|
||||
using( Graphics g = Graphics.FromImage( bmp ) ) {
|
||||
Utils2D.DrawRectBounds( g, Color.White, blockSize / 8, 0, 0, blockSize, blockSize );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
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;
|
||||
|
@ -32,7 +32,7 @@ namespace ClassicalSharp {
|
||||
readonly Font font;
|
||||
|
||||
public override void Init() {
|
||||
defaultHeight = Utils2D.MeasureSize( "I", font, true ).Height;
|
||||
defaultHeight = game.Drawer2D.MeasureSize( "I", font, true ).Height;
|
||||
Height = defaultHeight;
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
public override void Render( double delta ) {
|
||||
if( texture.IsValid ) {
|
||||
if( texture.IsValid ) {
|
||||
FastColour col = Active ? FastColour.White : new FastColour( 200, 200, 200 );
|
||||
graphicsApi.BindTexture( texture.ID );
|
||||
graphicsApi.Draw2DTexture( ref texture, col );
|
||||
@ -80,9 +80,8 @@ namespace ClassicalSharp {
|
||||
public Action<Game, string> SetValue;
|
||||
public bool Active;
|
||||
|
||||
void MakeTexture( string text ) {
|
||||
DrawTextArgs args = new DrawTextArgs( graphicsApi, text, true );
|
||||
Size size = Utils2D.MeasureSize( text, font, true );
|
||||
void MakeTexture( string text ) {
|
||||
Size size = game.Drawer2D.MeasureSize( text, font, true );
|
||||
int xOffset = Math.Max( size.Width, DesiredMaxWidth ) - size.Width;
|
||||
size.Width = Math.Max( size.Width, DesiredMaxWidth );
|
||||
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
|
||||
size.Width += borderSize; size.Height += borderSize;
|
||||
|
||||
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) {
|
||||
using( Graphics g = Graphics.FromImage( bmp ) ) {
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
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;
|
||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||
Utils2D.DrawRoundedRect( g, shadowCol, 1.3f, 1.3f, baseSize.Width, baseSize.Height );
|
||||
Utils2D.DrawRoundedRect( g, boxCol, 0, 0, baseSize.Width, baseSize.Height );
|
||||
Utils2D.DrawText( g, font, ref args, 1 + xOffset / 2, 1 + yOffset / 2 );
|
||||
drawer.DrawText( font, ref args, 1 + xOffset / 2, 1 + yOffset / 2 );
|
||||
texture = drawer.Make2DTexture( bmp, size, 0, 0 );
|
||||
}
|
||||
texture = Utils2D.Make2DTexture( graphicsApi, bmp, size, 0, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,8 +106,8 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
void AddPlayerInfo( CpeListInfo player, int index ) {
|
||||
DrawTextArgs args = new DrawTextArgs( graphicsApi, player.ListName, true );
|
||||
Texture tex = Utils2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
DrawTextArgs args = new DrawTextArgs(player.ListName, true );
|
||||
Texture tex = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
if( index < 0 ) {
|
||||
info[namesCount] = new PlayerInfo( player );
|
||||
textures[namesCount] = tex;
|
||||
|
@ -48,31 +48,32 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
public override void Init() {
|
||||
DrawTextArgs caretArgs = new DrawTextArgs( graphicsApi, "_", Color.White, false );
|
||||
chatCaretTexture = Utils2D.MakeTextTexture( boldFont, 0, 0, ref caretArgs );
|
||||
DrawTextArgs caretArgs = new DrawTextArgs( "_", Color.White, false );
|
||||
chatCaretTexture = game.Drawer2D.MakeTextTexture( boldFont, 0, 0, ref caretArgs );
|
||||
SetText( chatInputText.GetString() );
|
||||
}
|
||||
|
||||
public void SetText( string 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 ),
|
||||
Math.Max( textSize.Height, DesiredMaxHeight ) );
|
||||
|
||||
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) {
|
||||
using( Graphics g = Graphics.FromImage( bmp ) ) {
|
||||
Utils2D.DrawRect( g, backColour, 0, 0, size.Width, size.Height );
|
||||
DrawTextArgs args = new DrawTextArgs( graphicsApi, value, Color.White, false );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRect( backColour, 0, 0, size.Width, size.Height );
|
||||
DrawTextArgs args = new DrawTextArgs( value, Color.White, false );
|
||||
args.SkipPartsCheck = true;
|
||||
Utils2D.DrawText( g, font, ref args, 0, 0 );
|
||||
drawer.DrawText( font, ref args, 0, 0 );
|
||||
|
||||
string range = Validator.Range;
|
||||
Size hintSize = Utils2D.MeasureSize( range, hintFont, true );
|
||||
args = new DrawTextArgs( graphicsApi, range, Color.White, false );
|
||||
Size hintSize = drawer.MeasureSize( range, hintFont, true );
|
||||
args = new DrawTextArgs( range, Color.White, false );
|
||||
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 );
|
||||
|
@ -50,8 +50,8 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
void AddPlayerInfo( Player player ) {
|
||||
DrawTextArgs args = new DrawTextArgs( graphicsApi, player.DisplayName, true );
|
||||
Texture tex = Utils2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
DrawTextArgs args = new DrawTextArgs( player.DisplayName, true );
|
||||
Texture tex = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
info[namesCount] = new PlayerInfo( player );
|
||||
textures[namesCount] = tex;
|
||||
namesCount++;
|
||||
|
@ -18,7 +18,7 @@ namespace ClassicalSharp {
|
||||
|
||||
public override void Init() {
|
||||
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++ ) {
|
||||
textures[i].Height = defaultHeight;
|
||||
}
|
||||
@ -29,8 +29,8 @@ namespace ClassicalSharp {
|
||||
graphicsApi.DeleteTexture( ref textures[index] );
|
||||
|
||||
if( !String.IsNullOrEmpty( text ) ) {
|
||||
DrawTextArgs args = new DrawTextArgs( graphicsApi, text, true );
|
||||
Texture tex = Utils2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
DrawTextArgs args = new DrawTextArgs( text, true );
|
||||
Texture tex = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
tex.X1 = CalcOffset( game.Width, tex.Width, XOffset, HorizontalDocking );
|
||||
tex.Y1 = CalcY( index, tex.Height );
|
||||
textures[index] = tex;
|
||||
|
@ -31,14 +31,14 @@ namespace ClassicalSharp {
|
||||
|
||||
public override void Init() {
|
||||
X = 10;
|
||||
DrawTextArgs caretArgs = new DrawTextArgs( graphicsApi, "_", Color.White, false );
|
||||
chatCaretTexture = Utils2D.MakeTextTexture( boldFont, 0, 0, ref caretArgs );
|
||||
DrawTextArgs caretArgs = new DrawTextArgs( "_", Color.White, false );
|
||||
chatCaretTexture = game.Drawer2D.MakeTextTexture( boldFont, 0, 0, ref caretArgs );
|
||||
string value = chatInputText.GetString();
|
||||
|
||||
if( chatInputText.Empty ) {
|
||||
caretPos = -1;
|
||||
}
|
||||
Size size = Utils2D.MeasureSize( value, font, false );
|
||||
Size size = game.Drawer2D.MeasureSize( value, font, false );
|
||||
|
||||
if( caretPos == -1 ) {
|
||||
chatCaretTexture.X1 = 10 + size.Width;
|
||||
@ -46,10 +46,10 @@ namespace ClassicalSharp {
|
||||
DrawString( size, value, true );
|
||||
} else {
|
||||
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;
|
||||
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;
|
||||
DrawString( size, value, false );
|
||||
}
|
||||
@ -59,14 +59,15 @@ namespace ClassicalSharp {
|
||||
size.Height = Math.Max( size.Height, chatCaretTexture.Height );
|
||||
int y = game.Height - ChatInputYOffset - size.Height / 2;
|
||||
|
||||
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) {
|
||||
using( Graphics g = Graphics.FromImage( bmp ) ) {
|
||||
Utils2D.DrawRect( g, backColour, 0, 0, bmp.Width, bmp.Height );
|
||||
DrawTextArgs args = new DrawTextArgs( graphicsApi, value, Color.White, false );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRect( backColour, 0, 0, bmp.Width, bmp.Height );
|
||||
DrawTextArgs args = new DrawTextArgs( value, Color.White, false );
|
||||
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;
|
||||
@ -133,7 +134,7 @@ namespace ClassicalSharp {
|
||||
void BackspaceKey() {
|
||||
if( !chatInputText.Empty && caretPos != 0 ) {
|
||||
if( caretPos == -1 ) {
|
||||
chatInputText.DeleteAt( chatInputText.Length - 1 );
|
||||
chatInputText.DeleteAt( chatInputText.Length - 1 );
|
||||
} else {
|
||||
caretPos--;
|
||||
chatInputText.DeleteAt( caretPos );
|
||||
|
@ -27,7 +27,7 @@ namespace ClassicalSharp {
|
||||
readonly Font font;
|
||||
|
||||
public override void Init() {
|
||||
defaultHeight = Utils2D.MeasureSize( "I", font, true ).Height;
|
||||
defaultHeight = game.Drawer2D.MeasureSize( "I", font, true ).Height;
|
||||
Height = defaultHeight;
|
||||
}
|
||||
|
||||
@ -37,8 +37,8 @@ namespace ClassicalSharp {
|
||||
texture = new Texture();
|
||||
Height = defaultHeight;
|
||||
} else {
|
||||
DrawTextArgs args = new DrawTextArgs( graphicsApi, text, true );
|
||||
texture = Utils2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
DrawTextArgs args = new DrawTextArgs( text, true );
|
||||
texture = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
X = texture.X1 = CalcOffset( game.Width, texture.Width, XOffset, HorizontalDocking );
|
||||
Y = texture.Y1 = CalcOffset( game.Height, texture.Height, YOffset, VerticalDocking );
|
||||
Height = texture.Height;
|
||||
|
@ -65,7 +65,9 @@
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</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\ChatScreen.cs" />
|
||||
<Compile Include="2D\Screens\ErrorScreen.cs" />
|
||||
@ -81,7 +83,6 @@
|
||||
<Compile Include="2D\Screens\NormalScreen.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" />
|
||||
<Compile Include="2D\Widgets\Menu\MenuInputValidator.cs" />
|
||||
@ -197,6 +198,7 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="2D\Drawing" />
|
||||
<Folder Include="2D\Screens" />
|
||||
<Folder Include="2D\Screens\Menu" />
|
||||
<Folder Include="2D\Widgets" />
|
||||
|
@ -21,8 +21,8 @@ namespace ClassicalSharp {
|
||||
api = game.Graphics;
|
||||
|
||||
using( Font font = new Font( "Arial", 14 ) ) {
|
||||
DrawTextArgs args = new DrawTextArgs( api, DisplayName, true );
|
||||
nameTex = Utils2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
DrawTextArgs args = new DrawTextArgs( DisplayName, true );
|
||||
nameTex = game.Drawer2D.MakeTextTexture( font, 0, 0, ref args );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ namespace ClassicalSharp {
|
||||
public EnvRenderer EnvRenderer;
|
||||
public WeatherRenderer WeatherRenderer;
|
||||
public Inventory Inventory;
|
||||
public IDrawer2D Drawer2D;
|
||||
|
||||
public CommandManager CommandManager;
|
||||
public SelectionManager SelectionManager;
|
||||
@ -98,6 +99,7 @@ namespace ClassicalSharp {
|
||||
Utils.LogWarning( "Unable to load options.txt" );
|
||||
}
|
||||
Keys = new KeyMap();
|
||||
Drawer2D = new GdiDrawer2D( this );
|
||||
ViewDistance = Options.GetInt( "viewdist", 16, 8192, 512 );
|
||||
defaultIb = Graphics.MakeDefaultIb();
|
||||
ModelCache = new ModelCache( this );
|
||||
@ -346,7 +348,7 @@ namespace ClassicalSharp {
|
||||
}
|
||||
Graphics.DeleteIb( defaultIb );
|
||||
Graphics.Dispose();
|
||||
Utils2D.Dispose();
|
||||
Drawer2D.DisposeInstance();
|
||||
Animations.Dispose();
|
||||
Graphics.DeleteTexture( ref CloudsTextureId );
|
||||
Graphics.DeleteTexture( ref RainTextureId );
|
||||
|
Loading…
x
Reference in New Issue
Block a user