mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-14 09:03:07 -04:00
281 lines
8.9 KiB
C#
281 lines
8.9 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using ClassicalSharp.GraphicsAPI;
|
|
using OpenTK.Input;
|
|
|
|
namespace ClassicalSharp {
|
|
|
|
public partial class BlockSelectScreen : Screen {
|
|
|
|
public BlockSelectScreen( Game game ) : base( game ) {
|
|
font = new Font( "Arial", 13 );
|
|
}
|
|
|
|
Block[] blocksTable;
|
|
Texture blockInfoTexture;
|
|
const int blocksPerRow = 10, maxRows = 7;
|
|
int selIndex, rows;
|
|
int startX, startY, blockSize;
|
|
float selBlockExpand;
|
|
readonly Font font;
|
|
StringBuffer buffer = new StringBuffer( 96 );
|
|
|
|
int TableX { get { return startX - 5 - 10; } }
|
|
int TableY { get { return startY - 5 - 30; } }
|
|
int TableWidth { get { return blocksPerRow * blockSize + 10 + 10; } }
|
|
int TableHeight { get { return maxRows * blockSize + 10 + 30; } }
|
|
|
|
static FastColour backCol = new FastColour( 30, 30, 30, 200 );
|
|
static FastColour selCol = new FastColour( 213, 200, 223 );
|
|
public override void Render( double delta ) {
|
|
graphicsApi.Draw2DQuad( TableX, TableY, TableWidth, TableHeight, backCol );
|
|
DrawScrollbar();
|
|
graphicsApi.Texturing = true;
|
|
graphicsApi.BindTexture( game.TerrainAtlas.TexId );
|
|
graphicsApi.SetBatchFormat( VertexFormat.Pos3fTex2fCol4b );
|
|
|
|
for( int i = 0; i < blocksTable.Length; i++ ) {
|
|
int x, y;
|
|
if( !GetCoords( i, out x, out y ) )
|
|
continue;
|
|
|
|
// We want to always draw the selected block on top of others
|
|
if( i == selIndex ) continue;
|
|
IsometricBlockDrawer.Draw( game, (byte)blocksTable[i], blockSize * 0.7f / 2f,
|
|
x + blockSize / 2, y + blockSize / 2 );
|
|
}
|
|
|
|
if( selIndex != -1 ) {
|
|
int x, y;
|
|
GetCoords( selIndex, out x, out y );
|
|
IsometricBlockDrawer.Draw( game, (byte)blocksTable[selIndex], (blockSize + selBlockExpand) * 0.7f / 2,
|
|
x + blockSize / 2, y + blockSize / 2 );
|
|
}
|
|
|
|
if( blockInfoTexture.IsValid )
|
|
blockInfoTexture.Render( graphicsApi );
|
|
game.hudScreen.RenderHotbar( delta );
|
|
graphicsApi.Texturing = false;
|
|
}
|
|
|
|
bool GetCoords( int i, out int x, out int y ) {
|
|
int col = i % blocksPerRow;
|
|
int row = i / blocksPerRow;
|
|
x = startX + blockSize * col;
|
|
y = startY + blockSize * row + 3;
|
|
y -= scrollY * blockSize;
|
|
row -= scrollY;
|
|
return row >= 0 && row < maxRows;
|
|
}
|
|
|
|
public override void Dispose() {
|
|
font.Dispose();
|
|
graphicsApi.DeleteTexture( ref blockInfoTexture );
|
|
game.Events.BlockPermissionsChanged -= BlockPermissionsChanged;
|
|
game.Keyboard.KeyRepeat = false;
|
|
}
|
|
|
|
public override void OnResize( int oldWidth, int oldHeight, int width, int height ) {
|
|
blockSize = (int)(50 * Math.Sqrt(game.GuiScale));
|
|
selBlockExpand = (float)(25 * Math.Sqrt(game.GuiScale));
|
|
|
|
startX = game.Width / 2 - (blockSize * blocksPerRow) / 2;
|
|
startY = game.Height / 2 - (maxRows * blockSize) / 2;
|
|
blockInfoTexture.X1 = startX + (blockSize * blocksPerRow) / 2 - blockInfoTexture.Width / 2;
|
|
blockInfoTexture.Y1 = startY - blockInfoTexture.Height - 5;
|
|
}
|
|
|
|
public override void Init() {
|
|
blockSize = (int)(50 * Math.Sqrt(game.GuiScale));
|
|
selBlockExpand = (float)(25 * Math.Sqrt(game.GuiScale));
|
|
game.Events.BlockPermissionsChanged += BlockPermissionsChanged;
|
|
|
|
RecreateBlockTable();
|
|
Block held = game.Inventory.HeldBlock;
|
|
selIndex = Array.IndexOf<Block>( blocksTable, held );
|
|
UpdateScrollY();
|
|
MoveCursorToSelected();
|
|
game.Keyboard.KeyRepeat = true;
|
|
}
|
|
|
|
void MoveCursorToSelected() {
|
|
if( selIndex == -1 ) return;
|
|
int x, y;
|
|
GetCoords( selIndex, out x, out y );
|
|
x += blockSize / 2; y += blockSize / 2;
|
|
|
|
Point topLeft = game.PointToScreen( Point.Empty );
|
|
x += topLeft.X; y += topLeft.Y;
|
|
game.DesktopCursorPos = new Point( x, y );
|
|
}
|
|
|
|
void BlockPermissionsChanged( object sender, EventArgs e ) {
|
|
RecreateBlockTable();
|
|
if( selIndex >= blocksTable.Length )
|
|
selIndex = blocksTable.Length - 1;
|
|
UpdateScrollY();
|
|
RecreateBlockInfoTexture();
|
|
}
|
|
|
|
static string[] normalNames = null;
|
|
void UpdateBlockInfoString( Block block ) {
|
|
if( normalNames == null )
|
|
MakeNormalNames();
|
|
|
|
int index = 0;
|
|
buffer.Clear();
|
|
buffer.Append( ref index, "&f" );
|
|
if( block == Block.TNT ) {
|
|
buffer.Append( ref index, "TNT" );
|
|
} else {
|
|
string value = game.BlockInfo.Name[(byte)block];
|
|
if( (byte)block < BlockInfo.CpeBlocksCount && value == "Invalid" ) {
|
|
buffer.Append( ref index, normalNames[(byte)block] );
|
|
} else {
|
|
buffer.Append( ref index, value );
|
|
}
|
|
}
|
|
buffer.Append( ref index, " (can place: " );
|
|
buffer.Append( ref index, game.Inventory.CanPlace[(int)block] ? "&aYes" : "&cNo" );
|
|
buffer.Append( ref index, "&f, can delete: " );
|
|
buffer.Append( ref index, game.Inventory.CanDelete[(int)block] ? "&aYes" : "&cNo" );
|
|
buffer.Append( ref index, "&f)" );
|
|
}
|
|
|
|
void MakeNormalNames() {
|
|
normalNames = new string[BlockInfo.CpeBlocksCount];
|
|
for( int i = 0; i < normalNames.Length; i++ ) {
|
|
string origName = Enum.GetName( typeof(Block), (byte)i );
|
|
buffer.Clear();
|
|
|
|
int index = 0;
|
|
SplitUppercase( origName, ref index );
|
|
normalNames[i] = buffer.ToString();
|
|
}
|
|
}
|
|
|
|
void SplitUppercase( string value, ref int index ) {
|
|
for( int i = 0; i < value.Length; i++ ) {
|
|
char c = value[i];
|
|
if( Char.IsUpper( c ) && i > 0 ) {
|
|
buffer.Append( ref index, ' ' );
|
|
}
|
|
buffer.Append( ref index, c );
|
|
}
|
|
}
|
|
|
|
int lastCreatedIndex = -1000;
|
|
void RecreateBlockInfoTexture() {
|
|
if( selIndex == lastCreatedIndex ) return;
|
|
lastCreatedIndex = selIndex;
|
|
|
|
graphicsApi.DeleteTexture( ref blockInfoTexture );
|
|
if( selIndex == -1 ) return;
|
|
|
|
Block block = blocksTable[selIndex];
|
|
UpdateBlockInfoString( block );
|
|
string value = buffer.GetString();
|
|
|
|
DrawTextArgs args = new DrawTextArgs( value, font, true );
|
|
Size size = game.Drawer2D.MeasureSize( ref args );
|
|
int x = startX + (blockSize * blocksPerRow) / 2 - size.Width / 2;
|
|
int y = startY - size.Height - 5;
|
|
|
|
args.SkipPartsCheck = true;
|
|
blockInfoTexture = game.Drawer2D.MakeTextTexture( ref args, x, y );
|
|
}
|
|
|
|
void RecreateBlockTable() {
|
|
int blocksCount = 0;
|
|
for( int tile = 1; tile < BlockInfo.BlocksCount; tile++ ) {
|
|
if( game.Inventory.CanPlace[tile] || game.Inventory.CanDelete[tile] )
|
|
blocksCount++;
|
|
}
|
|
|
|
rows = Utils.CeilDiv( blocksCount, blocksPerRow );
|
|
startX = game.Width / 2 - (blockSize * blocksPerRow) / 2;
|
|
startY = game.Height / 2 - (maxRows * blockSize) / 2;
|
|
blocksTable = new Block[blocksCount];
|
|
|
|
int tableIndex = 0;
|
|
for( int tile = 1; tile < BlockInfo.BlocksCount; tile++ ) {
|
|
if( game.Inventory.CanPlace[tile] || game.Inventory.CanDelete[tile] )
|
|
blocksTable[tableIndex++] = (Block)tile;
|
|
}
|
|
}
|
|
|
|
public override bool HandlesAllInput {
|
|
get { return true; }
|
|
}
|
|
|
|
public override bool HandlesMouseMove( int mouseX, int mouseY ) {
|
|
selIndex = -1;
|
|
if( Contains( startX, startY, blocksPerRow * blockSize,
|
|
maxRows * blockSize, mouseX, mouseY ) ) {
|
|
for( int i = 0; i < blocksTable.Length; i++ ) {
|
|
int x, y;
|
|
GetCoords( i, out x, out y );
|
|
|
|
if( Contains( x, y, blockSize, blockSize, mouseX, mouseY ) ) {
|
|
selIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
RecreateBlockInfoTexture();
|
|
return true;
|
|
}
|
|
|
|
public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) {
|
|
if( button == MouseButton.Left && mouseX >= TableX && mouseX < TableX + scrollbarWidth ) {
|
|
ScrollbarClick( mouseY );
|
|
} else if( button == MouseButton.Left && selIndex != -1 ) {
|
|
game.Inventory.HeldBlock = blocksTable[selIndex];
|
|
game.SetNewScreen( null );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public override bool HandlesKeyDown( Key key ) {
|
|
if( key == game.Mapping( KeyBinding.PauseOrExit ) ||
|
|
key == game.Mapping( KeyBinding.OpenInventory ) ) {
|
|
game.SetNewScreen( null );
|
|
} else if( key == Key.Enter && selIndex != -1 ) {
|
|
game.Inventory.HeldBlock = blocksTable[selIndex];
|
|
game.SetNewScreen( null );
|
|
} else if( (key == Key.Left || key == Key.Keypad4) && selIndex != -1 ) {
|
|
selIndex--;
|
|
if( selIndex < 0 )
|
|
selIndex = 0;
|
|
UpdateSelectedState();
|
|
} else if( (key == Key.Right || key == Key.Keypad6) && selIndex != -1 ) {
|
|
selIndex++;
|
|
if( selIndex >= blocksTable.Length )
|
|
selIndex = blocksTable.Length - 1;
|
|
UpdateSelectedState();
|
|
} else if( (key == Key.Up || key == Key.Keypad8) && selIndex != -1 ) {
|
|
selIndex -= blocksPerRow;
|
|
if( selIndex < 0 )
|
|
selIndex += blocksPerRow;
|
|
UpdateSelectedState();
|
|
} else if( (key == Key.Down || key == Key.Keypad2) && selIndex != -1 ) {
|
|
selIndex += blocksPerRow;
|
|
if( selIndex >= blocksTable.Length )
|
|
selIndex -= blocksPerRow;
|
|
UpdateSelectedState();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void UpdateSelectedState() {
|
|
UpdateScrollY();
|
|
RecreateBlockInfoTexture();
|
|
MoveCursorToSelected();
|
|
}
|
|
|
|
static bool Contains( int recX, int recY, int width, int height, int x, int y ) {
|
|
return x >= recX && y >= recY && x < recX + width && y < recY + height;
|
|
}
|
|
}
|
|
}
|