private static void RotateHandler( Player player, Command cmd )
{
CopyState originalInfo = player.GetCopyInformation();
if ( originalInfo == null ) {
player.MessageNow( "Nothing to rotate! Copy something first." );
return;
}
int degrees;
if ( !cmd.NextInt( out degrees ) || ( degrees != 90 && degrees != -90 && degrees != 180 && degrees != 270 ) ) {
CdRotate.PrintUsage( player );
return;
}
string axisName = cmd.Next();
Axis axis = Axis.Z;
if ( axisName != null ) {
switch ( axisName.ToLower() ) {
case "x":
axis = Axis.X;
break;
case "y":
axis = Axis.Y;
break;
case "z":
case "h":
axis = Axis.Z;
break;
default:
CdRotate.PrintUsage( player );
return;
}
}
// allocate the new buffer
Block[, ,] oldBuffer = originalInfo.Buffer;
Block[, ,] newBuffer;
if ( degrees == 180 ) {
newBuffer = new Block[oldBuffer.GetLength( 0 ), oldBuffer.GetLength( 1 ), oldBuffer.GetLength( 2 )];
} else switch (axis)
{
case Axis.X:
newBuffer = new Block[oldBuffer.GetLength( 0 ), oldBuffer.GetLength( 2 ), oldBuffer.GetLength( 1 )];
break;
case Axis.Y:
newBuffer = new Block[oldBuffer.GetLength( 2 ), oldBuffer.GetLength( 1 ), oldBuffer.GetLength( 0 )];
break;
default:
newBuffer = new Block[oldBuffer.GetLength( 1 ), oldBuffer.GetLength( 0 ), oldBuffer.GetLength( 2 )];
break;
}
// clone to avoid messing up any paste-in-progress
var info = new CopyState( originalInfo, newBuffer );
// construct the rotation matrix
var matrix = new[,]{
{1,0,0},
{0,1,0},
{0,0,1}
};
int a, b;
switch ( axis ) {
case Axis.X:
a = 1;
b = 2;
break;
case Axis.Y:
a = 0;
b = 2;
break;
default:
a = 0;
b = 1;
break;
}
switch ( degrees ) {
case 90:
matrix[a, a] = 0;
matrix[b, b] = 0;
matrix[a, b] = -1;
matrix[b, a] = 1;
break;
case 180:
matrix[a, a] = -1;
matrix[b, b] = -1;
break;
case -90:
case 270:
matrix[a, a] = 0;
matrix[b, b] = 0;
matrix[a, b] = 1;
matrix[b, a] = -1;
break;
}
// apply the rotation matrix
for ( int x = oldBuffer.GetLength( 0 ) - 1; x >= 0; x-- ) {
for ( int y = oldBuffer.GetLength( 1 ) - 1; y >= 0; y-- ) {
for ( int z = oldBuffer.GetLength( 2 ) - 1; z >= 0; z-- ) {
int nx = ( matrix[0, 0] < 0 ? oldBuffer.GetLength( 0 ) - 1 - x : ( matrix[0, 0] > 0 ? x : 0 ) ) +
( matrix[0, 1] < 0 ? oldBuffer.GetLength( 1 ) - 1 - y : ( matrix[0, 1] > 0 ? y : 0 ) ) +
( matrix[0, 2] < 0 ? oldBuffer.GetLength( 2 ) - 1 - z : ( matrix[0, 2] > 0 ? z : 0 ) );
int ny = ( matrix[1, 0] < 0 ? oldBuffer.GetLength( 0 ) - 1 - x : ( matrix[1, 0] > 0 ? x : 0 ) ) +
( matrix[1, 1] < 0 ? oldBuffer.GetLength( 1 ) - 1 - y : ( matrix[1, 1] > 0 ? y : 0 ) ) +
( matrix[1, 2] < 0 ? oldBuffer.GetLength( 2 ) - 1 - z : ( matrix[1, 2] > 0 ? z : 0 ) );
int nz = ( matrix[2, 0] < 0 ? oldBuffer.GetLength( 0 ) - 1 - x : ( matrix[2, 0] > 0 ? x : 0 ) ) +
( matrix[2, 1] < 0 ? oldBuffer.GetLength( 1 ) - 1 - y : ( matrix[2, 1] > 0 ? y : 0 ) ) +
( matrix[2, 2] < 0 ? oldBuffer.GetLength( 2 ) - 1 - z : ( matrix[2, 2] > 0 ? z : 0 ) );
newBuffer[nx, ny, nz] = oldBuffer[x, y, z];
}
}
}
player.Message( "Rotated copy (slot {0}) by {1} degrees around {2} axis.",
info.Slot + 1, degrees, axis );
player.SetCopyInformation( info );
}