diff --git a/animdefs.misc b/animdefs.misc index 7f369d516..5d1cbd7ac 100644 --- a/animdefs.misc +++ b/animdefs.misc @@ -1,7 +1,13 @@ +// title stuff canvastexture LOGOFADE 4 4 + +// ammo leds canvastexture PLASBLED 64 64 canvastexture PLASBFAD 4 4 canvastexture SHEENLED 128 128 canvastexture QUADRLED 64 64 canvastexture MORTLED1 256 128 canvastexture MORTLED2 64 16 + +// minimap +canvastexture MMCANVAS 80 80 diff --git a/cvarinfo.base b/cvarinfo.base index 0e45833df..d9c7f3d2c 100644 --- a/cvarinfo.base +++ b/cvarinfo.base @@ -85,6 +85,7 @@ nosave bool swwm_mm_enable = true; // show a minimap below the score counter nosave noarchive float swwm_mm_zoom = 1; // zoom level of minimap nosave bool swwm_mm_missiles = true; // show projectiles (how revolutionary) nosave int swwm_mm_colorset = 0; // 0: Demolitionist, 1: GZDoom, 2: Doom, 3: Strife, 4: Raven +nosave bool swwm_mm_usecanvas = false; // use a canvas to draw the minimap, so its pixel density is consistent with the rest of the HUD server noarchive bool swwm_iseriouslywanttoplaythiswithbd = false; // self-explanatory diff --git a/language.def_menu b/language.def_menu index 626ce03f3..6b045ba68 100644 --- a/language.def_menu +++ b/language.def_menu @@ -191,6 +191,7 @@ SWWM_GZDOOMCOLORS = "GZDoom Custom"; SWWM_DOOMCOLORS = "Vanilla Doom"; SWWM_STRIFECOLORS = "Vanilla Strife"; SWWM_RAVENCOLORS = "Vanilla Raven"; +SWWM_MM_USECANVAS = "Fixed Scale Minimap"; SWWM_AC_UNLOCKED = "Unlocked: "; SWWM_AC_INCOMPLETE = "Incomplete: "; SWWM_AC_UNDISCOVERED = "Undiscovered: "; @@ -277,6 +278,7 @@ TOOLTIP_SWWMACHIEVEMENTMENU = "View your achievements."; TOOLTIP_SWWM_MM_ENABLE = "Displays a minimap on the top right corner of the screen."; TOOLTIP_SWWM_MM_MISSILES = "Displays projectiles in the minimap. Can be toggled if this clutters too much."; TOOLTIP_SWWM_MM_COLORSET = "Choose what palette to use for the minimap."; +TOOLTIP_SWWM_MM_USECANVAS = "Rather than being drawn directly on-screen, the minimap will be drawn to a texture, maintaining the same pixel density as the rest of the HUD. Due to engine quirks, this causes the map to have a one-frame delay."; TOOLTIP_SWWMDEBUGMENU = "Don't touch this unless you know what you're doing."; TOOLTIP_SWWM_DEBUGBLAST = "Shows radii of DoExplosion calls. Damaging explosions are green, with yellow for the hotspot. Non-damaging explosions are blue, with magenta for the hotspot."; TOOLTIP_SWWM_DEBUGVIEW = "Shows collision, orientation and velocity of actors, as well as relationship lines to their target/tracer/master pointers (gold/orange/purple respectively)."; diff --git a/language.es_menu b/language.es_menu index 43b59e0d0..35a6f436b 100644 --- a/language.es_menu +++ b/language.es_menu @@ -188,6 +188,7 @@ SWWM_GZDOOMCOLORS = "Personalizado de GZDoom"; SWWM_DOOMCOLORS = "Doom Vanilla"; SWWM_STRIFECOLORS = "Strife Vanilla"; SWWM_RAVENCOLORS = "Raven Vanilla"; +SWWM_MM_USECANVAS = "Minimapa a Escala Fija"; SWWM_AC_UNLOCKED = "Desbloqueados: "; SWWM_AC_INCOMPLETE = "Incompletos: "; SWWM_AC_UNDISCOVERED = "Sin descubrir: "; @@ -275,6 +276,7 @@ TOOLTIP_SWWMACHIEVEMENTMENU = "Revisa tus logros."; TOOLTIP_SWWM_MM_ENABLE = "Muestra un minimapa en la esquina superior derecha de la pantalla."; TOOLTIP_SWWM_MM_MISSILES = "Muestra proyectiles en el minimapa. Puede ser desactivado si causa problemas de visibilidad."; TOOLTIP_SWWM_MM_COLORSET = "Selecciona que paleta usar para el minimapa."; +TOOLTIP_SWWM_MM_USECANVAS = "En vez de dibujarse directamente a la pantalla, el mapa se dibujará en una texture, mantentiendo la misma densidad de píxel que el resto del HUD. Debido a peculiaridades del motor, esto causa que el mapa tenga un frame de retardo."; TOOLTIP_SWWMDEBUGMENU = "No toques esto a menos que sepas lo que estás haciendo."; TOOLTIP_SWWM_DEBUGBLAST = "Muestra el radio de funciones DoExplosion. Las explosiones con daño son verdes, con amarillo para su punto caliente. Las explosiones sin daño son azules, con magenta para su punto caliente."; TOOLTIP_SWWM_DEBUGVIEW = "Muestra la colisión, orientación y velocidad de actores, junto con lineas de relación hacia sus punteros de objetivo/trazador/maestro (dorado/naranja/púrpura respectivamente)."; diff --git a/language.version b/language.version index fb9e5ab9a..58d934523 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r736 \cu(Mon 16 Jan 13:27:25 CET 2023)\c-"; -SWWM_SHORTVER="\cw1.3pre r736 \cu(2023-01-16 13:27:25)\c-"; +SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r737 \cu(Mon 16 Jan 13:28:10 CET 2023)\c-"; +SWWM_SHORTVER="\cw1.3pre r737 \cu(2023-01-16 13:28:10)\c-"; diff --git a/menudef.txt b/menudef.txt index 7d07b6d4a..c971e6522 100644 --- a/menudef.txt +++ b/menudef.txt @@ -153,6 +153,7 @@ OptionMenu "SWWMOptionMenu" Option "$SWWM_MM_ENABLE", "swwm_mm_enable", "YesNo" Option "$SWWM_MM_MISSILES", "swwm_mm_missiles", "YesNo" Option "$SWWM_MM_COLORSET", "swwm_mm_colorset", "SWWMMinimapColorset" + Option "$SWWM_MM_USECANVAS", "swwm_mm_usecanvas", "YesNo" Option "$SWWM_TARGET", "swwm_targeter", "SWWMTarget" ScaleSliderFix "$SWWM_BARDIST", "swwm_bardist", 0, 4000, 100, "$SWWM_UNLIMITED" Option "$SWWM_TARGETTAG", "swwm_targettags", "YesNo" diff --git a/zscript/hud/swwm_hud.zsc b/zscript/hud/swwm_hud.zsc index a44fe4116..637d0934d 100644 --- a/zscript/hud/swwm_hud.zsc +++ b/zscript/hud/swwm_hud.zsc @@ -154,6 +154,9 @@ Class SWWMStatusBar : BaseStatusBar int mm_colorset; Color mm_backcolor, mm_cdwallcolor, mm_efwallcolor, mm_fdwallcolor, mm_interlevelcolor, mm_intralevelcolor, mm_lockedcolor, mm_notseencolor, mm_portalcolor, mm_secretsectorcolor, mm_secretwallcolor, mm_specialwallcolor, mm_thingcolor, mm_thingcolor_citem, mm_thingcolor_friend, mm_thingcolor_item, mm_thingcolor_monster, mm_thingcolor_ncmonster, mm_thingcolor_shootable, mm_thingcolor_vipitem, mm_thingcolor_missile, mm_tswallcolor, mm_unexploredsecretcolor, mm_wallcolor, mm_yourcolor; bool mm_displaylocks; + transient bool mm_cvfirstdraw; + transient Canvas mm_canvas; + transient TextureID mm_canvastex; // deathmatch stuff int playercount, rank, lead; diff --git a/zscript/hud/swwm_hud_topstuff.zsc b/zscript/hud/swwm_hud_topstuff.zsc index 93d4a0179..eb6545c14 100644 --- a/zscript/hud/swwm_hud_topstuff.zsc +++ b/zscript/hud/swwm_hud_topstuff.zsc @@ -436,7 +436,7 @@ extend Class SWWMStatusBar return false; } - private void DrawMapLines( Vector2 basepos ) + private void DrawMapLines( Vector2 basepos, bool bUseCanvas = false ) { double zoomlevel = SWWMUtility.Lerp(oldminimapzoom,minimapzoom,FracTic); double zoomview = MAPVIEWDIST*zoomlevel, zoomclip = CLIPDIST*zoomlevel; @@ -482,8 +482,13 @@ extend Class SWWMStatusBar [visible, rv1, rv2] = SWWMUtility.LiangBarsky((-1,-1)*zoomclip,(1,1)*zoomclip,rv1,rv2); if ( !visible ) continue; // scale to minimap frame - rv1 *= (HALFMAPSIZE/zoomclip)*hs; - rv2 *= (HALFMAPSIZE/zoomclip)*hs; + rv1 *= HALFMAPSIZE/zoomclip; + rv2 *= HALFMAPSIZE/zoomclip; + if ( !bUseCanvas ) + { + rv1 *= hs; + rv2 *= hs; + } // offset to minimap center rv1 += basepos; rv2 += basepos; @@ -562,13 +567,18 @@ extend Class SWWMStatusBar if ( isportal ) { col = Color((col.r+mm_portalcolor.r*7)/8,(col.g+mm_portalcolor.g*7)/8,(col.b+mm_portalcolor.b*7)/8); - Screen.DrawThickLine(int(rv1.x),int(rv1.y),int(rv2.x),int(rv2.y),max(1.,hs*.25),col); + if ( bUseCanvas ) mm_canvas.DrawLine(int(rv1.x),int(rv1.y),int(rv2.x),int(rv2.y),col); + else Screen.DrawThickLine(int(rv1.x),int(rv1.y),int(rv2.x),int(rv2.y),max(1.,hs*.25),col); + } + else + { + if ( bUseCanvas ) mm_canvas.DrawLine(int(rv1.x),int(rv1.y),int(rv2.x),int(rv2.y),col); + else Screen.DrawThickLine(int(rv1.x),int(rv1.y),int(rv2.x),int(rv2.y),max(1.,hs*.5),col); } - else Screen.DrawThickLine(int(rv1.x),int(rv1.y),int(rv2.x),int(rv2.y),max(1.,hs*.5),col); } } } - private void DrawMapMarkers( Vector2 basepos ) + private void DrawMapMarkers( Vector2 basepos, bool bUseCanvas = false ) { double zoomlevel = SWWMUtility.Lerp(oldminimapzoom,minimapzoom,FracTic); double zoomview = MAPVIEWDIST*zoomlevel, zoomclip = CLIPDIST*zoomlevel; @@ -615,11 +625,13 @@ extend Class SWWMStatusBar // rotate by view rv = Actor.RotateVector(rv,ViewRot.x-90); // scale to minimap frame - rv *= (HALFMAPSIZE/zoomclip)*hs; + rv *= HALFMAPSIZE/zoomclip; + if ( !bUseCanvas ) rv *= hs; // offset to minimap center rv += basepos; // draw - Screen.DrawTexture(tx,false,rv.x,rv.y,DTA_ColorOverlay,isportal?Color(128,mm_portalcolor.r,mm_portalcolor.g,mm_portalcolor.b):Color(0,0,0,0),DTA_ScaleX,hs*scl.x,DTA_ScaleY,hs*scl.y,DTA_LegacyRenderStyle,m.GetRenderStyle(),DTA_Alpha,m.Alpha,DTA_FillColor,m.FillColor,DTA_TranslationIndex,m.Translation); + if ( bUseCanvas ) mm_canvas.DrawTexture(tx,false,rv.x,rv.y,DTA_ColorOverlay,isportal?Color(128,mm_portalcolor.r,mm_portalcolor.g,mm_portalcolor.b):Color(0,0,0,0),DTA_ScaleX,scl.x,DTA_ScaleY,scl.y,DTA_LegacyRenderStyle,m.GetRenderStyle(),DTA_Alpha,m.Alpha,DTA_FillColor,m.FillColor,DTA_TranslationIndex,m.Translation); + else Screen.DrawTexture(tx,false,rv.x,rv.y,DTA_ColorOverlay,isportal?Color(128,mm_portalcolor.r,mm_portalcolor.g,mm_portalcolor.b):Color(0,0,0,0),DTA_ScaleX,hs*scl.x,DTA_ScaleY,hs*scl.y,DTA_LegacyRenderStyle,m.GetRenderStyle(),DTA_Alpha,m.Alpha,DTA_FillColor,m.FillColor,DTA_TranslationIndex,m.Translation); } ai.Destroy(); continue; @@ -640,14 +652,16 @@ extend Class SWWMStatusBar // rotate by view rv = Actor.RotateVector(rv,ViewRot.x-90); // scale to minimap frame - rv *= (HALFMAPSIZE/zoomclip)*hs; + rv *= HALFMAPSIZE/zoomclip; + if ( !bUseCanvas ) rv *= hs; // offset to minimap center rv += basepos; // draw - Screen.DrawTexture(tx,false,rv.x,rv.y,DTA_ColorOverlay,isportal?Color(128,mm_portalcolor.r,mm_portalcolor.g,mm_portalcolor.b):Color(0,0,0,0),DTA_ScaleX,hs*scl.x,DTA_ScaleY,hs*scl.y,DTA_LegacyRenderStyle,m.GetRenderStyle(),DTA_Alpha,m.Alpha,DTA_FillColor,m.FillColor,DTA_TranslationIndex,m.Translation); + if ( bUseCanvas ) mm_canvas.DrawTexture(tx,false,rv.x,rv.y,DTA_ColorOverlay,isportal?Color(128,mm_portalcolor.r,mm_portalcolor.g,mm_portalcolor.b):Color(0,0,0,0),DTA_ScaleX,scl.x,DTA_ScaleY,scl.y,DTA_LegacyRenderStyle,m.GetRenderStyle(),DTA_Alpha,m.Alpha,DTA_FillColor,m.FillColor,DTA_TranslationIndex,m.Translation); + else Screen.DrawTexture(tx,false,rv.x,rv.y,DTA_ColorOverlay,isportal?Color(128,mm_portalcolor.r,mm_portalcolor.g,mm_portalcolor.b):Color(0,0,0,0),DTA_ScaleX,hs*scl.x,DTA_ScaleY,hs*scl.y,DTA_LegacyRenderStyle,m.GetRenderStyle(),DTA_Alpha,m.Alpha,DTA_FillColor,m.FillColor,DTA_TranslationIndex,m.Translation); } } - private void DrawMapThings( Vector2 basepos ) + private void DrawMapThings( Vector2 basepos, bool bUseCanvas = false ) { double zoomlevel = SWWMUtility.Lerp(oldminimapzoom,minimapzoom,FracTic); double zoomview = MAPVIEWDIST*zoomlevel, zoomclip = CLIPDIST*zoomlevel; @@ -756,13 +770,19 @@ extend Class SWWMStatusBar if ( visible ) { // scale to minimap frame - x0 *= (HALFMAPSIZE/zoomclip)*hs; - x1 *= (HALFMAPSIZE/zoomclip)*hs; + x0 *= HALFMAPSIZE/zoomclip; + x1 *= HALFMAPSIZE/zoomclip; + if ( !bUseCanvas ) + { + x0 *= hs; + x1 *= hs; + } // offset to minimap center x0 += basepos; x1 += basepos; // draw the line - if ( isportal ) Screen.DrawThickLine(int(x0.x),int(x0.y),int(x1.x),int(x1.y),max(1.,hs*.25),col,int(t.smoothalpha*255)); + if ( bUseCanvas ) mm_canvas.DrawLine(int(x0.x),int(x0.y),int(x1.x),int(x1.y),col,int(t.smoothalpha*255)); + else if ( isportal ) Screen.DrawThickLine(int(x0.x),int(x0.y),int(x1.x),int(x1.y),max(1.,hs*.25),col,int(t.smoothalpha*255)); else Screen.DrawThickLine(int(x0.x),int(x0.y),int(x1.x),int(x1.y),max(1.,hs*.5),col,int(t.smoothalpha*255)); drawn = true; } @@ -786,6 +806,45 @@ extend Class SWWMStatusBar return StringTable.Localize("$SWWM_PLACE"..val); } + private void DrawMinimap( int xx, int yy ) + { + // experiment: use canvas + if ( swwm_mm_usecanvas ) + { + if ( !mm_canvas ) mm_canvas = TexMan.GetCanvas("MMCANVAS"); + if ( !mm_canvastex ) mm_canvastex = TexMan.CheckForTexture("MMCANVAS"); + mm_canvas.Clear(0,0,HALFMAPSIZE*2,HALFMAPSIZE*2,mm_backcolor); + Vector2 basemappos = (HALFMAPSIZE,HALFMAPSIZE); + // draw dat stuff + DrawMapLines(basemappos,true); + DrawMapThings(basemappos,true); + DrawMapMarkers(basemappos,true); + // finally, draw the player arrow + Vector2 tv[] = {(0,-4),(-3,2),(3,2)}; + for ( int i=0; i<3; i++ ) mm_canvas.DrawLine(int(tv[i].x+HALFMAPSIZE),int(tv[i].y+HALFMAPSIZE),int(tv[(i+1)%3].x+HALFMAPSIZE),int(tv[(i+1)%3].y+HALFMAPSIZE),mm_yourcolor); + // HACK: don't draw before the first refresh of the canvas + // there is a one-frame delay for its contents to get updated when drawing in the HUD + if ( (level.maptime > 1) && mm_cvfirstdraw ) + Screen.DrawTexture(mm_canvastex,false,xx+2,yy+2,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + else Screen.Dim(mm_backcolor,1.,int((xx+2)*hs),int((yy+2)*hs),int(HALFMAPSIZE*2*hs),int(HALFMAPSIZE*2*hs)); + mm_cvfirstdraw = true; + return; + } + mm_cvfirstdraw = false; + Vector2 basemappos = (xx+HALFMAPSIZE+2,yy+HALFMAPSIZE+2); + Screen.Dim(mm_backcolor,1.,int((basemappos.x-HALFMAPSIZE)*hs),int((basemappos.y-HALFMAPSIZE)*hs),int(HALFMAPSIZE*2*hs),int(HALFMAPSIZE*2*hs)); + Screen.SetClipRect(int((basemappos.x-HALFMAPSIZE)*hs),int((basemappos.y-HALFMAPSIZE)*hs),int(HALFMAPSIZE*2*hs),int(HALFMAPSIZE*2*hs)); + // draw dat stuff + DrawMapLines(basemappos*hs); + DrawMapThings(basemappos*hs); + DrawMapMarkers(basemappos*hs); + // finally, draw the player arrow + Vector2 tv[] = {(0,-4),(-3,2),(3,2)}; + for ( int i=0; i<3; i++ ) tv[i] = (tv[i]+basemappos)*hs; + for ( int i=0; i<3; i++ ) Screen.DrawThickLine(int(tv[i].x),int(tv[i].y),int(tv[(i+1)%3].x),int(tv[(i+1)%3].y),max(1.,hs*.5),mm_yourcolor); + Screen.ClearClipRect(); + } + private void DrawTopStuff() { int xx, yy = margin; @@ -795,21 +854,7 @@ extend Class SWWMStatusBar GetMinimapColors(); xx = int(ss.x-(margin+(HALFMAPSIZE+2)*2)); Screen.DrawTexture(MiniBox,false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); - Vector2 basemappos = (xx+HALFMAPSIZE+2,yy+HALFMAPSIZE+2); - Screen.Dim(mm_backcolor,1.,int((basemappos.x-HALFMAPSIZE)*hs),int((basemappos.y-HALFMAPSIZE)*hs),int(HALFMAPSIZE*2*hs),int(HALFMAPSIZE*2*hs)); - Screen.SetClipRect(int((basemappos.x-HALFMAPSIZE)*hs),int((basemappos.y-HALFMAPSIZE)*hs),int(HALFMAPSIZE*2*hs),int(HALFMAPSIZE*2*hs)); - // draw dat stuff - DrawMapLines(basemappos*hs); - DrawMapThings(basemappos*hs); - DrawMapMarkers(basemappos*hs); - // finally, draw the player arrow - Vector2 tv[3]; - tv[0] = (0,-4); - tv[1] = (-3,2); - tv[2] = (3,2); - for ( int i=0; i<3; i++ ) tv[i] = (tv[i]+basemappos)*hs; - for ( int i=0; i<3; i++ ) Screen.DrawThickLine(int(tv[i].x),int(tv[i].y),int(tv[(i+1)%3].x),int(tv[(i+1)%3].y),max(1.,hs*.5),mm_yourcolor); - Screen.ClearClipRect(); + DrawMinimap(xx,yy); yy += ((HALFMAPSIZE+2)*2)+5; } // draw stats and timer when automap is open