Add Welcome Screen
This commit is contained in:
parent
3088a13725
commit
0e44bb5f06
@ -78,5 +78,8 @@ mcpi_option(APP_TITLE "App Title" STRING "${DEFAULT_APP_TITLE}")
|
||||
# Skin Server
|
||||
mcpi_option(SKIN_SERVER "Skin Server" STRING "https://raw.githubusercontent.com/MCPI-Revival/Skins/data")
|
||||
|
||||
# Discord Invite
|
||||
# Discord Invite URL
|
||||
mcpi_option(DISCORD_INVITE "Discord Invite URL" STRING "https://discord.gg/mcpi-revival-740287937727561779")
|
||||
|
||||
# Documentation URL
|
||||
mcpi_option(DOCUMENTATION "Documentation URL" STRING "https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/")
|
@ -67,3 +67,4 @@ TRUE Optimized Chunk Sorting
|
||||
TRUE Fix Held Item Caching
|
||||
TRUE Add Reborn Info To Options
|
||||
FALSE Track FPS
|
||||
TRUE Add Welcome Screen
|
@ -15,3 +15,4 @@
|
||||
#cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@"
|
||||
#cmakedefine MCPI_USE_QEMU
|
||||
#cmakedefine MCPI_DISCORD_INVITE "@MCPI_DISCORD_INVITE@"
|
||||
#cmakedefine MCPI_DOCUMENTATION "@MCPI_DOCUMENTATION@"
|
||||
|
@ -94,6 +94,7 @@ else()
|
||||
# title-screen
|
||||
src/title-screen/title-screen.cpp
|
||||
src/title-screen/splashes.txt # Show In IDE
|
||||
src/title-screen/welcome.cpp
|
||||
# skin
|
||||
src/skin/skin.cpp
|
||||
src/skin/loader.cpp
|
||||
|
9
mods/include/mods/options/info.h
Normal file
9
mods/include/mods/options/info.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#define CHANGELOG_FILE "CHANGELOG.md"
|
||||
|
||||
extern "C" {
|
||||
void open_url(const std::string &url);
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <mods/touch/touch.h>
|
||||
#include <mods/misc/misc.h>
|
||||
#include <mods/options/info.h>
|
||||
|
||||
#include "options-internal.h"
|
||||
|
||||
@ -63,7 +64,7 @@ static info_line info[] = {
|
||||
.get_text = []() {
|
||||
return std::string("Version: v") + reborn_get_version() + extra_version_info_full;
|
||||
},
|
||||
.button_url = "https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/CHANGELOG.md",
|
||||
.button_url = MCPI_DOCUMENTATION CHANGELOG_FILE,
|
||||
.button_text = "Changelog"
|
||||
},
|
||||
{
|
||||
@ -77,7 +78,7 @@ static info_line info[] = {
|
||||
.get_text = []() {
|
||||
return std::string("Sound Data: ") + info_sound_data_state;
|
||||
},
|
||||
.button_url = "https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/SOUND.md",
|
||||
.button_url = MCPI_DOCUMENTATION "SOUND.md",
|
||||
.button_text = "More Info"
|
||||
},
|
||||
};
|
||||
@ -148,7 +149,7 @@ static void position_info(Font *font, int width, int height) {
|
||||
}
|
||||
|
||||
// Open URL
|
||||
static void open_url(const std::string &url) {
|
||||
void open_url(const std::string &url) {
|
||||
int return_code;
|
||||
const char *command[] = {"xdg-open", url.c_str(), nullptr};
|
||||
char *output = run_command(command, &return_code, nullptr);
|
||||
|
3
mods/src/title-screen/title-screen-internal.h
Normal file
3
mods/src/title-screen/title-screen-internal.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
__attribute__((visibility("internal"))) void _init_welcome();
|
@ -11,6 +11,8 @@
|
||||
#include <mods/touch/touch.h>
|
||||
#include <mods/title-screen/title-screen.h>
|
||||
|
||||
#include "title-screen-internal.h"
|
||||
|
||||
// Improved Title Screen Background
|
||||
static void StartMenuScreen_render_Screen_renderBackground_injection(Screen *screen) {
|
||||
// Draw
|
||||
@ -165,4 +167,9 @@ void init_title_screen() {
|
||||
// Init Random
|
||||
srand(time(nullptr));
|
||||
}
|
||||
|
||||
// Init Welcome Screen
|
||||
if (feature_has("Add Welcome Screen", server_disabled)) {
|
||||
_init_welcome();
|
||||
}
|
||||
}
|
||||
|
150
mods/src/title-screen/welcome.cpp
Normal file
150
mods/src/title-screen/welcome.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include <fstream>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include <mods/home/home.h>
|
||||
#include <mods/touch/touch.h>
|
||||
#include <mods/options/info.h>
|
||||
|
||||
#include "title-screen-internal.h"
|
||||
|
||||
// Constants
|
||||
static std::string line1 = "Welcome to " MCPI_APP_BASE_TITLE " v" MCPI_VERSION "!";
|
||||
static int line_height = 8;
|
||||
static int button_width = 120;
|
||||
static int button_height = 24;
|
||||
static int line_padding = 28;
|
||||
static int button_padding = 4;
|
||||
|
||||
// Track Whether To Show Screen
|
||||
static std::string get_tracker_file() {
|
||||
return std::string(home_get()) + "/.welcome-tracker";
|
||||
}
|
||||
static bool should_show_welcome() {
|
||||
// Open File
|
||||
std::ifstream stream(get_tracker_file());
|
||||
if (!stream) {
|
||||
return true;
|
||||
}
|
||||
// Read Line
|
||||
std::string line;
|
||||
std::getline(stream, line);
|
||||
bool invalid = line != MCPI_VERSION;
|
||||
// Close File
|
||||
stream.close();
|
||||
// Return
|
||||
return invalid;
|
||||
}
|
||||
static void mark_welcome_as_shown() {
|
||||
// Open File
|
||||
std::ofstream stream(get_tracker_file());
|
||||
if (!stream) {
|
||||
return;
|
||||
}
|
||||
// Write
|
||||
stream << MCPI_VERSION << std::endl;
|
||||
// Close File
|
||||
stream.close();
|
||||
}
|
||||
|
||||
// Position GUI
|
||||
static Button *getting_started;
|
||||
static Button *changelog;
|
||||
static Button *proceed;
|
||||
static int text_y;
|
||||
static void position_screen(int width, int height) {
|
||||
// Width/Height
|
||||
getting_started->width = changelog->width = proceed->width = button_width;
|
||||
getting_started->height = changelog->height = proceed->height = button_height;
|
||||
// X
|
||||
proceed->x = (width / 2) - (button_width / 2);
|
||||
getting_started->x = (width / 2) - button_padding - button_width;
|
||||
changelog->x = (width / 2) + button_padding;
|
||||
// Y
|
||||
text_y = 0;
|
||||
getting_started->y = changelog->y = line_height + line_padding;
|
||||
proceed->y = getting_started->y + button_height + (button_padding * 2);
|
||||
// Center
|
||||
int content_height = proceed->y + proceed->height;
|
||||
int y_offset = (height - content_height) / 2;
|
||||
text_y += y_offset;
|
||||
getting_started->y += y_offset;
|
||||
changelog->y += y_offset;
|
||||
proceed->y += y_offset;
|
||||
}
|
||||
|
||||
// Welcome Screen
|
||||
CUSTOM_VTABLE(welcome_screen, Screen) {
|
||||
// Init
|
||||
vtable->init = [](__attribute__((unused)) Screen *self) {
|
||||
// Buttons
|
||||
getting_started = touch_create_button(0, "Getting Started");
|
||||
changelog = touch_create_button(1, "Changelog");
|
||||
proceed = touch_create_button(2, "Proceed");
|
||||
for (Button *button : {getting_started, changelog, proceed}) {
|
||||
self->rendered_buttons.push_back(button);
|
||||
self->selectable_buttons.push_back(button);
|
||||
}
|
||||
};
|
||||
// Rendering
|
||||
static Screen_render_t original_render = vtable->render;
|
||||
vtable->render = [](Screen *self, int x, int y, float param_1) {
|
||||
// Background
|
||||
self->renderBackground();
|
||||
// Call Original Method
|
||||
original_render(self, x, y, param_1);
|
||||
// Text
|
||||
self->drawCenteredString(self->font, &line1, self->width / 2, text_y, 0xFFFFFFFF);
|
||||
};
|
||||
// Positioning
|
||||
vtable->setupPositions = [](Screen *self) {
|
||||
position_screen(self->width, self->height);
|
||||
};
|
||||
// Cleanup
|
||||
vtable->removed = [](Screen *self) {
|
||||
for (Button *button : self->rendered_buttons) {
|
||||
button->destructor_deleting();
|
||||
}
|
||||
};
|
||||
// Handle Button Click
|
||||
vtable->buttonClicked = [](Screen *self, Button *button) {
|
||||
if (button == getting_started) {
|
||||
open_url(MCPI_DOCUMENTATION "GETTING_STARTED.md");
|
||||
} else if (button == changelog) {
|
||||
open_url(MCPI_DOCUMENTATION CHANGELOG_FILE);
|
||||
} else if (button == proceed) {
|
||||
mark_welcome_as_shown();
|
||||
self->minecraft->screen_chooser.setScreen(1);
|
||||
}
|
||||
};
|
||||
}
|
||||
static Screen *create_welcome_screen() {
|
||||
// Allocate
|
||||
Screen *screen = new Screen;
|
||||
ALLOC_CHECK(screen);
|
||||
screen->constructor();
|
||||
|
||||
// Set VTable
|
||||
screen->vtable = get_welcome_screen_vtable();
|
||||
|
||||
// Return
|
||||
return screen;
|
||||
}
|
||||
|
||||
// Show Welcome Screen
|
||||
static void NinecraftApp_init_ScreenChooser_setScreen_injection(ScreenChooser *self, int id) {
|
||||
if (should_show_welcome()) {
|
||||
// Show Welcome Screen
|
||||
self->minecraft->setScreen(create_welcome_screen());
|
||||
} else {
|
||||
// Show Start Screen
|
||||
self->setScreen(id);
|
||||
}
|
||||
}
|
||||
|
||||
// Init
|
||||
void _init_welcome() {
|
||||
// Hijack Start Screen
|
||||
overwrite_call((void *) 0x14a34, (void *) NinecraftApp_init_ScreenChooser_setScreen_injection);
|
||||
}
|
@ -1 +1,3 @@
|
||||
method void setScreen(uint id) = 0x29490;
|
||||
|
||||
property Minecraft *minecraft = 0x0;
|
Loading…
Reference in New Issue
Block a user