mirror of
https://github.com/coah80/LegacyVulkEdition.git
synced 2026-07-19 06:58:07 +00:00
804 lines
31 KiB
C++
804 lines
31 KiB
C++
#define NK_INCLUDE_FIXED_TYPES
|
|
#define NK_INCLUDE_STANDARD_IO
|
|
#define NK_INCLUDE_STANDARD_VARARGS
|
|
#define NK_INCLUDE_DEFAULT_ALLOCATOR
|
|
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
|
|
#define NK_INCLUDE_FONT_BAKING
|
|
#define NK_INCLUDE_DEFAULT_FONT
|
|
#include "nuklear.h"
|
|
|
|
#include "NkInventoryMenus.h"
|
|
#include "NkCommon.h"
|
|
#include "MenuScreens.h"
|
|
#include "NuklearBridge.h"
|
|
#include <cstring>
|
|
#include <cstdio>
|
|
|
|
namespace lve { namespace ui {
|
|
|
|
static const float BASE_W = 1280.0f;
|
|
static const float BASE_H = 720.0f;
|
|
|
|
static const float INV_PANEL_W = 887.0f;
|
|
static const float INV_PANEL_H = 735.0f;
|
|
|
|
static const float CRAFT3_PANEL_W = 1034.0f;
|
|
static const float CRAFT3_PANEL_H = 735.0f;
|
|
|
|
static const float CREATIVE_PANEL_W = 965.0f;
|
|
static const float CREATIVE_PANEL_H = 735.0f;
|
|
|
|
static const float SLOT_SIZE = 20.0f;
|
|
static const float SLOT_PADDING = 2.0f;
|
|
static const float SLOT_STRIDE = SLOT_SIZE + SLOT_PADDING;
|
|
|
|
static const float ARMOR_SLOT_SIZE = 24.0f;
|
|
|
|
static const float TAB_W = 160.0f;
|
|
static const float TAB_H = 128.0f;
|
|
|
|
static const float TAB_CREATIVE_W = 125.0f;
|
|
static const float TAB_CREATIVE_H = 117.0f;
|
|
|
|
static const float SCROLL_W = 32.0f;
|
|
static const float SCROLL_H = 18.0f;
|
|
|
|
static const float ICON_SIZE = 72.0f;
|
|
|
|
static const int INV_COLS = 9;
|
|
static const int INV_ROWS = 3;
|
|
static const int HOTBAR_COLS = 9;
|
|
static const int ARMOR_COUNT = 4;
|
|
|
|
static const int CREATIVE_COLS = 10;
|
|
static const int CREATIVE_ROWS = 5;
|
|
static const int CREATIVE_TAB_COUNT = 8;
|
|
|
|
static const int CRAFT2_GRID = 2;
|
|
static const int CRAFT3_GRID = 3;
|
|
static const int CRAFT2_TAB_COUNT = 6;
|
|
static const int CRAFT3_TAB_COUNT = 7;
|
|
|
|
static const float SHADOW_OFF = 2.0f;
|
|
|
|
static MenuTextureSlot loadSlotPath(const char *path)
|
|
{
|
|
int w = 0, h = 0;
|
|
struct nk_image img = loadTextureWithSize(path, &w, &h);
|
|
return {img.handle.id, w, h};
|
|
}
|
|
|
|
bool loadInventoryMenuTextures(InventoryMenuTextures &out)
|
|
{
|
|
out.panelCraftingSmall = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/166_Crafting_Panel_Small.png");
|
|
out.panelCraftingSmall2x2 = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/167_Crafting_Panel_Small_2x2.png");
|
|
out.panelCrafting3x3 = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/168_Crafting_Panel_3x3.png");
|
|
out.panelCrafting2x2 = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/169_Crafting_Panel2x2.png");
|
|
out.panelCreative8 = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/165_Creative_Panel_8.png");
|
|
out.iconHolder = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/129_IconHolder_1x1border.png");
|
|
out.iconHolderRed = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/128_IconHolderRed_1x1border.png");
|
|
out.slotHighlight = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/130_SlotHighlight.png");
|
|
out.armorHead = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/87_Armour_Slot_Head.png");
|
|
out.armorBody = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/89_Armour_Slot_Body.png");
|
|
out.armorLegs = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/86_Armour_Slot_Legs.png");
|
|
out.armorFeet = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/88_Armour_Slot_Feet.png");
|
|
out.scrollUp = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/83_Craft_Scroll_up.png");
|
|
out.scrollDown = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/84_Craft_Scroll_Down.png");
|
|
out.tabLeft = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/127_Tab_Left.png");
|
|
out.tabMiddle = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/126_Tab_Middle.png");
|
|
out.tabRight = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/125_Tab_Right.png");
|
|
out.tabCreativeLeft = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/121_Tab_Creative8_L.png");
|
|
out.tabCreativeMiddle = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/120_Tab_Creative8_M.png");
|
|
out.tabCreativeRight = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/119_Tab_Creative8_R.png");
|
|
out.craftHighlight = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/145_Craft_Highlight_L_Small.png");
|
|
out.craft3SlotV = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/146_Crafting_3SlotLargeV.png");
|
|
out.craft2SlotV = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/147_Crafting_2SlotLargeV.png");
|
|
out.iconShank = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/131_Icon_Shank.png");
|
|
out.iconArmour = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/132_icon_armour.png");
|
|
out.iconBrewing = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/133_icon_brewing.png");
|
|
out.iconDecoration = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/134_icon_decoration.png");
|
|
out.iconFood = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/135_icon_food.png");
|
|
out.iconMaterials = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/136_icon_Materials.png");
|
|
out.iconMechanisms = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/137_icon_mechanisms.png");
|
|
out.iconMisc = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/138_icon_misc.png");
|
|
out.iconRedstone = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/139_icon_Redstone_and_Transport.png");
|
|
out.iconStructures = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/140_icon_structures.png");
|
|
out.iconTools = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/141_icon_tools.png");
|
|
out.iconTransport = loadSlotPath("../Assets/ui/skinHDGraphicsInGame/142_icon_transport.png");
|
|
|
|
out.activeCraft2x2Tab = 0;
|
|
out.activeCraft3x3Tab = 0;
|
|
out.activeCreativeTab = 0;
|
|
|
|
out.loaded = (out.panelCrafting2x2.w > 0 && out.panelCrafting3x3.w > 0 &&
|
|
out.panelCreative8.w > 0 && out.iconHolder.w > 0 &&
|
|
out.slotHighlight.w > 0 && out.tabLeft.w > 0 &&
|
|
out.tabCreativeLeft.w > 0 && out.armorHead.w > 0);
|
|
|
|
if (!out.loaded)
|
|
fprintf(stderr, "[NkInventoryMenus] WARNING: some textures failed to load\n");
|
|
|
|
return out.loaded;
|
|
}
|
|
|
|
static void drawPanel(nk_context *ctx, float px, float py, float pw, float ph,
|
|
const MenuTextureSlot &panelTex)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
if (panelTex.w > 0) {
|
|
struct nk_image img = slotToNkImage(panelTex);
|
|
nk_draw_image(canvas, nk_rect(px, py, pw, ph), &img, nk_rgb(255, 255, 255));
|
|
} else {
|
|
nk_fill_rect(canvas, nk_rect(px, py, pw, ph), 4, nk_rgb(198, 198, 198));
|
|
nk_stroke_rect(canvas, nk_rect(px, py, pw, ph), 4, 2.0f, nk_rgb(80, 80, 80));
|
|
}
|
|
}
|
|
|
|
static void drawSlot(nk_context *ctx, float sx, float sy, float sw, float sh,
|
|
const InventoryMenuTextures &invTex, bool red)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
const MenuTextureSlot &holder = red ? invTex.iconHolderRed : invTex.iconHolder;
|
|
if (holder.w > 0) {
|
|
struct nk_image img = slotToNkImage(holder);
|
|
nk_draw_image(canvas, nk_rect(sx, sy, sw, sh), &img, nk_rgb(255, 255, 255));
|
|
} else {
|
|
nk_fill_rect(canvas, nk_rect(sx, sy, sw, sh), 0, nk_rgb(139, 139, 139));
|
|
nk_stroke_rect(canvas, nk_rect(sx, sy, sw, sh), 0, 1.0f, nk_rgb(55, 55, 55));
|
|
}
|
|
}
|
|
|
|
static void drawSlotHighlight(nk_context *ctx, float sx, float sy, float sw, float sh,
|
|
const InventoryMenuTextures &invTex)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
if (invTex.slotHighlight.w > 0) {
|
|
struct nk_image img = slotToNkImage(invTex.slotHighlight);
|
|
nk_draw_image(canvas, nk_rect(sx, sy, sw, sh), &img, nk_rgba(255, 255, 255, 180));
|
|
} else {
|
|
nk_fill_rect(canvas, nk_rect(sx, sy, sw, sh), 0, nk_rgba(255, 255, 255, 100));
|
|
}
|
|
}
|
|
|
|
static void drawArmorSlot(nk_context *ctx, float sx, float sy, float sw, float sh,
|
|
const MenuTextureSlot &armorTex)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
if (armorTex.w > 0) {
|
|
struct nk_image img = slotToNkImage(armorTex);
|
|
nk_draw_image(canvas, nk_rect(sx, sy, sw, sh), &img, nk_rgb(255, 255, 255));
|
|
} else {
|
|
nk_fill_rect(canvas, nk_rect(sx, sy, sw, sh), 0, nk_rgb(139, 139, 139));
|
|
nk_stroke_rect(canvas, nk_rect(sx, sy, sw, sh), 0, 1.0f, nk_rgb(55, 55, 55));
|
|
}
|
|
}
|
|
|
|
static void drawSlotGrid(nk_context *ctx, float gridX, float gridY,
|
|
int cols, int rows, float slotSz, float stride,
|
|
const InventoryMenuTextures &invTex,
|
|
const nk_input *input, int *hoveredSlot)
|
|
{
|
|
for (int row = 0; row < rows; row++) {
|
|
for (int col = 0; col < cols; col++) {
|
|
float sx = gridX + (float)col * stride;
|
|
float sy = gridY + (float)row * stride;
|
|
drawSlot(ctx, sx, sy, slotSz, slotSz, invTex, false);
|
|
|
|
struct nk_rect slotRect = nk_rect(sx, sy, slotSz, slotSz);
|
|
if (nk_input_is_mouse_hovering_rect(input, slotRect)) {
|
|
drawSlotHighlight(ctx, sx, sy, slotSz, slotSz, invTex);
|
|
if (hoveredSlot != nullptr)
|
|
*hoveredSlot = row * cols + col;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void drawCraftingTab(nk_context *ctx, float tx, float ty, float tw, float th,
|
|
const MenuTextureSlot &tabTex, bool active)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
struct nk_color tint = active ? nk_rgb(255, 255, 255) : nk_rgb(180, 180, 180);
|
|
|
|
if (tabTex.w > 0) {
|
|
struct nk_image img = slotToNkImage(tabTex);
|
|
nk_draw_image(canvas, nk_rect(tx, ty, tw, th), &img, tint);
|
|
} else {
|
|
struct nk_color bg = active ? nk_rgb(198, 198, 198) : nk_rgb(140, 140, 140);
|
|
nk_fill_rect(canvas, nk_rect(tx, ty, tw, th), 2, bg);
|
|
nk_stroke_rect(canvas, nk_rect(tx, ty, tw, th), 2, 1.0f, nk_rgb(80, 80, 80));
|
|
}
|
|
}
|
|
|
|
static void drawTabIcon(nk_context *ctx, float cx, float cy, float sz,
|
|
const MenuTextureSlot &iconTex)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr || iconTex.w <= 0) return;
|
|
|
|
struct nk_image img = slotToNkImage(iconTex);
|
|
nk_draw_image(canvas, nk_rect(cx, cy, sz, sz), &img, nk_rgb(255, 255, 255));
|
|
}
|
|
|
|
static void drawScrollArrow(nk_context *ctx, float ax, float ay, float aw, float ah,
|
|
const MenuTextureSlot &arrowTex)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
if (arrowTex.w > 0) {
|
|
struct nk_image img = slotToNkImage(arrowTex);
|
|
nk_draw_image(canvas, nk_rect(ax, ay, aw, ah), &img, nk_rgb(255, 255, 255));
|
|
}
|
|
}
|
|
|
|
|
|
static void drawCenteredLabel(nk_context *ctx, const char *text,
|
|
float x, float y, float w, float h,
|
|
struct nk_color color)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
const struct nk_user_font *font = ctx->style.font;
|
|
if (font == nullptr) return;
|
|
|
|
int len = (int)strlen(text);
|
|
float textW = font->width(font->userdata, font->height, text, len);
|
|
float textX = x + (w - textW) * 0.5f;
|
|
float textY = y + (h - font->height) * 0.5f;
|
|
|
|
nk_draw_text(canvas, nk_rect(textX + SHADOW_OFF, textY + SHADOW_OFF, textW, font->height),
|
|
text, len, font, nk_rgba(0, 0, 0, 0), nk_rgba(63, 63, 63, 255));
|
|
nk_draw_text(canvas, nk_rect(textX, textY, textW, font->height),
|
|
text, len, font, nk_rgba(0, 0, 0, 0), color);
|
|
}
|
|
|
|
static void drawLeftLabel(nk_context *ctx, const char *text,
|
|
float x, float y, float h,
|
|
struct nk_color color)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
const struct nk_user_font *font = ctx->style.font;
|
|
if (font == nullptr) return;
|
|
|
|
int len = (int)strlen(text);
|
|
float textW = font->width(font->userdata, font->height, text, len);
|
|
float textY = y + (h - font->height) * 0.5f;
|
|
|
|
nk_draw_text(canvas, nk_rect(x + SHADOW_OFF, textY + SHADOW_OFF, textW, font->height),
|
|
text, len, font, nk_rgba(0, 0, 0, 0), nk_rgba(63, 63, 63, 255));
|
|
nk_draw_text(canvas, nk_rect(x, textY, textW, font->height),
|
|
text, len, font, nk_rgba(0, 0, 0, 0), color);
|
|
}
|
|
|
|
static void drawPlayerPreviewArea(nk_context *ctx, float px, float py, float pw, float ph)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
nk_fill_rect(canvas, nk_rect(px, py, pw, ph), 0, nk_rgba(60, 60, 60, 120));
|
|
nk_stroke_rect(canvas, nk_rect(px, py, pw, ph), 0, 1.0f, nk_rgb(40, 40, 40));
|
|
}
|
|
|
|
static void drawCraftingRecipeSlot(nk_context *ctx, float sx, float sy, float sw, float sh,
|
|
const InventoryMenuTextures &invTex,
|
|
const nk_input *input, bool isResult)
|
|
{
|
|
drawSlot(ctx, sx, sy, sw, sh, invTex, isResult);
|
|
|
|
struct nk_rect slotRect = nk_rect(sx, sy, sw, sh);
|
|
if (nk_input_is_mouse_hovering_rect(input, slotRect))
|
|
drawSlotHighlight(ctx, sx, sy, sw, sh, invTex);
|
|
}
|
|
|
|
static void drawRecipeGrid(nk_context *ctx, float gx, float gy,
|
|
int gridSize, float slotSz, float stride,
|
|
const InventoryMenuTextures &invTex,
|
|
const nk_input *input)
|
|
{
|
|
for (int row = 0; row < gridSize; row++) {
|
|
for (int col = 0; col < gridSize; col++) {
|
|
float sx = gx + (float)col * stride;
|
|
float sy = gy + (float)row * stride;
|
|
drawCraftingRecipeSlot(ctx, sx, sy, slotSz, slotSz, invTex, input, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
static const MenuTextureSlot &getCraft2x2TabIcon(const InventoryMenuTextures &invTex, int index)
|
|
{
|
|
switch (index) {
|
|
case 0: return invTex.iconStructures;
|
|
case 1: return invTex.iconTools;
|
|
case 2: return invTex.iconArmour;
|
|
case 3: return invTex.iconFood;
|
|
case 4: return invTex.iconMechanisms;
|
|
case 5: return invTex.iconMisc;
|
|
default: return invTex.iconMisc;
|
|
}
|
|
}
|
|
|
|
static const char *getCraft2x2TabName(int index)
|
|
{
|
|
switch (index) {
|
|
case 0: return "Structures";
|
|
case 1: return "Tools";
|
|
case 2: return "Armour";
|
|
case 3: return "Food";
|
|
case 4: return "Mechanisms";
|
|
case 5: return "Miscellaneous";
|
|
default: return "";
|
|
}
|
|
}
|
|
|
|
static const MenuTextureSlot &getCraft3x3TabIcon(const InventoryMenuTextures &invTex, int index)
|
|
{
|
|
switch (index) {
|
|
case 0: return invTex.iconStructures;
|
|
case 1: return invTex.iconTools;
|
|
case 2: return invTex.iconArmour;
|
|
case 3: return invTex.iconFood;
|
|
case 4: return invTex.iconDecoration;
|
|
case 5: return invTex.iconMechanisms;
|
|
case 6: return invTex.iconMisc;
|
|
default: return invTex.iconMisc;
|
|
}
|
|
}
|
|
|
|
static const char *getCraft3x3TabName(int index)
|
|
{
|
|
switch (index) {
|
|
case 0: return "Structures";
|
|
case 1: return "Tools";
|
|
case 2: return "Armour";
|
|
case 3: return "Food";
|
|
case 4: return "Decoration";
|
|
case 5: return "Mechanisms";
|
|
case 6: return "Miscellaneous";
|
|
default: return "";
|
|
}
|
|
}
|
|
|
|
static const MenuTextureSlot &getCreativeTabIcon(const InventoryMenuTextures &invTex, int index)
|
|
{
|
|
switch (index) {
|
|
case 0: return invTex.iconStructures;
|
|
case 1: return invTex.iconDecoration;
|
|
case 2: return invTex.iconRedstone;
|
|
case 3: return invTex.iconMaterials;
|
|
case 4: return invTex.iconTools;
|
|
case 5: return invTex.iconFood;
|
|
case 6: return invTex.iconBrewing;
|
|
case 7: return invTex.iconMisc;
|
|
default: return invTex.iconMisc;
|
|
}
|
|
}
|
|
|
|
static const char *getCreativeTabName(int index)
|
|
{
|
|
switch (index) {
|
|
case 0: return "Building Blocks";
|
|
case 1: return "Decoration Blocks";
|
|
case 2: return "Redstone";
|
|
case 3: return "Materials";
|
|
case 4: return "Tools & Weapons";
|
|
case 5: return "Food";
|
|
case 6: return "Brewing";
|
|
case 7: return "Miscellaneous";
|
|
default: return "";
|
|
}
|
|
}
|
|
|
|
static const MenuTextureSlot &getTabTexForIndex(const InventoryMenuTextures &invTex,
|
|
int index, int count)
|
|
{
|
|
if (index == 0) return invTex.tabLeft;
|
|
if (index == count - 1) return invTex.tabRight;
|
|
return invTex.tabMiddle;
|
|
}
|
|
|
|
static const MenuTextureSlot &getCreativeTabTexForIndex(const InventoryMenuTextures &invTex,
|
|
int index, int count)
|
|
{
|
|
if (index == 0) return invTex.tabCreativeLeft;
|
|
if (index == count - 1) return invTex.tabCreativeRight;
|
|
return invTex.tabCreativeMiddle;
|
|
}
|
|
|
|
void renderInventory(nk_context *ctx, int winW, int winH,
|
|
MenuTextures &tex, InventoryMenuTextures &invTex)
|
|
{
|
|
float scaleX = (float)winW / BASE_W;
|
|
float scaleY = (float)winH / BASE_H;
|
|
float scale = (scaleX < scaleY) ? scaleX : scaleY;
|
|
|
|
float panelW = INV_PANEL_W * scale * 0.75f;
|
|
float panelH = INV_PANEL_H * scale * 0.75f;
|
|
float panelX = ((float)winW - panelW) * 0.5f;
|
|
float panelY = ((float)winH - panelH) * 0.5f;
|
|
|
|
float slotSz = SLOT_SIZE * scale * 0.75f;
|
|
float stride = SLOT_STRIDE * scale * 0.75f;
|
|
float armorSz = ARMOR_SLOT_SIZE * scale * 0.75f;
|
|
|
|
float contentPadX = panelW * 0.04f;
|
|
float contentPadY = panelH * 0.12f;
|
|
|
|
float armorX = panelX + contentPadX;
|
|
float armorY = panelY + contentPadY;
|
|
float armorStride = armorSz + 4.0f * scale;
|
|
|
|
float playerW = panelW * 0.18f;
|
|
float playerH = armorSz * 4.0f + armorStride;
|
|
float playerX = armorX + armorSz + 8.0f * scale;
|
|
float playerY = armorY;
|
|
|
|
float gridX = playerX + playerW + 12.0f * scale;
|
|
float gridY = armorY;
|
|
|
|
float invGridY = panelY + panelH * 0.52f;
|
|
float invGridX = panelX + contentPadX;
|
|
|
|
float hotbarY = panelY + panelH * 0.85f;
|
|
float hotbarX = invGridX;
|
|
|
|
pushCleanStyle(ctx);
|
|
|
|
if (nk_begin(ctx, "InventoryMenu", nk_rect(0, 0, (float)winW, (float)winH),
|
|
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
|
|
|
|
drawDirtBg(ctx, winW, winH, tex);
|
|
drawDirtOverlay(ctx, winW, winH);
|
|
|
|
drawPanel(ctx, panelX, panelY, panelW, panelH, invTex.panelCrafting2x2);
|
|
|
|
drawCenteredLabel(ctx, "Inventory", panelX, panelY + 4.0f * scale, panelW, 20.0f * scale,
|
|
nk_rgb(64, 64, 64));
|
|
|
|
const MenuTextureSlot *armorSlots[ARMOR_COUNT] = {
|
|
&invTex.armorHead, &invTex.armorBody, &invTex.armorLegs, &invTex.armorFeet
|
|
};
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
|
|
for (int i = 0; i < ARMOR_COUNT; i++) {
|
|
float ay = armorY + (float)i * armorStride;
|
|
drawArmorSlot(ctx, armorX, ay, armorSz, armorSz, *armorSlots[i]);
|
|
|
|
struct nk_rect armorRect = nk_rect(armorX, ay, armorSz, armorSz);
|
|
if (nk_input_is_mouse_hovering_rect(input, armorRect))
|
|
drawSlotHighlight(ctx, armorX, ay, armorSz, armorSz, invTex);
|
|
}
|
|
|
|
drawPlayerPreviewArea(ctx, playerX, playerY, playerW, playerH);
|
|
|
|
float craft2x2X = gridX;
|
|
float craft2x2Y = gridY;
|
|
drawRecipeGrid(ctx, craft2x2X, craft2x2Y, CRAFT2_GRID, slotSz, stride, invTex, input);
|
|
|
|
float resultX = craft2x2X + (float)CRAFT2_GRID * stride + stride;
|
|
float resultY = craft2x2Y + stride * 0.5f;
|
|
drawCraftingRecipeSlot(ctx, resultX, resultY, slotSz, slotSz, invTex, input, true);
|
|
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas != nullptr) {
|
|
float arrowX = craft2x2X + (float)CRAFT2_GRID * stride + 2.0f * scale;
|
|
float arrowY = resultY + slotSz * 0.25f;
|
|
float arrowW = stride * 0.8f;
|
|
float arrowH = slotSz * 0.5f;
|
|
nk_fill_rect(canvas, nk_rect(arrowX, arrowY, arrowW, arrowH), 0, nk_rgb(120, 120, 120));
|
|
}
|
|
|
|
int hoveredInv = -1;
|
|
drawSlotGrid(ctx, invGridX, invGridY, INV_COLS, INV_ROWS, slotSz, stride,
|
|
invTex, input, &hoveredInv);
|
|
|
|
int hoveredHotbar = -1;
|
|
drawSlotGrid(ctx, hotbarX, hotbarY, HOTBAR_COLS, 1, slotSz, stride,
|
|
invTex, input, &hoveredHotbar);
|
|
|
|
drawControllerPrompts(ctx, winW, winH, tex);
|
|
}
|
|
nk_end(ctx);
|
|
|
|
popCleanStyle(ctx);
|
|
}
|
|
|
|
static void drawCraftingCommon(nk_context *ctx, int winW, int winH,
|
|
MenuTextures &tex, InventoryMenuTextures &invTex,
|
|
const MenuTextureSlot &panelTex,
|
|
float panelNativeW, float panelNativeH,
|
|
int gridSize, int tabCount,
|
|
int *activeTabPtr,
|
|
const MenuTextureSlot &(*getTabIcon)(const InventoryMenuTextures &, int),
|
|
const char *(*getTabName)(int))
|
|
{
|
|
float scaleX = (float)winW / BASE_W;
|
|
float scaleY = (float)winH / BASE_H;
|
|
float scale = (scaleX < scaleY) ? scaleX : scaleY;
|
|
|
|
float panelW = panelNativeW * scale * 0.7f;
|
|
float panelH = panelNativeH * scale * 0.7f;
|
|
float panelX = ((float)winW - panelW) * 0.5f;
|
|
float panelY = ((float)winH - panelH) * 0.5f;
|
|
|
|
float slotSz = SLOT_SIZE * scale * 0.7f;
|
|
float stride = SLOT_STRIDE * scale * 0.7f;
|
|
|
|
float tabW = TAB_W * scale * 0.45f;
|
|
float tabH = TAB_H * scale * 0.45f;
|
|
|
|
float tabRowY = panelY - tabH + 4.0f * scale;
|
|
float tabStartX = panelX + 4.0f * scale;
|
|
float tabStride = tabW + 2.0f * scale;
|
|
|
|
float iconInTab = ICON_SIZE * scale * 0.35f;
|
|
|
|
float upperAreaY = panelY + panelH * 0.12f;
|
|
float recipeListX = panelX + panelW * 0.04f;
|
|
float recipeListW = panelW * 0.45f;
|
|
|
|
float gridAreaX = panelX + panelW * 0.52f;
|
|
float gridAreaY = upperAreaY;
|
|
|
|
float resultGap = stride * 1.2f;
|
|
|
|
float invGridY = panelY + panelH * 0.55f;
|
|
float invGridX = panelX + panelW * 0.04f;
|
|
|
|
float hotbarY = panelY + panelH * 0.85f;
|
|
float hotbarX = invGridX;
|
|
|
|
float scrollUpX = recipeListX + recipeListW * 0.35f;
|
|
float scrollUpY = upperAreaY - 2.0f * scale;
|
|
float scrollW = SCROLL_W * scale * 0.7f;
|
|
float scrollH = SCROLL_H * scale * 0.7f;
|
|
|
|
pushCleanStyle(ctx);
|
|
|
|
const char *winName = (gridSize == 3) ? "CraftingMenu3x3" : "CraftingMenu2x2";
|
|
|
|
if (nk_begin(ctx, winName, nk_rect(0, 0, (float)winW, (float)winH),
|
|
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
|
|
|
|
drawDirtBg(ctx, winW, winH, tex);
|
|
drawDirtOverlay(ctx, winW, winH);
|
|
|
|
drawPanel(ctx, panelX, panelY, panelW, panelH, panelTex);
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
|
|
int activeTab = *activeTabPtr;
|
|
|
|
for (int i = 0; i < tabCount; i++) {
|
|
float tx = tabStartX + (float)i * tabStride;
|
|
bool active = (i == activeTab);
|
|
const MenuTextureSlot &tabTex = getTabTexForIndex(invTex, i, tabCount);
|
|
drawCraftingTab(ctx, tx, tabRowY, tabW, tabH, tabTex, active);
|
|
|
|
float iconX = tx + (tabW - iconInTab) * 0.5f;
|
|
float iconY = tabRowY + (tabH - iconInTab) * 0.4f;
|
|
drawTabIcon(ctx, iconX, iconY, iconInTab, getTabIcon(invTex, i));
|
|
|
|
struct nk_rect tabRect = nk_rect(tx, tabRowY, tabW, tabH);
|
|
if (nk_input_is_mouse_hovering_rect(input, tabRect) &&
|
|
nk_input_is_mouse_released(input, NK_BUTTON_LEFT))
|
|
activeTab = i;
|
|
}
|
|
|
|
*activeTabPtr = activeTab;
|
|
|
|
drawLeftLabel(ctx, getTabName(activeTab),
|
|
panelX + panelW * 0.04f, panelY + 2.0f * scale, 20.0f * scale,
|
|
nk_rgb(64, 64, 64));
|
|
|
|
drawScrollArrow(ctx, scrollUpX, scrollUpY, scrollW, scrollH, invTex.scrollUp);
|
|
|
|
float recipeSlotY = upperAreaY + scrollH + 4.0f * scale;
|
|
int recipeSlotCount = (gridSize == 3) ? 7 : 5;
|
|
for (int i = 0; i < recipeSlotCount; i++) {
|
|
float rx = recipeListX + (float)i * stride;
|
|
float ry = recipeSlotY;
|
|
drawSlot(ctx, rx, ry, slotSz, slotSz, invTex, false);
|
|
|
|
struct nk_rect slotRect = nk_rect(rx, ry, slotSz, slotSz);
|
|
if (nk_input_is_mouse_hovering_rect(input, slotRect))
|
|
drawSlotHighlight(ctx, rx, ry, slotSz, slotSz, invTex);
|
|
}
|
|
|
|
float scrollDownY = recipeSlotY + slotSz + 4.0f * scale;
|
|
drawScrollArrow(ctx, scrollUpX, scrollDownY, scrollW, scrollH, invTex.scrollDown);
|
|
|
|
float vSlotX = recipeListX + (float)recipeSlotCount * stride + 8.0f * scale;
|
|
float vSlotY = recipeSlotY - scrollH;
|
|
float vSlotW = slotSz + 8.0f * scale;
|
|
float vSlotH = slotSz * 3.0f + 16.0f * scale;
|
|
|
|
const MenuTextureSlot &vSlotTex = (gridSize == 3) ? invTex.craft3SlotV : invTex.craft2SlotV;
|
|
if (vSlotTex.w > 0) {
|
|
struct nk_image vImg = slotToNkImage(vSlotTex);
|
|
nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas != nullptr)
|
|
nk_draw_image(canvas, nk_rect(vSlotX, vSlotY, vSlotW, vSlotH), &vImg, nk_rgb(255, 255, 255));
|
|
}
|
|
|
|
drawRecipeGrid(ctx, gridAreaX, gridAreaY, gridSize, slotSz, stride, invTex, input);
|
|
|
|
float resultX = gridAreaX + (float)gridSize * stride + resultGap;
|
|
float resultY = gridAreaY + ((float)gridSize * stride - slotSz) * 0.5f;
|
|
drawCraftingRecipeSlot(ctx, resultX, resultY, slotSz, slotSz, invTex, input, true);
|
|
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas != nullptr) {
|
|
float arrowBaseX = gridAreaX + (float)gridSize * stride + 2.0f * scale;
|
|
float arrowBaseY = resultY + slotSz * 0.25f;
|
|
float arrowW = resultGap - 4.0f * scale;
|
|
float arrowH = slotSz * 0.5f;
|
|
nk_fill_rect(canvas, nk_rect(arrowBaseX, arrowBaseY, arrowW, arrowH),
|
|
0, nk_rgb(120, 120, 120));
|
|
}
|
|
|
|
float descAreaX = gridAreaX;
|
|
float descAreaY = gridAreaY + (float)gridSize * stride + 12.0f * scale;
|
|
|
|
drawLeftLabel(ctx, "Ingredients:", descAreaX, descAreaY, 16.0f * scale,
|
|
nk_rgb(80, 80, 80));
|
|
|
|
int ingredientDisplayCount = 4;
|
|
float ingY = descAreaY + 18.0f * scale;
|
|
for (int i = 0; i < ingredientDisplayCount; i++) {
|
|
float ix = descAreaX;
|
|
float iy = ingY + (float)i * (slotSz + 4.0f * scale);
|
|
drawSlot(ctx, ix, iy, slotSz, slotSz, invTex, false);
|
|
}
|
|
|
|
int hoveredInv = -1;
|
|
drawSlotGrid(ctx, invGridX, invGridY, INV_COLS, INV_ROWS, slotSz, stride,
|
|
invTex, input, &hoveredInv);
|
|
|
|
int hoveredHotbar = -1;
|
|
drawSlotGrid(ctx, hotbarX, hotbarY, HOTBAR_COLS, 1, slotSz, stride,
|
|
invTex, input, &hoveredHotbar);
|
|
|
|
drawLeftLabel(ctx, "Inventory", invGridX, invGridY - 16.0f * scale, 14.0f * scale,
|
|
nk_rgb(64, 64, 64));
|
|
|
|
drawControllerPrompts(ctx, winW, winH, tex);
|
|
}
|
|
nk_end(ctx);
|
|
|
|
popCleanStyle(ctx);
|
|
}
|
|
|
|
void renderCrafting2x2(nk_context *ctx, int winW, int winH,
|
|
MenuTextures &tex, InventoryMenuTextures &invTex)
|
|
{
|
|
drawCraftingCommon(ctx, winW, winH, tex, invTex,
|
|
invTex.panelCrafting2x2,
|
|
INV_PANEL_W, INV_PANEL_H,
|
|
CRAFT2_GRID, CRAFT2_TAB_COUNT,
|
|
&invTex.activeCraft2x2Tab,
|
|
getCraft2x2TabIcon, getCraft2x2TabName);
|
|
}
|
|
|
|
void renderCrafting3x3(nk_context *ctx, int winW, int winH,
|
|
MenuTextures &tex, InventoryMenuTextures &invTex)
|
|
{
|
|
drawCraftingCommon(ctx, winW, winH, tex, invTex,
|
|
invTex.panelCrafting3x3,
|
|
CRAFT3_PANEL_W, CRAFT3_PANEL_H,
|
|
CRAFT3_GRID, CRAFT3_TAB_COUNT,
|
|
&invTex.activeCraft3x3Tab,
|
|
getCraft3x3TabIcon, getCraft3x3TabName);
|
|
}
|
|
|
|
void renderCreative(nk_context *ctx, int winW, int winH,
|
|
MenuTextures &tex, InventoryMenuTextures &invTex)
|
|
{
|
|
float scaleX = (float)winW / BASE_W;
|
|
float scaleY = (float)winH / BASE_H;
|
|
float scale = (scaleX < scaleY) ? scaleX : scaleY;
|
|
|
|
float panelW = CREATIVE_PANEL_W * scale * 0.72f;
|
|
float panelH = CREATIVE_PANEL_H * scale * 0.72f;
|
|
float panelX = ((float)winW - panelW) * 0.5f;
|
|
float panelY = ((float)winH - panelH) * 0.5f;
|
|
|
|
float slotSz = SLOT_SIZE * scale * 0.72f;
|
|
float stride = SLOT_STRIDE * scale * 0.72f;
|
|
|
|
float tabW = TAB_CREATIVE_W * scale * 0.42f;
|
|
float tabH = TAB_CREATIVE_H * scale * 0.42f;
|
|
|
|
float tabRowY = panelY - tabH + 4.0f * scale;
|
|
float tabStartX = panelX + 2.0f * scale;
|
|
float tabStride = tabW + 1.0f * scale;
|
|
|
|
float iconInTab = ICON_SIZE * scale * 0.3f;
|
|
|
|
float gridAreaY = panelY + panelH * 0.1f;
|
|
float gridAreaX = panelX + panelW * 0.04f;
|
|
|
|
float hotbarY = panelY + panelH * 0.82f;
|
|
float hotbarX = panelX + (panelW - (float)HOTBAR_COLS * stride) * 0.5f;
|
|
|
|
float scrollTrackX = gridAreaX + (float)CREATIVE_COLS * stride + 8.0f * scale;
|
|
float scrollTrackY = gridAreaY;
|
|
float scrollTrackW = 12.0f * scale;
|
|
float scrollTrackH = (float)CREATIVE_ROWS * stride;
|
|
|
|
pushCleanStyle(ctx);
|
|
|
|
if (nk_begin(ctx, "CreativeMenu", nk_rect(0, 0, (float)winW, (float)winH),
|
|
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
|
|
|
|
drawDirtBg(ctx, winW, winH, tex);
|
|
drawDirtOverlay(ctx, winW, winH);
|
|
|
|
drawPanel(ctx, panelX, panelY, panelW, panelH, invTex.panelCreative8);
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
|
|
for (int i = 0; i < CREATIVE_TAB_COUNT; i++) {
|
|
float tx = tabStartX + (float)i * tabStride;
|
|
bool active = (i == invTex.activeCreativeTab);
|
|
const MenuTextureSlot &tabTex = getCreativeTabTexForIndex(invTex, i, CREATIVE_TAB_COUNT);
|
|
drawCraftingTab(ctx, tx, tabRowY, tabW, tabH, tabTex, active);
|
|
|
|
float iconX = tx + (tabW - iconInTab) * 0.5f;
|
|
float iconY = tabRowY + (tabH - iconInTab) * 0.4f;
|
|
drawTabIcon(ctx, iconX, iconY, iconInTab, getCreativeTabIcon(invTex, i));
|
|
|
|
struct nk_rect tabRect = nk_rect(tx, tabRowY, tabW, tabH);
|
|
if (nk_input_is_mouse_hovering_rect(input, tabRect) &&
|
|
nk_input_is_mouse_released(input, NK_BUTTON_LEFT))
|
|
invTex.activeCreativeTab = i;
|
|
}
|
|
|
|
drawCenteredLabel(ctx, getCreativeTabName(invTex.activeCreativeTab),
|
|
panelX, panelY + 2.0f * scale, panelW, 16.0f * scale,
|
|
nk_rgb(64, 64, 64));
|
|
|
|
int hoveredGrid = -1;
|
|
drawSlotGrid(ctx, gridAreaX, gridAreaY, CREATIVE_COLS, CREATIVE_ROWS,
|
|
slotSz, stride, invTex, input, &hoveredGrid);
|
|
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas != nullptr) {
|
|
nk_fill_rect(canvas, nk_rect(scrollTrackX, scrollTrackY, scrollTrackW, scrollTrackH),
|
|
2, nk_rgb(100, 100, 100));
|
|
|
|
float thumbH = scrollTrackH * 0.15f;
|
|
nk_fill_rect(canvas, nk_rect(scrollTrackX, scrollTrackY, scrollTrackW, thumbH),
|
|
2, nk_rgb(180, 180, 180));
|
|
}
|
|
|
|
drawLeftLabel(ctx, "Inventory", hotbarX, hotbarY - 16.0f * scale, 14.0f * scale,
|
|
nk_rgb(64, 64, 64));
|
|
|
|
int hoveredHotbar = -1;
|
|
drawSlotGrid(ctx, hotbarX, hotbarY, HOTBAR_COLS, 1, slotSz, stride,
|
|
invTex, input, &hoveredHotbar);
|
|
|
|
drawControllerPrompts(ctx, winW, winH, tex);
|
|
}
|
|
nk_end(ctx);
|
|
|
|
popCleanStyle(ctx);
|
|
}
|
|
|
|
}}
|