mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-23 17:43:08 -05:00
251 lines
7.9 KiB
C#
251 lines
7.9 KiB
C#
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
|
using System;
|
|
using System.Drawing;
|
|
using ClassicalSharp.GraphicsAPI;
|
|
using OpenTK.Input;
|
|
|
|
#if USE16_BIT
|
|
using BlockID = System.UInt16;
|
|
#else
|
|
using BlockID = System.Byte;
|
|
#endif
|
|
|
|
namespace ClassicalSharp.Gui.Screens {
|
|
public partial class InventoryScreen : Screen {
|
|
|
|
public InventoryScreen(Game game) : base(game) {
|
|
font = new Font(game.FontName, 16);
|
|
HandlesAllInput = true;
|
|
}
|
|
|
|
BlockID[] blocksTable;
|
|
Texture blockInfoTexture;
|
|
const int maxRows = 8;
|
|
int blocksPerRow {
|
|
get { return game.ClassicMode && !game.ClassicHacks ? 9 : 10; }
|
|
}
|
|
|
|
int selIndex, rows;
|
|
int startX, startY, blockSize;
|
|
float selBlockExpand;
|
|
readonly Font font;
|
|
StringBuffer buffer = new StringBuffer(128);
|
|
IsometricBlockDrawer drawer = new IsometricBlockDrawer();
|
|
|
|
int TableX { get { return startX - 5 - 10; } }
|
|
int TableY { get { return startY - 5 - 30; } }
|
|
int TableWidth { get { return blocksPerRow * blockSize + 10 + 20; } }
|
|
int TableHeight { get { return Math.Min(rows, maxRows) * blockSize + 10 + 40; } }
|
|
|
|
// These were sourced by taking a screenshot of vanilla
|
|
// Then using paint to extract the colour components
|
|
// Then using wolfram alpha to solve the glblendfunc equation
|
|
static FastColour topCol = new FastColour(34, 34, 34, 168);
|
|
static FastColour bottomCol = new FastColour(57, 57, 104, 202);
|
|
static FastColour topSelCol = new FastColour(255, 255, 255, 142);
|
|
static FastColour bottomSelCol = new FastColour(255, 255, 255, 192);
|
|
|
|
static VertexP3fT2fC4b[] vertices = new VertexP3fT2fC4b[8 * 10 * (4 * 4)];
|
|
int vb;
|
|
public override void Render(double delta) {
|
|
gfx.Draw2DQuad(TableX, TableY, TableWidth, TableHeight, topCol, bottomCol);
|
|
if (rows > maxRows)
|
|
DrawScrollbar();
|
|
|
|
if (selIndex != -1 && game.ClassicMode) {
|
|
int x, y;
|
|
GetCoords(selIndex, out x, out y);
|
|
float off = blockSize * 0.1f;
|
|
gfx.Draw2DQuad(x - off, y - off, blockSize + off * 2,
|
|
blockSize + off * 2, topSelCol, bottomSelCol);
|
|
}
|
|
gfx.Texturing = true;
|
|
gfx.SetBatchFormat(VertexFormat.P3fT2fC4b);
|
|
|
|
drawer.BeginBatch(game, vertices, vb);
|
|
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;
|
|
drawer.DrawBatch(blocksTable[i], blockSize * 0.7f / 2f,
|
|
x + blockSize / 2, y + blockSize / 2);
|
|
}
|
|
|
|
if (selIndex != -1) {
|
|
int x, y;
|
|
GetCoords(selIndex, out x, out y);
|
|
drawer.DrawBatch(blocksTable[selIndex], (blockSize + selBlockExpand) * 0.7f / 2,
|
|
x + blockSize / 2, y + blockSize / 2);
|
|
}
|
|
drawer.EndBatch();
|
|
|
|
if (blockInfoTexture.IsValid)
|
|
blockInfoTexture.Render(gfx);
|
|
gfx.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;
|
|
}
|
|
|
|
Point GetMouseCoords(int i) {
|
|
int x, y;
|
|
GetCoords(i, out x, out y);
|
|
x += blockSize / 2; y += blockSize / 2;
|
|
|
|
Point topLeft = game.PointToScreen(Point.Empty);
|
|
x += topLeft.X; y += topLeft.Y;
|
|
return new Point(x, y);
|
|
}
|
|
|
|
public override void Dispose() {
|
|
font.Dispose();
|
|
game.Events.BlockPermissionsChanged -= BlockPermissionsChanged;
|
|
game.Keyboard.KeyRepeat = false;
|
|
|
|
ContextLost();
|
|
game.Graphics.ContextLost -= ContextLost;
|
|
game.Graphics.ContextRecreated -= ContextRecreated;
|
|
}
|
|
|
|
public override void OnResize(int width, int height) {
|
|
blockSize = (int)(50 * Math.Sqrt(game.GuiInventoryScale));
|
|
selBlockExpand = (float)(25 * Math.Sqrt(game.GuiInventoryScale));
|
|
|
|
int rowsUsed = Math.Min(maxRows, rows);
|
|
startX = game.Width / 2 - (blockSize * blocksPerRow) / 2;
|
|
startY = game.Height / 2 - (rowsUsed * 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.GuiInventoryScale));
|
|
selBlockExpand = (float)(25 * Math.Sqrt(game.GuiInventoryScale));
|
|
game.Events.BlockPermissionsChanged += BlockPermissionsChanged;
|
|
|
|
ContextRecreated();
|
|
game.Graphics.ContextLost += ContextLost;
|
|
game.Graphics.ContextRecreated += ContextRecreated;
|
|
|
|
RecreateBlockTable();
|
|
SetBlockTo(game.Inventory.Selected);
|
|
game.Keyboard.KeyRepeat = true;
|
|
}
|
|
|
|
public void SetBlockTo(BlockID block) {
|
|
selIndex = Array.IndexOf<BlockID>(blocksTable, block);
|
|
scrollY = (selIndex / blocksPerRow) - (maxRows - 1);
|
|
ClampScrollY();
|
|
MoveCursorToSelected();
|
|
RecreateBlockInfoTexture();
|
|
}
|
|
|
|
void MoveCursorToSelected() {
|
|
if (selIndex == -1) return;
|
|
game.DesktopCursorPos = GetMouseCoords(selIndex);
|
|
}
|
|
|
|
void BlockPermissionsChanged(object sender, EventArgs e) {
|
|
RecreateBlockTable();
|
|
if (selIndex >= blocksTable.Length)
|
|
selIndex = blocksTable.Length - 1;
|
|
|
|
scrollY = selIndex / blocksPerRow;
|
|
ClampScrollY();
|
|
RecreateBlockInfoTexture();
|
|
}
|
|
|
|
void UpdateBlockInfoString(BlockID block) {
|
|
int index = 0;
|
|
buffer.Clear();
|
|
buffer.Append(ref index, "&f");
|
|
string value = game.BlockInfo.Name[block];
|
|
buffer.Append(ref index, value);
|
|
if (game.ClassicMode) return;
|
|
|
|
buffer.Append(ref index, " (ID ");
|
|
buffer.AppendNum(ref index, block);
|
|
buffer.Append(ref index, "&f, place ");
|
|
buffer.Append(ref index, game.Inventory.CanPlace[block] ? "&aYes" : "&cNo");
|
|
buffer.Append(ref index, "&f, delete ");
|
|
buffer.Append(ref index, game.Inventory.CanDelete[block] ? "&aYes" : "&cNo");
|
|
buffer.Append(ref index, "&f)");
|
|
}
|
|
|
|
int lastCreatedIndex = -1000;
|
|
void RecreateBlockInfoTexture() {
|
|
if (selIndex == lastCreatedIndex || blocksTable == null) return;
|
|
lastCreatedIndex = selIndex;
|
|
|
|
gfx.DeleteTexture(ref blockInfoTexture);
|
|
if (selIndex == -1) return;
|
|
|
|
BlockID block = blocksTable[selIndex];
|
|
UpdateBlockInfoString(block);
|
|
string value = buffer.ToString();
|
|
|
|
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;
|
|
int count = game.UseCPE ? Block.Count : Block.OriginalCount;
|
|
for (int i = 1; i < count; i++) {
|
|
BlockID block = game.Inventory.Map[i];
|
|
if (Show(block)) blocksCount++;
|
|
}
|
|
|
|
rows = Utils.CeilDiv(blocksCount, blocksPerRow);
|
|
int rowsUsed = Math.Min(maxRows, rows);
|
|
startX = game.Width / 2 - (blockSize * blocksPerRow) / 2;
|
|
startY = game.Height / 2 - (rowsUsed * blockSize) / 2;
|
|
blocksTable = new BlockID[blocksCount];
|
|
|
|
int index = 0;
|
|
for (int i = 1; i < count; i++) {
|
|
BlockID block = game.Inventory.Map[i];
|
|
if (Show(block)) blocksTable[index++] = block;
|
|
}
|
|
}
|
|
|
|
bool Show(BlockID block) {
|
|
if (game.PureClassic && IsHackBlock(block)) return false;
|
|
if (block < Block.CpeCount) {
|
|
int count = game.UseCPEBlocks ? Block.CpeCount : Block.OriginalCount;
|
|
return block < count && game.BlockInfo.Name[block] != "Invalid";
|
|
}
|
|
return game.BlockInfo.Name[block] != "Invalid";
|
|
}
|
|
|
|
bool IsHackBlock(BlockID block) {
|
|
return block == Block.DoubleSlab || block == Block.Bedrock ||
|
|
block == Block.Grass || game.BlockInfo.IsLiquid(block);
|
|
}
|
|
|
|
protected override void ContextLost() {
|
|
gfx.DeleteVb(ref vb);
|
|
gfx.DeleteTexture(ref blockInfoTexture);
|
|
lastCreatedIndex = -1000;
|
|
}
|
|
|
|
protected override void ContextRecreated() {
|
|
vb = gfx.CreateDynamicVb(VertexFormat.P3fT2fC4b, vertices.Length);
|
|
RecreateBlockInfoTexture();
|
|
}
|
|
}
|
|
}
|