Files
coah80-LegacyVulkEdition/Minecraft.Client/CrossPlatform/NkGameMenus2.cpp

467 lines
17 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 "NkGameMenus.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 BUTTON_X = 415.0f;
static const float BUTTON_W = 450.0f;
static const float BUTTON_H = 40.0f;
static const float BUTTON_Y_START = 200.0f;
static const float BUTTON_Y_STEP = 50.0f;
static const float TITLE_Y = 120.0f;
static const float TITLE_H = 50.0f;
static const float KB_KEY_SIZE = 48.0f;
static const float KB_KEY_GAP = 4.0f;
static const float KB_INPUT_H = 40.0f;
static const float QUADRANT_W = 300.0f;
static const float QUADRANT_H = 360.0f;
static const float QUADRANT_GAP = 20.0f;
GameMenuAction renderReinstallMenu(nk_context *ctx, int winW, int winH,
MenuTextures &tex, ReinstallMenuState &state)
{
GameMenuAction result = kGameAction_None;
float scaleX = (float)winW / BASE_W;
float scaleY = (float)winH / BASE_H;
pushCleanStyle(ctx);
if (nk_begin(ctx, "ReinstallMenu", nk_rect(0, 0, (float)winW, (float)winH),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
drawDirtBg(ctx, winW, winH, tex);
drawTitle(ctx, "Reinstall", winW, winH, TITLE_Y, TITLE_H);
static const int BTN_COUNT = 6;
static const char *LABELS[BTN_COUNT] = {
"Reinstall Theme",
"Reinstall Gamerpic 1",
"Reinstall Gamerpic 2",
"Reinstall Avatar Item 1",
"Reinstall Avatar Item 2",
"Reinstall Avatar Item 3"
};
static const GameMenuAction ACTIONS[BTN_COUNT] = {
kGameAction_ReinstallTheme,
kGameAction_ReinstallGamepic1,
kGameAction_ReinstallGamepic2,
kGameAction_ReinstallAvatar1,
kGameAction_ReinstallAvatar2,
kGameAction_ReinstallAvatar3
};
float btnW = BUTTON_W * scaleX;
float btnH = BUTTON_H * scaleY;
float btnX = BUTTON_X * scaleX;
float step = BUTTON_Y_STEP * scaleY;
float baseY = BUTTON_Y_START * scaleY;
const struct nk_input *input = &ctx->input;
for (int i = 0; i < BTN_COUNT; i++) {
float btnY = baseY + step * (float)i;
struct nk_rect btnRect = nk_rect(btnX, btnY, btnW, btnH);
bool hovering = nk_input_is_mouse_hovering_rect(input, btnRect) != 0;
if (drawBtn(ctx, LABELS[i], btnX, btnY, btnW, btnH, hovering, winH, tex)) {
result = ACTIONS[i];
}
}
drawControllerPrompts(ctx, winW, winH, tex);
}
nk_end(ctx);
popCleanStyle(ctx);
return result;
}
GameMenuAction renderDebugOptions(nk_context *ctx, int winW, int winH,
MenuTextures &tex, DebugOptionsState &state)
{
GameMenuAction result = kGameAction_None;
float scaleX = (float)winW / BASE_W;
float scaleY = (float)winH / BASE_H;
pushCleanStyle(ctx);
if (nk_begin(ctx, "DebugOptions", nk_rect(0, 0, (float)winW, (float)winH),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
drawDirtBg(ctx, winW, winH, tex);
drawTitle(ctx, "Debug Options", winW, winH, TITLE_Y, TITLE_H);
float rowW = BUTTON_W * scaleX;
float rowH = 30.0f * scaleY;
float rowX = BUTTON_X * scaleX;
float step = 34.0f * scaleY;
float baseY = BUTTON_Y_START * scaleY;
int maxVisible = state.optionCount;
if (maxVisible > 21) maxVisible = 21;
for (int i = 0; i < maxVisible; i++) {
state.options[i] = drawCheckbox(ctx, DEBUG_OPTION_LABELS[i],
rowX, baseY + step * (float)i, rowW, rowH,
state.options[i], true, winH, tex);
}
drawControllerPrompts(ctx, winW, winH, tex);
}
nk_end(ctx);
popCleanStyle(ctx);
return result;
}
GameMenuAction renderDebugOverlay(nk_context *ctx, int winW, int winH,
MenuTextures &tex, DebugOverlayState &state)
{
GameMenuAction result = kGameAction_None;
float scaleX = (float)winW / BASE_W;
float scaleY = (float)winH / BASE_H;
pushCleanStyle(ctx);
if (nk_begin(ctx, "DebugOverlay", nk_rect(0, 0, (float)winW, (float)winH),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
drawDirtBg(ctx, winW, winH, tex);
drawTitle(ctx, "Debug Menu", winW, winH, TITLE_Y, TITLE_H);
float rowW = BUTTON_W * scaleX;
float rowH = BUTTON_H * scaleY;
float rowX = BUTTON_X * scaleX;
float step = BUTTON_Y_STEP * scaleY;
float baseY = BUTTON_Y_START * scaleY;
float halfW = rowW * 0.48f;
float gapW = rowW * 0.04f;
const struct nk_input *input = &ctx->input;
int row = 0;
char fovLabel[64];
snprintf(fovLabel, sizeof(fovLabel), "Set fov (%d)", state.fov);
state.fov = drawSlider(ctx, fovLabel,
rowX, baseY + step * (float)row, rowW, rowH,
state.fov, 0, 100, winH, tex);
row++;
char timeLabel[64];
snprintf(timeLabel, sizeof(timeLabel), "Set time (unsafe) (%d)", state.timeValue * 100);
state.timeValue = drawSlider(ctx, timeLabel,
rowX, baseY + step * (float)row, rowW, rowH,
state.timeValue, 0, 240, winH, tex);
row++;
struct nk_rect rainRect = nk_rect(rowX, baseY + step * (float)row, halfW, rowH);
bool rainHover = nk_input_is_mouse_hovering_rect(input, rainRect) != 0;
if (drawBtn(ctx, "Toggle Rain", rowX, baseY + step * (float)row, halfW, rowH, rainHover, winH, tex)) {
result = kGameAction_ToggleRain;
}
float rightX = rowX + halfW + gapW;
struct nk_rect thunderRect = nk_rect(rightX, baseY + step * (float)row, halfW, rowH);
bool thunderHover = nk_input_is_mouse_hovering_rect(input, thunderRect) != 0;
if (drawBtn(ctx, "Toggle Thunder", rightX, baseY + step * (float)row, halfW, rowH, thunderHover, winH, tex)) {
result = kGameAction_ToggleThunder;
}
row++;
struct nk_rect schRect = nk_rect(rowX, baseY + step * (float)row, halfW, rowH);
bool schHover = nk_input_is_mouse_hovering_rect(input, schRect) != 0;
if (drawBtn(ctx, "Create Schematic", rowX, baseY + step * (float)row, halfW, rowH, schHover, winH, tex)) {
result = kGameAction_CreateSchematic;
}
struct nk_rect rstRect = nk_rect(rightX, baseY + step * (float)row, halfW, rowH);
bool rstHover = nk_input_is_mouse_hovering_rect(input, rstRect) != 0;
if (drawBtn(ctx, "Reset profile tutorial progress", rightX, baseY + step * (float)row, halfW, rowH, rstHover, winH, tex)) {
result = kGameAction_ResetTutorial;
}
row++;
struct nk_rect camRect = nk_rect(rowX, baseY + step * (float)row, rowW, rowH);
bool camHover = nk_input_is_mouse_hovering_rect(input, camRect) != 0;
if (drawBtn(ctx, "Set camera", rowX, baseY + step * (float)row, rowW, rowH, camHover, winH, tex)) {
result = kGameAction_SetCamera;
}
row++;
struct nk_rect dayRect = nk_rect(rowX, baseY + step * (float)row, halfW, rowH);
bool dayHover = nk_input_is_mouse_hovering_rect(input, dayRect) != 0;
if (drawBtn(ctx, "Set Day", rowX, baseY + step * (float)row, halfW, rowH, dayHover, winH, tex)) {
result = kGameAction_SetDay;
}
struct nk_rect nightRect = nk_rect(rightX, baseY + step * (float)row, halfW, rowH);
bool nightHover = nk_input_is_mouse_hovering_rect(input, nightRect) != 0;
if (drawBtn(ctx, "Set Night", rightX, baseY + step * (float)row, halfW, rowH, nightHover, winH, tex)) {
result = kGameAction_SetNight;
}
drawControllerPrompts(ctx, winW, winH, tex);
}
nk_end(ctx);
popCleanStyle(ctx);
return result;
}
GameMenuAction renderTimerScreen(nk_context *ctx, int winW, int winH,
MenuTextures &tex, TimerState &state)
{
GameMenuAction result = kGameAction_None;
pushCleanStyle(ctx);
if (nk_begin(ctx, "TimerScreen", nk_rect(0, 0, (float)winW, (float)winH),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
if (state.showBackground) {
drawDirtBg(ctx, winW, winH, tex);
}
drawLabelCentered(ctx, "Loading...",
0.0f, 0.0f, (float)winW, (float)winH,
winH);
}
nk_end(ctx);
popCleanStyle(ctx);
return result;
}
GameMenuAction renderKeyboardScreen(nk_context *ctx, int winW, int winH,
MenuTextures &tex, KeyboardState &state)
{
GameMenuAction result = kGameAction_None;
float scaleX = (float)winW / BASE_W;
float scaleY = (float)winH / BASE_H;
pushCleanStyle(ctx);
if (nk_begin(ctx, "KeyboardScreen", nk_rect(0, 0, (float)winW, (float)winH),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
drawDirtBg(ctx, winW, winH, tex);
drawTitle(ctx, "Enter Sign Text", winW, winH, TITLE_Y, TITLE_H);
float inputW = 500.0f * scaleX;
float inputH = KB_INPUT_H * scaleY;
float inputX = ((float)winW - inputW) * 0.5f;
float inputY = BUTTON_Y_START * scaleY;
drawTextInput(ctx, state.inputText, inputX, inputY, inputW, inputH, true, winH);
float keySize = KB_KEY_SIZE * scaleX;
float keyGap = KB_KEY_GAP * scaleX;
float kbY = inputY + inputH + 20.0f * scaleY;
static const char *ROW1 = "QWERTYUIOP";
static const char *ROW2 = "ASDFGHJKL";
static const char *ROW3 = "ZXCVBNM";
const char *rows[3] = { ROW1, ROW2, ROW3 };
int rowLens[3] = { 10, 9, 7 };
const struct nk_input *input = &ctx->input;
const struct nk_user_font *font = ctx->style.font;
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
for (int r = 0; r < 3; r++) {
float totalW = (float)rowLens[r] * keySize + (float)(rowLens[r] - 1) * keyGap;
float startX = ((float)winW - totalW) * 0.5f;
float rowY = kbY + (float)r * (keySize + keyGap);
for (int k = 0; k < rowLens[r]; k++) {
float kx = startX + (float)k * (keySize + keyGap);
struct nk_rect keyRect = nk_rect(kx, rowY, keySize, keySize);
bool keyHover = nk_input_is_mouse_hovering_rect(input, keyRect) != 0;
struct nk_color bg = keyHover ? nk_rgb(80, 80, 80) : nk_rgb(50, 50, 50);
nk_fill_rect(canvas, keyRect, 4.0f, bg);
nk_stroke_rect(canvas, keyRect, 4.0f, 1.0f, nk_rgb(100, 100, 100));
if (font != nullptr) {
char ch[2];
ch[0] = state.capsLock ? rows[r][k] : (rows[r][k] + 32);
ch[1] = '\0';
float tw = font->width(font->userdata, font->height, ch, 1);
float tx = kx + (keySize - tw) * 0.5f;
float ty = rowY + (keySize - font->height) * 0.5f;
float shadowOff = 2.0f;
nk_draw_text(canvas, nk_rect(tx + shadowOff, ty + shadowOff, tw, font->height),
ch, 1, font,
nk_rgba(0, 0, 0, 0), nk_rgba(0x3F, 0x3F, 0x3F, 0xFE));
nk_draw_text(canvas, nk_rect(tx, ty, tw, font->height),
ch, 1, font,
nk_rgba(0, 0, 0, 0), nk_rgb(255, 255, 255));
}
if (keyHover && nk_input_is_mouse_released(input, NK_BUTTON_LEFT)) {
int len = (int)strlen(state.inputText);
if (len < 15) {
state.inputText[len] = state.capsLock ? rows[r][k] : (rows[r][k] + 32);
state.inputText[len + 1] = '\0';
}
}
}
}
float funcY = kbY + 3.0f * (keySize + keyGap) + keyGap;
float funcBtnW = 80.0f * scaleX;
float funcBtnH = BUTTON_H * scaleY;
float funcGap = 8.0f * scaleX;
float totalFuncW = funcBtnW * 7.0f + funcGap * 6.0f;
float funcStartX = ((float)winW - totalFuncW) * 0.5f;
static const char *FUNC_LABELS[7] = {
"Space", "Cursor Left", "Cursor Right", "Backspace", "Caps", "Symbols", "Done"
};
for (int f = 0; f < 7; f++) {
float fx = funcStartX + (float)f * (funcBtnW + funcGap);
struct nk_rect fRect = nk_rect(fx, funcY, funcBtnW, funcBtnH);
bool fHover = nk_input_is_mouse_hovering_rect(input, fRect) != 0;
if (drawBtn(ctx, FUNC_LABELS[f], fx, funcY, funcBtnW, funcBtnH, fHover, winH, tex)) {
int len = (int)strlen(state.inputText);
switch (f) {
case 0:
if (len < 15) {
state.inputText[len] = ' ';
state.inputText[len + 1] = '\0';
}
break;
case 1:
if (state.cursorPos > 0) {
state.cursorPos--;
}
break;
case 2:
if (state.cursorPos < len) {
state.cursorPos++;
}
break;
case 3:
if (len > 0) {
state.inputText[len - 1] = '\0';
}
break;
case 4:
state.capsLock = !state.capsLock;
break;
case 5:
state.symbolMode = !state.symbolMode;
break;
case 6:
result = kGameAction_KeyboardDone;
break;
}
}
}
}
nk_end(ctx);
popCleanStyle(ctx);
return result;
}
GameMenuAction renderQuadrantSignin(nk_context *ctx, int winW, int winH,
MenuTextures &tex, QuadrantSigninState &state)
{
GameMenuAction result = kGameAction_None;
float scaleX = (float)winW / BASE_W;
float scaleY = (float)winH / BASE_H;
pushCleanStyle(ctx);
if (nk_begin(ctx, "QuadrantSignin", nk_rect(0, 0, (float)winW, (float)winH),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
drawDirtBg(ctx, winW, winH, tex);
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
float quadW = QUADRANT_W * scaleX;
float quadH = QUADRANT_H * scaleY;
float gap = QUADRANT_GAP * scaleX;
float totalW = quadW * 2.0f + gap;
float totalH = quadH * 2.0f + gap;
float startX = ((float)winW - totalW) * 0.5f;
float startY = ((float)winH - totalH) * 0.5f;
for (int i = 0; i < 4; i++) {
int col = i % 2;
int rowIdx = i / 2;
float qx = startX + (float)col * (quadW + gap);
float qy = startY + (float)rowIdx * (quadH + gap);
struct nk_rect quadRect = nk_rect(qx, qy, quadW, quadH);
nk_fill_rect(canvas, quadRect, 0, nk_rgba(0, 0, 0, 120));
nk_stroke_rect(canvas, quadRect, 0, 2.0f, nk_rgb(80, 80, 80));
char playerNum[16];
snprintf(playerNum, sizeof(playerNum), "Player %d", i + 1);
drawLabelCentered(ctx, playerNum,
qx, qy + 10.0f * scaleY, quadW, 30.0f * scaleY,
winH);
if (state.controllerStatus[i] == kControllerStatus_ConnectController) {
drawLabelCentered(ctx, "Connect Controller",
qx, qy, quadW, quadH,
winH);
} else if (state.controllerStatus[i] == kControllerStatus_PressToJoin) {
drawLabelCentered(ctx, "Press to Join",
qx, qy, quadW, quadH,
winH);
} else if (state.controllerStatus[i] == kControllerStatus_PlayerDetails) {
drawLabelCentered(ctx, state.displayNames[i],
qx, qy + 40.0f * scaleY, quadW, quadH - 80.0f * scaleY,
winH);
}
}
}
nk_end(ctx);
popCleanStyle(ctx);
return result;
}
}}