diff --git a/hyperweb.cpp b/hyperweb.cpp index 2d2b5f9e..d9eafa73 100644 --- a/hyperweb.cpp +++ b/hyperweb.cpp @@ -112,16 +112,6 @@ EX void offer_choose_file(reaction_t r) { }); } -// -- demo -- - -#if CAP_URL -EX void open_url(string s) { - EM_ASM_({ - window.open(UTF8ToString($0, 1000)); - }, s.c_str()); - } -#endif - // window.open(Pointer_stringify($0)); bool demoanim; diff --git a/rogueviz/heatx.cpp b/rogueviz/heatx.cpp new file mode 100644 index 00000000..0a4cc51b --- /dev/null +++ b/rogueviz/heatx.cpp @@ -0,0 +1,145 @@ +#include "rogueviz.h" +#include + +// heat equation simulation +// https://twitter.com/ZenoRogue/status/1208409387733307392 + +// run with e.g. +// -geo 1 -canvas 0 -smart 1 -smartlimit 999999 -heatx +// -tes tessellations/sample/marjorie-rice.tes heat_scale=0.02 -canvas 0 -smart 1 -smartlimit 999999 -heatx + +namespace hr { + +namespace heatx { + +const int NOT_STARTED = 999999; +const int OFF = 999998; + +int last_steps = NOT_STARTED; + +std::unordered_map m1, m2, m3; + +ld delta = 0.01; + +int mode = 1; + +int qsteps = 2000; + +ld frac_per_frame = .001; + +ld frac; + +ld scale = 0.05; + +void advance_heat_wave() { + + if(euclid && GDIM == 2) + pconf.scale = scale / max(frac, .15); + + int steps = mode == 2 ? (frac * qsteps) : (frac * frac * qsteps); + + if(steps != last_steps) { + celllister cl(cwt.at, 400, 20000, nullptr); + if(steps < last_steps) { + last_steps = 0; + m1.clear(); + m2.clear(); + for(cell *c: cl.lst) m1[c] = 0; + m2 = m1; + m1[cwt.at] = 1; + } + while(last_steps < steps) { + switch(mode) { + case 0: + // heat: average of adjacent + for(cell *c: cl.lst) { + ld v = m1[c]; + forCellEx(c2, c) { + if(m1.count(c2)) v += m1[c2]; else v += m1[c]; + } + v /= (1 + c->type); + m2[c] = v; + } + swap(m1, m2); + break; + case 1: + // heat: transfer to adjacent + for(auto& p: m2) p.second = 0; + for(cell *c: cl.lst) { + ld v = m1[c] / (1 + c->type); + m2[c] += v; + forCellEx(c2, c) { + if(m1.count(c2)) m2[c2] += v; else m2[c] += v; + } + } + swap(m1, m2); + break; + case 2: + // wave + for(cell *c: cl.lst) { + m3[c] = 0; + forCellEx(c2, c) { + if(m1.count(c2)) m3[c] += (m1[c2] - m1[c]); + } + } + for(cell *c: cl.lst) { + m1[c] += m2[c] * delta + m3[c] * delta * delta / 2; + m2[c] += m3[c] * delta; + } + break; + } + last_steps++; + } + ld maxv = 0; + for(auto p: m1) maxv = max(maxv, abs(p.second)); + for(cell *c: cl.lst) { + ld x = m1[c] / maxv; + if(mode == 2) { + if(x < 0) c->landparam = gradient(0x001010, 0x1010FF, -1, x, 0); + else c->landparam = gradient(0x1010FF, 0xFFFFFF, 0, x, 1); + } + else { + if(x < 1/2.) c->landparam = gradient(0x001010, 0xFF1010, 0, x, 1/2.); + else c->landparam = gradient(0xFF1010, 0xFFFF10, 1/2., x, 1.); + if(x > .2 && x < .3) c->landparam |= 0x4040; + } + } + } + + // return false; + } + +void enable() { + using rogueviz::rv_hook; + rv_hook(hooks_frame, 100, advance_heat_wave); + rv_hook(anims::hooks_anim, 100, [] { + if(inHighQual) { + frac = std::fmod(ticks, anims::period) * 1. / anims::period; + } + else { + frac += frac_per_frame; + if(frac > 1) frac--; + } + }); + rv_hook(shot::hooks_take, 100, [] { + advance_heat_wave(); calcparam(); models::configure(); + }); + rv_hook(hooks_drawcell, 100, [] (cell *c, const shiftmatrix& V) { + if(WDIM == 3) + queuepoly(face_the_player(V), cgi.shRing, darkena(c->landparam_color, 0, 0xFF)); + return false; + }); + rogueviz::cleanup.push_back([] { m1.clear(); m2.clear(); m3.clear(); last_steps = OFF; }); + last_steps = NOT_STARTED; frac = 0; + } + +auto heathook = arg::add3("-heatx", enable) + + addHook(hooks_configfile, 100, [] { + param_f(delta, "heat_delta"); + param_i(qsteps, "heat_qsteps"); + param_f(frac_per_frame, "heat_pf"); + param_f(scale, "heat_scale"); + }); + +} +} diff --git a/rogueviz/rogueviz-all.cpp b/rogueviz/rogueviz-all.cpp index da7f9b01..c0e59e44 100644 --- a/rogueviz/rogueviz-all.cpp +++ b/rogueviz/rogueviz-all.cpp @@ -36,6 +36,8 @@ #include "hypcity.cpp" #include "hypocycloid.cpp" +#include "heatx.cpp" + #include "notknot.cpp" #include "inner-maps.cpp" diff --git a/sysconfig.h b/sysconfig.h index f2f28651..a93165ea 100644 --- a/sysconfig.h +++ b/sysconfig.h @@ -79,6 +79,10 @@ #define CAP_GMP 0 #endif +#ifndef CAP_URL +#define CAP_URL 1 +#endif + #define CAP_FRAMELIMIT (!ISMOBWEB) #if ISMOBILE @@ -339,6 +343,8 @@ #define hyper fake_hyper // avoid "hyper" typedef in <_mingw.h> #define WIN32_LEAN_AND_MEAN // avoid "rad1" macro in #define NOMINMAX // avoid "min" and "max" macros in +#include +#include #endif #include diff --git a/util.cpp b/util.cpp index 702357ac..b315f472 100644 --- a/util.cpp +++ b/util.cpp @@ -703,4 +703,25 @@ EX bool file_exists(string fname) { return access(fname.c_str(), F_OK) != -1; } +EX void open_url(string s) { + #if ISWEB + EM_ASM_({ + window.open(UTF8ToString($0, 1000)); + }, s.c_str()); + #else + +#ifdef WINDOWS + ShellExecute(0, 0, s.c_str(), 0, 0, SW_SHOW); +#endif + +#ifdef LINUX + system(("xdg-open "+s).c_str()); +#endif + +#ifdef MAC + system(("open "+s).c_str()); +#endif +#endif + } + }