mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-15 10:35:11 -04:00
More physics (still to go: saplings)
This commit is contained in:
parent
808d66ea6c
commit
6c69baeb38
@ -366,9 +366,9 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
public void UpdateBlock( int x, int y, int z, byte block ) {
|
||||
int oldHeight = Map.GetLightHeight( x, z );
|
||||
int oldHeight = Map.GetLightHeight( x, z ) + 1;
|
||||
Map.SetBlock( x, y, z, block );
|
||||
int newHeight = Map.GetLightHeight( x, z );
|
||||
int newHeight = Map.GetLightHeight( x, z ) + 1;
|
||||
MapRenderer.RedrawBlock( x, y, z, block, oldHeight, newHeight );
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ namespace ClassicalSharp {
|
||||
byte block = mapData[mapIndex];
|
||||
if( info.BlocksLight[block] ) {
|
||||
heightmap[index] = (short)( y - 1 );
|
||||
return y;
|
||||
return y - 1;
|
||||
}
|
||||
mapIndex -= oneY;
|
||||
}
|
||||
|
@ -149,19 +149,15 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
public void RedrawBlock( int x, int y, int z, byte block, int oldHeight, int newHeight ) {
|
||||
int cx = x >> 4;
|
||||
int cy = y >> 4;
|
||||
int cz = z >> 4;
|
||||
int cx = x >> 4, bX = x & 0x0F;
|
||||
int cy = y >> 4, bY = y & 0x0F;
|
||||
int cz = z >> 4, bZ = z & 0x0F;
|
||||
// NOTE: It's a lot faster to only update the chunks that are affected by the change in shadows,
|
||||
// rather than the entire column.
|
||||
int newLightcy = newHeight == -1 ? 0 : newHeight >> 4;
|
||||
int oldLightcy = oldHeight == -1 ? 0 : oldHeight >> 4;
|
||||
|
||||
ResetChunkAndBelow( cx, cy, cz, newLightcy, oldLightcy );
|
||||
int bX = x & 0x0F; // % 16
|
||||
int bY = y & 0x0F;
|
||||
int bZ = z & 0x0F;
|
||||
int newLightcy = newHeight < 0 ? 0 : newHeight >> 4;
|
||||
int oldLightcy = oldHeight < 0 ? 0 : oldHeight >> 4;
|
||||
|
||||
ResetChunkAndBelow( cx, cy, cz, newLightcy, oldLightcy );
|
||||
if( bX == 0 && cx > 0 ) ResetChunkAndBelow( cx - 1, cy, cz, newLightcy, oldLightcy );
|
||||
if( bY == 0 && cy > 0 ) ResetChunkAndBelow( cx, cy - 1, cz, newLightcy, oldLightcy );
|
||||
if( bZ == 0 && cz > 0 ) ResetChunkAndBelow( cx, cy, cz - 1, newLightcy, oldLightcy );
|
||||
|
@ -9,7 +9,7 @@ namespace ClassicalSharp.Singleplayer {
|
||||
Game game;
|
||||
public Map map;
|
||||
BlockInfo info;
|
||||
int width, length, height, oneY;
|
||||
int width, length, height, oneY, volume;
|
||||
|
||||
const uint tickMask = 0xF8000000;
|
||||
const uint posMask = 0x07FFFFFF;
|
||||
@ -50,10 +50,15 @@ namespace ClassicalSharp.Singleplayer {
|
||||
return true;
|
||||
}
|
||||
|
||||
int tickCount = 0;
|
||||
public void Tick() {
|
||||
//if( (tickCount % 5) == 0 ) {
|
||||
TickLava();
|
||||
TickWater();
|
||||
TickFalling();
|
||||
//}
|
||||
tickCount++;
|
||||
TickRandomBlocks();
|
||||
}
|
||||
|
||||
public void OnBlockPlaced( int x, int y, int z, byte block ) {
|
||||
@ -76,8 +81,72 @@ namespace ClassicalSharp.Singleplayer {
|
||||
length = map.Length;
|
||||
height = map.Height;
|
||||
oneY = height * width;
|
||||
volume = height * width * length;
|
||||
}
|
||||
|
||||
#region General
|
||||
// TODO: tree growing
|
||||
|
||||
void TickRandomBlocks() {
|
||||
for( int y = 0; y < height; y += 16 ) {
|
||||
for( int z = 0; z < length; z += 16 ) {
|
||||
for( int x = 0; x < width; x += 16 ) {
|
||||
int lo = (y * length + z) * width + x;
|
||||
int hi = ((y + 15) * length + (z + 15)) * width + (x + 15 );
|
||||
HandleBlock( rnd.Next( lo, hi ) );
|
||||
HandleBlock( rnd.Next( lo, hi ) );
|
||||
HandleBlock( rnd.Next( lo, hi ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleBlock( int posIndex ) {
|
||||
int x = posIndex % width;
|
||||
int y = posIndex / oneY; // posIndex / (width * length)
|
||||
int z = (posIndex / width) % length;
|
||||
byte block = map.mapData[posIndex];
|
||||
|
||||
switch( block ) {
|
||||
case (byte)Block.Dirt:
|
||||
if( y > map.GetLightHeight( x, z ) )
|
||||
game.UpdateBlock( x, y, z, (byte)Block.Grass );
|
||||
break;
|
||||
|
||||
case (byte)Block.Grass:
|
||||
if( y <= map.GetLightHeight( x, z ) ) {
|
||||
game.UpdateBlock( x, y, z, (byte)Block.Dirt );
|
||||
}
|
||||
break;
|
||||
|
||||
case (byte)Block.Dandelion:
|
||||
case (byte)Block.Rose:
|
||||
case (byte)Block.BrownMushroom:
|
||||
case (byte)Block.RedMushroom:
|
||||
if( y <= map.GetLightHeight( x, z ) )
|
||||
game.UpdateBlock( x, y, z, (byte)Block.Air );
|
||||
break;
|
||||
|
||||
case (byte)Block.Sapling:
|
||||
game.UpdateBlock( x, y, z, (byte)Block.ForestGreenWool );
|
||||
break;
|
||||
|
||||
case (byte)Block.Sand:
|
||||
case (byte)Block.Gravel:
|
||||
if( y > 0 ) PropagateFalling( posIndex, x, y, z, block, 0 );
|
||||
break;
|
||||
|
||||
case (byte)Block.Lava:
|
||||
HandleLava( posIndex, x, y, z );
|
||||
break;
|
||||
|
||||
case (byte)Block.Water:
|
||||
HandleWater( posIndex, x, y, z );
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Lava
|
||||
|
||||
Queue<uint> Lava = new Queue<uint>();
|
||||
@ -94,16 +163,19 @@ namespace ClassicalSharp.Singleplayer {
|
||||
int x = posIndex % width;
|
||||
int y = posIndex / oneY; // posIndex / (width * length)
|
||||
int z = (posIndex / width) % length;
|
||||
|
||||
if( x > 0 ) PropagateLava( posIndex - 1, x - 1, y, z );
|
||||
if( x < width - 1 ) PropagateLava( posIndex + 1, x + 1, y, z );
|
||||
if( z > 0 ) PropagateLava( posIndex - width, x, y, z - 1 );
|
||||
if( z < length - 1 ) PropagateLava( posIndex + width, x, y, z + 1 );
|
||||
if( y > 0 ) PropagateLava( posIndex - oneY, x, y - 1, z );
|
||||
HandleLava( posIndex, x, y, z );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleLava( int posIndex, int x, int y, int z ) {
|
||||
if( x > 0 ) PropagateLava( posIndex - 1, x - 1, y, z );
|
||||
if( x < width - 1 ) PropagateLava( posIndex + 1, x + 1, y, z );
|
||||
if( z > 0 ) PropagateLava( posIndex - width, x, y, z - 1 );
|
||||
if( z < length - 1 ) PropagateLava( posIndex + width, x, y, z + 1 );
|
||||
if( y > 0 ) PropagateLava( posIndex - oneY, x, y - 1, z );
|
||||
}
|
||||
|
||||
void PropagateLava( int posIndex, int x, int y, int z ) {
|
||||
byte block = map.mapData[posIndex];
|
||||
if( block == (byte)Block.Water || block == (byte)Block.StillWater ) {
|
||||
@ -132,16 +204,19 @@ namespace ClassicalSharp.Singleplayer {
|
||||
int x = posIndex % width;
|
||||
int y = posIndex / oneY; // posIndex / (width * length)
|
||||
int z = (posIndex / width) % length;
|
||||
|
||||
if( x > 0 ) PropagateWater( posIndex - 1, x - 1, y, z );
|
||||
if( x < width - 1 ) PropagateWater( posIndex + 1, x + 1, y, z );
|
||||
if( z > 0 ) PropagateWater( posIndex - width, x, y, z - 1 );
|
||||
if( z < length - 1 ) PropagateWater( posIndex + width, x, y, z + 1 );
|
||||
if( y > 0 ) PropagateWater( posIndex - oneY, x, y - 1, z );
|
||||
HandleWater( posIndex, x, y, z );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleWater( int posIndex, int x, int y, int z ) {
|
||||
if( x > 0 ) PropagateWater( posIndex - 1, x - 1, y, z );
|
||||
if( x < width - 1 ) PropagateWater( posIndex + 1, x + 1, y, z );
|
||||
if( z > 0 ) PropagateWater( posIndex - width, x, y, z - 1 );
|
||||
if( z < length - 1 ) PropagateWater( posIndex + width, x, y, z + 1 );
|
||||
if( y > 0 ) PropagateWater( posIndex - oneY, x, y - 1, z );
|
||||
}
|
||||
|
||||
void PropagateWater( int posIndex, int x, int y, int z ) {
|
||||
byte block = map.mapData[posIndex];
|
||||
if( block == (byte)Block.Lava || block == (byte)Block.StillLava ) {
|
||||
@ -154,6 +229,52 @@ namespace ClassicalSharp.Singleplayer {
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Sand/Gravel
|
||||
|
||||
Queue<uint> Falling = new Queue<uint>();
|
||||
const uint defFallingTick = 2u << tickShift;
|
||||
|
||||
void TickFalling() {
|
||||
int count = Falling.Count;
|
||||
for( int i = 0; i < count; i++ ) {
|
||||
int posIndex, flags;
|
||||
if( CheckItem( Falling, 0x2, out posIndex, out flags ) ) {
|
||||
byte block = map.mapData[posIndex];
|
||||
if( !(block == (byte)Block.Sand || block == (byte)Block.Gravel ) ) continue;
|
||||
|
||||
int x = posIndex % width;
|
||||
int y = posIndex / oneY; // posIndex / (width * length)
|
||||
int z = (posIndex / width) % length;
|
||||
if( y > 0 ) PropagateFalling( posIndex, x, y, z, block, flags );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PropagateFalling( int posIndex, int x, int y, int z, byte block, int flags ) {
|
||||
byte newBlock = map.mapData[posIndex - oneY];
|
||||
if( newBlock == 0 || info.IsLiquid[newBlock] ) {
|
||||
uint newFlags = MakeFallingFlags( newBlock ) << tickShift;
|
||||
Falling.Enqueue( newFlags | (uint)(posIndex - oneY) );
|
||||
|
||||
game.UpdateBlock( x, y, z, oldBlock[flags >> 2] );
|
||||
game.UpdateBlock( x, y - 1, z, block );
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] oldBlock = new byte[] { (byte)Block.Air, (byte)Block.StillWater,
|
||||
(byte)Block.Water, (byte)Block.StillLava, (Byte)Block.Lava };
|
||||
static uint MakeFallingFlags( byte above ) {
|
||||
byte flags = 2;
|
||||
if( above == (byte)Block.StillWater ) flags |= 0x04; // 1
|
||||
else if( above == (byte)Block.Water ) flags |= 0x08; // 2
|
||||
else if( above == (byte)Block.StillLava ) flags |= 0x0C; // 3
|
||||
else if( above == (byte)Block.Lava ) flags |= 0x10; // 4
|
||||
return flags;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TNT
|
||||
|
||||
Vector3[] rayDirs;
|
||||
@ -188,21 +309,21 @@ namespace ClassicalSharp.Singleplayer {
|
||||
}
|
||||
|
||||
void InitExplosionCache() {
|
||||
hardness = new float[] { 0, 30, 3, 2.5f, 30, 15, 0, 1.8E+07f, 500, 500, 500, 500, 2.5f,
|
||||
3, 15, 15, 15, 10, 1, 3, 1.5f, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0,
|
||||
hardness = new float[] { 0, 30, 3, 2.5f, 30, 15, 0, 1.8E+07f, 500, 500, 500, 500, 2.5f,
|
||||
3, 15, 15, 15, 10, 1, 3, 1.5f, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0,
|
||||
0, 0, 30, 30, 30, 30, 30, 0, 7.5f, 30, 6000, 30, 0, 4, 0.5f, 0, 4, 4, 4, 4, 4, 2.5f,
|
||||
// Note that the 30, 500, 15, 15 are guesses (CeramicTile --> Crate)
|
||||
30, 500, 15, 15, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
30, 500, 15, 15, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
rayDirs = new Vector3[1352];
|
||||
int index = 0;
|
||||
|
||||
// Y bottom and top planes
|
||||
// Y bottom and top planes
|
||||
for( float x = -1; x <= 1.001f; x += 2f/15) {
|
||||
for( float z = -1; z <= 1.001f; z += 2f/15) {
|
||||
rayDirs[index++] = Vector3.Normalize( x, -1, z );
|
||||
@ -226,57 +347,5 @@ namespace ClassicalSharp.Singleplayer {
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sapling
|
||||
// TODO: tree growing
|
||||
#endregion
|
||||
|
||||
#region Grass
|
||||
// TODO: grass growing
|
||||
#endregion
|
||||
|
||||
#region Sand/Gravel
|
||||
|
||||
Queue<uint> Falling = new Queue<uint>();
|
||||
const uint defFallingTick = 2u << tickShift;
|
||||
|
||||
void TickFalling() {
|
||||
int count = Falling.Count;
|
||||
for( int i = 0; i < count; i++ ) {
|
||||
int posIndex, flags;
|
||||
if( CheckItem( Falling, 0x2, out posIndex, out flags ) ) {
|
||||
byte block = map.mapData[posIndex];
|
||||
if( !(block == (byte)Block.Sand || block == (byte)Block.Gravel ) ) continue;
|
||||
|
||||
int x = posIndex % width;
|
||||
int y = posIndex / oneY; // posIndex / (width * length)
|
||||
int z = (posIndex / width) % length;
|
||||
if( y > 0 ) PropagateFalling( posIndex - oneY, x, y - 1, z, block, flags );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PropagateFalling( int posIndex, int x, int y, int z, byte block, int flags ) {
|
||||
byte newBlock = map.mapData[posIndex];
|
||||
if( newBlock == 0 || info.IsLiquid[newBlock] ) {
|
||||
uint newFlags = MakeFallingFlags( newBlock ) << tickShift;
|
||||
Falling.Enqueue( newFlags | (uint)posIndex );
|
||||
game.UpdateBlock( x, y, z, oldBlock[flags >> 2] );
|
||||
game.UpdateBlock( x, y - 1, z, block );
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] oldBlock = new byte[] { (byte)Block.Air, (byte)Block.StillWater,
|
||||
(byte)Block.Water, (byte)Block.StillLava, (Byte)Block.Lava };
|
||||
static uint MakeFallingFlags( byte above ) {
|
||||
byte flags = 2;
|
||||
if( above == (byte)Block.StillWater ) flags |= 0x04; // 1
|
||||
else if( above == (byte)Block.Water ) flags |= 0x08; // 2
|
||||
else if( above == (byte)Block.StillLava ) flags |= 0x0C; // 3
|
||||
else if( above == (byte)Block.Lava ) flags |= 0x10; // 4
|
||||
return flags;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -98,6 +98,7 @@
|
||||
<Compile Include="Platform\MacOS\MacOSException.cs" />
|
||||
<Compile Include="Platform\MacOS\MacOSKeyMap.cs" />
|
||||
<Compile Include="Platform\MacOS\QuartzDisplayDeviceDriver.cs" />
|
||||
<Compile Include="Platform\Minimal.cs" />
|
||||
<Compile Include="Platform\PlatformException.cs" />
|
||||
<Compile Include="Platform\Windows\API.cs" />
|
||||
<Compile Include="Platform\Windows\Wgl.cs" />
|
||||
|
264
OpenTK/Platform/Minimal.cs
Normal file
264
OpenTK/Platform/Minimal.cs
Normal file
@ -0,0 +1,264 @@
|
||||
#if OPENTK_MINIMAL
|
||||
using System;
|
||||
// These classes fill in for missing Rectangle, Point, and Size implementations
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public struct Color {
|
||||
public byte R, G, B, A;
|
||||
|
||||
public Color( int r, int g, int b, int a ) {
|
||||
A = (byte)a;
|
||||
R = (byte)r;
|
||||
G = (byte)g;
|
||||
B = (byte)b;
|
||||
}
|
||||
|
||||
public Color( int r, int g, int b ) {
|
||||
A = 255;
|
||||
R = (byte)r;
|
||||
G = (byte)g;
|
||||
B = (byte)b;
|
||||
}
|
||||
|
||||
public override bool Equals( object obj ) {
|
||||
return ( obj is Color ) && Equals( (Color)obj );
|
||||
}
|
||||
|
||||
public bool Equals( Color other ) {
|
||||
return A == other.A && R == other.R && G == other.G && B == other.B;
|
||||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
return A << 24 | R << 16 | G << 8 | B;
|
||||
}
|
||||
|
||||
public static bool operator == ( Color left, Color right ) {
|
||||
return left.Equals( right );
|
||||
}
|
||||
|
||||
public static bool operator != ( Color left, Color right ) {
|
||||
return !left.Equals( right );
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return R + ", " + G + ", " + B + " : " + A;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user