mirror of
https://github.com/coah80/LegacyVulkEdition.git
synced 2026-07-19 06:58:07 +00:00
374 lines
13 KiB
C++
374 lines
13 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 "NkScrollingMenus.h"
|
|
#include "NkCommon.h"
|
|
#include "MenuScreens.h"
|
|
#include "NuklearBridge.h"
|
|
#include <cstring>
|
|
|
|
namespace lve { namespace ui {
|
|
|
|
static const float BASE_W = 1280.0f;
|
|
static const float BASE_H = 720.0f;
|
|
|
|
static const float CREDITS_LINE_H = 24.0f;
|
|
static const float CREDITS_HEADING_H = 36.0f;
|
|
static const float CREDITS_SECTION_H = 48.0f;
|
|
static const float CREDITS_SCROLL_SPEED = 40.0f;
|
|
static const float CREDITS_FAST_SPEED = 120.0f;
|
|
|
|
static const float POEM_LINE_H = 28.0f;
|
|
static const float POEM_SCROLL_SPEED = 30.0f;
|
|
|
|
static const float SHADOW_OFFSET = 2.0f;
|
|
|
|
static void drawShadowedCenteredText(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_OFFSET, textY + SHADOW_OFFSET, textW, font->height),
|
|
text, len, font,
|
|
nk_rgba(0, 0, 0, 0), nk_rgba(0x0F, 0x0F, 0x0F, color.a));
|
|
nk_draw_text(canvas, nk_rect(textX, textY, textW, font->height),
|
|
text, len, font,
|
|
nk_rgba(0, 0, 0, 0), color);
|
|
}
|
|
|
|
struct CreditEntry {
|
|
const char *text;
|
|
int style;
|
|
};
|
|
|
|
static const int CREDIT_STYLE_SECTION = 0;
|
|
static const int CREDIT_STYLE_HEADING = 1;
|
|
static const int CREDIT_STYLE_NAME = 2;
|
|
static const int CREDIT_STYLE_BLANK = 3;
|
|
|
|
static const int CREDIT_STYLE_SUBHEADING = 4;
|
|
|
|
static const CreditEntry CREDIT_ENTRIES[] = {
|
|
{"MOJANG", CREDIT_STYLE_SECTION},
|
|
{"", CREDIT_STYLE_BLANK},
|
|
{"Original Design", CREDIT_STYLE_HEADING},
|
|
{"Markus Persson", CREDIT_STYLE_NAME},
|
|
{"", CREDIT_STYLE_BLANK},
|
|
{"Project Manager / Producer", CREDIT_STYLE_HEADING},
|
|
{"Daniel Kaplan", CREDIT_STYLE_NAME},
|
|
{"", CREDIT_STYLE_BLANK},
|
|
{"Rest of Mojang", CREDIT_STYLE_SUBHEADING},
|
|
{"Lead PC Developer", CREDIT_STYLE_HEADING},
|
|
{"Jens Bergensten", CREDIT_STYLE_NAME},
|
|
{"Jon Kagstrom", CREDIT_STYLE_NAME},
|
|
{"CEO", CREDIT_STYLE_HEADING},
|
|
{"Carl Manneh", CREDIT_STYLE_NAME},
|
|
{"Director of Fun", CREDIT_STYLE_HEADING},
|
|
{"Lydia Winters", CREDIT_STYLE_NAME},
|
|
{"Web Content Writer", CREDIT_STYLE_HEADING},
|
|
{"Karin Severinsson", CREDIT_STYLE_NAME},
|
|
{"Customer Support", CREDIT_STYLE_HEADING},
|
|
{"Marc Watson", CREDIT_STYLE_NAME},
|
|
{"", CREDIT_STYLE_BLANK},
|
|
{"Design & Programming", CREDIT_STYLE_HEADING},
|
|
{"Aron Nieminen", CREDIT_STYLE_NAME},
|
|
{"", CREDIT_STYLE_BLANK},
|
|
{"Chief Architect", CREDIT_STYLE_HEADING},
|
|
{"Daniel Frisk", CREDIT_STYLE_NAME},
|
|
{"Code Ninja", CREDIT_STYLE_HEADING},
|
|
{"Tobias Mollstam", CREDIT_STYLE_NAME},
|
|
{"Office DJ", CREDIT_STYLE_HEADING},
|
|
{"Kristoffer Jelbring", CREDIT_STYLE_NAME},
|
|
{"Developer", CREDIT_STYLE_HEADING},
|
|
{"Leonard Axelsson", CREDIT_STYLE_NAME},
|
|
{"Bully Coordinator", CREDIT_STYLE_HEADING},
|
|
{"Jakob Porser", CREDIT_STYLE_NAME},
|
|
{"Art Developer", CREDIT_STYLE_HEADING},
|
|
{"Junkboy", CREDIT_STYLE_NAME},
|
|
{"Explosion Animator", CREDIT_STYLE_HEADING},
|
|
{"Mattis Grahm", CREDIT_STYLE_NAME},
|
|
{"Concept Art", CREDIT_STYLE_HEADING},
|
|
{"Henrik Petterson", CREDIT_STYLE_NAME},
|
|
{"Cruncher", CREDIT_STYLE_HEADING},
|
|
{"Patrick Geuder", CREDIT_STYLE_NAME},
|
|
{"Music and Sounds", CREDIT_STYLE_HEADING},
|
|
{"Daniel Rosenfeld (C418)", CREDIT_STYLE_NAME},
|
|
{"", CREDIT_STYLE_BLANK},
|
|
{"4J Studios", CREDIT_STYLE_SECTION},
|
|
{"Programming", CREDIT_STYLE_HEADING},
|
|
{"Paddy Burns", CREDIT_STYLE_NAME},
|
|
{"Richard Reavy", CREDIT_STYLE_NAME},
|
|
{"Stuart Ross", CREDIT_STYLE_NAME},
|
|
{"James Vaughan", CREDIT_STYLE_NAME},
|
|
{"Mark Hughes", CREDIT_STYLE_NAME},
|
|
{"Harry Gordon", CREDIT_STYLE_NAME},
|
|
{"Thomas Kronberg", CREDIT_STYLE_NAME},
|
|
{"Art", CREDIT_STYLE_HEADING},
|
|
{"David Keningale", CREDIT_STYLE_NAME},
|
|
{"Alan Redmond", CREDIT_STYLE_NAME},
|
|
{"Chris Reeves", CREDIT_STYLE_NAME},
|
|
{"Kate Wright", CREDIT_STYLE_NAME},
|
|
{"Michael Hansen", CREDIT_STYLE_NAME},
|
|
{"Donald Robertson", CREDIT_STYLE_NAME},
|
|
{"Jamie Keddie", CREDIT_STYLE_NAME},
|
|
{"Thomas Naylor", CREDIT_STYLE_NAME},
|
|
{"Brian Lindsay", CREDIT_STYLE_NAME},
|
|
{"Hannah Watts", CREDIT_STYLE_NAME},
|
|
{"Rebecca O'Neil", CREDIT_STYLE_NAME},
|
|
{"QA", CREDIT_STYLE_HEADING},
|
|
{"Steven Gary Woodward", CREDIT_STYLE_NAME},
|
|
{"George Vaughan", CREDIT_STYLE_NAME},
|
|
{"", CREDIT_STYLE_BLANK},
|
|
{"Special Thanks", CREDIT_STYLE_HEADING},
|
|
{"Chris van der Kuyl", CREDIT_STYLE_NAME},
|
|
{"Roni Percy", CREDIT_STYLE_NAME},
|
|
{"Anne Clarke", CREDIT_STYLE_NAME},
|
|
{"Anthony Kent", CREDIT_STYLE_NAME},
|
|
};
|
|
|
|
static const int CREDIT_ENTRY_COUNT = sizeof(CREDIT_ENTRIES) / sizeof(CREDIT_ENTRIES[0]);
|
|
|
|
static const float CREDITS_SUBHEADING_H = 40.0f;
|
|
|
|
static float creditEntryHeight(int style, float scaleY)
|
|
{
|
|
switch (style) {
|
|
case CREDIT_STYLE_SECTION: return CREDITS_SECTION_H * scaleY;
|
|
case CREDIT_STYLE_HEADING: return CREDITS_HEADING_H * scaleY;
|
|
case CREDIT_STYLE_SUBHEADING: return CREDITS_SUBHEADING_H * scaleY;
|
|
case CREDIT_STYLE_NAME: return CREDITS_LINE_H * scaleY;
|
|
case CREDIT_STYLE_BLANK: return CREDITS_LINE_H * scaleY;
|
|
default: return CREDITS_LINE_H * scaleY;
|
|
}
|
|
}
|
|
|
|
static struct nk_color creditEntryColor(int style)
|
|
{
|
|
switch (style) {
|
|
case CREDIT_STYLE_SECTION: return nk_rgb(255, 255, 85);
|
|
case CREDIT_STYLE_HEADING: return nk_rgb(255, 170, 0);
|
|
case CREDIT_STYLE_SUBHEADING: return nk_rgb(255, 200, 50);
|
|
case CREDIT_STYLE_NAME: return nk_rgb(255, 255, 255);
|
|
default: return nk_rgba(0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
CreditsState createCreditsState()
|
|
{
|
|
CreditsState state;
|
|
state.scrollOffset = 0.0f;
|
|
state.scrollSpeed = CREDITS_SCROLL_SPEED;
|
|
state.fastScroll = false;
|
|
return state;
|
|
}
|
|
|
|
ScrollMenuAction renderCredits(nk_context *ctx, int winW, int winH, MenuTextures &tex, CreditsState &state, float dt)
|
|
{
|
|
ScrollMenuAction result = kScrollAction_None;
|
|
|
|
float scaleY = (float)winH / BASE_H;
|
|
|
|
float speed = state.fastScroll ? CREDITS_FAST_SPEED : CREDITS_SCROLL_SPEED;
|
|
state.scrollOffset += speed * scaleY * dt;
|
|
|
|
float totalH = 0.0f;
|
|
for (int i = 0; i < CREDIT_ENTRY_COUNT; i++) {
|
|
totalH += creditEntryHeight(CREDIT_ENTRIES[i].style, scaleY);
|
|
}
|
|
totalH += (float)winH;
|
|
|
|
if (state.scrollOffset > totalH) {
|
|
result = kScrollAction_Back;
|
|
}
|
|
|
|
pushCleanStyle(ctx);
|
|
|
|
if (nk_begin(ctx, "ScrollCredits", nk_rect(0, 0, (float)winW, (float)winH),
|
|
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
|
|
|
|
drawDirtBg(ctx, winW, winH, tex);
|
|
drawLogo(ctx, winW, winH, tex);
|
|
|
|
float yPos = (float)winH - state.scrollOffset;
|
|
float halfW = (float)winW;
|
|
|
|
for (int i = 0; i < CREDIT_ENTRY_COUNT; i++) {
|
|
float lineH = creditEntryHeight(CREDIT_ENTRIES[i].style, scaleY);
|
|
|
|
if (yPos + lineH > 0.0f && yPos < (float)winH) {
|
|
if (CREDIT_ENTRIES[i].style != CREDIT_STYLE_BLANK) {
|
|
drawShadowedCenteredText(ctx, CREDIT_ENTRIES[i].text,
|
|
0.0f, yPos, halfW, lineH,
|
|
creditEntryColor(CREDIT_ENTRIES[i].style));
|
|
}
|
|
}
|
|
yPos += lineH;
|
|
}
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
state.fastScroll = nk_input_is_mouse_hovering_rect(input,
|
|
nk_rect(0, 0, (float)winW, (float)winH)) != 0 &&
|
|
nk_input_is_mouse_down(input, NK_BUTTON_LEFT) != 0;
|
|
|
|
if (nk_input_is_mouse_released(input, NK_BUTTON_RIGHT) != 0) {
|
|
result = kScrollAction_Back;
|
|
}
|
|
}
|
|
nk_end(ctx);
|
|
|
|
popCleanStyle(ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
static const char *END_POEM_LINES[] = {
|
|
"I see the player you mean.",
|
|
"",
|
|
"{PLAYERNAME}?",
|
|
"",
|
|
"Yes. Take care. It has reached a higher level now. It can read our thoughts.",
|
|
"",
|
|
"That doesn't matter. It thinks we are part of the game.",
|
|
"",
|
|
"I like this player. It played well. It did not give up.",
|
|
"",
|
|
"It is reading our thoughts as though they were words on a screen.",
|
|
"",
|
|
"That is how it chooses to imagine many things, when it is deep in the dream of a game.",
|
|
"",
|
|
"Words make a wonderful interface. Very flexible. And less terrifying than staring",
|
|
"at the reality behind the screen.",
|
|
"",
|
|
"They used to hear voices. Before players could read. Back in the days when those",
|
|
"who did not play called the players combatants. And disrespected them.",
|
|
"",
|
|
"And rightly so. Their game was not a good one. And what good is a game that is not good?",
|
|
"",
|
|
"Sometimes the player created worlds that were too cruel. Sometimes it created worlds that",
|
|
"were too kind. Sometimes it built a shelter against the rain. Sometimes it just played,",
|
|
"without building anything.",
|
|
"",
|
|
"And the universe said I love you.",
|
|
"",
|
|
"And the universe said you have played the game well.",
|
|
"",
|
|
"And the universe said everything you need is within you.",
|
|
"",
|
|
"And the universe said you are stronger than you know.",
|
|
"",
|
|
"And the universe said you are the daylight.",
|
|
"",
|
|
"And the universe said you are the night.",
|
|
"",
|
|
"And the universe said the darkness you fight is within you.",
|
|
"",
|
|
"And the universe said the light you seek is within you.",
|
|
"",
|
|
"And the universe said you are not alone.",
|
|
"",
|
|
"And the universe said you are not separate from every other thing.",
|
|
"",
|
|
"And the universe said you are the universe tasting itself, talking to itself, reading its own code.",
|
|
"",
|
|
"And the universe said I love you because you are love.",
|
|
"",
|
|
"And the game was over and the player woke up from the dream. And the player began a new dream.",
|
|
"And the player dreamed again, dreamed better. And the player was the universe. And the player",
|
|
"was love.",
|
|
"",
|
|
"You are the player.",
|
|
"",
|
|
"Wake up.",
|
|
};
|
|
|
|
static const int END_POEM_LINE_COUNT = sizeof(END_POEM_LINES) / sizeof(END_POEM_LINES[0]);
|
|
|
|
EndPoemState createEndPoemState()
|
|
{
|
|
EndPoemState state;
|
|
state.scrollOffset = 0.0f;
|
|
state.scrollSpeed = POEM_SCROLL_SPEED;
|
|
state.currentParagraph = 0;
|
|
return state;
|
|
}
|
|
|
|
ScrollMenuAction renderEndPoem(nk_context *ctx, int winW, int winH, MenuTextures &tex, EndPoemState &state, float dt)
|
|
{
|
|
ScrollMenuAction result = kScrollAction_None;
|
|
|
|
float scaleY = (float)winH / BASE_H;
|
|
|
|
state.scrollOffset += state.scrollSpeed * scaleY * dt;
|
|
|
|
float lineH = POEM_LINE_H * scaleY;
|
|
float totalH = (float)END_POEM_LINE_COUNT * lineH + (float)winH;
|
|
|
|
if (state.scrollOffset > totalH) {
|
|
result = kScrollAction_Back;
|
|
}
|
|
|
|
pushCleanStyle(ctx);
|
|
|
|
if (nk_begin(ctx, "ScrollEndPoem", nk_rect(0, 0, (float)winW, (float)winH),
|
|
NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_NO_INPUT | NK_WINDOW_BACKGROUND)) {
|
|
|
|
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
|
|
if (canvas != nullptr) {
|
|
nk_fill_rect(canvas, nk_rect(0, 0, (float)winW, (float)winH), 0, nk_rgb(0, 0, 0));
|
|
}
|
|
|
|
float yPos = (float)winH - state.scrollOffset;
|
|
float textPadX = 100.0f * ((float)winW / BASE_W);
|
|
float textAreaW = (float)winW - textPadX * 2.0f;
|
|
|
|
int paragraph = 0;
|
|
for (int i = 0; i < END_POEM_LINE_COUNT; i++) {
|
|
if (yPos + lineH > 0.0f && yPos < (float)winH) {
|
|
if (strlen(END_POEM_LINES[i]) > 0) {
|
|
struct nk_color color;
|
|
if (paragraph % 2 == 0) {
|
|
color = nk_rgb(170, 170, 255);
|
|
} else {
|
|
color = nk_rgb(170, 255, 170);
|
|
}
|
|
drawShadowedCenteredText(ctx, END_POEM_LINES[i],
|
|
textPadX, yPos, textAreaW, lineH,
|
|
color);
|
|
}
|
|
}
|
|
if (strlen(END_POEM_LINES[i]) == 0) {
|
|
paragraph++;
|
|
}
|
|
yPos += lineH;
|
|
}
|
|
|
|
const struct nk_input *input = &ctx->input;
|
|
if (nk_input_is_mouse_released(input, NK_BUTTON_RIGHT) != 0) {
|
|
result = kScrollAction_Back;
|
|
}
|
|
}
|
|
nk_end(ctx);
|
|
|
|
popCleanStyle(ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
}}
|