hyperrogue/hyperweb.cpp

314 lines
7.8 KiB
C++
Raw Permalink Normal View History

// Hyperbolic Rogue
// This is the main file when the online version of HyperRogue is compiled with Emscripten.
// Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
2020-10-11 23:28:50 +00:00
#ifndef ISWEB
2017-07-22 23:33:27 +00:00
#define ISWEB 1
#define ISMINI 0
#define CAP_INV 0
2018-09-05 13:34:13 +00:00
#define CAP_URL 1
2018-02-11 18:08:17 +00:00
#define GLES_ONLY
2020-10-11 23:28:50 +00:00
#define SCU
#endif
2017-03-23 10:53:57 +00:00
2020-10-15 14:33:52 +00:00
#if CAP_ROGUEVIZ || defined(MAXMDIM)
2019-09-13 15:46:07 +00:00
#define MAXMDIM 4
#else
#define MAXMDIM 3
#endif
// we want newconformist, but we don't want CAP_GD there
#define CAP_NCONF 1
#define CAP_GD 0
#ifndef EMSCRIPTEN
#define EMSCRIPTEN
#endif
2017-03-23 10:53:57 +00:00
#ifdef FAKEWEB
namespace hr { void mainloopiter(); }
2017-03-23 10:53:57 +00:00
template<class A, class B, class C> void emscripten_set_main_loop(A a, B b, C c) { while(true) mainloopiter(); }
#else
#include <emscripten.h>
#include <emscripten/html5.h>
2017-03-23 10:53:57 +00:00
#endif
2018-06-13 22:06:54 +00:00
#include <string>
namespace hr {
void initweb();
void emscripten_get_commandline();
2017-03-23 10:53:57 +00:00
void loadCompressedChar(int &otwidth, int &otheight, int *tpix);
2020-10-15 14:35:44 +00:00
void get_canvas_size();
2017-03-23 10:53:57 +00:00
const char *wheresounds;
2020-01-19 10:49:49 +00:00
std::string get_value(std::string name);
void offer_download(std::string sfilename, std::string smimetype);
}
2020-10-11 23:28:50 +00:00
#ifdef SCU
2019-09-13 01:47:55 +00:00
#include "hyper.cpp"
2020-10-11 23:28:50 +00:00
#else
#include "hyper.h"
#endif
2018-06-13 22:06:54 +00:00
namespace hr {
2017-03-23 10:53:57 +00:00
EX string get_value(string name) {
2020-01-19 10:49:49 +00:00
char *str = (char*)EM_ASM_INT({
var name = UTF8ToString($0, $1);
var value = document.getElementById(name).value;
var lengthBytes = lengthBytesUTF8(value)+1;
var stringOnWasmHeap = _malloc(lengthBytes);
stringToUTF8(value, stringOnWasmHeap, lengthBytes);
return stringOnWasmHeap;
}, name.c_str(), int(name.size())
);
string res = str;
free(str);
return res;
}
2020-10-11 23:28:50 +00:00
EX void offer_download(string sfilename, string smimetype) {
EM_ASM({
var name = UTF8ToString($0, $1);
var mime = UTF8ToString($2, $3);
let content = Module.FS.readFile(name);
console.log(`Offering download of "${name}", with ${content.length} bytes...`);
var a = document.createElement('a');
a.download = name;
a.href = URL.createObjectURL(new Blob([content], {type: mime}));
a.style.display = 'none';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(a.href);
}, 2000);
}, sfilename.c_str(), isize(sfilename), smimetype.c_str(), isize(smimetype)
);
}
reaction_t on_use_file = [] {};
extern "C" {
void use_file() {
on_use_file();
}
}
2020-10-11 23:28:50 +00:00
EX void offer_choose_file(reaction_t r) {
on_use_file = r;
EM_ASM({
fileElem.click();
});
}
// window.open(Pointer_stringify($0));
bool demoanim;
void toggleanim(bool v) {
demoanim = v;
if(v) {
sightrange_bonus = -3;
vid.wallmode = 5;
vid.particles = true;
vid.sspeed = -1;
vid.mspeed = -1;
2019-06-01 15:03:33 +00:00
vid.highdetail = vid.middetail = 5;
}
else {
sightrange_bonus = 0;
vid.sspeed = 5;
vid.mspeed = 5;
vid.particles = false;
vid.wallmode = 3;
2019-06-01 15:03:33 +00:00
vid.highdetail = vid.middetail = -1;
}
}
void showDemo() {
cmode = sm::DARKEN;
gamescreen();
getcstat = ' ';
dialog::init(XLAT("HyperRogue %1: online demo", VER), 0xC00000, 200, 100);
dialog::addBreak(50);
2018-10-23 15:06:47 +00:00
dialog::addItem(XLAT("play the game"), 'f');
dialog::addItem(XLAT("learn about hyperbolic geometry"), 'T');
2019-09-12 22:31:54 +00:00
dialog::addHelp();
2018-02-11 18:08:17 +00:00
// dialog::addItem(XLAT("toggle high detail"), 'a');
dialog::addBreak(100);
dialog::addTitle("highlights", 0xC00000, 120);
2023-12-03 13:29:26 +00:00
dialog::addItem(XLAT1("Temple of Cthulhu"), 't');
dialog::addItem(XLAT1("Land of Storms"), 'l');
dialog::addItem(XLAT1("Burial Grounds"), 'b');
dialog::display();
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(sym == SDLK_F1 || uni == 'h') gotoHelp(help);
else if(uni == 'a') {
toggleanim(!demoanim);
popScreen();
}
else if(uni == 'f') {
firstland = laIce;
restart_game(tactic::on ? rg::tactic : rg::nothing);
}
#if CAP_TOUR
else if(uni == 'T') {
firstland = laIce;
if(!tour::on) tour::start();
}
#endif
else if(uni == 't') {
firstland = laTemple;
restart_game(tactic::on ? rg::tactic : rg::nothing);
}
else if(uni == 'l') {
firstland = laStorms;
restart_game(tactic::on ? rg::tactic : rg::nothing);
}
else if(uni == 'b') {
firstland = laBurial;
restart_game(tactic::on ? rg::tactic : rg::nothing);
items[itOrbSword] = 60;
}
};
}
2017-03-23 10:53:57 +00:00
2019-07-12 21:17:35 +00:00
int bak_xres, bak_yres;
EM_BOOL fsc_callback(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData) {
if(fullscreenChangeEvent->isFullscreen) {
2019-07-12 21:17:35 +00:00
bak_xres = vid.xres;
bak_yres = vid.yres;
2018-02-11 21:11:28 +00:00
vid.xres = vid.xscr = fullscreenChangeEvent->screenWidth;
vid.yres = vid.yscr = fullscreenChangeEvent->screenHeight;
vid.full = true;
printf("set to %d x %d\n", vid.xres, vid.yres);
setvideomode();
}
else {
2019-07-12 21:17:35 +00:00
vid.xres = vid.xscr = bak_xres;
vid.yres = vid.yscr = bak_yres;
2018-02-11 21:11:28 +00:00
vid.full = true;
printf("reset to %d x %d\n", vid.xres, vid.yres);
setvideomode();
}
return true;
}
2020-10-15 14:35:44 +00:00
EX void get_canvas_size() {
vid.xscr = vid.xres = EM_ASM_INT({
var d = document.getElementById("this_wide");
if(!d) return window.innerWidth;
return d.clientWidth;
});
if(vid.full) vid.yscr = vid.yres = EM_ASM_INT({
var d = document.getElementById("this_wide");
if(!d) return window.innerWidth;
return d.clientHeight;
});
else {
vid.xscr = vid.xres = vid.xres - 32;
vid.yscr = vid.yres = EM_ASM_INT({
return window.innerHeight;
}) - 32;
vid.yscr = vid.yres = min(vid.yscr, vid.xscr * 9 / 16);
vid.xscr = vid.xres = min(vid.xscr, vid.yscr * 16 / 9);
}
println(hlog, "X = ", vid.xscr, " Y = ", vid.yscr);
}
EM_BOOL resize_callback(int eventType, const EmscriptenUiEvent *resizeEvent, void *userData) {
if(vid.full) return true;
get_canvas_size();
setvideomode();
return true;
}
2020-10-11 23:28:50 +00:00
EX void initweb() {
2018-02-11 18:08:17 +00:00
// toggleanim(false);
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, false, fsc_callback);
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, resize_callback);
2018-02-12 15:21:19 +00:00
printf("showstartmenu = %d\n", showstartmenu);
if(showstartmenu) pushScreen(showDemo);
2017-03-23 10:53:57 +00:00
}
#if CAP_ORIENTATION
transmatrix getOrientation() {
ld alpha, beta, gamma;
alpha = EM_ASM_DOUBLE({ return rotation_alpha; });
beta = EM_ASM_DOUBLE({ return rotation_beta; });
gamma = EM_ASM_DOUBLE({ return rotation_gamma; });
return
cspin(0, 1, alpha * degree) *
cspin(1, 2, beta * degree) *
cspin(0, 2, gamma * degree);
}
#endif
2020-10-11 23:28:50 +00:00
EX void emscripten_get_commandline() {
2018-02-26 12:14:20 +00:00
#ifdef EMSCRIPTEN_FIXED_ARG
string s = EMSCRIPTEN_FIXED_ARG;
#else
char *str = (char*)EM_ASM_INT({
var jsString = document.location.href;
2019-07-12 21:17:53 +00:00
if (typeof(default_arg) != 'undefined' && jsString.indexOf('?') == -1)
jsString = default_arg;
var lengthBytes = lengthBytesUTF8(jsString)+1;
var stringOnWasmHeap = _malloc(lengthBytes);
stringToUTF8(jsString, stringOnWasmHeap, lengthBytes+1);
return stringOnWasmHeap;
});
string s = str;
2018-02-26 12:14:20 +00:00
#endif
s += "+xxxxxx";
2018-06-22 12:47:24 +00:00
for(int i=0; i<isize(s); i++) if(s[i] == '?') {
2018-02-26 12:14:20 +00:00
#ifndef EMSCRIPTEN_FIXED_ARG
2018-02-12 12:37:01 +00:00
printf("HREF: %s\n", str);
2018-02-26 12:14:20 +00:00
#endif
arg::argument.push_back("hyperweb"); arg::lshift();
string next = ""; i += 3;
2018-06-22 12:47:24 +00:00
for(; i<isize(s); i++) {
if(s[i] == '+') {
2018-02-26 12:14:20 +00:00
arg::argument.push_back(next);
next = "";
}
else if(s[i] == '%') {
string s2 = "";
s2 += s[i+1];
s2 += s[i+2];
i += 2;
next += strtol(s2.c_str(), NULL, 16);
}
else if(s[i] == '&') {
arg::argument.push_back(next); break;
}
else next += s[i];
}
2018-02-26 12:14:20 +00:00
printf("Arguments:"); for(string s: arg::argument) printf(" %s", s.c_str()); printf("\n");
break;
}
2018-02-26 12:14:20 +00:00
#ifndef EMSCRIPTEN_FIXED_ARG
free(str);
2018-02-26 12:14:20 +00:00
#endif
}
}