From 528d923f81ff63a19b787115a3c78c00c4a4c847 Mon Sep 17 00:00:00 2001 From: ac-stef Date: Sun, 11 Jun 2017 17:14:20 +0200 Subject: [PATCH] create map preview pictures during spectating pressing CTRL+F12 during spectating creates a clean screenshot and saves it as map preview picture modkeypressed returns 1, if a CTRL key is pressed and 0, if not screenshotpreview [lines] creates a screenshot cropped to 4:3 with a given number of lines (in the range of 144 to 480, default 240 or last given value) and jpeg quality 80 gotovantagepoint now returns 1, if the map actually has a vantage point set DOCREF screenshotpreview modkeypressed gotovantagepoint --- config/resetbinds.cfg | 2 ++ source/src/console.cpp | 2 ++ source/src/main.cpp | 60 +++++++++++++++++++++++++++++------------- source/src/texture.cpp | 2 +- source/src/worldio.cpp | 7 ++--- 5 files changed, 51 insertions(+), 22 deletions(-) diff --git a/config/resetbinds.cfg b/config/resetbinds.cfg index 971eb973..aa480460 100644 --- a/config/resetbinds.cfg +++ b/config/resetbinds.cfg @@ -68,6 +68,7 @@ alias speckey_demo_gamespeedup [ if (watchingdemo) [ if (< $gamespeed 100) [ gam alias speckey_demo_gamespeedreset [ if (watchingdemo) [ gamespeed 100; gamespeed ] ] alias speckey_demo_togglespeed [ if (watchingdemo) [ onrelease (concat gamespeed $gamespeed) ; gamespeed 1000 ] ] alias speckey_whois_spectatecn [ if (>= (spectatecn) 0) [ whois (spectatecn) ] ] +alias speckey_screenshot [ if (modkeypressed) [blankouthud 999 ; sleep 100 [ screenshotpreview ; blankouthud 0 ]] [screenshot] ] _defaultbinds 1 // do not save the following binds to saved.cfg _resetallbinds @@ -244,6 +245,7 @@ bind F9 [] bind F10 key_getdemo bind F11 key_toggleconsole bind F12 screenshot +specbind F12 speckey_screenshot bind F13 [] bind F14 [] bind F15 [] diff --git a/source/src/console.cpp b/source/src/console.cpp index 20bc94c3..35c9af98 100644 --- a/source/src/console.cpp +++ b/source/src/console.cpp @@ -206,6 +206,8 @@ void findkeycode(const char* s) } COMMAND(findkeycode, "s"); +COMMANDF(modkeypressed, "", () { intret((SDL_GetModState() & MOD_KEYS_CTRL) ? 1 : 0); }); + keym *keypressed = NULL; char *keyaction = NULL; diff --git a/source/src/main.cpp b/source/src/main.cpp index b870919b..7477f304 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -275,23 +275,35 @@ error: return -1; } -FVARP(screenshotscale, 0.1f, 1.0f, 1.0f); -VARP(jpegquality, 10, 85, 100); // best: 100 - good: 85 [default] - bad: 70 - terrible: 50 - #include "jpegenc.h" -void mapscreenshot(const char *imagepath, bool mapshot, int fileformat) +void mapscreenshot(const char *imagepath, bool mapshot, int fileformat, float scale, int height, int quality) { extern int minimaplastsize; int src_w = mapshot ? minimaplastsize : screen->w; int src_h = mapshot ? minimaplastsize : screen->h; - int dst_w = mapshot ? src_w : src_w * screenshotscale; - int dst_h = mapshot ? src_h : src_h * screenshotscale; + int dst_w = mapshot ? src_w : src_w * scale, img_w = dst_w; + int dst_h = mapshot ? src_h : src_h * scale, img_h = dst_h; + if(height) + { // create 4:3 of exact height + if(dst_w >= (dst_h * 4) / 3) + { // 4:3 or wider: crop width + dst_w = (src_w * height) / src_h; + img_h = dst_h = height; + img_w = (img_h * 4) / 3; + } + else + { // probably 5:4: crop height + img_h = height; + dst_w = img_w = (img_h * 4) / 3; + dst_h = (src_h * dst_w) / src_w; + } + } - SDL_Surface *image = creatergbsurface(dst_w, dst_h); + SDL_Surface *image = creatergbsurface(img_w, img_h); if(!image) return; - int tmpdstsize = dst_w * dst_h * 3, dstpitch = dst_w * 3; + int tmpdstsize = dst_w * dst_h * 3, tmpdstpitch = dst_w * 3; uchar *tmpdst = new uchar[tmpdstsize], *dst = (uchar *)image->pixels; if(mapshot) @@ -310,9 +322,9 @@ void mapscreenshot(const char *imagepath, bool mapshot, int fileformat) delete[] tmpdst; return; } - loopi(dst_h) + loopi(img_h) { // copy image - memcpy(dst, &tmpdst[dstpitch * i], dstpitch); + memcpy(dst, &tmpdst[tmpdstpitch * i], image->pitch); dst += image->pitch; } } @@ -327,9 +339,11 @@ void mapscreenshot(const char *imagepath, bool mapshot, int fileformat) delete[] tmpsrc; } else glReadPixels(0, 0, dst_w, dst_h, GL_RGB, GL_UNSIGNED_BYTE, tmpdst); - loopirev(dst_h) + int crop_w = height ? ((dst_w - img_w) / 2) * 3 : 0; + int crop_h = height ? (dst_h - img_h) / 2 : 0; + loopirev(img_h) { // flip image - memcpy(dst, &tmpdst[dstpitch * i], dstpitch); + memcpy(dst, &tmpdst[tmpdstpitch * (i + crop_h) + crop_w], image->pitch); dst += image->pitch; } } @@ -352,7 +366,7 @@ void mapscreenshot(const char *imagepath, bool mapshot, int fileformat) case 1: // jpeg { jpegenc jpegencoder; - jpegencoder.encode(imagepath, image, jpegquality); + jpegencoder.encode(imagepath, image, quality); break; } case 2: // png @@ -363,6 +377,8 @@ void mapscreenshot(const char *imagepath, bool mapshot, int fileformat) SDL_FreeSurface(image); } +FVARP(screenshotscale, 0.1f, 1.0f, 1.0f); +VARP(jpegquality, 10, 85, 100); // best: 100 - good: 85 [default] - bad: 70 - terrible: 50 VARP(screenshottype, 0, 1, 2); const char *getscrext() @@ -379,17 +395,26 @@ void screenshot(const char *filename) else if(getclientmap()[0]) formatstring(buf)("screenshots/%s_%s_%s%s", timestring(), behindpath(getclientmap()), modestr(gamemode, true), getscrext()); else formatstring(buf)("screenshots/%s%s", timestring(), getscrext()); path(buf); - mapscreenshot(buf, false, screenshottype); + mapscreenshot(buf, false, screenshottype, screenshotscale, 0, jpegquality); } COMMAND(screenshot, "s"); void mapshot() { defformatstring(buf)("screenshots" PATHDIVS "mapshot_%s_%s%s", behindpath(getclientmap()), timestring(), getscrext()); - mapscreenshot(buf, true, screenshottype); + mapscreenshot(buf, true, screenshottype, screenshotscale, 0, jpegquality); } COMMAND(mapshot, ""); +void screenshotpreview(int *res) +{ + static int lastres = 240; + defformatstring(buf)("packages" PATHDIVS "maps" PATHDIVS "%spreview" PATHDIVS "%s.jpg", securemapcheck(getclientmap(), false) ? "official" PATHDIVS : "", behindpath(getclientmap())); + mapscreenshot(buf, false, 1, 1.0f, (lastres = clamp(((*res ? *res : lastres) / 48) * 48, 144, 480)), 80); + reloadtexture(*textureload(buf, 3)); +} +COMMAND(screenshotpreview, "i"); + bool needsautoscreenshot = false; void screenres(int w, int h) @@ -579,7 +604,6 @@ void resetgl() gl_init(scr_w, scr_h, usedcolorbits, useddepthbits, usedfsaa); extern void reloadfonts(); - extern void reloadtextures(); extern Texture *startscreen; c2skeepalive(); if(!reloadtexture(*notexture) || @@ -739,7 +763,7 @@ static void checkmousemotion(int &dx, int &dy) } } -int ignoremouse = 5, bootstrapentropy = 0; +int ignoremouse = 5, bootstrapentropy = 2; void checkinput() { @@ -763,7 +787,7 @@ void checkinput() #endif case SDL_KEYDOWN: - if(bootstrapentropy > 0 && (--bootstrapentropy & 2)) mapscreenshot(NULL, false, -1); + if(bootstrapentropy > 0 && (--bootstrapentropy & 2)) mapscreenshot(NULL, false, -1, 1000.0f / (1000 + rnd(400)), 0, 0); case SDL_KEYUP: entropy_add_byte(event.key.keysym.sym ^ totalmillis); keypress(event.key.keysym.sym, event.key.state==SDL_PRESSED, event.key.keysym.unicode, event.key.keysym.mod); diff --git a/source/src/texture.cpp b/source/src/texture.cpp index 47ef2d1d..7da8617f 100644 --- a/source/src/texture.cpp +++ b/source/src/texture.cpp @@ -530,7 +530,7 @@ void cleanuptextures() bool reloadtexture(Texture &t) { - if(t.id) return true; + if(t.id) glDeleteTextures(1, &t.id); int xs = 1, ys = 1, bpp = 0; t.id = loadsurface(t.name, xs, ys, bpp, t.clamp, t.mipmap, t.canreduce, t.scale); t.xs = xs; diff --git a/source/src/worldio.cpp b/source/src/worldio.cpp index 1d74f375..df5014a7 100644 --- a/source/src/worldio.cpp +++ b/source/src/worldio.cpp @@ -522,7 +522,7 @@ COMMANDF(getvantagepoint, "", () result(res); }); -void gotovantagepoint() +bool gotovantagepoint() { short p[5]; if(getvantagepoint(p)) @@ -530,14 +530,15 @@ void gotovantagepoint() restoreposition(p); physent d = *player1; d.radius = d.eyeheight = d.maxeyeheight = d.aboveeye = 0.1; - if(!collide(&d, false)) return; // don't use out-of-map vantage points + if(!collide(&d, false)) return true; // don't use out-of-map vantage points } // if there is no (valid) vantage point set, we go to the first playerstart instead int s = findentity(PLAYERSTART, 0); if(ents.inrange(s)) gotoplayerstart(player1, &ents[s]); entinmap(player1); + return false; } -COMMANDF(gotovantagepoint, "", () { if(editmode) gotovantagepoint(); }); +COMMANDF(gotovantagepoint, "", () { intret((editmode || (!multiplayer(NULL) && player1->isspectating())) && gotovantagepoint() ? 1 : 0); }); void setmapinfo(const char *newlicense, const char *newcomment) {