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

616 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 "NkBrowseMenus.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 TITLE_Y_POS = 30.0f;
static const float TITLE_H_POS = 40.0f;
static const float BTN_X = 415.0f;
static const float BTN_W = 450.0f;
static const float BTN_H = 32.0f;
static const float BTN_Y_START = 80.0f;
static const float BTN_Y_STEP = 34.0f;
static const float TAB_Y = 80.0f;
static const float TAB_H = 36.0f;
static const float TAB_W = 200.0f;
static const float TAB_SPACING = 8.0f;
static const float SKIN_PREVIEW_Y = 180.0f;
static const float SKIN_PREVIEW_W = 200.0f;
static const float SKIN_PREVIEW_H = 300.0f;
static const float SKIN_NAME_Y = 500.0f;
static const float SKIN_NAME_H = 30.0f;
static const float HTP_IMAGE_X = 640.0f;
static const float HTP_IMAGE_Y = 140.0f;
static const float HTP_IMAGE_W = 580.0f;
static const float HTP_IMAGE_H = 400.0f;
static const float HTP_TEXT_X = 40.0f;
static const float HTP_TEXT_Y = 140.0f;
static const float HTP_TEXT_W = 560.0f;
static const float SHADOW_OFF = 2.0f;
static MenuTextureSlot loadBrowseSlot(const char *path)
{
int w = 0, h = 0;
struct nk_image img = loadTextureWithSize(path, &w, &h);
return {img.handle.id, w, h};
}
static void drawShadowedText(nk_context *ctx, const char *text,
float x, float y, float w, float h,
struct nk_color color, bool centered)
{
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 = centered ? x + (w - textW) * 0.5f : x;
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(0x0F, 0x0F, 0x0F, 200));
nk_draw_text(canvas, nk_rect(textX, textY, textW, font->height),
text, len, font,
nk_rgba(0, 0, 0, 0), color);
}
static void drawShadowedTitle(nk_context *ctx, const char *title, int winW, int winH)
{
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;
float scaleY = (float)winH / BASE_H;
float y = TITLE_Y_POS * scaleY;
float h = TITLE_H_POS * scaleY;
int len = (int)strlen(title);
float textW = font->width(font->userdata, font->height, title, len);
float textX = ((float)winW - 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),
title, len, font,
nk_rgba(0, 0, 0, 0), nk_rgba(0x0F, 0x0F, 0x0F, 200));
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 drawTabButton(nk_context *ctx, const char *label,
float x, float y, float w, float h,
bool selected, BrowseMenuTextures &btex)
{
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
if (canvas == nullptr) return false;
struct nk_rect r = nk_rect(x, y, w, h);
const struct nk_input *input = &ctx->input;
bool hovering = nk_input_is_mouse_hovering_rect(input, r) != 0;
if (btex.loaded) {
const MenuTextureSlot *slot;
if (selected) {
slot = hovering ? &btex.tabOverSelected : &btex.tabNormalSelected;
} else {
slot = hovering ? &btex.tabOver : &btex.tabNormal;
}
struct nk_image img = slotToNkImage(*slot);
nk_draw_image(canvas, r, &img, nk_rgb(255, 255, 255));
} else {
struct nk_color bg = selected ? nk_rgb(60, 60, 80) : nk_rgb(40, 40, 40);
if (hovering) bg = nk_rgb(80, 80, 100);
nk_fill_rect(canvas, r, 0, bg);
nk_stroke_rect(canvas, r, 0, 1.0f, nk_rgb(100, 100, 100));
}
drawShadowedText(ctx, label, x, y, w, h, nk_rgb(255, 255, 255), true);
bool clicked = hovering && nk_input_is_mouse_released(input, NK_BUTTON_LEFT) != 0;
return clicked;
}
static bool drawListRow(nk_context *ctx, const char *label,
float x, float y, float w, float h,
bool selected, bool hasTick,
BrowseMenuTextures &btex)
{
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
if (canvas == nullptr) return false;
struct nk_rect r = nk_rect(x, y, w, h);
const struct nk_input *input = &ctx->input;
bool hovering = nk_input_is_mouse_hovering_rect(input, r) != 0;
if (btex.loaded) {
const MenuTextureSlot *slot;
if (selected || hovering)
slot = &btex.listBtnOver;
else
slot = &btex.listBtnNorm;
struct nk_image img = slotToNkImage(*slot);
nk_draw_image(canvas, r, &img, nk_rgb(255, 255, 255));
} else {
struct nk_color bg = (selected || hovering) ? nk_rgb(70, 70, 70) : nk_rgb(40, 40, 40);
nk_fill_rect(canvas, r, 0, bg);
nk_stroke_rect(canvas, r, 0, 1.0f, nk_rgb(80, 80, 80));
}
if (hasTick && btex.loaded) {
float tickS = h * 0.6f;
float tickX = x + w - tickS - 4.0f;
float tickY = y + (h - tickS) * 0.5f;
struct nk_image tickImg = slotToNkImage(btex.dlcTickSmall);
nk_draw_image(canvas, nk_rect(tickX, tickY, tickS, tickS),
&tickImg, nk_rgb(255, 255, 255));
}
drawShadowedText(ctx, label, x + 8.0f, y, w - 16.0f, h, nk_rgb(255, 255, 255), false);
bool clicked = hovering && nk_input_is_mouse_released(input, NK_BUTTON_LEFT) != 0;
return clicked;
}
bool initBrowseMenuTextures(BrowseMenuTextures &out)
{
out.tabNormal = loadBrowseSlot("../Assets/ui/skinHDGraphics/95_SkinSelect_TabNormal.png");
out.tabNormalSelected = loadBrowseSlot("../Assets/ui/skinHDGraphics/96_SkinSelect_TabNormal_Selected.png");
out.tabOver = loadBrowseSlot("../Assets/ui/skinHDGraphics/93_SkinSelect_TabOver.png");
out.tabOverSelected = loadBrowseSlot("../Assets/ui/skinHDGraphics/94_SkinSelect_TabOver_Selected.png");
out.tabBar = loadBrowseSlot("../Assets/ui/skinHDGraphics/97_SkinSelect_TabBar.png");
out.tabBarSelected = loadBrowseSlot("../Assets/ui/skinHDGraphics/98_SkinSelect_TabBar_Selected.png");
out.charBg = loadBrowseSlot("../Assets/ui/skinHDGraphics/83_CharacterBackground.png");
out.charBgSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/84_CharacterBackground_Small.png");
out.skinBottomBar = loadBrowseSlot("../Assets/ui/skinHDGraphics/79_SkinSelect_BottomBar.png");
out.skinBottomBarSelected = loadBrowseSlot("../Assets/ui/skinHDGraphics/80_SkinSelect_BottomBar_Selected.png");
out.padlock = loadBrowseSlot("../Assets/ui/skinHDGraphics/162_Padlock_Small.png");
out.listBtnNorm = loadBrowseSlot("../Assets/ui/skinHDGraphics/185_ListButton_Norm.png");
out.listBtnOver = loadBrowseSlot("../Assets/ui/skinHDGraphics/183_ListButton_Over.png");
out.listBtnOutline = loadBrowseSlot("../Assets/ui/skinHDGraphics/184_ListButton_Outline.png");
out.leaderboardBtnNorm = loadBrowseSlot("../Assets/ui/skinHDGraphics/173_LeaderboardButton_Norm.png");
out.leaderboardBtnOver = loadBrowseSlot("../Assets/ui/skinHDGraphics/172_LeaderboardButton_Over.png");
out.dlcBg = loadBrowseSlot("../Assets/ui/skinHDGraphics/165_DLCBackground.png");
out.dlcTick = loadBrowseSlot("../Assets/ui/skinHDGraphics/175_DLC_Tick.png");
out.dlcTickSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/174_DLC_TickSmall.png");
out.smallTick = loadBrowseSlot("../Assets/ui/skinHDGraphics/107_SmallTick.png");
out.lbIconWalkedSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/110_LeaderBoard_Icon_Walked_Small.png");
out.lbIconFallenSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/118_LeaderBoard_Icon_Fallen_Small.png");
out.lbIconCreeperSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/119_LeaderBoard_Icon_Creeper_Small.png");
out.lbIconZombieSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/109_LeaderBoard_Icon_Zombie_Small.png");
out.lbIconSkeletonSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/115_LeaderBoard_Icon_Skeleton_Small.png");
out.lbIconSpiderSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/113_LeaderBoard_Icon_Spider_Small.png");
out.lbIconSlimeSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/114_LeaderBoard_Icon_Slime_Small.png");
out.lbIconSpiderJockeySmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/112_LeaderBoard_Icon_SpiderJockey_Small.png");
out.lbIconZombiePigmanSmall = loadBrowseSlot("../Assets/ui/skinHDGraphics/108_LeaderBoard_Icon_ZombiePigman_Small.png");
out.lbIconWalked = loadBrowseSlot("../Assets/ui/skinHDGraphics/152_LeaderBoard_Icon_Walked.png");
out.lbIconFallen = loadBrowseSlot("../Assets/ui/skinHDGraphics/147_LeaderBoard_Icon_Fallen.png");
out.lbIconCreeper = loadBrowseSlot("../Assets/ui/skinHDGraphics/148_LeaderBoard_Icon_Creeper.png");
out.lbIconZombie = loadBrowseSlot("../Assets/ui/skinHDGraphics/151_LeaderBoard_Icon_Zombie.png");
out.lbIconSkeleton = loadBrowseSlot("../Assets/ui/skinHDGraphics/157_LeaderBoard_Icon_Skeleton.png");
out.lbIconSpider = loadBrowseSlot("../Assets/ui/skinHDGraphics/155_LeaderBoard_Icon_Spider.png");
out.lbIconSlime = loadBrowseSlot("../Assets/ui/skinHDGraphics/156_LeaderBoard_Icon_Slime.png");
out.lbIconSpiderJockey = loadBrowseSlot("../Assets/ui/skinHDGraphics/154_LeaderBoard_Icon_SpiderJockey.png");
out.lbIconZombiePigman = loadBrowseSlot("../Assets/ui/skinHDGraphics/150_LeaderBoard_Icon_ZombiePigman.png");
out.htpTrading = loadBrowseSlot("../Assets/ui/skinHDGraphics/223_HowToPlay_Trading.png");
out.htpEnderchest = loadBrowseSlot("../Assets/ui/skinHDGraphics/224_HowToPlay_Enderchest.png");
out.htpAnvil = loadBrowseSlot("../Assets/ui/skinHDGraphics/225_HowToPlay_Anvil.png");
out.htpTheEnd = loadBrowseSlot("../Assets/ui/skinHDGraphics/226_HowToPlay_TheEnd.png");
out.htpNetherPortal = loadBrowseSlot("../Assets/ui/skinHDGraphics/227_HowToPlay_NetherPortal.png");
out.htpLargeChest = loadBrowseSlot("../Assets/ui/skinHDGraphics/228_HowToPlay_LargeChest.png");
out.htpInventory = loadBrowseSlot("../Assets/ui/skinHDGraphics/229_HowToPlay_Inventory.png");
out.htpHUD = loadBrowseSlot("../Assets/ui/skinHDGraphics/230_HowToPlay_HUD.png");
out.htpFurnace = loadBrowseSlot("../Assets/ui/skinHDGraphics/231_HowToPlay_Furnace.png");
out.htpFarmingAnimals = loadBrowseSlot("../Assets/ui/skinHDGraphics/232_HowToPlay_FarmingAnimals.png");
out.htpEnchantment = loadBrowseSlot("../Assets/ui/skinHDGraphics/233_HowToPlay_Enchantment.png");
out.htpDispenser = loadBrowseSlot("../Assets/ui/skinHDGraphics/234_HowToPlay_Dispenser.png");
out.htpCreative = loadBrowseSlot("../Assets/ui/skinHDGraphics/235_HowToPlay_Creative.png");
out.htpCraftTable = loadBrowseSlot("../Assets/ui/skinHDGraphics/236_HowToPlay_CraftTable.png");
out.htpCrafting = loadBrowseSlot("../Assets/ui/skinHDGraphics/237_HowToPlay_Crafting.png");
out.htpChest = loadBrowseSlot("../Assets/ui/skinHDGraphics/238_HowToPlay_Chest.png");
out.htpBrewing = loadBrowseSlot("../Assets/ui/skinHDGraphics/239_HowToPlay_Brewing.png");
out.htpBreeding = loadBrowseSlot("../Assets/ui/skinHDGraphics/240_HowToPlay_Breeding.png");
out.loaded = true;
return true;
}
static const int SKIN_PACK_DEFAULT = 0;
static const int SKIN_PACK_FAVORITES = 1;
static const char *DEFAULT_SKIN_NAMES[] = {
"Server Selected",
"Steve",
"Tennis Steve",
"Tuxedo Steve",
"Athlete Steve",
"Scottish Steve",
"Prisoner Steve",
"Cyclist Steve",
"Boxer Steve"
};
static const int DEFAULT_SKIN_COUNT = 9;
void renderSkinSelectMenu(nk_context *ctx, int winW, int winH,
MenuTextures &tex, BrowseMenuTextures &btex)
{
static int packIndex = SKIN_PACK_DEFAULT;
static int skinIndex = 0;
static bool skinSelected = false;
float scaleX = (float)winW / BASE_W;
float scaleY = (float)winH / BASE_H;
pushCleanStyle(ctx);
if (nk_begin(ctx, "SkinSelectMenu", nk_rect(0, 0, (float)winW, (float)winH),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
drawPanoramaBg(ctx, winW, winH, tex);
drawShadowedTitle(ctx, "Change Skin", winW, winH);
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
const struct nk_input *input = &ctx->input;
float tabW = TAB_W * scaleX;
float tabH = TAB_H * scaleY;
float tabY = TAB_Y * scaleY;
const char *packLabels[] = { "Default", "Favorites" };
int packCount = 2;
float totalTabW = (float)packCount * tabW + (float)(packCount - 1) * TAB_SPACING * scaleX;
float tabStartX = ((float)winW - totalTabW) * 0.5f;
for (int i = 0; i < packCount; i++) {
float tx = tabStartX + (float)i * (tabW + TAB_SPACING * scaleX);
bool selected = (packIndex == i);
if (drawTabButton(ctx, packLabels[i], tx, tabY, tabW, tabH, selected, btex)) {
packIndex = i;
skinIndex = 0;
skinSelected = false;
}
}
if (btex.loaded && canvas != nullptr) {
float barY = tabY + tabH;
float barH = 4.0f * scaleY;
struct nk_image barImg = (packIndex == SKIN_PACK_DEFAULT)
? slotToNkImage(btex.tabBar) : slotToNkImage(btex.tabBarSelected);
nk_draw_image(canvas, nk_rect(tabStartX, barY, totalTabW, barH),
&barImg, nk_rgb(255, 255, 255));
}
float previewW = SKIN_PREVIEW_W * scaleX;
float previewH = SKIN_PREVIEW_H * scaleY;
float previewX = ((float)winW - previewW) * 0.5f;
float previewY = SKIN_PREVIEW_Y * scaleY;
if (canvas != nullptr && btex.loaded) {
struct nk_image charBgImg = slotToNkImage(btex.charBg);
nk_draw_image(canvas, nk_rect(previewX, previewY, previewW, previewH),
&charBgImg, nk_rgb(255, 255, 255));
} else if (canvas != nullptr) {
nk_fill_rect(canvas, nk_rect(previewX, previewY, previewW, previewH),
0, nk_rgba(0, 0, 0, 120));
}
int maxSkin = DEFAULT_SKIN_COUNT;
if (packIndex == SKIN_PACK_FAVORITES) maxSkin = 0;
if (skinIndex >= maxSkin && maxSkin > 0) skinIndex = 0;
if (skinIndex < 0) skinIndex = maxSkin - 1;
float nameY = SKIN_NAME_Y * scaleY;
float nameH = SKIN_NAME_H * scaleY;
float nameW = 400.0f * scaleX;
float nameX = ((float)winW - nameW) * 0.5f;
if (canvas != nullptr && btex.loaded) {
const MenuTextureSlot *barSlot = skinSelected
? &btex.skinBottomBarSelected : &btex.skinBottomBar;
struct nk_image skinBarImg = slotToNkImage(*barSlot);
nk_draw_image(canvas, nk_rect(nameX, nameY, nameW, nameH),
&skinBarImg, nk_rgb(255, 255, 255));
}
if (packIndex == SKIN_PACK_DEFAULT && maxSkin > 0) {
drawShadowedText(ctx, DEFAULT_SKIN_NAMES[skinIndex],
nameX, nameY, nameW, nameH, nk_rgb(255, 255, 255), true);
} else if (packIndex == SKIN_PACK_FAVORITES) {
drawShadowedText(ctx, "No Favorites",
nameX, nameY, nameW, nameH, nk_rgb(180, 180, 180), true);
}
if (skinSelected && canvas != nullptr) {
float selLabelY = nameY + nameH + 2.0f * scaleY;
drawShadowedText(ctx, "Selected", 0, selLabelY, (float)winW, 20.0f * scaleY,
nk_rgb(100, 255, 100), true);
}
float arrowW = 60.0f * scaleX;
float arrowH = 40.0f * scaleY;
float arrowY = previewY + (previewH - arrowH) * 0.5f;
float arrowLeftX = previewX - arrowW - 10.0f * scaleX;
float arrowRightX = previewX + previewW + 10.0f * scaleX;
if (maxSkin > 1) {
struct nk_rect leftRect = nk_rect(arrowLeftX, arrowY, arrowW, arrowH);
struct nk_rect rightRect = nk_rect(arrowRightX, arrowY, arrowW, arrowH);
bool leftHover = nk_input_is_mouse_hovering_rect(input, leftRect) != 0;
bool rightHover = nk_input_is_mouse_hovering_rect(input, rightRect) != 0;
if (drawBtn(ctx, "<", arrowLeftX, arrowY, arrowW, arrowH, leftHover, winH, tex)) {
skinIndex--;
if (skinIndex < 0) skinIndex = maxSkin - 1;
skinSelected = false;
}
if (drawBtn(ctx, ">", arrowRightX, arrowY, arrowW, arrowH, rightHover, winH, tex)) {
skinIndex++;
if (skinIndex >= maxSkin) skinIndex = 0;
skinSelected = false;
}
}
float selectBtnW = 200.0f * scaleX;
float selectBtnH = BTN_H * scaleY;
float selectBtnX = ((float)winW - selectBtnW) * 0.5f;
float selectBtnY = 560.0f * scaleY;
if (maxSkin > 0) {
struct nk_rect selRect = nk_rect(selectBtnX, selectBtnY, selectBtnW, selectBtnH);
bool selHover = nk_input_is_mouse_hovering_rect(input, selRect) != 0;
if (drawBtn(ctx, "Select", selectBtnX, selectBtnY, selectBtnW, selectBtnH, selHover, winH, tex)) {
skinSelected = true;
}
}
drawControllerPrompts(ctx, winW, winH, tex);
}
nk_end(ctx);
popCleanStyle(ctx);
}
static const int HTP_TOPIC_COUNT = 19;
static const char *HTP_TOPIC_LABELS[HTP_TOPIC_COUNT] = {
"What's New",
"Basics",
"Multiplayer",
"HUD",
"Creative Mode",
"Inventory",
"Chests",
"Crafting",
"Furnace",
"Dispenser",
"Brewing",
"Enchantment",
"Anvil",
"Farming Animals",
"Breeding Animals",
"Trading",
"Nether Portal",
"The End",
"Host Options"
};
void renderHowToPlayMenu(nk_context *ctx, int winW, int winH,
MenuTextures &tex, BrowseMenuTextures &btex)
{
static int selectedItem = -1;
static int scrollOffset = 0;
float scaleX = (float)winW / BASE_W;
float scaleY = (float)winH / BASE_H;
pushCleanStyle(ctx);
if (nk_begin(ctx, "HowToPlayMenu", nk_rect(0, 0, (float)winW, (float)winH),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
drawPanoramaBg(ctx, winW, winH, tex);
drawShadowedTitle(ctx, "How to Play", winW, winH);
float listX = BTN_X * scaleX;
float listW = BTN_W * scaleX;
float rowH = BTN_H * scaleY;
float startY = BTN_Y_START * scaleY;
float step = BTN_Y_STEP * scaleY;
float bottomMargin = 50.0f * scaleY;
int visibleCount = (int)(((float)winH - bottomMargin - startY) / step);
if (visibleCount > HTP_TOPIC_COUNT) visibleCount = HTP_TOPIC_COUNT;
int maxScroll = HTP_TOPIC_COUNT - visibleCount;
if (maxScroll < 0) maxScroll = 0;
if (scrollOffset > maxScroll) scrollOffset = maxScroll;
if (scrollOffset < 0) scrollOffset = 0;
const struct nk_input *input = &ctx->input;
struct nk_rect listArea = nk_rect(listX, startY, listW,
(float)visibleCount * step);
if (nk_input_is_mouse_hovering_rect(input, listArea)) {
if (ctx->input.mouse.scroll_delta.y < 0.0f && scrollOffset < maxScroll)
scrollOffset++;
else if (ctx->input.mouse.scroll_delta.y > 0.0f && scrollOffset > 0)
scrollOffset--;
}
for (int i = 0; i < visibleCount; i++) {
int idx = i + scrollOffset;
if (idx >= HTP_TOPIC_COUNT) break;
float btnY = startY + (float)i * step;
struct nk_rect btnRect = nk_rect(listX, btnY, listW, rowH);
bool hovering = nk_input_is_mouse_hovering_rect(input, btnRect) != 0;
if (drawBtn(ctx, HTP_TOPIC_LABELS[idx], listX, btnY, listW, rowH, hovering, winH, tex)) {
selectedItem = idx;
}
}
if (scrollOffset > 0) {
float arrowY = startY - 16.0f * scaleY;
drawShadowedText(ctx, "^", listX, arrowY, listW, 14.0f * scaleY,
nk_rgb(200, 200, 200), true);
}
if (scrollOffset < maxScroll) {
float arrowY = startY + (float)visibleCount * step + 2.0f * scaleY;
drawShadowedText(ctx, "v", listX, arrowY, listW, 14.0f * scaleY,
nk_rgb(200, 200, 200), true);
}
drawControllerPrompts(ctx, winW, winH, tex);
}
nk_end(ctx);
popCleanStyle(ctx);
}
struct HtpPageDef {
const char *title;
MenuTextureSlot *illustration;
};
void renderHowToPlayPage(nk_context *ctx, int winW, int winH,
MenuTextures &tex, BrowseMenuTextures &btex)
{
static int currentPage = 1;
HtpPageDef pages[] = {
{ "What's New", nullptr },
{ "Basics", nullptr },
{ "Multiplayer", nullptr },
{ "HUD", &btex.htpHUD },
{ "Creative Mode", &btex.htpCreative },
{ "Inventory", &btex.htpInventory },
{ "Chest", &btex.htpChest },
{ "Large Chest", &btex.htpLargeChest },
{ "Ender Chest", &btex.htpEnderchest },
{ "Crafting", &btex.htpCrafting },
{ "Craft Table", &btex.htpCraftTable },
{ "Furnace", &btex.htpFurnace },
{ "Dispenser", &btex.htpDispenser },
{ "Brewing", &btex.htpBrewing },
{ "Enchantment", &btex.htpEnchantment },
{ "Anvil", &btex.htpAnvil },
{ "Farming Animals", &btex.htpFarmingAnimals },
{ "Breeding Animals", &btex.htpBreeding },
{ "Trading", &btex.htpTrading },
{ "Nether Portal", &btex.htpNetherPortal },
{ "The End", &btex.htpTheEnd },
{ "Host Options", nullptr }
};
int pageCount = 22;
if (currentPage < 0) currentPage = 0;
if (currentPage >= pageCount) currentPage = pageCount - 1;
float scaleX = (float)winW / BASE_W;
float scaleY = (float)winH / BASE_H;
pushCleanStyle(ctx);
if (nk_begin(ctx, "HowToPlayPage", nk_rect(0, 0, (float)winW, (float)winH),
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
drawPanoramaBg(ctx, winW, winH, tex);
drawShadowedTitle(ctx, pages[currentPage].title, winW, winH);
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
if (pages[currentPage].illustration != nullptr && canvas != nullptr) {
float imgX = HTP_IMAGE_X * scaleX;
float imgY = HTP_IMAGE_Y * scaleY;
float imgW = HTP_IMAGE_W * scaleX;
float imgH = HTP_IMAGE_H * scaleY;
struct nk_image illImg = slotToNkImage(*pages[currentPage].illustration);
nk_draw_image(canvas, nk_rect(imgX, imgY, imgW, imgH),
&illImg, nk_rgb(255, 255, 255));
}
float textX = HTP_TEXT_X * scaleX;
float textY = HTP_TEXT_Y * scaleY;
float textW = HTP_TEXT_W * scaleX;
float textH = 30.0f * scaleY;
drawShadowedText(ctx, "(Page content would be rendered here)",
textX, textY, textW, textH, nk_rgb(200, 200, 200), false);
char pageLabel[32];
snprintf(pageLabel, sizeof(pageLabel), "%d / %d", currentPage + 1, pageCount);
drawShadowedText(ctx, pageLabel,
0, 620.0f * scaleY, (float)winW, 24.0f * scaleY,
nk_rgb(180, 180, 180), true);
const struct nk_input *input = &ctx->input;
float navBtnW = 120.0f * scaleX;
float navBtnH = BTN_H * scaleY;
float navY = 660.0f * scaleY;
if (currentPage > 0) {
float prevX = 40.0f * scaleX;
struct nk_rect prevRect = nk_rect(prevX, navY, navBtnW, navBtnH);
bool prevHover = nk_input_is_mouse_hovering_rect(input, prevRect) != 0;
if (drawBtn(ctx, "Previous", prevX, navY, navBtnW, navBtnH, prevHover, winH, tex)) {
currentPage--;
}
}
if (currentPage < pageCount - 1) {
float nextX = (float)winW - navBtnW - 40.0f * scaleX;
struct nk_rect nextRect = nk_rect(nextX, navY, navBtnW, navBtnH);
bool nextHover = nk_input_is_mouse_hovering_rect(input, nextRect) != 0;
if (drawBtn(ctx, "Next", nextX, navY, navBtnW, navBtnH, nextHover, winH, tex)) {
currentPage++;
}
}
drawControllerPrompts(ctx, winW, winH, tex);
}
nk_end(ctx);
popCleanStyle(ctx);
}
}}