From dafd6d5dfa09bd02d0a524dbb5f440d72bbfc73d Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 23 Jan 2023 12:33:35 +0000 Subject: [PATCH] New console command "minigen" - Generates "MINIMAP.png" in your srb2home - Uses inherited automap code to render to a temporary buffer - Because am_map.c is a mess of filescope static variables right now, this only works when the automap is disabled. - Currently an equal alternate method to SLADE's map image export, but because we're in control, additional features can be added later... - TODO: Off vertically by one pixel on GHZ. Otherwise effectively identical in shape - TODO: the colours are rancid, I wonder if they were even updated for the 2.2 palette Related: - Use identical linear-time mechanisms for detecting borders of map geometry between automap and minimap - Automap was previously using iteration over all vertices - Minimap was previously pointlessly writing min/max values twice --- src/am_map.c | 121 +++++++++++++++++++++++++++++++++++++++++-------- src/am_map.h | 3 ++ src/d_netcmd.c | 1 + src/k_hud.c | 2 - src/m_misc.c | 37 +++++++++++++++ src/m_misc.h | 2 + 6 files changed, 144 insertions(+), 22 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index 1bfb145c4..8dde145ae 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -156,6 +156,9 @@ static boolean draw_grid = false; boolean automapactive = false; boolean am_recalc = false; //added : 05-02-98 : true when screen size changes static boolean am_stopped = true; +static boolean am_minigen = false; + +static UINT8 *am_buf = NULL; static INT32 f_x, f_y; // location of window on screen (always zero for both) static INT32 f_w, f_h; // size of window on screen (always the screen width and height respectively) @@ -256,25 +259,24 @@ static inline void AM_restoreScaleAndLoc(void) */ static void AM_findMinMaxBoundaries(void) { - size_t i; fixed_t a; fixed_t b; - min_x = min_y = +INT32_MAX; - max_x = max_y = -INT32_MAX; + node_t *bsp = &nodes[numnodes-1]; - for (i = 0; i < numvertexes; i++) - { - if (vertexes[i].x < min_x) - min_x = vertexes[i].x; - else if (vertexes[i].x > max_x) - max_x = vertexes[i].x; + min_x = bsp->bbox[0][BOXLEFT]; + max_x = bsp->bbox[0][BOXRIGHT]; + min_y = bsp->bbox[0][BOXBOTTOM]; + max_y = bsp->bbox[0][BOXTOP]; - if (vertexes[i].y < min_y) - min_y = vertexes[i].y; - else if (vertexes[i].y > max_y) - max_y = vertexes[i].y; - } + if (bsp->bbox[1][BOXLEFT] < min_x) + min_x = bsp->bbox[1][BOXLEFT]; + if (bsp->bbox[1][BOXRIGHT] > max_x) + max_x = bsp->bbox[1][BOXRIGHT]; + if (bsp->bbox[1][BOXBOTTOM] < min_y) + min_y = bsp->bbox[1][BOXBOTTOM]; + if (bsp->bbox[1][BOXTOP] > max_y) + max_y = bsp->bbox[1][BOXTOP]; max_w = (max_x >>= FRACTOMAPBITS) - (min_x >>= FRACTOMAPBITS); max_h = (max_y >>= FRACTOMAPBITS) - (min_y >>= FRACTOMAPBITS); @@ -282,8 +284,26 @@ static void AM_findMinMaxBoundaries(void) a = FixedDiv(f_w<>FRACBITS; + } + min_scale_mtof = a; + max_scale_mtof = f_h; + } + else + { + if (am_minigen) + { + f_w = FixedMul(b, max_w)>>FRACBITS; + } + min_scale_mtof = b; + max_scale_mtof = f_w; + } + max_scale_mtof = FixedDiv(max_scale_mtof<= vid.width || yy >= vid.height) + if (xx < 0 || yy < 0 || xx >= f_w || yy >= f_h) return; // off the screen - dest[(yy*vid.width) + xx] = cc; + am_buf[(yy*f_w) + xx] = cc; } // @@ -916,7 +936,7 @@ static void AM_drawGrid(INT32 color) // Determines visible lines, draws them. // This is LineDef based, not LineSeg based. // -static inline void AM_drawWalls(void) +static void AM_drawWalls(void) { size_t i; static mline_t l; @@ -1148,3 +1168,64 @@ void AM_Drawer(void) if (!followplayer) AM_drawCrosshair(XHAIRCOLORS); } + +UINT8 *AM_MinimapGenerate(INT32 wh) +{ + UINT8 *buf = NULL; + + if (automapactive) + return NULL; + + am_minigen = true; + + AM_drawFline = AM_drawFline_soft; // yes, even in GL + + //AM_FrameBufferInit(); + f_x = f_y = 0; + f_w = f_h = wh; + am_buf = NULL; + + //AM_LevelInit(); + AM_findMinMaxBoundaries(); + scale_mtof = FixedMul(min_scale_mtof, FRACUNIT-FRACUNIT/20); + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + + //AM_initVariables(); + f_oldloc.x = INT32_MAX; + + m_paninc.x = m_paninc.y = 0; + ftom_zoommul = FRACUNIT; + mtof_zoommul = FRACUNIT; + + m_w = FTOM(f_w); + m_h = FTOM(f_h); + + //AM_changeWindowLoc(); + m_x = min_x - FixedMul(m_w, FRACUNIT/40); + m_y = min_y - FixedMul(m_h, FRACUNIT/40); + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + + // for saving & restoring + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; + + buf = malloc(2 + (f_w*f_h)); + + am_buf = buf+2; + + //AM_clearFB(BACKGROUND); + memset(am_buf, 0xff, (f_w*f_h)); + AM_drawWalls(); + + am_buf = NULL; + am_recalc = true; + + am_minigen = false; + + buf[0] = (UINT8)f_w; + buf[1] = (UINT8)f_h; + return buf; +} diff --git a/src/am_map.h b/src/am_map.h index 56a5f9616..be32f342c 100644 --- a/src/am_map.h +++ b/src/am_map.h @@ -48,6 +48,9 @@ void AM_Start(void); // Called to force the automap to quit if the level is completed while it is up. void AM_Stop(void); +// Minimap generation +UINT8 *AM_MinimapGenerate(INT32 wh); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 56f827c46..95f45cc6d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -895,6 +895,7 @@ void D_RegisterClientCommands(void) COM_AddCommand("screenshot", M_ScreenShot); COM_AddCommand("startmovie", Command_StartMovie_f); COM_AddCommand("stopmovie", Command_StopMovie_f); + COM_AddCommand("minigen", M_MinimapGenerate); CV_RegisterVar(&cv_screenshot_option); CV_RegisterVar(&cv_screenshot_folder); diff --git a/src/k_hud.c b/src/k_hud.c index cc605df83..8abcb82f3 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3752,8 +3752,6 @@ static void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 fixed_t xoffset, yoffset; fixed_t xscale, yscale, zoom; - maxx = maxy = INT32_MAX; - minx = miny = INT32_MIN; minx = bsp->bbox[0][BOXLEFT]; maxx = bsp->bbox[0][BOXRIGHT]; miny = bsp->bbox[0][BOXBOTTOM]; diff --git a/src/m_misc.c b/src/m_misc.c index 25a6c8624..49f8f2ddc 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1749,6 +1749,43 @@ boolean M_ScreenshotResponder(event_t *ev) return true; } +void M_MinimapGenerate(void) +{ +#ifdef USE_PNG + char *filepath = va(pandf, srb2home, "MINIMAP.png"); + boolean ret = false; + UINT8 *linear = NULL; + INT32 wh = 100; + + if (gamestate != GS_LEVEL) + { + CONS_Alert(CONS_ERROR, "You must be in a level to generate a preliminary minimap!\n"); + return; + } + + linear = AM_MinimapGenerate(wh); + + if (linear == NULL) + goto failure; + + M_CreateScreenShotPalette(); + ret = M_SavePNG(filepath, linear+2, linear[0], linear[1], screenshot_palette); + +failure: + if (linear != NULL) + free(linear); + + if (ret) + { + CONS_Printf(M_GetText("%s saved.\nRemember that this is not a complete minimap,\nand must be edited before putting in-game.\n"), filepath); + } + else + { + CONS_Alert(CONS_ERROR, M_GetText("Couldn't create %s\n"), filepath); + } +#endif //#ifdef USE_PNG +} + // ========================================================================== // TRANSLATION FUNCTIONS // ========================================================================== diff --git a/src/m_misc.h b/src/m_misc.h index 97cc3e2c8..ec979dcb3 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -89,6 +89,8 @@ void M_ScreenShot(void); void M_DoScreenShot(void); boolean M_ScreenshotResponder(event_t *ev); +void M_MinimapGenerate(void); + void Command_SaveConfig_f(void); void Command_LoadConfig_f(void); void Command_ChangeConfig_f(void);