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 {