mirror of
https://github.com/coah80/LegacyVulkEdition.git
synced 2026-07-19 06:58:07 +00:00
666 lines
25 KiB
C++
666 lines
25 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 "NkWorldMenus.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 PANEL_W = 700.0f;
|
|
|
|
static const float FIELD_H = 36.0f;
|
|
static const float FIELD_SPACING = 8.0f;
|
|
static const float LABEL_H = 20.0f;
|
|
|
|
static const float BUTTON_W = 450.0f;
|
|
static const float BUTTON_H = 40.0f;
|
|
static const float HALF_BUTTON_W = 218.0f;
|
|
|
|
static const float LIST_ITEM_H = 40.0f;
|
|
static const float LIST_PANEL_X = 40.0f;
|
|
static const float LIST_PANEL_W = 560.0f;
|
|
static const float LIST_Y_START = 90.0f;
|
|
|
|
static const float JOIN_LIST_X = 660.0f;
|
|
static const float JOIN_LIST_W = 560.0f;
|
|
|
|
static const float BOTTOM_BTN_Y_OFFSET = 40.0f;
|
|
|
|
static const float SHADOW_OFF = 2.0f;
|
|
|
|
static const char *DIFFICULTY_NAMES[4] = {
|
|
"Peaceful",
|
|
"Easy",
|
|
"Normal",
|
|
"Hard"
|
|
};
|
|
|
|
static void drawShadowLabel(nk_context *ctx, const char *text,
|
|
float x, float y, float w,
|
|
struct nk_color fg)
|
|
{
|
|
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);
|
|
struct nk_color shadow = nk_rgb(0x3F, 0x3F, 0x3F);
|
|
nk_draw_text(canvas, nk_rect(x + SHADOW_OFF, y + SHADOW_OFF, w, font->height),
|
|
text, len, font, nk_rgba(0, 0, 0, 0), shadow);
|
|
nk_draw_text(canvas, nk_rect(x, y, w, font->height),
|
|
text, len, font, nk_rgba(0, 0, 0, 0), fg);
|
|
}
|
|
|
|
static void drawShadowLabelCentered(nk_context *ctx, const char *text,
|
|
float x, float y, float w, float h,
|
|
struct nk_color fg)
|
|
{
|
|
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;
|
|
|
|
struct nk_color shadow = nk_rgb(0x3F, 0x3F, 0x3F);
|
|
nk_draw_text(canvas, nk_rect(textX + SHADOW_OFF, textY + SHADOW_OFF, textW, font->height),
|
|
text, len, font, nk_rgba(0, 0, 0, 0), shadow);
|
|
nk_draw_text(canvas, nk_rect(textX, textY, textW, font->height),
|
|
text, len, font, nk_rgba(0, 0, 0, 0), fg);
|
|
}
|
|
|
|
static void drawShadowTitle(nk_context *ctx, const char *title,
|
|
float scaleY, int winW)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
nk_font *titleNkFont = getTitleFont();
|
|
const struct nk_user_font *font = titleNkFont ? &titleNkFont->handle : ctx->style.font;
|
|
if (font == nullptr) return;
|
|
|
|
int len = (int)strlen(title);
|
|
float textW = font->width(font->userdata, font->height, title, len);
|
|
float textX = ((float)winW - textW) * 0.5f;
|
|
float textY = 30.0f * scaleY;
|
|
|
|
struct nk_color shadow = nk_rgb(0x3F, 0x3F, 0x3F);
|
|
nk_draw_text(canvas, nk_rect(textX + SHADOW_OFF, textY + SHADOW_OFF, textW, font->height),
|
|
title, len, font, nk_rgba(0, 0, 0, 0), shadow);
|
|
nk_draw_text(canvas, nk_rect(textX, textY, textW, font->height),
|
|
title, len, font, nk_rgba(0, 0, 0, 0), nk_rgb(255, 255, 255));
|
|
}
|
|
|
|
static bool drawStyledTextInput(nk_context *ctx, const char *content,
|
|
float x, float y, float w, float h,
|
|
bool selected, MenuTextures &tex)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return false;
|
|
|
|
struct nk_rect fieldRect = nk_rect(x, y, w, h);
|
|
|
|
if (tex.textInputBg.w > 0) {
|
|
struct nk_image bgImg = slotToNkImage(tex.textInputBg);
|
|
nk_draw_image(canvas, fieldRect, &bgImg, nk_rgb(255, 255, 255));
|
|
} else {
|
|
nk_fill_rect(canvas, fieldRect, 0, nk_rgb(0, 0, 0));
|
|
}
|
|
|
|
if (selected && tex.textInputSelectedBorder.w > 0) {
|
|
struct nk_image selImg = slotToNkImage(tex.textInputSelectedBorder);
|
|
nk_draw_image(canvas, fieldRect, &selImg, nk_rgb(255, 255, 255));
|
|
} else if (tex.textInputBorder.w > 0) {
|
|
struct nk_image borderImg = slotToNkImage(tex.textInputBorder);
|
|
nk_draw_image(canvas, fieldRect, &borderImg, nk_rgb(255, 255, 255));
|
|
} else {
|
|
struct nk_color borderCol = selected ? nk_rgb(160, 160, 255) : nk_rgb(160, 160, 160);
|
|
float thick = selected ? 2.0f : 1.0f;
|
|
nk_stroke_rect(canvas, fieldRect, 0, thick, borderCol);
|
|
}
|
|
|
|
const struct nk_user_font *font = ctx->style.font;
|
|
if (font != nullptr) {
|
|
int len = (int)strlen(content);
|
|
float pad = 6.0f;
|
|
float textX = x + pad;
|
|
float textY = y + (h - font->height) * 0.5f;
|
|
float maxW = w - pad * 2.0f;
|
|
|
|
nk_draw_text(canvas, nk_rect(textX + SHADOW_OFF, textY + SHADOW_OFF, maxW, font->height),
|
|
content, len, font, nk_rgba(0, 0, 0, 0), nk_rgb(0x3F, 0x3F, 0x3F));
|
|
nk_draw_text(canvas, nk_rect(textX, textY, maxW, font->height),
|
|
content, len, font, nk_rgba(0, 0, 0, 0), nk_rgb(224, 224, 224));
|
|
|
|
if (selected) {
|
|
float caretX = textX + font->width(font->userdata, font->height, content, len);
|
|
if (caretX > x + w - 8.0f) caretX = x + w - 8.0f;
|
|
|
|
if (tex.textInputCaret.w > 0) {
|
|
struct nk_image caretImg = slotToNkImage(tex.textInputCaret);
|
|
float caretW = 2.0f;
|
|
float caretH = h - 8.0f;
|
|
nk_draw_image(canvas, nk_rect(caretX, y + 4.0f, caretW, caretH),
|
|
&caretImg, nk_rgb(255, 255, 255));
|
|
} else {
|
|
nk_stroke_line(canvas, caretX, y + 4.0f, caretX, y + h - 4.0f,
|
|
1.0f, nk_rgb(255, 255, 255));
|
|
}
|
|
}
|
|
}
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
bool hovering = nk_input_is_mouse_hovering_rect(input, fieldRect) != 0;
|
|
bool clicked = hovering && nk_input_is_mouse_released(input, NK_BUTTON_LEFT) != 0;
|
|
|
|
return clicked;
|
|
}
|
|
|
|
static void drawSliderTrack(nk_context *ctx, float x, float y, float w, float h,
|
|
int value, int maxVal, MenuTextures &tex)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return;
|
|
|
|
struct nk_rect trackRect = nk_rect(x, y, w, h);
|
|
|
|
if (tex.sliderBackground.w > 0) {
|
|
struct nk_image bgImg = slotToNkImage(tex.sliderBackground);
|
|
nk_draw_image(canvas, trackRect, &bgImg, nk_rgb(255, 255, 255));
|
|
} else {
|
|
nk_fill_rect(canvas, trackRect, 0, nk_rgb(0, 0, 0));
|
|
nk_stroke_rect(canvas, trackRect, 0, 1.0f, nk_rgb(160, 160, 160));
|
|
}
|
|
|
|
if (maxVal > 0) {
|
|
float inset = 2.0f;
|
|
float fillW = (w - inset * 2.0f) * ((float)value / (float)maxVal);
|
|
struct nk_rect fillRect = nk_rect(x + inset, y + inset, fillW, h - inset * 2.0f);
|
|
|
|
if (tex.sliderTrackActive.w > 0) {
|
|
struct nk_image activeImg = slotToNkImage(tex.sliderTrackActive);
|
|
nk_draw_image(canvas, fillRect, &activeImg, nk_rgb(255, 255, 255));
|
|
} else {
|
|
nk_fill_rect(canvas, fillRect, 0, nk_rgb(60, 120, 60));
|
|
}
|
|
|
|
float thumbW = 8.0f;
|
|
float thumbX = x + inset + fillW - thumbW * 0.5f;
|
|
if (thumbX < x) thumbX = x;
|
|
if (thumbX + thumbW > x + w) thumbX = x + w - thumbW;
|
|
|
|
if (tex.sliderThumb.w > 0) {
|
|
struct nk_image thumbImg = slotToNkImage(tex.sliderThumb);
|
|
nk_draw_image(canvas, nk_rect(thumbX, y, thumbW, h),
|
|
&thumbImg, nk_rgb(255, 255, 255));
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool drawShadowListItem(nk_context *ctx, const char *label,
|
|
float x, float y, float w, float h,
|
|
bool selected, bool isHovered)
|
|
{
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas == nullptr) return false;
|
|
|
|
struct nk_rect itemRect = nk_rect(x, y, w, h);
|
|
|
|
if (selected) {
|
|
nk_fill_rect(canvas, itemRect, 0, nk_rgb(60, 60, 100));
|
|
} else if (isHovered) {
|
|
nk_fill_rect(canvas, itemRect, 0, nk_rgb(50, 50, 70));
|
|
} else {
|
|
nk_fill_rect(canvas, itemRect, 0, nk_rgba(0, 0, 0, 120));
|
|
}
|
|
|
|
nk_stroke_rect(canvas, itemRect, 0, 1.0f, nk_rgb(80, 80, 80));
|
|
|
|
const struct nk_user_font *font = ctx->style.font;
|
|
if (font != nullptr) {
|
|
int len = (int)strlen(label);
|
|
float textX = x + 8.0f;
|
|
float textY = y + (h - font->height) * 0.5f;
|
|
float maxW = w - 16.0f;
|
|
|
|
nk_draw_text(canvas, nk_rect(textX + SHADOW_OFF, textY + SHADOW_OFF, maxW, font->height),
|
|
label, len, font, nk_rgba(0, 0, 0, 0), nk_rgb(0x3F, 0x3F, 0x3F));
|
|
nk_draw_text(canvas, nk_rect(textX, textY, maxW, font->height),
|
|
label, len, font, nk_rgba(0, 0, 0, 0), nk_rgb(255, 255, 255));
|
|
}
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
bool hovering = nk_input_is_mouse_hovering_rect(input, itemRect) != 0;
|
|
bool clicked = hovering && nk_input_is_mouse_released(input, NK_BUTTON_LEFT) != 0;
|
|
|
|
return clicked;
|
|
}
|
|
|
|
WorldMenuAction renderCreateWorld(nk_context *ctx, int winW, int winH,
|
|
MenuTextures &tex, CreateWorldState &state)
|
|
{
|
|
WorldMenuAction result = kWorldAction_None;
|
|
|
|
float scaleX = (float)winW / BASE_W;
|
|
float scaleY = (float)winH / BASE_H;
|
|
|
|
pushCleanStyle(ctx);
|
|
|
|
if (nk_begin(ctx, "CreateWorldMenu", nk_rect(0, 0, (float)winW, (float)winH),
|
|
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
|
|
|
|
drawPanoramaBg(ctx, winW, winH, tex);
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
|
|
float panelW = PANEL_W * scaleX;
|
|
float panelX = ((float)winW - panelW) * 0.5f;
|
|
float curY = 80.0f * scaleY;
|
|
|
|
float fieldH = FIELD_H * scaleY;
|
|
float labelH = LABEL_H * scaleY;
|
|
float spacing = FIELD_SPACING * scaleY;
|
|
|
|
drawShadowTitle(ctx, "Create New World", scaleY, winW);
|
|
|
|
drawShadowLabel(ctx, "World Name", panelX, curY, panelW, nk_rgb(160, 160, 160));
|
|
curY += labelH;
|
|
|
|
if (drawStyledTextInput(ctx, state.worldName, panelX, curY, panelW, fieldH,
|
|
state.activeField == kField_WorldName, tex)) {
|
|
state.activeField = kField_WorldName;
|
|
}
|
|
curY += fieldH + spacing;
|
|
|
|
drawShadowLabel(ctx, "Seed for the World Generator (Leave blank for random)",
|
|
panelX, curY, panelW, nk_rgb(160, 160, 160));
|
|
curY += labelH;
|
|
|
|
if (drawStyledTextInput(ctx, state.seed, panelX, curY, panelW, fieldH,
|
|
state.activeField == kField_Seed, tex)) {
|
|
state.activeField = kField_Seed;
|
|
}
|
|
curY += fieldH + spacing * 2.0f;
|
|
|
|
float btnW = BUTTON_W * scaleX;
|
|
float btnH = BUTTON_H * scaleY;
|
|
float btnX = ((float)winW - btnW) * 0.5f;
|
|
|
|
const char *gameModeLabel = state.survivalMode
|
|
? "Game Mode: Survival"
|
|
: "Game Mode: Creative";
|
|
|
|
struct nk_rect gmRect = nk_rect(btnX, curY, btnW, btnH);
|
|
bool gmHover = nk_input_is_mouse_hovering_rect(input, gmRect) != 0;
|
|
if (drawBtn(ctx, gameModeLabel, btnX, curY, btnW, btnH, gmHover, winH, tex)) {
|
|
result = kWorldAction_ToggleGameMode;
|
|
}
|
|
curY += btnH + spacing;
|
|
|
|
char diffLabel[64];
|
|
snprintf(diffLabel, sizeof(diffLabel), "Difficulty: %s", DIFFICULTY_NAMES[state.difficulty]);
|
|
|
|
drawShadowLabelCentered(ctx, diffLabel, btnX, curY, btnW, labelH, nk_rgb(255, 255, 255));
|
|
curY += labelH + 2.0f * scaleY;
|
|
|
|
float sliderH = 16.0f * scaleY;
|
|
drawSliderTrack(ctx, btnX, curY, btnW, sliderH, state.difficulty, 3, tex);
|
|
|
|
struct nk_rect sliderRect = nk_rect(btnX, curY, btnW, sliderH);
|
|
bool sliderHover = nk_input_is_mouse_hovering_rect(input, sliderRect) != 0;
|
|
if (sliderHover && nk_input_is_mouse_released(input, NK_BUTTON_LEFT)) {
|
|
float mouseX = input->mouse.pos.x;
|
|
float rel = (mouseX - btnX) / btnW;
|
|
if (rel < 0.0f) rel = 0.0f;
|
|
if (rel > 1.0f) rel = 1.0f;
|
|
state.difficulty = (int)(rel * 3.0f + 0.5f);
|
|
if (state.difficulty > 3) state.difficulty = 3;
|
|
}
|
|
curY += sliderH + spacing * 2.0f;
|
|
|
|
struct nk_rect moRect = nk_rect(btnX, curY, btnW, btnH);
|
|
bool moHover = nk_input_is_mouse_hovering_rect(input, moRect) != 0;
|
|
if (drawBtn(ctx, "More Options...", btnX, curY, btnW, btnH, moHover, winH, tex)) {
|
|
result = kWorldAction_MoreOptions;
|
|
}
|
|
curY += btnH + spacing;
|
|
|
|
struct nk_rect cwRect = nk_rect(btnX, curY, btnW, btnH);
|
|
bool cwHover = nk_input_is_mouse_hovering_rect(input, cwRect) != 0;
|
|
if (drawBtn(ctx, "Create New World", btnX, curY, btnW, btnH, cwHover, winH, tex)) {
|
|
result = kWorldAction_CreateWorld;
|
|
}
|
|
curY += btnH + spacing;
|
|
|
|
float backY = (float)winH - BOTTOM_BTN_Y_OFFSET * scaleY - btnH;
|
|
struct nk_rect backRect = nk_rect(btnX, backY, btnW, btnH);
|
|
bool backHover = nk_input_is_mouse_hovering_rect(input, backRect) != 0;
|
|
if (drawBtn(ctx, "Cancel", btnX, backY, btnW, btnH, backHover, winH, tex)) {
|
|
result = kWorldAction_Back;
|
|
}
|
|
|
|
drawControllerPrompts(ctx, winW, winH, tex);
|
|
}
|
|
nk_end(ctx);
|
|
|
|
popCleanStyle(ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
WorldMenuAction renderLoadMenu(nk_context *ctx, int winW, int winH,
|
|
MenuTextures &tex, LoadMenuState &state)
|
|
{
|
|
WorldMenuAction result = kWorldAction_None;
|
|
|
|
float scaleX = (float)winW / BASE_W;
|
|
float scaleY = (float)winH / BASE_H;
|
|
|
|
pushCleanStyle(ctx);
|
|
|
|
if (nk_begin(ctx, "LoadMenuScreen", nk_rect(0, 0, (float)winW, (float)winH),
|
|
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
|
|
|
|
drawPanoramaBg(ctx, winW, winH, tex);
|
|
drawLogo(ctx, winW, winH, tex);
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
|
|
float panelW = PANEL_W * scaleX;
|
|
float panelX = ((float)winW - panelW) * 0.5f;
|
|
float curY = 80.0f * scaleY;
|
|
|
|
float itemH = LIST_ITEM_H * scaleY;
|
|
float spacing = FIELD_SPACING * scaleY;
|
|
float btnH = BUTTON_H * scaleY;
|
|
|
|
drawShadowTitle(ctx, "Load Saved World", scaleY, winW);
|
|
|
|
int visibleItems = 8;
|
|
float listH = itemH * (float)visibleItems;
|
|
|
|
if (state.itemCount == 0) {
|
|
drawShadowLabelCentered(ctx, "No saved worlds", panelX, curY, panelW, listH,
|
|
nk_rgb(160, 160, 160));
|
|
} else {
|
|
for (int i = 0; i < state.itemCount && i < visibleItems; i++) {
|
|
int idx = i + state.scrollOffset;
|
|
if (idx >= state.itemCount) break;
|
|
|
|
float itemY = curY + (float)i * itemH;
|
|
bool isSelected = (idx == state.selectedIndex);
|
|
|
|
char itemLabel[64];
|
|
snprintf(itemLabel, sizeof(itemLabel), "World %d", idx + 1);
|
|
|
|
struct nk_rect itemRect = nk_rect(panelX, itemY, panelW, itemH);
|
|
bool itemHover = nk_input_is_mouse_hovering_rect(input, itemRect) != 0;
|
|
|
|
if (drawShadowListItem(ctx, itemLabel, panelX, itemY, panelW, itemH,
|
|
isSelected, itemHover)) {
|
|
state.selectedIndex = idx;
|
|
result = kWorldAction_SelectSave;
|
|
}
|
|
}
|
|
}
|
|
curY += listH + spacing * 2.0f;
|
|
|
|
float halfBtnW = HALF_BUTTON_W * scaleX;
|
|
float btnGap = 14.0f * scaleX;
|
|
float threeW = halfBtnW * 3.0f + btnGap * 2.0f;
|
|
float threeX = ((float)winW - threeW) * 0.5f;
|
|
|
|
struct nk_rect loadRect = nk_rect(threeX, curY, halfBtnW, btnH);
|
|
bool loadHover = nk_input_is_mouse_hovering_rect(input, loadRect) != 0;
|
|
if (drawBtn(ctx, "Load", threeX, curY, halfBtnW, btnH, loadHover, winH, tex)) {
|
|
result = kWorldAction_LoadWorld;
|
|
}
|
|
|
|
float delX = threeX + halfBtnW + btnGap;
|
|
struct nk_rect delRect = nk_rect(delX, curY, halfBtnW, btnH);
|
|
bool delHover = nk_input_is_mouse_hovering_rect(input, delRect) != 0;
|
|
if (drawBtn(ctx, "Delete", delX, curY, halfBtnW, btnH, delHover, winH, tex)) {
|
|
result = kWorldAction_DeleteSave;
|
|
}
|
|
|
|
float renX = delX + halfBtnW + btnGap;
|
|
struct nk_rect renRect = nk_rect(renX, curY, halfBtnW, btnH);
|
|
bool renHover = nk_input_is_mouse_hovering_rect(input, renRect) != 0;
|
|
if (drawBtn(ctx, "Rename", renX, curY, halfBtnW, btnH, renHover, winH, tex)) {
|
|
result = kWorldAction_RenameSave;
|
|
}
|
|
curY += btnH + spacing;
|
|
|
|
float backBtnW = BUTTON_W * scaleX;
|
|
float backX = ((float)winW - backBtnW) * 0.5f;
|
|
float backY = (float)winH - BOTTOM_BTN_Y_OFFSET * scaleY - btnH;
|
|
struct nk_rect backRect = nk_rect(backX, backY, backBtnW, btnH);
|
|
bool backHover = nk_input_is_mouse_hovering_rect(input, backRect) != 0;
|
|
if (drawBtn(ctx, "Cancel", backX, backY, backBtnW, btnH, backHover, winH, tex)) {
|
|
result = kWorldAction_Back;
|
|
}
|
|
|
|
drawControllerPrompts(ctx, winW, winH, tex);
|
|
}
|
|
nk_end(ctx);
|
|
|
|
popCleanStyle(ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
WorldMenuAction renderLoadOrJoin(nk_context *ctx, int winW, int winH,
|
|
MenuTextures &tex, LoadMenuState &state)
|
|
{
|
|
WorldMenuAction result = kWorldAction_None;
|
|
|
|
float scaleX = (float)winW / BASE_W;
|
|
float scaleY = (float)winH / BASE_H;
|
|
|
|
pushCleanStyle(ctx);
|
|
|
|
if (nk_begin(ctx, "LoadOrJoinMenu", nk_rect(0, 0, (float)winW, (float)winH),
|
|
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
|
|
|
|
drawPanoramaBg(ctx, winW, winH, tex);
|
|
drawLogo(ctx, winW, winH, tex);
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
|
|
float listX = LIST_PANEL_X * scaleX;
|
|
float listW = LIST_PANEL_W * scaleX;
|
|
float listStartY = LIST_Y_START * scaleY;
|
|
float itemH = LIST_ITEM_H * scaleY;
|
|
float btnH = BUTTON_H * scaleY;
|
|
|
|
drawShadowLabel(ctx, "Start Game", listX, 50.0f * scaleY, listW,
|
|
nk_rgb(255, 255, 255));
|
|
|
|
float curY = listStartY;
|
|
|
|
struct nk_rect createRect = nk_rect(listX, curY, listW, itemH);
|
|
bool createHover = nk_input_is_mouse_hovering_rect(input, createRect) != 0;
|
|
if (drawShadowListItem(ctx, "Create New World", listX, curY, listW, itemH,
|
|
false, createHover)) {
|
|
result = kWorldAction_CreateNewWorld;
|
|
}
|
|
curY += itemH;
|
|
|
|
int visibleSaves = 10;
|
|
for (int i = 0; i < state.itemCount && i < visibleSaves; i++) {
|
|
int idx = i + state.scrollOffset;
|
|
if (idx >= state.itemCount) break;
|
|
|
|
float itemY = curY + (float)i * itemH;
|
|
bool isSelected = (idx == state.selectedIndex);
|
|
|
|
char itemLabel[64];
|
|
snprintf(itemLabel, sizeof(itemLabel), "World %d", idx + 1);
|
|
|
|
struct nk_rect itemRect = nk_rect(listX, itemY, listW, itemH);
|
|
bool itemHover = nk_input_is_mouse_hovering_rect(input, itemRect) != 0;
|
|
|
|
if (drawShadowListItem(ctx, itemLabel, listX, itemY, listW, itemH,
|
|
isSelected, itemHover)) {
|
|
state.selectedIndex = idx;
|
|
result = kWorldAction_PlayGame;
|
|
}
|
|
}
|
|
|
|
float joinX = JOIN_LIST_X * scaleX;
|
|
float joinW = JOIN_LIST_W * scaleX;
|
|
|
|
drawShadowLabel(ctx, "Join Game", joinX, 50.0f * scaleY, joinW,
|
|
nk_rgb(255, 255, 255));
|
|
|
|
drawShadowLabelCentered(ctx, "No games found", joinX, listStartY, joinW, itemH * 3.0f,
|
|
nk_rgb(160, 160, 160));
|
|
|
|
float backBtnW = BUTTON_W * scaleX;
|
|
float backX = ((float)winW - backBtnW) * 0.5f;
|
|
float backY = (float)winH - BOTTOM_BTN_Y_OFFSET * scaleY - btnH;
|
|
struct nk_rect backRect = nk_rect(backX, backY, backBtnW, btnH);
|
|
bool backHover = nk_input_is_mouse_hovering_rect(input, backRect) != 0;
|
|
if (drawBtn(ctx, "Cancel", backX, backY, backBtnW, btnH, backHover, winH, tex)) {
|
|
result = kWorldAction_Back;
|
|
}
|
|
|
|
drawControllerPrompts(ctx, winW, winH, tex);
|
|
}
|
|
nk_end(ctx);
|
|
|
|
popCleanStyle(ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
WorldMenuAction renderJoinMenu(nk_context *ctx, int winW, int winH,
|
|
MenuTextures &tex, JoinMenuState &state)
|
|
{
|
|
WorldMenuAction result = kWorldAction_None;
|
|
|
|
float scaleX = (float)winW / BASE_W;
|
|
float scaleY = (float)winH / BASE_H;
|
|
|
|
pushCleanStyle(ctx);
|
|
|
|
if (nk_begin(ctx, "JoinMenuScreen", nk_rect(0, 0, (float)winW, (float)winH),
|
|
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
|
|
|
|
drawPanoramaBg(ctx, winW, winH, tex);
|
|
drawLogo(ctx, winW, winH, tex);
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
|
|
float panelW = PANEL_W * scaleX;
|
|
float panelX = ((float)winW - panelW) * 0.5f;
|
|
float curY = 80.0f * scaleY;
|
|
|
|
float itemH = LIST_ITEM_H * scaleY;
|
|
float spacing = FIELD_SPACING * scaleY;
|
|
float labelH = LABEL_H * scaleY;
|
|
float btnH = BUTTON_H * scaleY;
|
|
|
|
drawShadowTitle(ctx, "Join Game", scaleY, winW);
|
|
|
|
drawShadowLabel(ctx, "Players", panelX, curY, panelW, nk_rgb(160, 160, 160));
|
|
curY += labelH;
|
|
|
|
int visiblePlayers = 4;
|
|
float playerListH = itemH * (float)visiblePlayers;
|
|
|
|
if (state.itemCount == 0) {
|
|
drawShadowLabelCentered(ctx, "No players", panelX, curY, panelW, playerListH,
|
|
nk_rgb(160, 160, 160));
|
|
} else {
|
|
for (int i = 0; i < state.itemCount && i < visiblePlayers; i++) {
|
|
int idx = i + state.scrollOffset;
|
|
if (idx >= state.itemCount) break;
|
|
|
|
float itemY = curY + (float)i * itemH;
|
|
bool isSelected = (idx == state.selectedIndex);
|
|
|
|
char playerLabel[64];
|
|
snprintf(playerLabel, sizeof(playerLabel), "Player %d", idx + 1);
|
|
|
|
struct nk_rect itemRect = nk_rect(panelX, itemY, panelW, itemH);
|
|
bool itemHover = nk_input_is_mouse_hovering_rect(input, itemRect) != 0;
|
|
|
|
drawShadowListItem(ctx, playerLabel, panelX, itemY, panelW, itemH,
|
|
isSelected, itemHover);
|
|
}
|
|
}
|
|
curY += playerListH + spacing;
|
|
|
|
float labelColW = panelW * 0.5f;
|
|
|
|
struct { const char *label; const char *value; } infoRows[] = {
|
|
{"Difficulty:", "Normal"},
|
|
{"Game Type:", "Survival"},
|
|
{"Gamertags:", "On"},
|
|
{"Generate Structures:", "On"},
|
|
{"Level Type:", "Normal"},
|
|
{"PvP:", "On"},
|
|
{"Trust Players:", "On"},
|
|
{"TNT Explodes:", "On"},
|
|
{"Fire Spreads:", "On"}
|
|
};
|
|
|
|
int rowCount = 9;
|
|
float rowH = labelH + 4.0f * scaleY;
|
|
|
|
for (int i = 0; i < rowCount; i++) {
|
|
float rowY = curY + (float)i * rowH;
|
|
drawShadowLabel(ctx, infoRows[i].label, panelX, rowY, labelColW,
|
|
nk_rgb(160, 160, 160));
|
|
drawShadowLabel(ctx, infoRows[i].value, panelX + labelColW, rowY, labelColW,
|
|
nk_rgb(255, 255, 255));
|
|
}
|
|
curY += (float)rowCount * rowH + spacing * 2.0f;
|
|
|
|
float btnW = BUTTON_W * scaleX;
|
|
float btnX = ((float)winW - btnW) * 0.5f;
|
|
|
|
struct nk_rect joinRect = nk_rect(btnX, curY, btnW, btnH);
|
|
bool joinHover = nk_input_is_mouse_hovering_rect(input, joinRect) != 0;
|
|
if (drawBtn(ctx, "Join Game", btnX, curY, btnW, btnH, joinHover, winH, tex)) {
|
|
result = kWorldAction_JoinGame;
|
|
}
|
|
|
|
float backY = (float)winH - BOTTOM_BTN_Y_OFFSET * scaleY - btnH;
|
|
struct nk_rect backRect = nk_rect(btnX, backY, btnW, btnH);
|
|
bool backHover = nk_input_is_mouse_hovering_rect(input, backRect) != 0;
|
|
if (drawBtn(ctx, "Cancel", btnX, backY, btnW, btnH, backHover, winH, tex)) {
|
|
result = kWorldAction_Back;
|
|
}
|
|
|
|
drawControllerPrompts(ctx, winW, winH, tex);
|
|
}
|
|
nk_end(ctx);
|
|
|
|
popCleanStyle(ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
}}
|