2011-06-13 18:48:36 +02:00
|
|
|
/*
|
2019-08-03 19:43:48 +02:00
|
|
|
* This software is licensed under the terms of the MIT License.
|
2017-02-11 04:52:08 +01:00
|
|
|
* See COPYING for further information.
|
2011-06-13 18:48:36 +02:00
|
|
|
* ---
|
2024-05-16 23:30:41 +02:00
|
|
|
* Copyright (c) 2011-2024, Lukas Weber <laochailan@web.de>.
|
|
|
|
* Copyright (c) 2012-2024, Andrei Alexeyev <akari@taisei-project.org>.
|
2011-06-13 18:48:36 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "mainmenu.h"
|
2011-06-24 19:16:05 +02:00
|
|
|
|
2019-08-22 21:43:34 +02:00
|
|
|
#include "charselect.h"
|
2024-05-17 04:41:28 +02:00
|
|
|
#include "common.h"
|
|
|
|
#include "menu.h"
|
|
|
|
#include "submenus.h"
|
2011-06-24 19:16:05 +02:00
|
|
|
|
2024-05-17 04:41:28 +02:00
|
|
|
#include "audio/audio.h"
|
|
|
|
#include "events.h"
|
2011-06-13 18:48:36 +02:00
|
|
|
#include "global.h"
|
2024-05-17 04:41:28 +02:00
|
|
|
#include "resource/font.h"
|
|
|
|
#include "util/graphics.h"
|
2017-09-18 10:49:06 +02:00
|
|
|
#include "version.h"
|
2024-05-17 04:41:28 +02:00
|
|
|
#include "video.h"
|
2024-05-04 12:47:00 +02:00
|
|
|
#include "watchdog.h"
|
2011-06-13 18:48:36 +02:00
|
|
|
|
2017-02-12 05:30:25 +01:00
|
|
|
static MenuEntry *spell_practice_entry;
|
2017-09-11 21:09:30 +02:00
|
|
|
static MenuEntry *stage_practice_entry;
|
2017-02-12 05:30:25 +01:00
|
|
|
|
2017-09-11 21:09:30 +02:00
|
|
|
void main_menu_update_practice_menus(void) {
|
|
|
|
spell_practice_entry->action = NULL;
|
|
|
|
stage_practice_entry->action = NULL;
|
2017-02-12 05:30:25 +01:00
|
|
|
|
2020-05-16 22:41:54 +02:00
|
|
|
int n = stageinfo_get_num_stages();
|
|
|
|
for(int i = 0; i < n; ++i) {
|
|
|
|
StageInfo *stg = stageinfo_get_by_index(i);
|
|
|
|
|
2017-02-12 05:30:25 +01:00
|
|
|
if(stg->type == STAGE_SPELL) {
|
2020-05-16 22:41:54 +02:00
|
|
|
StageProgress *p = stageinfo_get_progress(stg, D_Any, false);
|
2017-09-11 21:09:30 +02:00
|
|
|
|
2017-02-12 05:30:25 +01:00
|
|
|
if(p && p->unlocked) {
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
spell_practice_entry->action = menu_action_enter_spellpractice;
|
2020-04-05 04:51:00 +02:00
|
|
|
if(stage_practice_entry->action) {
|
|
|
|
break;
|
|
|
|
}
|
2017-09-11 21:09:30 +02:00
|
|
|
}
|
|
|
|
} else if(stg->type == STAGE_STORY) {
|
|
|
|
for(Difficulty d = D_Easy; d <= D_Lunatic; ++d) {
|
2020-05-16 22:41:54 +02:00
|
|
|
StageProgress *p = stageinfo_get_progress(stg, d, false);
|
2017-09-11 21:09:30 +02:00
|
|
|
|
|
|
|
if(p && p->unlocked) {
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
stage_practice_entry->action = menu_action_enter_stagepractice;
|
2020-04-05 04:51:00 +02:00
|
|
|
if(spell_practice_entry->action) {
|
|
|
|
break;
|
|
|
|
}
|
2017-09-11 21:09:30 +02:00
|
|
|
}
|
2017-02-12 05:30:25 +01:00
|
|
|
}
|
|
|
|
}
|
2020-05-16 22:41:54 +02:00
|
|
|
}
|
2017-02-12 05:30:25 +01:00
|
|
|
}
|
|
|
|
|
2017-12-26 12:07:40 +01:00
|
|
|
static void begin_main_menu(MenuData *m) {
|
2020-06-22 16:41:03 +02:00
|
|
|
audio_bgm_play(res_bgm("menu"), true, 0, 0);
|
2017-02-24 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
2019-01-24 21:21:08 +01:00
|
|
|
static void update_main_menu(MenuData *menu) {
|
2024-05-04 12:47:00 +02:00
|
|
|
if(watchdog_signaled()) {
|
|
|
|
menu->cursor = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
watchdog_reset();
|
|
|
|
|
2019-04-20 18:06:27 +02:00
|
|
|
menu->drawdata[1] += 0.1*(menu->cursor-menu->drawdata[1]);
|
2019-01-24 21:21:08 +01:00
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
dynarray_foreach(&menu->entries, int i, MenuEntry *e, {
|
|
|
|
e->drawdata += 0.2 * ((i == menu->cursor) - e->drawdata);
|
|
|
|
});
|
2019-01-24 21:21:08 +01:00
|
|
|
}
|
2017-12-26 12:07:40 +01:00
|
|
|
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
attr_unused
|
2019-03-01 16:55:32 +01:00
|
|
|
static bool main_menu_input_handler(SDL_Event *event, void *arg) {
|
|
|
|
MenuData *m = arg;
|
|
|
|
TaiseiEvent te = TAISEI_EVENT(event->type);
|
|
|
|
static hrtime_t last_abort_time = 0;
|
|
|
|
|
2023-06-20 00:50:17 +02:00
|
|
|
if(te == TE_MENU_ABORT && dynarray_get(&m->entries, m->entries.num_elements - 1).action) {
|
2020-06-22 16:41:03 +02:00
|
|
|
play_sfx_ui("hit");
|
2020-04-05 04:51:00 +02:00
|
|
|
m->cursor = m->entries.num_elements - 1;
|
2019-03-01 16:55:32 +01:00
|
|
|
hrtime_t t = time_get();
|
|
|
|
|
|
|
|
if(t - last_abort_time < HRTIME_RESOLUTION/5 && last_abort_time > 0) {
|
|
|
|
m->selected = m->cursor;
|
|
|
|
close_menu(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
last_abort_time = t;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return menu_input_handler(event, arg);
|
|
|
|
}
|
|
|
|
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
attr_unused
|
2019-03-01 16:55:32 +01:00
|
|
|
static void main_menu_input(MenuData *m) {
|
|
|
|
events_poll((EventHandler[]){
|
|
|
|
{ .proc = main_menu_input_handler, .arg = m },
|
|
|
|
{ NULL }
|
|
|
|
}, EFLAG_MENU);
|
|
|
|
}
|
|
|
|
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
MenuData* create_main_menu(void) {
|
|
|
|
MenuData *m = alloc_menu();
|
|
|
|
|
|
|
|
m->begin = begin_main_menu;
|
2017-02-24 22:58:27 +01:00
|
|
|
m->draw = draw_main_menu;
|
2017-12-26 12:07:40 +01:00
|
|
|
m->logic = update_main_menu;
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
ptrdiff_t stage_practice_idx, spell_practice_idx;
|
|
|
|
|
2017-02-12 04:43:52 +01:00
|
|
|
add_menu_entry(m, "Start Story", start_game, NULL);
|
2011-06-24 12:35:03 +02:00
|
|
|
add_menu_entry(m, "Start Extra", NULL, NULL);
|
2020-04-05 04:51:00 +02:00
|
|
|
stage_practice_entry = add_menu_entry(m, "Stage Practice", menu_action_enter_stagepractice, NULL);
|
|
|
|
stage_practice_idx = dynarray_indexof(&m->entries, stage_practice_entry);
|
|
|
|
spell_practice_entry = add_menu_entry(m, "Spell Practice", menu_action_enter_spellpractice, NULL);
|
|
|
|
spell_practice_idx = dynarray_indexof(&m->entries, spell_practice_entry);
|
2012-07-14 10:40:21 +02:00
|
|
|
#ifdef DEBUG
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
add_menu_entry(m, "Select Stage", menu_action_enter_stagemenu, NULL);
|
|
|
|
#endif
|
|
|
|
add_menu_entry(m, "Replays", menu_action_enter_replayview, NULL);
|
2020-11-28 11:11:10 +01:00
|
|
|
add_menu_entry(m, "Media Room", menu_action_enter_media, NULL);
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
add_menu_entry(m, "Options", menu_action_enter_options, NULL);
|
2024-06-04 16:31:46 +02:00
|
|
|
|
|
|
|
if(!taisei_is_quit_hidden()) {
|
|
|
|
add_menu_entry(m, "Quit", menu_action_close, NULL)->transition = TransFadeBlack;
|
|
|
|
m->input = main_menu_input;
|
|
|
|
}
|
2011-06-13 18:48:36 +02:00
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
stage_practice_entry = dynarray_get_ptr(&m->entries, stage_practice_idx);
|
|
|
|
spell_practice_entry = dynarray_get_ptr(&m->entries, spell_practice_idx);
|
2017-09-11 21:09:30 +02:00
|
|
|
main_menu_update_practice_menus();
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
|
2019-03-11 00:21:43 +01:00
|
|
|
progress_unlock_bgm("menu");
|
2020-06-22 16:41:03 +02:00
|
|
|
audio_bgm_play(res_bgm("menu"), true, 0, 0);
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
|
|
|
|
return m;
|
2017-02-12 05:30:25 +01:00
|
|
|
}
|
2011-06-13 18:48:36 +02:00
|
|
|
|
2019-04-22 02:07:14 +02:00
|
|
|
void draw_main_menu_bg(MenuData* menu, double center_x, double center_y, double R, const char *tex1, const char *tex2) {
|
2018-07-23 19:07:59 +02:00
|
|
|
r_color4(1, 1, 1, 1);
|
2019-04-20 18:06:27 +02:00
|
|
|
r_shader("mainmenubg");
|
|
|
|
r_uniform_float("R", R/(1-menu_fade(menu)));
|
|
|
|
r_uniform_vec2("bg_translation", 0.001*menu->frames, 0);
|
2019-04-22 09:28:40 +02:00
|
|
|
r_uniform_vec2("center", 0.5 + center_x / SCREEN_W, 0.5 + center_y / SCREEN_H);
|
|
|
|
r_uniform_float("inv_aspect_ratio", 1.0 / VIDEO_ASPECT_RATIO);
|
2019-04-22 02:07:14 +02:00
|
|
|
r_uniform_sampler("blend_mask", "cell_noise");
|
2019-04-21 10:37:50 +02:00
|
|
|
r_uniform_sampler("tex2", tex2);
|
2019-04-22 02:07:14 +02:00
|
|
|
fill_screen(tex1);
|
2019-04-20 18:06:27 +02:00
|
|
|
r_shader_standard();
|
2011-06-24 12:35:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void draw_main_menu(MenuData *menu) {
|
2019-04-22 02:07:14 +02:00
|
|
|
draw_main_menu_bg(menu, 0, 0, 0.05, "menu/mainmenubg", "stage1/cirnobg");
|
2019-10-12 14:02:15 +02:00
|
|
|
r_state_push();
|
2019-04-22 02:07:14 +02:00
|
|
|
|
|
|
|
float rot = sqrt(menu->frames/120.0);
|
|
|
|
float rotfac = (1 - pow(menu_fade(menu), 2.0));
|
|
|
|
|
|
|
|
r_draw_sprite(&(SpriteParams) {
|
2024-09-22 21:06:57 +02:00
|
|
|
.sprite_ptr = res_sprite("menu/logo"),
|
|
|
|
.shader_ptr = res_shader("sprite_default"),
|
2019-04-22 02:07:14 +02:00
|
|
|
.pos = { SCREEN_W/2, SCREEN_H/2 },
|
|
|
|
.rotation.vector = { 0, -1, 0 },
|
2023-09-23 21:56:34 +02:00
|
|
|
.rotation.angle = max(0, M_PI/1.5 - min(M_PI/1.5, rot) * rotfac),
|
|
|
|
.color = color_mul_scalar(RGBA(1, 1, 1, 1), min(1, rot) * rotfac),
|
2019-04-22 02:07:14 +02:00
|
|
|
});
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2019-10-12 14:02:15 +02:00
|
|
|
r_mat_mv_push();
|
|
|
|
r_mat_mv_translate(0, SCREEN_H/2, 0);
|
2018-06-29 23:36:51 +02:00
|
|
|
r_shader("text_default");
|
2018-07-23 19:07:59 +02:00
|
|
|
|
|
|
|
float o = 0.7;
|
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
dynarray_foreach(&menu->entries, int i, MenuEntry *e, {
|
|
|
|
if(e->action == NULL) {
|
2018-07-23 19:07:59 +02:00
|
|
|
r_color4(0.2 * o, 0.3 * o, 0.5 * o, o);
|
2012-08-06 07:54:22 +02:00
|
|
|
} else {
|
2020-04-05 04:51:00 +02:00
|
|
|
float a = 1 - e->drawdata;
|
2023-09-23 21:56:34 +02:00
|
|
|
r_color4(o, min(1, 0.7 + a) * o, min(1, 0.4 + a) * o, o);
|
2012-04-05 14:24:55 +02:00
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
text_draw(e->name, &(TextParams) {
|
|
|
|
.pos = { 50 - 15 * e->drawdata, 20 * (i - menu->drawdata[1]) },
|
2019-04-20 18:06:27 +02:00
|
|
|
.font = "standard",
|
2018-06-29 23:36:51 +02:00
|
|
|
});
|
2020-04-05 04:51:00 +02:00
|
|
|
});
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2019-10-12 14:02:15 +02:00
|
|
|
r_mat_mv_pop();
|
2018-04-12 16:08:48 +02:00
|
|
|
|
|
|
|
r_disable(RCAP_CULL_FACE);
|
|
|
|
r_shader("sprite_default");
|
2017-03-04 22:51:23 +01:00
|
|
|
|
|
|
|
for(int i = 0; i < 50; i++) { // who needs persistent state for a particle system?
|
|
|
|
int period = 900;
|
|
|
|
int t = menu->frames+100*i + 30*sin(35*i);
|
|
|
|
int cycle = t/period;
|
|
|
|
float posx = SCREEN_W+300+100*sin(100345*i)+200*sin(1003*i+13537*cycle)-(0.6+0.01*sin(35*i))*(t%period);
|
|
|
|
float posy = 50+ 50*sin(503*i+14677*cycle)+0.8*(t%period);
|
|
|
|
float rx = sin(56*i+2147*cycle);
|
|
|
|
float ry = sin(913*i+137*cycle);
|
|
|
|
float rz = sin(1303*i+89631*cycle);
|
|
|
|
float r = sqrt(rx*rx+ry*ry+rz*rz);
|
2017-09-26 02:38:34 +02:00
|
|
|
|
|
|
|
if(!r) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-03-04 22:51:23 +01:00
|
|
|
rx /= r;
|
|
|
|
ry /= r;
|
|
|
|
rz /= r;
|
2017-09-26 02:38:34 +02:00
|
|
|
|
2017-03-04 22:51:23 +01:00
|
|
|
if(posx > SCREEN_W+20 || posy < -20 || posy > SCREEN_H+20)
|
|
|
|
continue;
|
|
|
|
|
2019-10-12 14:02:15 +02:00
|
|
|
r_draw_sprite(&(SpriteParams) {
|
2024-09-22 21:06:57 +02:00
|
|
|
.sprite_ptr = res_sprite("part/petal"),
|
2019-10-12 14:02:15 +02:00
|
|
|
.color = RGBA(1, 1, 1, 0),
|
|
|
|
.pos = { posx, posy },
|
|
|
|
.scale.both = 0.2,
|
|
|
|
.rotation.angle = DEG2RAD * 2 * (t % period),
|
|
|
|
.rotation.vector = { rx, ry, rz },
|
|
|
|
});
|
2017-03-04 22:51:23 +01:00
|
|
|
}
|
|
|
|
|
2019-10-12 14:02:15 +02:00
|
|
|
r_enable(RCAP_CULL_FACE);
|
2018-04-12 16:08:48 +02:00
|
|
|
|
2017-09-24 01:16:30 +02:00
|
|
|
char version[32];
|
|
|
|
snprintf(version, sizeof(version), "v%s", TAISEI_VERSION);
|
2018-06-29 23:36:51 +02:00
|
|
|
text_draw(TAISEI_VERSION, &(TextParams) {
|
|
|
|
.align = ALIGN_RIGHT,
|
|
|
|
.pos = { SCREEN_W-5, SCREEN_H-10 },
|
|
|
|
.font = "small",
|
2024-09-22 21:06:57 +02:00
|
|
|
.shader_ptr = res_shader("text_default"),
|
2019-10-12 14:02:15 +02:00
|
|
|
.color = RGBA(1, 1, 1, 1),
|
2018-06-29 23:36:51 +02:00
|
|
|
});
|
2018-07-25 00:33:01 +02:00
|
|
|
|
2019-10-12 14:02:15 +02:00
|
|
|
r_state_pop();
|
2011-06-13 18:48:36 +02:00
|
|
|
}
|
2017-03-07 02:04:23 +01:00
|
|
|
|
|
|
|
void draw_loading_screen(void) {
|
2023-03-22 23:41:32 +01:00
|
|
|
ResourceGroup rg;
|
|
|
|
res_group_init(&rg);
|
|
|
|
res_group_preload(&rg, RES_TEXTURE, RESF_DEFAULT, "loading", NULL);
|
|
|
|
res_group_preload(&rg, RES_SHADER_PROGRAM, RESF_DEFAULT, "text_default", NULL);
|
2019-04-22 23:09:58 +02:00
|
|
|
|
2018-04-26 01:50:48 +02:00
|
|
|
set_ortho(SCREEN_W, SCREEN_H);
|
2018-02-06 07:19:25 +01:00
|
|
|
fill_screen("loading");
|
2019-04-22 02:07:14 +02:00
|
|
|
text_draw("Please wait warmly…", &(TextParams) {
|
|
|
|
.align = ALIGN_CENTER,
|
2019-04-25 18:22:30 +02:00
|
|
|
.pos = { SCREEN_W/2, SCREEN_H-20 },
|
2019-04-22 02:07:14 +02:00
|
|
|
.font = "standard",
|
2024-09-22 21:06:57 +02:00
|
|
|
.shader_ptr = res_shader("text_default"),
|
2019-04-25 18:22:30 +02:00
|
|
|
.color = RGBA(0.35, 0.35, 0.35, 0.35),
|
2018-06-29 23:36:51 +02:00
|
|
|
});
|
2019-04-22 23:09:58 +02:00
|
|
|
|
2017-12-26 09:56:21 +01:00
|
|
|
video_swap_buffers();
|
2023-03-22 23:41:32 +01:00
|
|
|
res_group_release(&rg);
|
2017-03-07 02:04:23 +01:00
|
|
|
}
|
2017-03-11 04:41:57 +01:00
|
|
|
|
2023-03-22 23:41:32 +01:00
|
|
|
void menu_preload(ResourceGroup *rg) {
|
|
|
|
difficulty_preload(rg);
|
2017-03-11 04:41:57 +01:00
|
|
|
|
2023-03-22 23:41:32 +01:00
|
|
|
res_group_preload(rg, RES_FONT, RESF_DEFAULT,
|
2018-06-29 23:36:51 +02:00
|
|
|
"big",
|
|
|
|
"small",
|
|
|
|
NULL);
|
|
|
|
|
2023-03-22 23:41:32 +01:00
|
|
|
res_group_preload(rg, RES_TEXTURE, RESF_DEFAULT,
|
2019-04-22 23:09:58 +02:00
|
|
|
"abstract_brown",
|
|
|
|
"cell_noise",
|
|
|
|
"stage1/cirnobg",
|
2018-02-06 07:19:25 +01:00
|
|
|
"menu/mainmenubg",
|
2023-06-17 04:19:11 +02:00
|
|
|
"loading",
|
2018-02-06 07:19:25 +01:00
|
|
|
NULL);
|
|
|
|
|
2023-03-22 23:41:32 +01:00
|
|
|
res_group_preload(rg, RES_SPRITE, RESF_DEFAULT,
|
2017-03-11 04:41:57 +01:00
|
|
|
"part/smoke",
|
|
|
|
"part/petal",
|
2018-02-06 07:19:25 +01:00
|
|
|
"menu/logo",
|
|
|
|
"menu/arrow",
|
|
|
|
"star",
|
|
|
|
NULL);
|
|
|
|
|
2023-03-22 23:41:32 +01:00
|
|
|
res_group_preload(rg, RES_SHADER_PROGRAM, RESF_DEFAULT,
|
2024-05-27 19:12:28 +02:00
|
|
|
"gamepad_circle",
|
2019-04-22 23:09:58 +02:00
|
|
|
"mainmenubg",
|
2018-04-12 16:08:48 +02:00
|
|
|
"sprite_circleclipped_indicator",
|
2017-03-11 04:41:57 +01:00
|
|
|
NULL);
|
|
|
|
|
2023-03-22 23:41:32 +01:00
|
|
|
res_group_preload(rg, RES_SFX, RESF_OPTIONAL,
|
2017-03-11 04:41:57 +01:00
|
|
|
"generic_shot",
|
|
|
|
"shot_special1",
|
|
|
|
"hit",
|
|
|
|
NULL);
|
|
|
|
|
2023-03-22 23:41:32 +01:00
|
|
|
res_group_preload(rg, RES_BGM, RESF_OPTIONAL,
|
2017-10-02 04:34:51 +02:00
|
|
|
"menu",
|
2017-03-11 04:41:57 +01:00
|
|
|
NULL);
|
2017-10-08 13:30:51 +02:00
|
|
|
|
2023-03-22 23:41:32 +01:00
|
|
|
preload_char_menu(rg);
|
2017-03-11 04:41:57 +01:00
|
|
|
}
|