diff --git a/basegraph.cpp b/basegraph.cpp index cb7a0e2d..bcacfcbf 100644 --- a/basegraph.cpp +++ b/basegraph.cpp @@ -984,96 +984,6 @@ ld textscale() { // bool notgl = false; -int pngres = 2000; -int pngformat = 0; - -#if CAP_PNG -void IMAGESAVE(SDL_Surface *s, const char *fname) { - SDL_Surface *s2 = SDL_PNGFormatAlpha(s); - SDL_SavePNG(s2, fname); - SDL_FreeSurface(s2); - } -#endif - -hookset *hooks_hqshot; - -#if CAP_SDL -void saveHighQualityShot(const char *fname, const char *caption, int fade) { - - resetbuffer rb; - - // int maxrange = getDistLimit() * 3/2; - - // dynamicval v3(sightrange, (cheater && sightrange < maxrange) ? maxrange : sightrange); - - if(cheater) doOvergenerate(); - - time_t timer; - timer = time(NULL); - - dynamicval v(vid, vid); - dynamicval v2(inHighQual, true); - dynamicval v6(auraNOGL, fname ? true : false); - - vid.xres = vid.yres = pngres; - if(pngformat == 1) vid.xres = vid.yres * 4/3; - if(pngformat == 2) vid.xres = vid.yres * 16/9; - if(pngformat == 3) { - vid.xres = vid.yres * 22/16; - while(vid.xres & 15) vid.xres++; - } - - // if(vid.pmodel == 0) vid.scale = 0.99; - calcparam(); - - renderbuffer glbuf(vid.xres, vid.yres, vid.usingGL); - glbuf.enable(); - stereo::set_viewport(0); - - // printf("format = %d, %d x %d\n", pngformat, vid.xres, vid.yres); - - darken = 0; - - int numi = (fname?1:2); - - for(int i=0; i= isize(gxcur.primes)) nextPrime(gxcur); - - fgeomextras[current_extra].current_prime_id = b; - enableFieldChange(); - if(geometry != gFieldQuotient) { - targetgeometry = gFieldQuotient; stop_game_and_switch_mode(rg::geometry); - } - } - else if(argis("-tpar")) { - torusconfig::torus_mode = torusconfig::tmSingle; - shift(); sscanf(argcs(), "%d,%d,%d", - &torusconfig::qty, - &torusconfig::dx, - &torusconfig::dy - ); - } - else if(argis("-tparx")) { - shift(); - sscanf(argcs(), "%d,%d,%d", - (int*) &torusconfig::torus_mode, - &torusconfig::sdx, - &torusconfig::sdy - ); - if(torusconfig::torus_mode == torusconfig::tmSingle) - torusconfig::qty = torusconfig::sdx, - torusconfig::dy = torusconfig::sdy; - torusconfig::activate(); - } - else if(argis("-cs")) { - shift(); CHEAT - fieldpattern::matrix M = currfp.strtomatrix(args()); - fieldpattern::subpathid = currfp.matcode[M]; - fieldpattern::subpathorder = currfp.order(M); - } - else if(argis("-csp")) { - CHEAT - currfp.findsubpath(); - } else if(argis("-quantum")) { - CHEAT; + cheat(); quantum = true; } else if(argis("-P")) { @@ -396,17 +304,13 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { PHASEFROM(2); if(itemclass(eItem(i)) == IC_TREASURE) items[i] = q; } - else if(argis("-ch")) { autocheat = true; } + else if(argis("-ch")) { cheat(); } else if(argis("-zoom")) { PHASEFROM(2); shift(); vid.scale = argf(); } else if(argis("-alpha")) { PHASEFROM(2); shift(); vid.alpha = argf(); } - else if(argis("-Y")) { - yendor::on = true; - shift(); yendor::challenge = argi(); - } else if(argis("-r")) { PHASEFROM(2); shift(); @@ -457,7 +361,7 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { PHASEFROM(2); shift(); sightrange_bonus = argi(); } else if(argis("-srx")) { - PHASEFROM(2); CHEAT; + PHASEFROM(2); cheat(); shift(); sightrange_bonus = genrange_bonus = gamerange_bonus = argi(); } else if(argis("-els")) { @@ -478,43 +382,7 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { PHASEFROM(2); else if(argis("-bright")) { bright = true; } -#if CAP_SDL - else if(argis("-pngshot")) { - PHASE(3); shift(); start_game(); - printf("saving PNG screenshot to %s\n", argcs()); - saveHighQualityShot(argcs()); - } -#endif - else if(argis("-svgsize")) { - shift(); sscanf(argcs(), "%d/%d", &svg::svgsize, &svg::divby); - } - else if(argis("-svgfont")) { - shift(); svg::font = args(); - // note: use '-svgfont latex' to produce text output as: \myfont{size}{text} - // (this is helpful with Inkscape's PDF+TeX output feature; define \myfont yourself) - } - else if(argis("-pngsize")) { - shift(); pngres = argi(); - } - else if(argis("-pngformat")) { - shift(); pngformat = argi(); - } - else if(argis("-svggamma")) { - shift(); svg::gamma = argf(); - } - else if(argis("-svgshot")) { - PHASE(3); shift(); start_game(); - printf("saving SVG screenshot to %s\n", argcs()); - svg::render(argcs()); - } -// other -#if CAP_EDIT - else if(argis("-lev")) { shift(); levelfile = args(); } - else if(argis("-pic")) { shift(); picfile = args(); } - else if(argis("-load")) { PHASE(3); shift(); mapstream::loadMap(args()); } - else if(argis("-picload")) { PHASE(3); shift(); mapeditor::loadPicFile(args()); } -#endif // graphical options else if(argis("-noscr")) { PHASE(3); @@ -523,7 +391,7 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { PHASEFROM(2); } else if(argis("-W3")) { - shift(); top_land = readland(args()); CHEAT; + shift(); top_land = readland(args()); cheat(); showstartmenu = false; } else if(argis("-top")) { @@ -535,10 +403,6 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { PHASEFROM(2); printf("HyperRogue version " VER "\n"); exit(0); } - else if(argis("-fi")) { - fieldpattern::info(); - exit(0); - } else if(argis("-L")) { printf("Treasures:\n"); for(int i=1; iland != laCA) return; vector& allcells = currentmap->allcells(); diff --git a/geom-exp.cpp b/geom-exp.cpp index fe53fb41..1324c087 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -510,4 +510,85 @@ void runGeometryExperiments() { pushScreen(showEuclideanMenu); } +#if CAP_COMMANDLINE +int read_geom_args() { + using namespace arg; + if(argis("-qpar")) { + int p; + shift(); sscanf(argcs(), "%d,%d,%d", + &p, "ientspace::rvadd, "ientspace::rvdir + ); + autocheat = true; + currfp.init(p); + } + else if(argis("-qpar2")) { + stop_game_and_switch_mode(rg::nothing); + int a, b; + shift(); sscanf(argcs(), "%d,%d", &a, &b); + using namespace fieldpattern; + current_extra = a; + + auto& gxcur = fgeomextras[current_extra]; + while(b >= isize(gxcur.primes)) nextPrime(gxcur); + + fgeomextras[current_extra].current_prime_id = b; + enableFieldChange(); + if(geometry != gFieldQuotient) { + targetgeometry = gFieldQuotient; stop_game_and_switch_mode(rg::geometry); + } + } + else if(argis("-cs")) { + shift(); cheat(); + fieldpattern::matrix M = currfp.strtomatrix(args()); + fieldpattern::subpathid = currfp.matcode[M]; + fieldpattern::subpathorder = currfp.order(M); + } + else if(argis("-csp")) { + cheat(); + currfp.findsubpath(); + } + else if(argis("-tpar")) { + torusconfig::torus_mode = torusconfig::tmSingle; + shift(); sscanf(argcs(), "%d,%d,%d", + &torusconfig::qty, + &torusconfig::dx, + &torusconfig::dy + ); + } + else if(argis("-tparx")) { + shift(); + sscanf(argcs(), "%d,%d,%d", + (int*) &torusconfig::torus_mode, + &torusconfig::sdx, + &torusconfig::sdy + ); + if(torusconfig::torus_mode == torusconfig::tmSingle) + torusconfig::qty = torusconfig::sdx, + torusconfig::dy = torusconfig::sdy; + torusconfig::activate(); + } + TOGGLE('7', nonbitrunc, stop_game_and_switch_mode(rg::bitrunc)) + else if(argis("-geo")) { + shift(); targetgeometry = (eGeometry) argi(); + if(targetgeometry != geometry) + stop_game_and_switch_mode(rg::geometry); + } + else if(argis("-gp")) { + PHASEFROM(2); + stop_game_and_switch_mode(rg::nothing); + shift(); gp::param.first = argi(); + shift(); gp::param.second = argi(); + stop_game_and_switch_mode(rg::gp); + } + else if(argis("-fi")) { + fieldpattern::info(); + exit(0); + } + else return 1; + return 0; + } + +auto ah_geom = addHook(hooks_args, 0, read_geom_args); +#endif + } diff --git a/hyper.h b/hyper.h index bcb9372d..6bb29ec8 100644 --- a/hyper.h +++ b/hyper.h @@ -1832,6 +1832,14 @@ namespace arg { // an useful macro #define PHASE(x) { if(arg::curphase > x) phaseerror(x); else if(arg::curphase < x) return 2; } #define PHASEFROM(x) { if(arg::curphase < x) return 2; } + + void cheat() { autocheat = true; cheater++; timerghost = false; } + +#define TOGGLE(x, param, act) \ +else if(args()[0] == '-' && args()[1] == x && !args()[2]) { PHASEFROM(2); showstartmenu = false; act; } \ +else if(args()[0] == '-' && args()[1] == x && args()[2] == '1') { PHASEFROM(2); showstartmenu = false; if(!param) act; } \ +else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { PHASEFROM(2); showstartmenu = false; if(param) act; } + void read(int phase); diff --git a/mapeditor.cpp b/mapeditor.cpp index 61dc72c0..fc7cc776 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -1794,4 +1794,23 @@ namespace mapeditor { } +#if CAP_EDIT +#if CAP_COMMANDLINE +string levelfile = "hyperrogue.lev"; +const char *loadlevel = NULL; +string picfile = "hyperrogue.pic"; + +int read_editor_args() { + using namespace arg; + if(argis("-lev")) { shift(); levelfile = args(); } + else if(argis("-pic")) { shift(); picfile = args(); } + else if(argis("-load")) { PHASE(3); shift(); mapstream::loadMap(args()); } + else if(argis("-picload")) { PHASE(3); shift(); mapeditor::loadPicFile(args()); } + else return 1; + return 0; + } + +auto ah_editor = addHook(hooks_args, 0, read_editor_args); +#endif +#endif } diff --git a/polygons.cpp b/polygons.cpp index 17dfee3d..d250bf20 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -2399,202 +2399,6 @@ void queuecircle(int x, int y, int size, int color, int prio = PPR_CIRCLE) { ptd.prio = prio << PSHIFT; } -#if ISMOBILE==1 -namespace svg { - bool in = false; - } -#endif - -#if ISMOBILE==0 -// svg renderer -namespace svg { - FILE *f; - bool in = false; - - ld cta(int col) { - // col >>= 24; - col &= 0xFF; - return col / 255.0; - } - - bool invisible(int col) { return (col & 0xFF) == 0; } - - ld gamma = .5; - - void fixgamma(unsigned int& color) { - unsigned char *c = (unsigned char*) (&color); - for(int i=1; i<4; i++) c[i] = 255 * pow(float(c[i] / 255.0), float(gamma)); - } - - int svgsize; - int divby = 10; - - const char* coord(int val) { - static char buf[10][20]; - static int id; - id++; id %= 10; - if(divby == 1) { - sprintf(buf[id], "%d", val); return buf[id]; - } - else if(divby <= 10) { - sprintf(buf[id], "%.1f", val*1./divby); return buf[id]; - } - else { - sprintf(buf[id], "%.2f", val*1./divby); return buf[id]; - } - } - - char* stylestr(unsigned int fill, unsigned int stroke, ld width=1) { - fixgamma(fill); - fixgamma(stroke); - static char buf[600]; - // printf("fill = %08X stroke = %08x\n", fill, stroke); - - if(stroke == 0xFF00FF) { - stroke = 0x000000FF; - - if(fill == 0x332a22ff) fill = 0x000000FF; - else if(fill == 0x686868FF) fill = 0x000000FF; - else if(fill == 0xd0d0d0FF) fill = 0x000000FF; - else fill = 0xFFFFFFFF; - } - - sprintf(buf, "style=\"stroke:#%06x;stroke-opacity:%.3" PLDF ";stroke-width:%" PLDF "px;fill:#%06x;fill-opacity:%.3" PLDF "\"", - (stroke>>8) & 0xFFFFFF, cta(stroke), - width/divby, - (fill>>8) & 0xFFFFFF, cta(fill) - ); - return buf; - } - - void circle(int x, int y, int size, int col) { - int ba = (backcolor << 8) + 0xFF; - if(!invisible(col)) - fprintf(f, "\n", - coord(x), coord(y), coord(size), stylestr(ba, col)); - } - - const string *link; - - void startstring() { - if(link) fprintf(f, "", link->c_str()); - } - - void stopstring() { - if(link) fprintf(f, ""); - } - - string font = "Times"; - - void text(int x, int y, int size, const string& str, bool frame, int col, int align) { - - double dfc = (x - vid.xcenter) * (x - vid.xcenter) + - (y - vid.ycenter) * (y - vid.ycenter); - dfc /= vid.radius; - dfc /= vid.radius; - // 0 = center, 1 = edge - dfc = 1 - dfc; - - col = 0xFF + (col << 8); - - bool uselatex = font == "latex"; - - if(!invisible(col)) { - startstring(); - string str2 = ""; - for(int i=0; i<(int) str.size(); i++) - if(str[i] == '&') - str2 += "&"; - else if(str[i] == '<') - str2 += "<"; - else if(str[i] == '>') - str2 += ">"; - else if(uselatex && str[i] == '#') - str2 += "\\#"; - else str2 += str[i]; - if(uselatex) str2 = string("\\myfont{")+coord(size)+"}{" + str2 + "}"; - fprintf(f, "%s", - stylestr(col, frame ? 0x0000000FF : 0, (1<(dfc, 1) * minwidth; - } - else dfc = .8 * minwidth; - - startstring(); - for(int i=0; i", stylestr(col, outline, (hyperbolic ? vid.radius : vid.scrsize) *dfc/256)); - stopstring(); - fprintf(f, "\n"); - } - - void render(const char *fname) { - - if(cheater) doOvergenerate(); - - dynamicval v(vid, vid); - dynamicval v2(in, true); - dynamicval v5(ringcolor, 0x808080FF); - - vid.usingGL = false; - vid.xres = vid.yres = svgsize ? svgsize : min(1 << (get_sightrange()+7), 16384); - calcparam(); - dynamicval v6(inHighQual, true); - darken = 0; - - time_t timer; - timer = time(NULL); - - char buf[128]; strftime(buf, 128, "svgshot-%y%m%d-%H%M%S.svg", localtime(&timer)); - if(!fname) fname = buf; - - f = fopen(fname, "wt"); - fprintf(f, "\n", coord(vid.xres), coord(vid.yres)); - drawfullmap(); - fprintf(f, "\n"); - fclose(f); - addMessage(XLAT("Saved the SVG shot to %1 (sightrange %2)", fname, its(get_sightrange()))); - } - } -#endif - void getcoord0(const hyperpoint& h, int& xc, int &yc, int &sc) { hyperpoint hscr; applymodel(h, hscr); diff --git a/screenshot.cpp b/screenshot.cpp new file mode 100644 index 00000000..22b6a1d9 --- /dev/null +++ b/screenshot.cpp @@ -0,0 +1,338 @@ +// Hyperbolic Rogue -- screenshots in SVG and PNG formats +// Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details + +namespace hr { + +#if ISMOBILE==1 +namespace svg { + bool in = false; + } +#endif + +#if ISMOBILE==0 +// svg renderer +namespace svg { + FILE *f; + bool in = false; + + ld cta(int col) { + // col >>= 24; + col &= 0xFF; + return col / 255.0; + } + + bool invisible(int col) { return (col & 0xFF) == 0; } + + ld gamma = .5; + + void fixgamma(unsigned int& color) { + unsigned char *c = (unsigned char*) (&color); + for(int i=1; i<4; i++) c[i] = 255 * pow(float(c[i] / 255.0), float(gamma)); + } + + int svgsize; + int divby = 10; + + const char* coord(int val) { + static char buf[10][20]; + static int id; + id++; id %= 10; + if(divby == 1) { + sprintf(buf[id], "%d", val); return buf[id]; + } + else if(divby <= 10) { + sprintf(buf[id], "%.1f", val*1./divby); return buf[id]; + } + else { + sprintf(buf[id], "%.2f", val*1./divby); return buf[id]; + } + } + + char* stylestr(unsigned int fill, unsigned int stroke, ld width=1) { + fixgamma(fill); + fixgamma(stroke); + static char buf[600]; + // printf("fill = %08X stroke = %08x\n", fill, stroke); + + if(stroke == 0xFF00FF) { + stroke = 0x000000FF; + + if(fill == 0x332a22ff) fill = 0x000000FF; + else if(fill == 0x686868FF) fill = 0x000000FF; + else if(fill == 0xd0d0d0FF) fill = 0x000000FF; + else fill = 0xFFFFFFFF; + } + + sprintf(buf, "style=\"stroke:#%06x;stroke-opacity:%.3" PLDF ";stroke-width:%" PLDF "px;fill:#%06x;fill-opacity:%.3" PLDF "\"", + (stroke>>8) & 0xFFFFFF, cta(stroke), + width/divby, + (fill>>8) & 0xFFFFFF, cta(fill) + ); + return buf; + } + + void circle(int x, int y, int size, int col) { + int ba = (backcolor << 8) + 0xFF; + if(!invisible(col)) + fprintf(f, "\n", + coord(x), coord(y), coord(size), stylestr(ba, col)); + } + + const string *link; + + void startstring() { + if(link) fprintf(f, "", link->c_str()); + } + + void stopstring() { + if(link) fprintf(f, ""); + } + + string font = "Times"; + + void text(int x, int y, int size, const string& str, bool frame, int col, int align) { + + double dfc = (x - vid.xcenter) * (x - vid.xcenter) + + (y - vid.ycenter) * (y - vid.ycenter); + dfc /= vid.radius; + dfc /= vid.radius; + // 0 = center, 1 = edge + dfc = 1 - dfc; + + col = 0xFF + (col << 8); + + bool uselatex = font == "latex"; + + if(!invisible(col)) { + startstring(); + string str2 = ""; + for(int i=0; i<(int) str.size(); i++) + if(str[i] == '&') + str2 += "&"; + else if(str[i] == '<') + str2 += "<"; + else if(str[i] == '>') + str2 += ">"; + else if(uselatex && str[i] == '#') + str2 += "\\#"; + else str2 += str[i]; + if(uselatex) str2 = string("\\myfont{")+coord(size)+"}{" + str2 + "}"; + fprintf(f, "%s", + stylestr(col, frame ? 0x0000000FF : 0, (1<(dfc, 1) * minwidth; + } + else dfc = .8 * minwidth; + + startstring(); + for(int i=0; i", stylestr(col, outline, (hyperbolic ? vid.radius : vid.scrsize) *dfc/256)); + stopstring(); + fprintf(f, "\n"); + } + + void render(const char *fname) { + + if(cheater) doOvergenerate(); + + dynamicval v(vid, vid); + dynamicval v2(in, true); + dynamicval v5(ringcolor, 0x808080FF); + + vid.usingGL = false; + vid.xres = vid.yres = svgsize ? svgsize : min(1 << (get_sightrange()+7), 16384); + calcparam(); + dynamicval v6(inHighQual, true); + darken = 0; + + time_t timer; + timer = time(NULL); + + char buf[128]; strftime(buf, 128, "svgshot-%y%m%d-%H%M%S.svg", localtime(&timer)); + if(!fname) fname = buf; + + f = fopen(fname, "wt"); + fprintf(f, "\n", coord(vid.xres), coord(vid.yres)); + drawfullmap(); + fprintf(f, "\n"); + fclose(f); + addMessage(XLAT("Saved the SVG shot to %1 (sightrange %2)", fname, its(get_sightrange()))); + } + +#if CAP_COMMANDLINE +int read_args() { + using namespace arg; + if(argis("-svgsize")) { + shift(); sscanf(argcs(), "%d/%d", &svg::svgsize, &svg::divby); + } + else if(argis("-svgfont")) { + shift(); svg::font = args(); + // note: use '-svgfont latex' to produce text output as: \myfont{size}{text} + // (this is helpful with Inkscape's PDF+TeX output feature; define \myfont yourself) + } + else if(argis("-svggamma")) { + shift(); svg::gamma = argf(); + } + else if(argis("-svgshot")) { + PHASE(3); shift(); start_game(); + printf("saving SVG screenshot to %s\n", argcs()); + svg::render(argcs()); + } + else return 1; + return 0; + } + +auto ah = addHook(hooks_args, 0, read_args); +#endif + } +#endif + +#if CAP_SDL +int pngres = 2000; +int pngformat = 0; + +#if CAP_PNG +void IMAGESAVE(SDL_Surface *s, const char *fname) { + SDL_Surface *s2 = SDL_PNGFormatAlpha(s); + SDL_SavePNG(s2, fname); + SDL_FreeSurface(s2); + } +#endif + +hookset *hooks_hqshot; + +void saveHighQualityShot(const char *fname, const char *caption, int fade) { + + resetbuffer rb; + + // int maxrange = getDistLimit() * 3/2; + + // dynamicval v3(sightrange, (cheater && sightrange < maxrange) ? maxrange : sightrange); + + if(cheater) doOvergenerate(); + + time_t timer; + timer = time(NULL); + + dynamicval v(vid, vid); + dynamicval v2(inHighQual, true); + dynamicval v6(auraNOGL, fname ? true : false); + + vid.xres = vid.yres = pngres; + if(pngformat == 1) vid.xres = vid.yres * 4/3; + if(pngformat == 2) vid.xres = vid.yres * 16/9; + if(pngformat == 3) { + vid.xres = vid.yres * 22/16; + while(vid.xres & 15) vid.xres++; + } + + // if(vid.pmodel == 0) vid.scale = 0.99; + calcparam(); + + renderbuffer glbuf(vid.xres, vid.yres, vid.usingGL); + glbuf.enable(); + stereo::set_viewport(0); + + // printf("format = %d, %d x %d\n", pngformat, vid.xres, vid.yres); + + darken = 0; + + int numi = (fname?1:2); + + for(int i=0; i