From 101cbc5f06da37fddb43df2a54849f4d82560208 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 7 Jan 2016 22:29:40 +1100 Subject: [PATCH] Add more methods for android, add platform class to abstract away some platform differences. --- .../Drawing}/CanvasDrawer2D.Text.cs | 3 +- .../{Android => 2D/Drawing}/CanvasDrawer2D.cs | 2 + .../2D/Drawing/GdiPlusDrawer2D.Text.cs | 4 +- ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.cs | 4 +- ClassicalSharp/2D/Drawing/IDrawer2D.TextMC.cs | 3 + ClassicalSharp/2D/Drawing/IDrawer2D.cs | 5 +- .../2D/Drawing/IsometricBlockDrawer.cs | 143 ++++++++++++ ClassicalSharp/2D/Utils/FastBitmap.cs | 80 +++++-- .../2D/Utils/IsometricBlockDrawer.cs | 128 ---------- ClassicalSharp/2D/Widgets/ButtonWidget.cs | 4 +- ClassicalSharp/Android/FastBitmap.cs | 84 ------- ClassicalSharp/Android/Minimal.cs | 221 ------------------ ClassicalSharp/ClassicalSharp.csproj | 13 +- ClassicalSharp/Entities/Player.cs | 3 + ClassicalSharp/Game/Game.cs | 5 +- ClassicalSharp/GraphicsAPI/Direct3D9Api.cs | 8 +- ClassicalSharp/GraphicsAPI/IGraphicsApi.cs | 2 +- ClassicalSharp/GraphicsAPI/OpenGLApi.cs | 11 +- .../{Android => GraphicsAPI}/OpenGLESApi.cs | 2 +- .../Network/Utils/AsyncDownloader.cs | 2 +- ClassicalSharp/{Android => Platform}/Font.cs | 0 ClassicalSharp/Platform/Platform.cs | 38 +++ ClassicalSharp/TexturePack/Animations.cs | 3 + ClassicalSharp/TexturePack/TerrainAtlas2D.cs | 3 + ClassicalSharp/TexturePack/TextureCache.cs | 6 +- .../TexturePack/TexturePackExtractor.cs | 8 +- ClassicalSharp/Utils/Utils.cs | 3 + 27 files changed, 300 insertions(+), 488 deletions(-) rename ClassicalSharp/{Android => 2D/Drawing}/CanvasDrawer2D.Text.cs (94%) rename ClassicalSharp/{Android => 2D/Drawing}/CanvasDrawer2D.cs (93%) create mode 100644 ClassicalSharp/2D/Drawing/IsometricBlockDrawer.cs delete mode 100644 ClassicalSharp/2D/Utils/IsometricBlockDrawer.cs delete mode 100644 ClassicalSharp/Android/FastBitmap.cs delete mode 100644 ClassicalSharp/Android/Minimal.cs rename ClassicalSharp/{Android => GraphicsAPI}/OpenGLESApi.cs (96%) rename ClassicalSharp/{Android => Platform}/Font.cs (100%) create mode 100644 ClassicalSharp/Platform/Platform.cs diff --git a/ClassicalSharp/Android/CanvasDrawer2D.Text.cs b/ClassicalSharp/2D/Drawing/CanvasDrawer2D.Text.cs similarity index 94% rename from ClassicalSharp/Android/CanvasDrawer2D.Text.cs rename to ClassicalSharp/2D/Drawing/CanvasDrawer2D.Text.cs index 04fc49faa..ca4d671af 100644 --- a/ClassicalSharp/Android/CanvasDrawer2D.Text.cs +++ b/ClassicalSharp/2D/Drawing/CanvasDrawer2D.Text.cs @@ -3,6 +3,7 @@ using System; using ClassicalSharp.GraphicsAPI; using Android.Graphics; using Android.Graphics.Drawables; +using System.Drawing; namespace ClassicalSharp { @@ -11,7 +12,7 @@ namespace ClassicalSharp { Bitmap measuringBmp; Canvas measuringC; - public GdiPlusDrawer2D( IGraphicsApi graphics ) { + public CanvasDrawer2D( IGraphicsApi graphics ) { this.graphics = graphics; measuringBmp = Bitmap.CreateBitmap( 1, 1, Bitmap.Config.Argb8888 ); measuringC = new Canvas( measuringBmp ); diff --git a/ClassicalSharp/Android/CanvasDrawer2D.cs b/ClassicalSharp/2D/Drawing/CanvasDrawer2D.cs similarity index 93% rename from ClassicalSharp/Android/CanvasDrawer2D.cs rename to ClassicalSharp/2D/Drawing/CanvasDrawer2D.cs index 246737df4..3da270ad2 100644 --- a/ClassicalSharp/Android/CanvasDrawer2D.cs +++ b/ClassicalSharp/2D/Drawing/CanvasDrawer2D.cs @@ -21,6 +21,8 @@ namespace ClassicalSharp { c = new Canvas( bmp ); curBmp = bmp; } + + public override Bitmap ConvertTo32Bpp( Bitmap src ) { return src; } public override void DrawRect( FastColour colour, int x, int y, int width, int height ) { RectF rec = new RectF( x, y, x + width, y + height ); diff --git a/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.Text.cs b/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.Text.cs index 42a96942a..c5aa537fb 100644 --- a/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.Text.cs +++ b/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.Text.cs @@ -1,4 +1,5 @@ -using System; +#if !ANDROID +using System; using System.Drawing; using System.Drawing.Text; using ClassicalSharp.GraphicsAPI; @@ -119,3 +120,4 @@ namespace ClassicalSharp { } } } +#endif \ No newline at end of file diff --git a/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.cs b/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.cs index 79747f3ab..73e8abb96 100644 --- a/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.cs +++ b/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.cs @@ -1,4 +1,5 @@ -using System; +#if !ANDROID +using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; @@ -102,3 +103,4 @@ namespace ClassicalSharp { } } } +#endif \ No newline at end of file diff --git a/ClassicalSharp/2D/Drawing/IDrawer2D.TextMC.cs b/ClassicalSharp/2D/Drawing/IDrawer2D.TextMC.cs index 0065d5534..d2958e8a7 100644 --- a/ClassicalSharp/2D/Drawing/IDrawer2D.TextMC.cs +++ b/ClassicalSharp/2D/Drawing/IDrawer2D.TextMC.cs @@ -1,6 +1,9 @@ using System; using System.Drawing; using ClassicalSharp.GraphicsAPI; +#if ANDROID +using Android.Graphics; +#endif namespace ClassicalSharp { diff --git a/ClassicalSharp/2D/Drawing/IDrawer2D.cs b/ClassicalSharp/2D/Drawing/IDrawer2D.cs index 2489ea6b0..af517dc9e 100644 --- a/ClassicalSharp/2D/Drawing/IDrawer2D.cs +++ b/ClassicalSharp/2D/Drawing/IDrawer2D.cs @@ -2,6 +2,9 @@ using System.Collections.Generic; using System.Drawing; using ClassicalSharp.GraphicsAPI; +#if ANDROID +using Android.Graphics; +#endif namespace ClassicalSharp { @@ -140,7 +143,7 @@ namespace ClassicalSharp { /// Creates a power-of-2 sized bitmap larger or equal to to the given size. public static Bitmap CreatePow2Bitmap( Size size ) { - return new Bitmap( Utils.NextPowerOf2( size.Width ), Utils.NextPowerOf2( size.Height ) ); + return Platform.CreateBmp( Utils.NextPowerOf2( size.Width ), Utils.NextPowerOf2( size.Height ) ); } protected List parts = new List( 64 ); diff --git a/ClassicalSharp/2D/Drawing/IsometricBlockDrawer.cs b/ClassicalSharp/2D/Drawing/IsometricBlockDrawer.cs new file mode 100644 index 000000000..e4be633b2 --- /dev/null +++ b/ClassicalSharp/2D/Drawing/IsometricBlockDrawer.cs @@ -0,0 +1,143 @@ +using System; +using ClassicalSharp.GraphicsAPI; +using ClassicalSharp.Model; +using OpenTK; + +namespace ClassicalSharp { + + public static class IsometricBlockDrawer { + + static BlockInfo info; + static ModelCache cache; + static TerrainAtlas2D atlas; + static int index; + static float scale; + static Vector3 minBB, maxBB; + const float invElemSize = TerrainAtlas2D.invElementSize; + static bool fullBright; + + static FastColour colNormal, colXSide, colZSide, colYBottom; + static float cosX, sinX, cosY, sinY; + static IsometricBlockDrawer() { + colNormal = FastColour.White; + FastColour.GetShaded( colNormal, ref colXSide, ref colZSide, ref colYBottom ); + + cosX = (float)Math.Cos( 26.565f * Utils.Deg2Rad ); + sinX = (float)Math.Sin( 26.565f * Utils.Deg2Rad ); + cosY = (float)Math.Cos( -45f * Utils.Deg2Rad ); + sinY = (float)Math.Sin( -45f * Utils.Deg2Rad ); + } + + public static void Draw( Game game, byte block, float size, float x, float y ) { + info = game.BlockInfo; + cache = game.ModelCache; + atlas = game.TerrainAtlas; + minBB = info.MinBB[block]; + maxBB = info.MaxBB[block]; + fullBright = info.FullBright[block]; + if( info.IsSprite[block] ) { + minBB = Vector3.Zero; maxBB = Vector3.One; + } + if( info.IsAir[block] ) return; + index = 0; + + // isometric coords size: cosY * -scale - sinY * scale + // we need to divide by (2 * cosY), as the calling function expects size to be in pixels. + scale = size / (2 * cosY); + // screen to isometric coords (cos(-x) = cos(x), sin(-x) = -sin(x)) + pos.X = x; pos.Y = y; pos.Z = 0; + pos = Utils.RotateY( Utils.RotateX( pos, cosX, -sinX ), cosY, -sinY ); + + if( info.IsSprite[block] ) { + XQuad( block, 0f, TileSide.Right ); + ZQuad( block, 0f, TileSide.Back ); + } else { + XQuad( block, Make( maxBB.X ), TileSide.Left ); + ZQuad( block, Make( minBB.Z ), TileSide.Back ); + YQuad( block, Make( maxBB.Y ), TileSide.Top ); + } + + for( int i = 0; i < index; i++ ) + TransformVertex( ref cache.vertices[i] ); + game.Graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, cache.vb, + cache.vertices, index, index * 6 / 4 ); + } + + static void TransformVertex( ref VertexPos3fTex2fCol4b vertex ) { + Vector3 p = new Vector3( vertex.X, vertex.Y, vertex.Z ); + //p = Utils.RotateY( p - pos, time ) + pos; + // See comment in IGraphicsApi.Draw2DTexture() + p.X -= 0.5f; p.Y -= 0.5f; + p = Utils.RotateX( Utils.RotateY( p, cosY, sinY ), cosX, sinX ); + vertex.X = p.X; vertex.Y = p.Y; vertex.Z = p.Z; + } + + static Vector3 pos = Vector3.Zero; + static void YQuad( byte block, float y, int side ) { + int texId = info.GetTextureLoc( block, side ); + TextureRec rec = atlas.GetTexRec( texId ); + FastColour col = colNormal; + float uOrigin = rec.U1, vOrigin = rec.V1; + + rec.U1 = uOrigin + minBB.Z * invElemSize; + rec.U2 = uOrigin + maxBB.Z * invElemSize * 15.99f/16f; + rec.V1 = vOrigin + minBB.X * invElemSize; + rec.V2 = vOrigin + maxBB.X * invElemSize * 15.99f/16f; + + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + Make( minBB.X ), pos.Y + y, + pos.Z + Make( minBB.Z ), rec.U2, rec.V2, col ); + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + Make( minBB.X ), pos.Y + y, + pos.Z + Make( maxBB.Z ), rec.U1, rec.V2, col ); + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + Make( maxBB.X ), pos.Y + y, + pos.Z + Make( maxBB.Z ), rec.U1, rec.V1, col ); + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + Make( maxBB.X ), pos.Y + y, + pos.Z + Make( minBB.Z ), rec.U2, rec.V1, col ); + } + + static void ZQuad( byte block, float z, int side ) { + int texId = info.GetTextureLoc( block, side ); + TextureRec rec = atlas.GetTexRec( texId ); + FastColour col = fullBright ? colNormal : colZSide; + float uOrigin = rec.U1, vOrigin = rec.V1; + + rec.U1 = uOrigin + minBB.X * invElemSize; + rec.U2 = uOrigin + maxBB.X * invElemSize * 15.99f/16f; + rec.V1 = vOrigin + (1 - maxBB.Y) * invElemSize; + rec.V2 = vOrigin + (1 - minBB.Y) * invElemSize; + + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + Make( minBB.X ), pos.Y + Make( minBB.Y ), + pos.Z + z, rec.U2, rec.V2, col ); + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + Make( minBB.X ), pos.Y + Make( maxBB.Y ), + pos.Z + z, rec.U2, rec.V1, col ); + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + Make( maxBB.X ), pos.Y + Make( maxBB.Y ), + pos.Z + z, rec.U1, rec.V1, col ); + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + Make( maxBB.X ), pos.Y + Make( minBB.Y ), + pos.Z + z, rec.U1, rec.V2, col ); + } + + static float Make( float value ) { + return scale - (scale * value * 2); + } + + static void XQuad( byte block, float x, int side ) { + int texId = info.GetTextureLoc( block, side ); + TextureRec rec = atlas.GetTexRec( texId ); + FastColour col = fullBright ? colNormal : colXSide; + float uOrigin = rec.U1, vOrigin = rec.V1; + + rec.U1 = uOrigin + minBB.Z * invElemSize; + rec.U2 = uOrigin + maxBB.Z * invElemSize * 15.99f/16f; + rec.V1 = vOrigin + (1 - maxBB.Y) * invElemSize; + rec.V2 = vOrigin + (1 - minBB.Y) * invElemSize * 15.99f/16f; + + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + Make( minBB.Y ), + pos.Z + Make( minBB.Z ), rec.U2, rec.V2, col ); + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + Make( maxBB.Y ), + pos.Z + Make( minBB.Z ), rec.U2, rec.V1, col ); + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + Make( maxBB.Y ), + pos.Z + Make( maxBB.Z ), rec.U1, rec.V1, col ); + cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + Make( minBB.Y ), + pos.Z + Make( maxBB.Z ), rec.U1, rec.V2, col ); + } + } +} \ No newline at end of file diff --git a/ClassicalSharp/2D/Utils/FastBitmap.cs b/ClassicalSharp/2D/Utils/FastBitmap.cs index 27cdb6437..bf835347a 100644 --- a/ClassicalSharp/2D/Utils/FastBitmap.cs +++ b/ClassicalSharp/2D/Utils/FastBitmap.cs @@ -1,6 +1,10 @@ using System; using System.Drawing; using System.Drawing.Imaging; +#if ANDROID +using Android.Graphics; +using Java.Nio; +#endif namespace ClassicalSharp { @@ -38,6 +42,24 @@ namespace ClassicalSharp { return format == PixelFormat.Format32bppRgb || format == PixelFormat.Format32bppArgb; } + /// Returns a pointer to the start of the y'th scanline. + public int* GetRowPtr( int y ) { + return (int*)(scan0Byte + (y * Stride)); + } + + public static void MovePortion( int srcX, int srcY, int dstX, int dstY, FastBitmap src, FastBitmap dst, int size ) { + for( int y = 0; y < size; y++ ) { + int* srcRow = src.GetRowPtr( srcY + y ); + int* dstRow = dst.GetRowPtr( dstY + y ); + for( int x = 0; x < size; x++ ) { + dstRow[dstX + x] = srcRow[srcX + x]; + } + } + } + + public void Dispose() { UnlockBits(); } + + #if !ANDROID public void LockBits() { if( Bitmap == null ) throw new InvalidOperationException( "Underlying bitmap is null." ); if( data != null ) return; @@ -55,33 +77,43 @@ namespace ClassicalSharp { Height = data.Height; } - public void Dispose() { - UnlockBits(); + public void UnlockBits() { + if( Bitmap == null || data == null ) + return; + Bitmap.UnlockBits( data ); + data = null; + scan0Byte = (byte*)IntPtr.Zero; + Scan0 = IntPtr.Zero; + Width = Height = Stride = 0; + } + + #else + + public void LockBits() { + if( Bitmap == null ) throw new InvalidOperationException( "Underlying bitmap is null." ); + if( data != null ) return; + + data = ByteBuffer.AllocateDirect( Bitmap.Width * Bitmap.Height * 4 ); + Bitmap.CopyPixelsToBuffer( data ); + scan0Byte = (byte*)data.GetDirectBufferAddress(); + Scan0 = data.GetDirectBufferAddress(); + Stride = Bitmap.Width * 4; + Width = Bitmap.Width; + Height = Bitmap.Height; } public void UnlockBits() { - if( Bitmap != null && data != null ) { - Bitmap.UnlockBits( data ); - data = null; - scan0Byte = (byte*)IntPtr.Zero; - Scan0 = IntPtr.Zero; - Width = Height = Stride = 0; - } - } - - /// Returns a pointer to the start of the y'th scanline. - public int* GetRowPtr( int y ) { - return (int*)(scan0Byte + (y * Stride)); - } - - public static void MovePortion( int srcX, int srcY, int dstX, int dstY, FastBitmap src, FastBitmap dst, int size ) { - for( int y = 0; y < size; y++ ) { - int* srcRow = src.GetRowPtr( srcY + y ); - int* dstRow = dst.GetRowPtr( dstY + y ); - for( int x = 0; x < size; x++ ) { - dstRow[dstX + x] = srcRow[srcX + x]; - } - } + if( Bitmap == null || data == null ) + return; + data.Rewind(); + Bitmap.CopyPixelsFromBuffer( data ); // TODO: Only if not readonly + data.Dispose(); + + data = null; + scan0Byte = (byte*)IntPtr.Zero; + Scan0 = IntPtr.Zero; + Width = Height = Stride = 0; } + #endif } } \ No newline at end of file diff --git a/ClassicalSharp/2D/Utils/IsometricBlockDrawer.cs b/ClassicalSharp/2D/Utils/IsometricBlockDrawer.cs deleted file mode 100644 index 1d4b3ed31..000000000 --- a/ClassicalSharp/2D/Utils/IsometricBlockDrawer.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using ClassicalSharp.GraphicsAPI; -using ClassicalSharp.Model; -using OpenTK; - -namespace ClassicalSharp { - - public static class IsometricBlockDrawer { - - static BlockInfo info; - static ModelCache cache; - static TerrainAtlas2D atlas; - static float blockHeight; - static int index; - static float scale; - static Vector3 minBB, maxBB; - - static FastColour colNormal, colXSide, colZSide, colYBottom; - static float cosX, sinX, cosY, sinY; - static IsometricBlockDrawer() { - colNormal = FastColour.White; - FastColour.GetShaded( colNormal, ref colXSide, ref colZSide, ref colYBottom ); - - cosX = (float)Math.Cos( 26.565f * Utils.Deg2Rad ); - sinX = (float)Math.Sin( 26.565f * Utils.Deg2Rad ); - cosY = (float)Math.Cos( -45f * Utils.Deg2Rad ); - sinY = (float)Math.Sin( -45f * Utils.Deg2Rad ); - } - - public static void Draw( Game game, byte block, float size, float x, float y ) { - info = game.BlockInfo; - cache = game.ModelCache; - atlas = game.TerrainAtlas; - minBB = info.MinBB[block]; - maxBB = info.MaxBB[block]; - blockHeight = info.Height[block]; - index = 0; - // isometric coords size: cosY * -scale - sinY * scale - // we need to divide by (2 * cosY), as the calling function expects size to be in pixels. - scale = size / (2 * cosY); - - // screen to isometric coords (cos(-x) = cos(x), sin(-x) = -sin(x)) - pos.X = x; pos.Y = y; pos.Z = 0; - pos = Utils.RotateY( Utils.RotateX( pos, cosX, -sinX ), cosY, -sinY ); - - if( info.IsSprite[block] ) { - XQuad( block, 0f, TileSide.Right ); - ZQuad( block, 0f, TileSide.Back ); - } else { - XQuad( block, scale, TileSide.Left ); - ZQuad( block, -scale, TileSide.Back ); - YQuad( block, Y( maxBB.Y ), TileSide.Top ); - } - - for( int i = 0; i < index; i++ ) - TransformVertex( ref cache.vertices[i] ); - game.Graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, cache.vb, - cache.vertices, index, index * 6 / 4 ); - } - - static void TransformVertex( ref VertexPos3fTex2fCol4b vertex ) { - Vector3 p = new Vector3( vertex.X, vertex.Y, vertex.Z ); - //p = Utils.RotateY( p - pos, time ) + pos; - // See comment in IGraphicsApi.Draw2DTexture() - p.X -= 0.5f; p.Y -= 0.5f; - p = Utils.RotateX( Utils.RotateY( p, cosY, sinY ), cosX, sinX ); - vertex.X = p.X; vertex.Y = p.Y; vertex.Z = p.Z; - } - - static Vector3 pos = Vector3.Zero; - static void YQuad( byte block, float y, int side ) { - int texId = info.GetTextureLoc( block, side ); - TextureRec rec = atlas.GetTexRec( texId ); - FastColour col = colNormal; - - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - scale, pos.Y - y, - pos.Z - scale, rec.U2, rec.V2, col ); - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - scale, pos.Y - y, - pos.Z + scale, rec.U1, rec.V2, col ); - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + scale, pos.Y - y, - pos.Z + scale, rec.U1, rec.V1, col ); - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + scale, pos.Y - y, - pos.Z - scale, rec.U2, rec.V1, col ); - } - - static void ZQuad( byte block, float z, int side ) { - int texId = info.GetTextureLoc( block, side ); - TextureRec rec = atlas.GetTexRec( texId ); - FastColour col = colZSide; - - float vOrigin = rec.V1; - rec.V1 = vOrigin + minBB.Y * TerrainAtlas2D.invElementSize; - rec.V2 = vOrigin + maxBB.Y * TerrainAtlas2D.invElementSize; - - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - scale, pos.Y + Y( minBB.Y ), - pos.Z - z, rec.U1, rec.V1, col ); - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - scale, pos.Y + Y( maxBB.Y ), - pos.Z - z, rec.U1, rec.V2, col ); - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + scale, pos.Y + Y( maxBB.Y ), - pos.Z - z, rec.U2, rec.V2, col ); - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + scale, pos.Y + Y( minBB.Y ), - pos.Z - z, rec.U2, rec.V1, col ); - } - - static float Y( float value ) { - return (scale * value * 2) - scale; - } - - static void XQuad( byte block, float x, int side ) { - int texId = info.GetTextureLoc( block, side ); - TextureRec rec = atlas.GetTexRec( texId ); - FastColour col = colXSide; - - float vOrigin = rec.V1; - rec.V1 = vOrigin + minBB.Y * TerrainAtlas2D.invElementSize; - rec.V2 = vOrigin + maxBB.Y * TerrainAtlas2D.invElementSize; - - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - x, pos.Y + Y( minBB.Y ), - pos.Z - scale , rec.U1, rec.V1, col ); - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - x, pos.Y + Y( maxBB.Y ), - pos.Z - scale, rec.U1, rec.V2, col ); - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - x, pos.Y + Y( maxBB.Y ), - pos.Z + scale, rec.U2, rec.V2, col ); - cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - x, pos.Y + Y( minBB.Y ), - pos.Z + scale, rec.U2, rec.V1, col ); - } - } -} \ No newline at end of file diff --git a/ClassicalSharp/2D/Widgets/ButtonWidget.cs b/ClassicalSharp/2D/Widgets/ButtonWidget.cs index 9a1138416..3bcf7a1c2 100644 --- a/ClassicalSharp/2D/Widgets/ButtonWidget.cs +++ b/ClassicalSharp/2D/Widgets/ButtonWidget.cs @@ -1,6 +1,8 @@ using System; using System.Drawing; -using System.Drawing.Drawing2D; +#if ANDROID +using Android.Graphics; +#endif namespace ClassicalSharp { diff --git a/ClassicalSharp/Android/FastBitmap.cs b/ClassicalSharp/Android/FastBitmap.cs deleted file mode 100644 index f802482a8..000000000 --- a/ClassicalSharp/Android/FastBitmap.cs +++ /dev/null @@ -1,84 +0,0 @@ -#if ANDROID -using System; -using Android.Graphics; -using Java.Nio; - -namespace ClassicalSharp { - - /// Wrapper around a bitmap that allows extremely fast manipulation of 32bpp images. - public unsafe class FastBitmap : IDisposable { - - public FastBitmap( Bitmap bmp, bool lockBits ) { - Bitmap = bmp; - if( lockBits ) { - LockBits(); - } - } - - public FastBitmap( int width, int height, int stride, IntPtr scan0 ) { - Width = width; - Height = height; - Stride = stride; - Scan0 = scan0; - scan0Byte = (byte*)scan0; - } - - public Bitmap Bitmap; - ByteBuffer data; - byte* scan0Byte; - - public bool IsLocked { - get { return data != null; } - } - - public IntPtr Scan0; - public int Stride; - public int Width, Height; - - public void LockBits() { - if( Bitmap == null ) throw new InvalidOperationException( "Underlying bitmap is null." ); - if( data != null ) return; - - data = ByteBuffer.AllocateDirect( Bitmap.Width * Bitmap.Height * 4 ); - Bitmap.CopyPixelsToBuffer( data ); - scan0Byte = (byte*)data.GetDirectBufferAddress(); - Scan0 = data.GetDirectBufferAddress(); - Stride = Bitmap.Width * 4; - Width = Bitmap.Width; - Height = Bitmap.Height; - } - - public void Dispose() { - UnlockBits(); - } - - public void UnlockBits() { - if( Bitmap != null && data != null ) { - data.Rewind(); - Bitmap.CopyPixelsFromBuffer( data ); // TODO: Only if not readonly - data.Dispose(); - - data = null; - scan0Byte = (byte*)IntPtr.Zero; - Scan0 = IntPtr.Zero; - Width = Height = Stride = 0; - } - } - - /// Returns a pointer to the start of the y'th scanline. - public int* GetRowPtr( int y ) { - return (int*)(scan0Byte + (y * Stride)); - } - - public static void MovePortion( int srcX, int srcY, int dstX, int dstY, FastBitmap src, FastBitmap dst, int size ) { - for( int y = 0; y < size; y++ ) { - int* srcRow = src.GetRowPtr( srcY + y ); - int* dstRow = dst.GetRowPtr( dstY + y ); - for( int x = 0; x < size; x++ ) { - dstRow[dstX + x] = srcRow[srcX + x]; - } - } - } - } -} -#endif \ No newline at end of file diff --git a/ClassicalSharp/Android/Minimal.cs b/ClassicalSharp/Android/Minimal.cs deleted file mode 100644 index 0f247f97c..000000000 --- a/ClassicalSharp/Android/Minimal.cs +++ /dev/null @@ -1,221 +0,0 @@ -#if ANDROID -using System; - -namespace System.Drawing { - - public struct Rectangle { - - public static readonly Rectangle Empty = default(Rectangle); - public int X, Y; - public int Width, Height; - - public Point Location { - get { return new Point( X, Y ); } - set { X = value.X; Y = value.Y; } - } - - public Size Size { - get { return new Size( Width, Height ); } - set { Width = value.Width; Height = value.Height; } - } - - public int Left { - get { return X; } - } - - public int Top { - get { return Y; } - } - - public int Right { - get { return X + Width; } - } - - public int Bottom { - get { return Y + Height; } - } - - public bool IsEmpty { - get { return Height == 0 && Width == 0 && X == 0 && Y == 0; } - } - - public Rectangle( int x, int y, int width, int height ) { - X = x; Y = y; - Width = width; Height = height; - } - - public Rectangle( Point loc, Size size ) { - X = loc.X; Y = loc.Y; - Width = size.Width; Height = size.Height; - } - - public static Rectangle FromLTRB( int left, int top, int right, int bottom ) { - return new Rectangle( left, top, right - left, bottom - top ); - } - - public override bool Equals( object obj ) { - return (obj is Rectangle) && Equals( (Rectangle)obj ); - } - - public bool Equals( Rectangle other ) { - return X == other.X && Y == other.Y && Width == other.Width && Height == other.Height; - } - - public override int GetHashCode() { - return 1000000007 * X + 1000000009 * Y + - 1000000021 * Width + 1000000033 * Height; - } - - public static bool operator == ( Rectangle lhs, Rectangle rhs ) { - return lhs.Equals( rhs ); - } - - public static bool operator != ( Rectangle lhs, Rectangle rhs ) { - return !(lhs == rhs); - } - - public bool Contains(int x, int y) { - return X <= x && x < X + Width && Y <= y && y < Y + Height; - } - - public bool Contains( Point pt ) { - return Contains( pt.X, pt.Y ); - } - - public bool Contains( Rectangle rect ) { - return X <= rect.X && rect.X + rect.Width <= X + Width && Y <= rect.Y && rect.Y + rect.Height <= Y + Height; - } - - public override string ToString() { - return X + ", " + Y + " : " + Width + "," + Height; - } - } - - public struct Size { - - public static readonly Size Empty = default(Size); - public int Width, Height; - - public bool IsEmpty { - get { return Width == 0 && Height == 0; } - } - - public Size( Point point ) { - Width = point.X; Height = point.Y; - } - - public Size( int width, int height ) { - Width = width; Height = height; - } - - public static Size Ceiling( SizeF value ) { - return new Size( (int)Math.Ceiling( value.Width ), (int)Math.Ceiling( value.Height ) ); - } - - public override bool Equals( object obj ) { - return (obj is Size) && Equals( (Size)obj ); - } - - public bool Equals( Size other ) { - return Width == other.Width && Height == other.Height; - } - - public override int GetHashCode() { - return 1000000007 * Width + 1000000009 * Height; - } - - public static bool operator == ( Size lhs, Size rhs ) { - return lhs.Width == rhs.Width && lhs.Height == rhs.Height; - } - - public static bool operator != ( Size lhs, Size rhs ) { - return !(lhs == rhs); - } - - public override string ToString() { - return Width + "," + Height; - } - } - - public struct SizeF { - - public static readonly SizeF Empty = default(SizeF); - public float Width, Height; - - public bool IsEmpty { - get { return Width == 0 && Height == 0; } - } - - public SizeF( float width, float height ) { - Width = width; Height = height; - } - - public override bool Equals( object obj ) { - return (obj is SizeF) && Equals( (SizeF)obj ); - } - - public bool Equals( SizeF other ) { - return Width == other.Width && Height == other.Height; - } - - public override int GetHashCode() { - return 1000000007 * Width.GetHashCode() + - 1000000009 * Height.GetHashCode(); - } - - public static bool operator == ( SizeF lhs, SizeF rhs ) { - return lhs.Width == rhs.Width && lhs.Height == rhs.Height; - } - - public static bool operator != ( SizeF lhs, SizeF rhs ) { - return !(lhs == rhs); - } - - public override string ToString() { - return Width + "," + Height; - } - } - - public struct Point { - - public static readonly Point Empty = default(Point); - public int X, Y; - - public bool IsEmpty { - get { return X == 0 && Y == 0; } - } - - public Point( Size size ) { - X = size.Width; Y = size.Height; - } - - public Point( int x, int y ) { - X = x; Y = y; - } - - public override bool Equals( object obj ) { - return (obj is Point) && Equals( (Point)obj ); - } - - public bool Equals( Point other ) { - return X == other.X && Y == other.Y; - } - - public override int GetHashCode() { - return 1000000007 * X + 1000000009 * Y; - } - - public static bool operator == ( Point lhs, Point rhs ) { - return lhs.X == rhs.X && lhs.Y == rhs.Y; - } - - public static bool operator != ( Point lhs, Point rhs ) { - return !(lhs == rhs); - } - - public override string ToString() { - return X + "," + Y; - } - } -} -#endif \ No newline at end of file diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index 0bde0e13d..b761bcd87 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -78,6 +78,8 @@ + + @@ -130,12 +132,6 @@ - - - - - - @@ -161,6 +157,7 @@ + @@ -225,6 +222,8 @@ + + @@ -286,7 +285,7 @@ - + diff --git a/ClassicalSharp/Entities/Player.cs b/ClassicalSharp/Entities/Player.cs index 682fe78aa..10a9cd5a1 100644 --- a/ClassicalSharp/Entities/Player.cs +++ b/ClassicalSharp/Entities/Player.cs @@ -3,6 +3,9 @@ using System.Drawing; using ClassicalSharp.Model; using ClassicalSharp.Network; using OpenTK; +#if ANDROID +using Android.Graphics; +#endif namespace ClassicalSharp { diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs index 2667eb477..99ad5db96 100644 --- a/ClassicalSharp/Game/Game.cs +++ b/ClassicalSharp/Game/Game.cs @@ -15,6 +15,9 @@ using ClassicalSharp.TexturePack; using OpenTK; using OpenTK.Graphics; using OpenTK.Input; +#if ANDROID +using Android.Graphics; +#endif namespace ClassicalSharp { @@ -279,7 +282,7 @@ namespace ClassicalSharp { string timestamp = DateTime.Now.ToString( "dd-MM-yyyy-HH-mm-ss" ); string file = "screenshot_" + timestamp + ".png"; path = Path.Combine( "screenshots", file ); - Graphics.TakeScreenshot( path, ClientSize ); + Graphics.TakeScreenshot( path, ClientSize.Width, ClientSize.Height ); Chat.Add( "&eTaken screenshot as: " + file ); screenshotRequested = false; } diff --git a/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs b/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs index 8a3695c65..2b9fe6871 100644 --- a/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs +++ b/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs @@ -1,4 +1,4 @@ -#if USE_DX +#if USE_DX && !ANDROID using System; using System.Drawing; using System.Drawing.Imaging; @@ -562,14 +562,14 @@ namespace ClassicalSharp.GraphicsAPI { }; } - public override void TakeScreenshot( string output, Size size ) { + public override void TakeScreenshot( string output, int width, int height ) { using( Surface backbuffer = device.GetBackBuffer( 0, 0, BackBufferType.Mono ), - tempSurface = device.CreateOffscreenPlainSurface( size.Width, size.Height, Format.X8R8G8B8, Pool.SystemMemory ) ) { + tempSurface = device.CreateOffscreenPlainSurface( width, height, Format.X8R8G8B8, Pool.SystemMemory ) ) { // For DX 8 use IDirect3DDevice8::CreateImageSurface device.GetRenderTargetData( backbuffer, tempSurface ); LockedRectangle rect = tempSurface.LockRectangle( LockFlags.ReadOnly | LockFlags.NoDirtyUpdate ); - using( Bitmap bmp = new Bitmap( size.Width, size.Height, size.Width * 4, + using( Bitmap bmp = new Bitmap( width, height, width * sizeof(int), PixelFormat.Format32bppRgb, rect.DataPointer ) ) { bmp.Save( output, ImageFormat.Png ); } diff --git a/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs b/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs index 9172d7b80..14415d0b5 100644 --- a/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs +++ b/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs @@ -202,7 +202,7 @@ namespace ClassicalSharp.GraphicsAPI { public abstract void PopMatrix(); /// Outputs a .png screenshot of the backbuffer to the specified file. - public abstract void TakeScreenshot( string output, Size size ); + public abstract void TakeScreenshot( string output, int width, int height ); protected abstract void MakeApiInfo(); diff --git a/ClassicalSharp/GraphicsAPI/OpenGLApi.cs b/ClassicalSharp/GraphicsAPI/OpenGLApi.cs index 5ba253731..ccd33a89d 100644 --- a/ClassicalSharp/GraphicsAPI/OpenGLApi.cs +++ b/ClassicalSharp/GraphicsAPI/OpenGLApi.cs @@ -1,4 +1,4 @@ -#if !USE_DX +#if !USE_DX && !ANDROID using System; using System.Drawing; using System.Drawing.Imaging; @@ -405,11 +405,10 @@ namespace ClassicalSharp.GraphicsAPI { } // Based on http://www.opentk.com/doc/graphics/save-opengl-rendering-to-disk - public override void TakeScreenshot( string output, Size size ) { - using( Bitmap bmp = new Bitmap( size.Width, size.Height, BmpPixelFormat.Format32bppRgb ) ) { // ignore alpha component - using( FastBitmap fastBmp = new FastBitmap( bmp, true ) ) { - GL.ReadPixels( 0, 0, size.Width, size.Height, GlPixelFormat.Bgra, PixelType.UnsignedByte, fastBmp.Scan0 ); - } + public override void TakeScreenshot( string output, int width, int height ) { + using( Bitmap bmp = new Bitmap( width, height, BmpPixelFormat.Format32bppRgb ) ) { // ignore alpha component + using( FastBitmap fastBmp = new FastBitmap( bmp, true ) ) + GL.ReadPixels( 0, 0, width, height, GlPixelFormat.Bgra, PixelType.UnsignedByte, fastBmp.Scan0 ); bmp.RotateFlip( RotateFlipType.RotateNoneFlipY ); bmp.Save( output, ImageFormat.Png ); } diff --git a/ClassicalSharp/Android/OpenGLESApi.cs b/ClassicalSharp/GraphicsAPI/OpenGLESApi.cs similarity index 96% rename from ClassicalSharp/Android/OpenGLESApi.cs rename to ClassicalSharp/GraphicsAPI/OpenGLESApi.cs index 52c627581..ed1d7a513 100644 --- a/ClassicalSharp/Android/OpenGLESApi.cs +++ b/ClassicalSharp/GraphicsAPI/OpenGLESApi.cs @@ -12,7 +12,7 @@ namespace ClassicalSharp.GraphicsAPI { public unsafe class OpenGLESApi : IGraphicsApi { All[] modeMappings; - public OpenGLApi() { + public OpenGLESApi() { InitFields(); int texDims; GL.GetInteger( All.MaxTextureSize, &texDims ); diff --git a/ClassicalSharp/Network/Utils/AsyncDownloader.cs b/ClassicalSharp/Network/Utils/AsyncDownloader.cs index 1afab390e..9c707f436 100644 --- a/ClassicalSharp/Network/Utils/AsyncDownloader.cs +++ b/ClassicalSharp/Network/Utils/AsyncDownloader.cs @@ -196,7 +196,7 @@ namespace ClassicalSharp.Network { object DownloadContent( Request request, HttpWebResponse response ) { if( request.Type == RequestType.Bitmap ) { MemoryStream data = DownloadBytes( response ); - return new Bitmap( data ); + return Platform.ReadBmp( data ); } else if( request.Type == RequestType.String ) { MemoryStream data = DownloadBytes( response ); byte[] rawBuffer = data.GetBuffer(); diff --git a/ClassicalSharp/Android/Font.cs b/ClassicalSharp/Platform/Font.cs similarity index 100% rename from ClassicalSharp/Android/Font.cs rename to ClassicalSharp/Platform/Font.cs diff --git a/ClassicalSharp/Platform/Platform.cs b/ClassicalSharp/Platform/Platform.cs new file mode 100644 index 000000000..34cbe53b6 --- /dev/null +++ b/ClassicalSharp/Platform/Platform.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; +using System.IO; +#if ANDROID +using Android.Graphics; +#else +using System.Drawing.Imaging; +#endif + +namespace ClassicalSharp { + + public static class Platform { + + public static Bitmap CreateBmp( int width, int height ) { + #if !ANDROID + return new Bitmap( width, height ); + #else + return Bitmap.CreateBitmap( width, height, Bitmap.Config.Argb8888 ); + #endif + } + + public static Bitmap ReadBmp( Stream src ) { + #if !ANDROID + return new Bitmap( src ); + #else + return BitmapFactory.DecodeStream( src ); + #endif + } + + public static void WriteBmp( Bitmap bmp, Stream dst ) { + #if !ANDROID + bmp.Save( dst, ImageFormat.Png ); + #else + bmp.Compress( Bitmap.CompressFormat.Png, 100, dst ); + #endif + } + } +} diff --git a/ClassicalSharp/TexturePack/Animations.cs b/ClassicalSharp/TexturePack/Animations.cs index 54314b8c5..5a1ee58c9 100644 --- a/ClassicalSharp/TexturePack/Animations.cs +++ b/ClassicalSharp/TexturePack/Animations.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using ClassicalSharp.GraphicsAPI; +#if ANDROID +using Android.Graphics; +#endif namespace ClassicalSharp.TexturePack { diff --git a/ClassicalSharp/TexturePack/TerrainAtlas2D.cs b/ClassicalSharp/TexturePack/TerrainAtlas2D.cs index 48ebeddd0..ef6348b4c 100644 --- a/ClassicalSharp/TexturePack/TerrainAtlas2D.cs +++ b/ClassicalSharp/TexturePack/TerrainAtlas2D.cs @@ -1,6 +1,9 @@ using System; using System.Drawing; using ClassicalSharp.GraphicsAPI; +#if ANDROID +using Android.Graphics; +#endif namespace ClassicalSharp { diff --git a/ClassicalSharp/TexturePack/TextureCache.cs b/ClassicalSharp/TexturePack/TextureCache.cs index b12358f8b..de75f8ebe 100644 --- a/ClassicalSharp/TexturePack/TextureCache.cs +++ b/ClassicalSharp/TexturePack/TextureCache.cs @@ -3,6 +3,9 @@ using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Text; +#if ANDROID +using Android.Graphics; +#endif namespace ClassicalSharp.TexturePack { @@ -63,7 +66,8 @@ namespace ClassicalSharp.TexturePack { if( !Directory.Exists( basePath ) ) Directory.CreateDirectory( basePath ); - bmp.Save( path, ImageFormat.Png ); + using( FileStream fs = File.Create( path ) ) + Platform.WriteBmp( bmp, fs ); } catch( IOException ex ) { ErrorHandler.LogError( "Cache.AddToCache", ex ); } diff --git a/ClassicalSharp/TexturePack/TexturePackExtractor.cs b/ClassicalSharp/TexturePack/TexturePackExtractor.cs index 4bd5450d2..5c78e67ff 100644 --- a/ClassicalSharp/TexturePack/TexturePackExtractor.cs +++ b/ClassicalSharp/TexturePack/TexturePackExtractor.cs @@ -39,7 +39,7 @@ namespace ClassicalSharp.TexturePack { IGraphicsApi api = game.Graphics; switch( filename ) { case "terrain.png": - game.ChangeTerrainAtlas( new Bitmap( stream ) ); break; + game.ChangeTerrainAtlas( Platform.ReadBmp( stream ) ); break; case "mob/chicken.png": case "chicken.png": UpdateTexture( ref cache.ChickenTexId, stream, false ); break; @@ -79,7 +79,7 @@ namespace ClassicalSharp.TexturePack { UpdateTexture( ref game.GuiClassicTexId, stream, false ); break; case "animations.png": case "animation.png": - game.Animations.SetAtlas( new Bitmap( stream ) ); break; + game.Animations.SetAtlas( Platform.ReadBmp( stream ) ); break; case "animations.txt": case "animation.txt": StreamReader reader = new StreamReader( stream ); @@ -95,14 +95,14 @@ namespace ClassicalSharp.TexturePack { } void SetFontBitmap( Game game, Stream stream ) { - Bitmap bmp = new Bitmap( stream ); + Bitmap bmp = Platform.ReadBmp( stream ); game.Drawer2D.SetFontBitmap( bmp ); game.Events.RaiseChatFontChanged(); } void UpdateTexture( ref int texId, Stream stream, bool setSkinType ) { game.Graphics.DeleteTexture( ref texId ); - using( Bitmap bmp = new Bitmap( stream ) ) { + using( Bitmap bmp = Platform.ReadBmp( stream ) ) { if( setSkinType ) game.DefaultPlayerSkinType = Utils.GetSkinType( bmp ); diff --git a/ClassicalSharp/Utils/Utils.cs b/ClassicalSharp/Utils/Utils.cs index dc43f1d54..ad89e8a38 100644 --- a/ClassicalSharp/Utils/Utils.cs +++ b/ClassicalSharp/Utils/Utils.cs @@ -2,6 +2,9 @@ using System.Drawing; using OpenTK; using OpenTK.Input; +#if ANDROID +using Android.Graphics; +#endif namespace ClassicalSharp {