mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -04:00
Fix block model on AMD, fix /client gpu info crashing client, add support for default minecraft font.
This commit is contained in:
parent
4f4b6e2a2f
commit
c7ebbf985b
@ -9,32 +9,30 @@ namespace ClassicalSharp {
|
|||||||
// NOTE: This drawer is still a big work in progress and not close to done
|
// NOTE: This drawer is still a big work in progress and not close to done
|
||||||
// TODO: proper shadow colour
|
// TODO: proper shadow colour
|
||||||
// TODO: italic and bold
|
// TODO: italic and bold
|
||||||
Bitmap realBmp;
|
Bitmap fontBmp;
|
||||||
|
FastBitmap fontPixels;
|
||||||
|
int boxSize;
|
||||||
public GdiPlusDrawerMCFont( IGraphicsApi graphics ) : base( graphics ) {
|
public GdiPlusDrawerMCFont( IGraphicsApi graphics ) : base( graphics ) {
|
||||||
realBmp = new Bitmap( "default.png" );
|
fontBmp = new Bitmap( "default.png" );
|
||||||
|
boxSize = fontBmp.Width / 16;
|
||||||
|
fontPixels = new FastBitmap( fontBmp, true );
|
||||||
CalculateTextWidths();
|
CalculateTextWidths();
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] widths = new int[256];
|
int[] widths = new int[256];
|
||||||
unsafe void CalculateTextWidths() {
|
void CalculateTextWidths() {
|
||||||
using( FastBitmap fastBmp = new FastBitmap( realBmp, true ) ) {
|
for( int i = 0; i < 256; i++ )
|
||||||
for( int i = 0; i < 256; i++ ) {
|
MakeTile( i, (i & 0x0F) * boxSize, (i >> 4) * boxSize );
|
||||||
int tileX = (i & 0x0F) * 8;
|
widths[(int)' '] = boxSize / 2;
|
||||||
int tileY = (i >> 4) * 8;
|
|
||||||
MakeTile( fastBmp, i, tileX, tileY );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
widths[(int)' '] = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe void MakeTile( FastBitmap fastBmp, int i, int tileX, int tileY ) {
|
unsafe void MakeTile( int i, int tileX, int tileY ) {
|
||||||
for( int x = 7; x >= 0; x-- ) {
|
for( int x = boxSize - 1; x >= 0; x-- ) {
|
||||||
for( int y = 0; y < 8; y++ ) {
|
for( int y = 0; y < boxSize; y++ ) {
|
||||||
uint pixel = (uint)fastBmp.GetRowPtr( tileY + y )[tileX + x];
|
uint pixel = (uint)fontPixels.GetRowPtr( tileY + y )[tileX + x];
|
||||||
uint a = pixel >> 24;
|
uint a = pixel >> 24;
|
||||||
if( a >= 127 ) {
|
if( a >= 127 ) {
|
||||||
widths[i] = x + 1;
|
widths[i] = x + 1;
|
||||||
Console.WriteLine( widths[i] );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,7 +45,7 @@ namespace ClassicalSharp {
|
|||||||
GetTextParts( args.Text );
|
GetTextParts( args.Text );
|
||||||
|
|
||||||
if( args.UseShadow ) {
|
if( args.UseShadow ) {
|
||||||
int shadowX = x + 1, shadowY = y + 1;
|
int shadowX = x + 2, shadowY = y + 2;
|
||||||
for( int i = 0; i < parts.Count; i++ ) {
|
for( int i = 0; i < parts.Count; i++ ) {
|
||||||
TextPart part = parts[i];
|
TextPart part = parts[i];
|
||||||
part.TextColour = FastColour.Black;
|
part.TextColour = FastColour.Black;
|
||||||
@ -61,45 +59,31 @@ namespace ClassicalSharp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawPart( ref int x, int y, float point, TextPart part ) {
|
unsafe void DrawPart( ref int x, int y, float point, TextPart part ) {
|
||||||
string text = part.Text;
|
string text = part.Text;
|
||||||
foreach( char c in text ) {
|
foreach( char c in text ) {
|
||||||
int coords = (int)c;
|
int coords = ConvertToCP437( c );
|
||||||
int srcX = (coords & 0x0F) * 8;
|
int srcX = (coords & 0x0F) * boxSize;
|
||||||
int srcY = (coords >> 4) * 8;
|
int srcY = (coords >> 4) * boxSize;
|
||||||
|
|
||||||
for( int yy = 0; yy < 8; yy++ ) {
|
int srcWidth = widths[coords], dstWidth = PtToPx( point, srcWidth );
|
||||||
for( int xx = 0; xx < widths[coords]; xx++ ) {
|
int srcHeight = boxSize, dstHeight = PtToPx( point, srcHeight );
|
||||||
FastColour col = realBmp.GetPixel( srcX + xx, srcY + yy );
|
for( int yy = 0; yy < dstHeight; yy++ ) {
|
||||||
|
int fontY = srcY + yy * srcHeight / dstHeight;
|
||||||
|
int* fontRow = fontPixels.GetRowPtr( fontY );
|
||||||
|
|
||||||
|
for( int xx = 0; xx < dstWidth; xx++ ) {
|
||||||
|
int fontX = srcX + xx * srcWidth / dstWidth;
|
||||||
|
FastColour col = new FastColour( fontRow[fontX] );
|
||||||
if( col.A < 127 ) continue;
|
if( col.A < 127 ) continue;
|
||||||
|
|
||||||
col.R = (byte)(col.R * part.TextColour.R / 255);
|
col.R = (byte)(col.R * part.TextColour.R / 255);
|
||||||
col.G = (byte)(col.G * part.TextColour.G / 255);
|
col.G = (byte)(col.G * part.TextColour.G / 255);
|
||||||
col.B = (byte)(col.B * part.TextColour.B / 255);
|
col.B = (byte)(col.B * part.TextColour.B / 255);
|
||||||
|
|
||||||
curBmp.SetPixel( x + xx, y + yy, col );
|
curBmp.SetPixel( x + xx, y + yy, col );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x += widths[coords] + 1;
|
x += PtToPx( point, srcWidth + 1 );
|
||||||
/*int rawWidth = widths[coords] + 1;
|
|
||||||
int rawHeight = 8;
|
|
||||||
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
|
|
||||||
g.DrawImage( realBmp,
|
|
||||||
new Rectangle( x, y, PtToPx( point, rawWidth ), PtToPx( point, rawHeight ) ),
|
|
||||||
new Rectangle( srcX, srcY, 8, 8 ),
|
|
||||||
GraphicsUnit.Pixel );
|
|
||||||
|
|
||||||
for( int yy = 0; yy < PtToPx( point, rawHeight ); yy++ ) {
|
|
||||||
for( int xx = 0; xx < PtToPx( point, rawWidth ); xx++ ) {
|
|
||||||
FastColour col = curBmp.GetPixel( x + xx, y + yy );
|
|
||||||
if( col.A < 127 ) continue;
|
|
||||||
col.R = (byte)(col.R * part.TextColour.R / 255);
|
|
||||||
col.G = (byte)(col.G * part.TextColour.G / 255);
|
|
||||||
col.B = (byte)(col.B * part.TextColour.B / 255);
|
|
||||||
|
|
||||||
curBmp.SetPixel( x + xx, y + yy, col );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x += PtToPx( point, rawWidth );*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,31 +94,44 @@ namespace ClassicalSharp {
|
|||||||
public override Size MeasureSize( ref DrawTextArgs args ) {
|
public override Size MeasureSize( ref DrawTextArgs args ) {
|
||||||
GetTextParts( args.Text );
|
GetTextParts( args.Text );
|
||||||
float point = args.Font.Size;
|
float point = args.Font.Size;
|
||||||
//Size total = new Size( 0, PtToPx( point, 8 ) );
|
Size total = new Size( 0, PtToPx( point, boxSize ) );
|
||||||
Size total = new Size( 0, 8 );
|
|
||||||
|
|
||||||
for( int i = 0; i < parts.Count; i++ ) {
|
for( int i = 0; i < parts.Count; i++ ) {
|
||||||
foreach( char c in parts[i].Text ) {
|
foreach( char c in parts[i].Text ) {
|
||||||
total.Width += widths[(int)c] + 1;//PtToPx( point, widths[(int)c] + 1 );
|
int coords = ConvertToCP437( c );
|
||||||
|
total.Width += PtToPx( point, widths[coords] + 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( args.UseShadow && parts.Count > 0 ) {
|
if( args.UseShadow && parts.Count > 0 ) {
|
||||||
total.Width += 1; total.Height += 1;
|
total.Width += 2; total.Height += 2;
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ConvertToCP437( char c ) {
|
||||||
|
if( c >= ' ' && c <= '~')
|
||||||
|
return (int)c;
|
||||||
|
|
||||||
|
int cIndex = Utils.ControlCharReplacements.IndexOf( c );
|
||||||
|
if( cIndex >= 0 ) return cIndex;
|
||||||
|
int eIndex = Utils.ExtendedCharReplacements.IndexOf( c );
|
||||||
|
if( eIndex >= 0 ) return 127 + eIndex;
|
||||||
|
return (int)'?';
|
||||||
|
}
|
||||||
|
|
||||||
int PtToPx( int point ) {
|
int PtToPx( int point ) {
|
||||||
return (int)Math.Ceiling( (float)point / 72 * 96 ); // TODO: non 96 dpi?
|
return (int)Math.Ceiling( (float)point / 72 * 96 ); // TODO: non 96 dpi?
|
||||||
}
|
}
|
||||||
|
|
||||||
int PtToPx( float point, float value ) {
|
int PtToPx( float point, float value ) {
|
||||||
return (int)Math.Ceiling( (value / 8f) * point / 72f * 96f );
|
return (int)Math.Ceiling( (value / boxSize) * point / 72f * 96f );
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DisposeInstance() {
|
public override void DisposeInstance() {
|
||||||
base.DisposeInstance();
|
base.DisposeInstance();
|
||||||
|
fontPixels.Dispose();
|
||||||
|
fontBmp.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,6 @@ namespace ClassicalSharp.Commands {
|
|||||||
foreach( string line in game.Graphics.ApiInfo ) {
|
foreach( string line in game.Graphics.ApiInfo ) {
|
||||||
game.Chat.Add( "&a" + line );
|
game.Chat.Add( "&a" + line );
|
||||||
}
|
}
|
||||||
throw new InvalidCastException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,15 +43,15 @@ namespace ClassicalSharp.Model {
|
|||||||
BlockInfo = game.BlockInfo;
|
BlockInfo = game.BlockInfo;
|
||||||
|
|
||||||
if( BlockInfo.IsSprite[block] ) {
|
if( BlockInfo.IsSprite[block] ) {
|
||||||
DrawXFace( 0f, TileSide.Right, false );
|
XQuad( 0f, TileSide.Right, false );
|
||||||
DrawZFace( 0f, TileSide.Back, false );
|
ZQuad( 0f, TileSide.Back, false );
|
||||||
} else {
|
} else {
|
||||||
DrawYFace( blockHeight, TileSide.Top );
|
YQuad( blockHeight, TileSide.Top );
|
||||||
DrawXFace( -0.5f, TileSide.Right, false );
|
XQuad( -0.5f, TileSide.Right, false );
|
||||||
DrawXFace( 0.5f, TileSide.Left, true );
|
XQuad( 0.5f, TileSide.Left, true );
|
||||||
DrawZFace( -0.5f, TileSide.Front, true );
|
ZQuad( -0.5f, TileSide.Front, true );
|
||||||
DrawZFace( 0.5f, TileSide.Back, false );
|
ZQuad( 0.5f, TileSide.Back, false );
|
||||||
DrawYFace( 0f, TileSide.Bottom );
|
YQuad( 0f, TileSide.Bottom );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float blockHeight;
|
float blockHeight;
|
||||||
@ -61,9 +61,9 @@ namespace ClassicalSharp.Model {
|
|||||||
public override void Dispose() {
|
public override void Dispose() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawYFace( float y, int side ) {
|
void YQuad( float y, int side ) {
|
||||||
int texId = BlockInfo.GetTextureLoc( block, side );
|
int texId = BlockInfo.GetTextureLoc( block, side );
|
||||||
TextureRec rec = atlas.GetTexRec( texId );
|
TextureRec rec = atlas.GetAdjTexRec( texId );
|
||||||
|
|
||||||
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + -0.5f, pos.Y + y, pos.Z + -0.5f, rec.U1, rec.V1, col );
|
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + -0.5f, pos.Y + y, pos.Z + -0.5f, rec.U1, rec.V1, col );
|
||||||
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + 0.5f, pos.Y + y, pos.Z + -0.5f, rec.U2, rec.V1, col );
|
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + 0.5f, pos.Y + y, pos.Z + -0.5f, rec.U2, rec.V1, col );
|
||||||
@ -71,12 +71,11 @@ namespace ClassicalSharp.Model {
|
|||||||
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + -0.5f, pos.Y + y, pos.Z + 0.5f, rec.U1, rec.V2, col );
|
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + -0.5f, pos.Y + y, pos.Z + 0.5f, rec.U1, rec.V2, col );
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawZFace( float z, int side, bool swapU ) {
|
void ZQuad( float z, int side, bool swapU ) {
|
||||||
int texId = BlockInfo.GetTextureLoc( block, side );
|
int texId = BlockInfo.GetTextureLoc( block, side );
|
||||||
TextureRec rec = atlas.GetTexRec( texId );
|
TextureRec rec = atlas.GetAdjTexRec( texId );
|
||||||
if( blockHeight != 1 ) {
|
if( blockHeight != 1 )
|
||||||
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize;
|
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize * (15.99f/16f);
|
||||||
}
|
|
||||||
if( swapU ) rec.SwapU();
|
if( swapU ) rec.SwapU();
|
||||||
|
|
||||||
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + -0.5f, pos.Y + 0f, pos.Z + z, rec.U1, rec.V2, col );
|
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + -0.5f, pos.Y + 0f, pos.Z + z, rec.U1, rec.V2, col );
|
||||||
@ -85,12 +84,11 @@ namespace ClassicalSharp.Model {
|
|||||||
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + 0.5f, pos.Y + 0f, pos.Z + z, rec.U2, rec.V2, col );
|
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + 0.5f, pos.Y + 0f, pos.Z + z, rec.U2, rec.V2, col );
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawXFace( float x, int side, bool swapU ) {
|
void XQuad( float x, int side, bool swapU ) {
|
||||||
int texId = BlockInfo.GetTextureLoc( block, side );
|
int texId = BlockInfo.GetTextureLoc( block, side );
|
||||||
TextureRec rec = atlas.GetTexRec( texId );
|
TextureRec rec = atlas.GetAdjTexRec( texId );
|
||||||
if( blockHeight != 1 ) {
|
if( blockHeight != 1 )
|
||||||
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize;
|
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize * (15.99f/16f);
|
||||||
}
|
|
||||||
if( swapU ) rec.SwapU();
|
if( swapU ) rec.SwapU();
|
||||||
|
|
||||||
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + 0f, pos.Z + -0.5f, rec.U1, rec.V2, col );
|
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + 0f, pos.Z + -0.5f, rec.U1, rec.V2, col );
|
||||||
|
@ -111,19 +111,14 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
// Treat code as an index in code page 437
|
// Treat code as an index in code page 437
|
||||||
if( code < 0x20 ) {
|
if( code < 0x20 ) {
|
||||||
characters[i] = controlCharReplacements[code];
|
characters[i] = Utils.ControlCharReplacements[code];
|
||||||
} else if( code < 0x7F ) {
|
} else if( code < 0x7F ) {
|
||||||
characters[i] = (char)code;
|
characters[i] = (char)code;
|
||||||
} else {
|
} else {
|
||||||
characters[i] = extendedCharReplacements[code - 0x7F];
|
characters[i] = Utils.ExtendedCharReplacements[code - 0x7F];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
const string controlCharReplacements = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼";
|
|
||||||
static string extendedCharReplacements = "⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»" +
|
|
||||||
"░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌" +
|
|
||||||
"█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■\u00a0";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -68,6 +68,15 @@ namespace ClassicalSharp {
|
|||||||
invElementSize, invElementSize, invElementSize );
|
invElementSize, invElementSize, invElementSize );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets a rectangle that describes the UV coordinates for
|
||||||
|
/// the tile at the specified index, adjusted to work for AMD/ATI cards. </summary>
|
||||||
|
public TextureRec GetAdjTexRec( int index ) {
|
||||||
|
// Adjust coords to be slightly inside - fixes issues with AMD/ATI cards.
|
||||||
|
const float invAdjSize = invElementSize * (15.99f/16f);
|
||||||
|
return new TextureRec( (index & 0x0F) * invElementSize, (index >> 4) *
|
||||||
|
invElementSize, invAdjSize, invAdjSize );
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary> Disposes of the underlying atlas bitmap and texture. </summary>
|
/// <summary> Disposes of the underlying atlas bitmap and texture. </summary>
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
if( AtlasBitmap != null )
|
if( AtlasBitmap != null )
|
||||||
|
@ -286,5 +286,13 @@ namespace ClassicalSharp {
|
|||||||
public static bool IsUrlPrefix( string value ) {
|
public static bool IsUrlPrefix( string value ) {
|
||||||
return value.StartsWith( "http://" ) || value.StartsWith( "https://" );
|
return value.StartsWith( "http://" ) || value.StartsWith( "https://" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Conversion for code page 437 characters from index 0 to 31 to unicode. </summary>
|
||||||
|
public const string ControlCharReplacements = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼";
|
||||||
|
|
||||||
|
/// <summary> Conversion for code page 437 characters from index 127 to 255 to unicode. </summary>
|
||||||
|
public const string ExtendedCharReplacements = "⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»" +
|
||||||
|
"░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌" +
|
||||||
|
"█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■\u00a0";
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user