From 488fface50969cc01da48e6f1585d41efa7f20d0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Mar 2017 21:40:17 +0100 Subject: [PATCH 01/29] - started port of Doom status bar to ZScript. Fullscreen HUD done with the exception of key and inventory bar. I also used the opportunity to make it a bit more resistant against badly designed inventory icons. --- src/g_game.cpp | 2 - src/g_statusbar/shared_sbar.cpp | 10 +- src/polyrenderer/poly_renderer.cpp | 1 - wadsrc/static/mapinfo/doomcommon.txt | 4 +- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/shared/player.txt | 21 ++ wadsrc/static/zscript/statusbar/doom_sbar.txt | 203 ++++++++++++++++++ .../static/zscript/statusbar/strife_sbar.txt | 8 +- 8 files changed, 236 insertions(+), 14 deletions(-) create mode 100644 wadsrc/static/zscript/statusbar/doom_sbar.txt diff --git a/src/g_game.cpp b/src/g_game.cpp index 92ccc6555..17cd67a7a 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -234,8 +234,6 @@ FString shotfile; AActor* bodyque[BODYQUESIZE]; int bodyqueslot; -void R_ExecuteSetViewSize (FViewWindow &viewwindow); - FString savename; FString BackupSaveName; diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index d8c46a1dd..7e8683eb1 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -327,6 +327,9 @@ void DBaseStatusBar::SetSize(int reltop, int hres, int vres) RelTop = reltop; HorizontalResolution = hres; VerticalResolution = vres; + int x, y; + V_CalcCleanFacs(hres, vres, SCREENWIDTH, SCREENHEIGHT, &x, &y); + defaultScale = { (double)x, (double)y }; CallSetScaled(st_scale); } @@ -1397,11 +1400,8 @@ void DBaseStatusBar::SerializeMessages(FSerializer &arc) void DBaseStatusBar::ScreenSizeChanged () { - st_scale.Callback (); - - int x, y; - V_CalcCleanFacs(HorizontalResolution, VerticalResolution, SCREENWIDTH, SCREENHEIGHT, &x, &y); - defaultScale = { (double)x, (double)y }; + // We need to recalculate the sizing info + SetSize(RelTop, HorizontalResolution, VerticalResolution); for (size_t i = 0; i < countof(Messages); ++i) { diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index 2e400975f..a8e6f34c2 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -63,7 +63,6 @@ void PolyRenderer::RenderView(player_t *player) int width = SCREENWIDTH; int height = SCREENHEIGHT; - int stHeight = gST_Y; float trueratio; ActiveRatio(width, height, &trueratio); //viewport->SetViewport(&Thread, width, height, trueratio); diff --git a/wadsrc/static/mapinfo/doomcommon.txt b/wadsrc/static/mapinfo/doomcommon.txt index c80a8a030..c033ce09c 100644 --- a/wadsrc/static/mapinfo/doomcommon.txt +++ b/wadsrc/static/mapinfo/doomcommon.txt @@ -26,8 +26,8 @@ gameinfo defaultbloodparticlecolor = "ff 00 00" backpacktype = "Backpack" armoricons = "ARM1A0", 0.5, "ARM2A0" - statusbar = "sbarinfo/doom.txt" - //statusbarclass = "DoomStatusBar" + //statusbar = "sbarinfo/doom.txt" + statusbarclass = "DoomStatusBar" intermissionmusic = "$MUSIC_DM2INT" intermissioncounter = true weaponslot = 1, "Fist", "Chainsaw" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 82987b55f..a8a1d2586 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -33,6 +33,7 @@ version "2.5" #include "zscript/statscreen/statscreen_coop.txt" #include "zscript/statusbar/statusbar.txt" +#include "zscript/statusbar/doom_sbar.txt" #include "zscript/statusbar/strife_sbar.txt" #include "zscript/statusbar/sbarinfowrapper.txt" diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 8851242b0..a37617289 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -373,6 +373,27 @@ usercmd_t original_cmd; native float GetAutoaim() const; native bool GetNoAutostartMap() const; native void SetFOV(float fov); + + clearscope int fragSum () const + { + int i; + int allfrags = 0; + int playernum = mo.PlayerNumber(); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] + && i!=playernum) + { + allfrags += frags[i]; + } + } + + // JDC hack - negative frags. + allfrags -= frags[playernum]; + return allfrags; + } + } struct PlayerClass native diff --git a/wadsrc/static/zscript/statusbar/doom_sbar.txt b/wadsrc/static/zscript/statusbar/doom_sbar.txt new file mode 100644 index 000000000..79bc6e23c --- /dev/null +++ b/wadsrc/static/zscript/statusbar/doom_sbar.txt @@ -0,0 +1,203 @@ +class DoomStatusBar : BaseStatusBar +{ + // it is not really needed to precache all textures but should be good practice to reduce execution time. + enum eImg + { + imgMEDIA0, + imgPSTRA0, + imgSTBAR, + imgSTTPRCNT, + imgSTKEYS0, + imgSTKEYS1, + imgSTKEYS2, + imgSTKEYS3, + imgSTKEYS4, + imgSTKEYS5, + imgSTKEYS6, + imgSTKEYS7, + imgSTKEYS8, + imgSTARMS, + imgSTGNUM2, + imgSTGNUM3, + imgSTGNUM4, + imgSTGNUM5, + imgSTGNUM6, + imgSTGNUM7, + imgSTYSNUM2, + imgSTYSNUM3, + imgSTYSNUM4, + imgSTYSNUM5, + imgSTYSNUM6, + imgSTYSNUM7, + imgSTFBANY, + + NUMIMG + } + + TextureID Images[NUMIMG]; + int HUDFontSpacing; + + + override void Init() + { + Super.Init(); + SetSize(32, 320, 200); + DoCommonInit(); + } + + override void NewGame () + { + DoCommonInit (); + if (CPlayer != NULL) + { + AttachToPlayer (CPlayer); + } + } + + override void Draw (int state, double TicFrac) + { + Super.Draw (state, TicFrac); + + if (state == HUD_StatusBar) + { + BeginStatusBar(320, 200, 32); + DrawMainBar (TicFrac); + } + else if (state == HUD_Fullscreen) + { + BeginHUD(320, 200, 1., false); + DrawFullScreenStuff (); + } + } + + void DoCommonInit () + { + static const String LumpNames[] = + { + "MEDIA0", "PSTRA0", "STBAR", "STTPRCNT", "STKEYS0", + "STKEYS1", "STKEYS2", "STKEYS3", "STKEYS4", "STKEYS5", "STKEYS6", "STKEYS7", "STKEYS8", + "STARMS", + "STGNUM2", "STGNUM3", "STGNUM4", "STGNUM5", "STGNUM6", "STGNUM7", + "STYSNUM2", "STYSNUM3", "STYSNUM4", "STYSNUM5", "STYSNUM6", "STYSNUM7", + "STFBANY" + }; + + for(int i = 0; i < NUMIMG; i++) + { + Images[i] = TexMan.CheckForTexture(LumpNames[i], TexMan.TYPE_MiscPatch); + } + + Font fnt = "HUDFONT_DOOM"; + if (fnt != null) HudFontSpacing = fnt.GetCharWidth("0"); + } + + protected void DrawMainBar (double TicFrac) + { + //DrawTexture(Images[imgINVBACK], (0, 0), true, 1.0, itemAlign:ALIGN_OFFSETS); + //DrawTexture(Images[imgINVTOP], (0, -8), true, 1.0, itemAlign:ALIGN_OFFSETS); + + // Health + //DrawString("Indexfont_Strife_Green", FormatNumber(CPlayer.health, 3, 5, 0), (86, -6), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, 0, 7, true, 1, 1); + } + + protected void DrawFullScreenStuff () + { + Vector2 iconbox = (40, 20); + // Draw health + let berserk = CPlayer.mo.FindInventory("PowerStrength"); + DrawTexture(Images[berserk? imgPSTRA0 : imgMEDIA0], (20, -2), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.health, 3, 0, 0), (44, -20), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + + let armor = CPlayer.mo.FindInventory("BasicArmor"); + if (armor != null) + { + DrawTexture(armor.Icon, (20, -22), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(armor.Amount, 3, 0, 0), (44, -40), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + } + Inventory ammotype1, ammotype2; + int ammoamount1, ammoamount2; + [ammotype1, ammotype2, ammoamount1, ammoamount2] = GetCurrentAmmo(); + int invY = -20; + if (ammotype1 != null) + { + DrawTexture(ammotype1.Icon, (-14, -4), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(ammoamount1, 3, 0, 0), (-25, -20), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + invY -= 20; + } + if (ammotype2 != null && ammotype2 != ammotype1) + { + DrawTexture(ammotype2.Icon, (-14, invY + 17), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(ammoamount2, 3, 0, 0), (-25, invY), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + invY -= 20; + } + if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null) + { + DrawTexture(CPlayer.mo.InvSel.Icon, (-14, invY + 17), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.mo.InvSel.Amount, 3, 0, 0), (-25, invY), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + } + if (deathmatch) + { + DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.fragSum(), 3, 0, 0), (-3, -1), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_TOP, HUdFontSpacing, true, 2, 2); + } + //drawkeybar 100, vertical, reverserows, auto, -10, 2, 0, 3, auto; + } +} + +/* +statusbar normal // Standard Doom Status bar +{ + drawimage "STBAR", 0, 168; + drawimage "STTPRCNT", 90, 171; + drawimage "STTPRCNT", 221, 171; + drawnumber 3, HUDFONT_DOOM, untranslated, ammo1, 44, 171; + drawnumber 3, HUDFONT_DOOM, untranslated, health, 90, 171; + drawnumber 3, HUDFONT_DOOM, untranslated, armor, 221, 171; + + //keys + drawswitchableimage keyslot 2 && 5, "nullimage", "STKEYS0", "STKEYS3", "STKEYS6", 239, 171; + drawswitchableimage keyslot 3 && 6, "nullimage", "STKEYS1", "STKEYS4", "STKEYS7", 239, 181; + drawswitchableimage keyslot 1 && 4, "nullimage", "STKEYS2", "STKEYS5", "STKEYS8", 239, 191; + + drawnumber 3, INDEXFONT_DOOM, untranslated, ammo(Clip), 288, 173; + drawnumber 3, INDEXFONT_DOOM, untranslated, ammo(Shell), 288, 179; + drawnumber 3, INDEXFONT_DOOM, untranslated, ammo(RocketAmmo), 288, 185; + drawnumber 3, INDEXFONT_DOOM, untranslated, ammo(Cell), 288, 191; + + drawnumber 3, INDEXFONT_DOOM, untranslated, ammocapacity(Clip), 314, 173; + drawnumber 3, INDEXFONT_DOOM, untranslated, ammocapacity(Shell), 314, 179; + drawnumber 3, INDEXFONT_DOOM, untranslated, ammocapacity(RocketAmmo), 314, 185; + drawnumber 3, INDEXFONT_DOOM, untranslated, ammocapacity(Cell), 314, 191; + gamemode deathmatch, teamgame + { + drawnumber 2, HUDFONT_DOOM, untranslated, frags, 138, 171; + } + gamemode cooperative, singleplayer + { + drawimage "STARMS", 104, 168; + drawswitchableimage weaponslot 2, "STGNUM2", "STYSNUM2", 111, 172; + drawswitchableimage weaponslot 3, "STGNUM3", "STYSNUM3", 123, 172; + drawswitchableimage weaponslot 4, "STGNUM4", "STYSNUM4", 135, 172; + drawswitchableimage weaponslot 5, "STGNUM5", "STYSNUM5", 111, 182; + drawswitchableimage weaponslot 6, "STGNUM6", "STYSNUM6", 123, 182; + drawswitchableimage weaponslot 7, "STGNUM7", "STYSNUM7", 135, 182; + } + gamemode cooperative, deathmatch, teamgame + { + drawimage translatable "STFBANY", 143, 169; + } + drawselectedinventory alternateonempty, INDEXFONT, 143, 168 + { + drawmugshot "STF", 5, 143, 168; + } +} + +statusbar inventory // Standard bar overlay (ZDoom Addition) +{ + drawinventorybar Doom, 7, INDEXFONT, 50, 170; +} + +statusbar inventoryfullscreen, fullscreenoffsets // ZDoom HUD overlay. +{ + drawinventorybar Doom, translucent, 7, INDEXFONT, -106+center, -31; +} +*/ \ No newline at end of file diff --git a/wadsrc/static/zscript/statusbar/strife_sbar.txt b/wadsrc/static/zscript/statusbar/strife_sbar.txt index cb2ef8a5c..03f12ca54 100644 --- a/wadsrc/static/zscript/statusbar/strife_sbar.txt +++ b/wadsrc/static/zscript/statusbar/strife_sbar.txt @@ -78,21 +78,22 @@ class StrifeStatusBar : BaseStatusBar if (state == HUD_StatusBar) { - fullscreenoffsets = false; + BeginStatusBar(320, 200, 32); DrawMainBar (TicFrac); } else { if (state == HUD_Fullscreen) { - fullscreenoffsets = true; + BeginHUD(320, 200, 1., false); DrawFullScreenStuff (); } // Draw pop screen (log, keys, and status) if (CurrentPop != POP_None && PopHeight < 0) { - fullscreenoffsets = false; + // This uses direct low level draw commands and would otherwise require calling + // BeginStatusBar(320, 200, false, true); DrawPopScreen (screen.GetHeight(), TicFrac); } } @@ -440,7 +441,6 @@ class StrifeStatusBar : BaseStatusBar } } } - fullscreenoffsets = false; } protected void DrawPopScreen (int bottom, double TicFrac) From 1c71d038dded3c13d09efdf677043329751aa434 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Mar 2017 23:43:19 +0100 Subject: [PATCH 02/29] - Doom keybar is working. I did not implement an equivalent to SBARINFO's DrawKeyBar. This is too limiting because it needs to consider any possibility. It really is easier to let a mod implement this itself and custom adjust it to its needs. - fixed some stuff, in particular use DrawInventoryIcon to get smarter icon lookup. --- wadsrc/static/zscript/statusbar/doom_sbar.txt | 52 ++++++++++++----- wadsrc/static/zscript/statusbar/statusbar.txt | 57 +++---------------- .../static/zscript/statusbar/strife_sbar.txt | 28 ++++----- 3 files changed, 58 insertions(+), 79 deletions(-) diff --git a/wadsrc/static/zscript/statusbar/doom_sbar.txt b/wadsrc/static/zscript/statusbar/doom_sbar.txt index 79bc6e23c..efeac9404 100644 --- a/wadsrc/static/zscript/statusbar/doom_sbar.txt +++ b/wadsrc/static/zscript/statusbar/doom_sbar.txt @@ -105,14 +105,14 @@ class DoomStatusBar : BaseStatusBar Vector2 iconbox = (40, 20); // Draw health let berserk = CPlayer.mo.FindInventory("PowerStrength"); - DrawTexture(Images[berserk? imgPSTRA0 : imgMEDIA0], (20, -2), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.health, 3, 0, 0), (44, -20), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + DrawTexture(Images[berserk? imgPSTRA0 : imgMEDIA0], (20, -2), true, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.health, 3, 0, 0), (44, -20), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); let armor = CPlayer.mo.FindInventory("BasicArmor"); if (armor != null) { - DrawTexture(armor.Icon, (20, -22), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(armor.Amount, 3, 0, 0), (44, -40), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + DrawInventoryIcon(armor, (20, -22), true, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(armor.Amount, 3, 0, 0), (44, -40), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); } Inventory ammotype1, ammotype2; int ammoamount1, ammoamount2; @@ -120,26 +120,53 @@ class DoomStatusBar : BaseStatusBar int invY = -20; if (ammotype1 != null) { - DrawTexture(ammotype1.Icon, (-14, -4), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(ammoamount1, 3, 0, 0), (-25, -20), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + DrawInventoryIcon(ammotype1, (-14, -4), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(ammoamount1, 3, 0, 0), (-25, -20), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); invY -= 20; } if (ammotype2 != null && ammotype2 != ammotype1) { - DrawTexture(ammotype2.Icon, (-14, invY + 17), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(ammoamount2, 3, 0, 0), (-25, invY), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + DrawInventoryIcon(ammotype2, (-14, invY + 17), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(ammoamount2, 3, 0, 0), (-25, invY), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); invY -= 20; } if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null) { - DrawTexture(CPlayer.mo.InvSel.Icon, (-14, invY + 17), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.mo.InvSel.Amount, 3, 0, 0), (-25, invY), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 2, 2); + DrawInventoryIcon(CPlayer.mo.InvSel, (-14, invY + 17), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.mo.InvSel.Amount, 3, 0, 0), (-25, invY), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); } if (deathmatch) { - DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.fragSum(), 3, 0, 0), (-3, -1), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_TOP, HUdFontSpacing, true, 2, 2); + DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.fragSum(), 3, 0, 0), (-3, -1), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_TOP, HUdFontSpacing, true, 1, 1); + } + + // Draw the keys. This does not use a special draw function like SBARINFO because the specifics will be different for each mod + // so it's easier to copy or reimplement the following piece of code instead of trying to write a complicated all-encompassing solution. + Vector2 keypos = (-10, 2); + int rowc = 0; + double roww = 0; + for(let i = CPlayer.mo.Inv; i != null; i = i.Inv) + { + if (i is "Key" && i.Icon.IsValid()) + { + DrawTexture(i.Icon, keypos, true, 1., ALIGN_TOP|ALIGN_RIGHT, (-1,-1), ALIGN_TOP|ALIGN_LEFT); + Vector2 size = TexMan.GetScaledSize(i.Icon); + keypos.Y += size.Y + 2; + roww = max(roww, size.X); + if (++rowc == 3) + { + keypos.Y = 2; + keypos.X -= roww + 2; + roww = 0; + rowc = 0; + } + } + } + if (CPlayer.inventorytics != 0) + { + //DrawInventoryBar("A + //drawinventorybar Doom, translucent, 7, INDEXFONT, -106+center, -31; } - //drawkeybar 100, vertical, reverserows, auto, -10, 2, 0, 3, auto; } } @@ -198,6 +225,5 @@ statusbar inventory // Standard bar overlay (ZDoom Addition) statusbar inventoryfullscreen, fullscreenoffsets // ZDoom HUD overlay. { - drawinventorybar Doom, translucent, 7, INDEXFONT, -106+center, -31; } */ \ No newline at end of file diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index 97a153e4b..dc708e20a 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -235,7 +235,7 @@ class BaseStatusBar native ui // //============================================================================ - TextureID, Vector2 GetIcon(Inventory item, int flags, bool showdepleted = false) + TextureID, Vector2 GetIcon(Inventory item, int flags, bool showdepleted = true) { TextureID icon; Vector2 scale = (1,1); @@ -245,12 +245,12 @@ class BaseStatusBar native ui bool applyscale; [icon, applyscale] = GetInventoryIcon(item, flags); - if (item.Amount == 0 && !showdepleted) return icon; + if (item.Amount == 0 && !showdepleted) return icon, scale; if (applyscale) scale = item.Scale; } - return icon; + return icon, scale; } //============================================================================ @@ -623,49 +623,6 @@ class BaseStatusBar native ui // //============================================================================ - void DrawIcon(int icontype, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0) - { - TextureID texture; - Vector2 applyscale = (1, 1); - Inventory atype1, atype2; - switch (icontype) - { - case ITYPE_PLAYERICON: - texture = CPlayer.mo.ScoreIcon; - break; - - case ITYPE_AMMO1: - case ITYPE_AMMO2: - [atype1, atype2] = GetCurrentAmmo(); - [texture, applyscale] = GetIcon(icontype == ITYPE_AMMO1? atype1 : atype2, flags, true); - break; - - case ITYPE_ARMOR: - [texture, applyscale] = GetIcon(CPlayer.mo.FindInventory("BasicArmor"), flags, false); - break; - - case ITYPE_WEAPON: - [texture, applyscale] = GetIcon(CPlayer.ReadyWeapon, flags, false); - break; - - case ITYPE_SIGIL: - [texture, applyscale] = GetIcon(CPlayer.mo.FindInventory("Sigil"), flags, false); - break; - - case ITYPE_SELECTEDINVENTORY: - if (CPlayer.mo.InvSel != NULL) - texture = CPlayer.mo.InvSel.Icon; - break; - } - DrawTexture(texture, pos, animated, screenalign, alpha, boxsize, itemAlign, flags, applyscale); - } - - //============================================================================ - // - // - // - //============================================================================ - void DrawHexenArmor(int armortype, String image, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0) { let harmor = HexenArmor(statusBar.CPlayer.mo.FindInventory("HexenArmor")); @@ -690,12 +647,14 @@ class BaseStatusBar native ui // //============================================================================ - void DrawInventoryIcon(class item, String image, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0) + void DrawInventoryIcon(Inventory item, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0) { - let texture = GetDefaultByType(item).Icon; + TextureID texture; + Vector2 applyscale = (1, 1); + [texture, applyscale] = GetIcon(item, flags, false); if (texture.IsValid()) { - DrawTexture(texture, pos, animated, screenalign, alpha, boxsize, itemAlign, flags); + DrawTexture(texture, pos, animated, alpha, screenalign, boxsize, itemAlign, flags, applyscale); } } diff --git a/wadsrc/static/zscript/statusbar/strife_sbar.txt b/wadsrc/static/zscript/statusbar/strife_sbar.txt index 03f12ca54..59e4cd71f 100644 --- a/wadsrc/static/zscript/statusbar/strife_sbar.txt +++ b/wadsrc/static/zscript/statusbar/strife_sbar.txt @@ -326,26 +326,23 @@ class StrifeStatusBar : BaseStatusBar item = CPlayer.mo.FindInventory('BasicArmor'); if (item != NULL && item.Amount > 0) { - DrawTexture(item.Icon, (2, 9), true, 1.0, itemAlign:ALIGN_OFFSETS); + DrawInventoryIcon(item, (2, 9), true, 1.0, itemAlign:ALIGN_OFFSETS); DrawString("Indexfont_Strife_Yellow", FormatNumber(item.Amount, 3, 5, 0), (34, 23), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, 0, 7, true, 1, 1); } // Ammo - Inventory ammo1, ammo2; - int ammocount1, ammocount2; - - [ammo1, ammo2, ammocount1, ammocount2] = GetCurrentAmmo (); + Inventory = GetCurrentAmmo (); if (ammo1 != NULL) { DrawString("Indexfont_Strife_Green", FormatNumber(ammo1.Amount, 3, 5, 0), (318, -6), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, 0, 7, true, 1, 1); - DrawTexture (ammo1.Icon, (290, 13), true, 1.0, itemAlign:ALIGN_OFFSETS); + DrawInventoryIcon (ammo1, (290, 13), true, 1.0, itemAlign:ALIGN_OFFSETS); } // Sigil item = CPlayer.mo.FindInventory('Sigil'); if (item != NULL) { - DrawTexture (item.Icon, (253, 7), true, 1.0, itemAlign:ALIGN_OFFSETS); + DrawInventoryIcon (item, (253, 7), true, 1.0, itemAlign:ALIGN_OFFSETS); } // Inventory @@ -356,12 +353,9 @@ class StrifeStatusBar : BaseStatusBar { if (item == CPlayer.mo.InvSel) { - DrawTexture (item.Icon, (42 + 35*i, 12), true, 1. - ItemFlash, itemAlign:ALIGN_OFFSETS, item.Amount <= 0? DI_DIM : 0); - } - if (item.Icon.isValid()) - { - DrawTexture (item.Icon, (48 + 35*i, 14), true, 1.0, itemAlign:ALIGN_OFFSETS, item.Amount <= 0? DI_DIM : 0); + DrawTexture (Images[CursorImage], (42 + 35*i, 12), true, 1. - ItemFlash, itemAlign:ALIGN_OFFSETS, item.Amount <= 0? DI_DIM : 0); } + DrawInventoryIcon (item, (48 + 35*i, 14), true, 1.0, itemAlign:ALIGN_OFFSETS, item.Amount <= 0? DI_DIM : 0); DrawString("Indexfont_Strife_Yellow", FormatNumber(item.Amount, 3, 5, 0), (81 + 35*i, 23), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, 0, 7, true, 1, 1); i++; } @@ -379,7 +373,7 @@ class StrifeStatusBar : BaseStatusBar if (armor != NULL && armor.Amount != 0) { DrawString("Indexfont_Strife_Yellow", FormatNumber(armor.Amount, 3, 0, 0), (35, -10), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, 7, true, 1, 1); - DrawTexture(armor.Icon, (45, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); + DrawInventoryIcon(armor, (45, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); } // Draw ammo @@ -391,12 +385,12 @@ class StrifeStatusBar : BaseStatusBar { // Draw primary ammo in the bottom-right corner DrawString("Indexfont_Strife_Green", FormatNumber(ammo1.Amount, 3, 0, 0), (-23, -10), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_RIGHT|ALIGN_BOTTOM, 7, true, 1, 1); - DrawTexture(ammo1.Icon, (-14, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); + DrawInventoryIcon(ammo1, (-14, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); if (ammo2 != NULL && ammo1!=ammo2) { // Draw secondary ammo just above the primary ammo DrawString("Indexfont_Strife_Green", FormatNumber(ammo1.Amount, 3, 0, 0), (-23, -48), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_RIGHT|ALIGN_BOTTOM, 7, true, 1, 1); - DrawTexture(ammo1.Icon, (-14, -55), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); + DrawInventoryIcon(ammo1, (-14, -55), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); } } @@ -415,7 +409,7 @@ class StrifeStatusBar : BaseStatusBar DrawTexture(Images[CursorImage], (-28, -15), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, ItemAlign:ALIGN_BOTTOM|ALIGN_RIGHT); } DrawString("Indexfont_Strife_Yellow", FormatNumber(CPlayer.mo.InvSel.Amount, 3, 5, 0), (-23, -10), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_BOTTOM|ALIGN_RIGHT, 7, true, 1, 1); - DrawTexture(CPlayer.mo.InvSel.Icon, (-42, -17), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, ItemAlign:ALIGN_BOTTOM|ALIGN_HCENTER, CPlayer.mo.InvSel.Amount > 0 ? 0 : DI_DIM); + DrawInventoryIcon(CPlayer.mo.InvSel, (-42, -17), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, ItemAlign:ALIGN_BOTTOM|ALIGN_HCENTER, CPlayer.mo.InvSel.Amount > 0 ? 0 : DI_DIM); } } else @@ -434,7 +428,7 @@ class StrifeStatusBar : BaseStatusBar } if (item.Icon.isValid()) { - DrawTexture(item.Icon, (-90+i*35, -5), true, 0.75, ALIGN_CENTER_BOTTOM, box, ALIGN_CENTER_BOTTOM, CPlayer.mo.InvSel.Amount > 0 ? 0 : DI_DIM); + DrawInventoryIcon(item, (-90+i*35, -5), true, 0.75, ALIGN_CENTER_BOTTOM, box, ALIGN_CENTER_BOTTOM, CPlayer.mo.InvSel.Amount > 0 ? 0 : DI_DIM); } DrawString("Indexfont_Strife_Yellow", FormatNumber(item.Amount, 3, 5, 0), (-65 + i*35, -8), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_CENTER_BOTTOM, 7, true, 1, 1); ++i; From 08b3c383040e9e6866a4a578d7aa99a94b95f110 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 26 Mar 2017 18:41:24 +0200 Subject: [PATCH 03/29] - simplified the parameters of the HUD draw functions by moving all booleans into one flags word and ordering them so that the less likely ones to be used can be made optional. - got rid of the image list in the Doom status bar. The cost of the texture lookup is mostly irrelevant here so clearer and shorter code is preferrable. - moved the box fitting code from DrawTexture into the native function to have all coordinate calculations in one place which is necessary to implement proper alignment default handling. Without higher level functions altering positioning the default can be set to automatic alignment determination, i.e. the value's sign decides where something is placed. Of course for special cases this can be overridden. - use ANIMDEFS to animate the inventory arrow, --- src/g_statusbar/sbar.h | 81 ++++-- src/g_statusbar/sbarinfo.cpp | 5 +- src/g_statusbar/sbarinfo_commands.cpp | 6 +- src/g_statusbar/shared_sbar.cpp | 249 ++++++++++++------ wadsrc/static/animdefs.txt | 8 + wadsrc/static/zscript/base.txt | 2 +- wadsrc/static/zscript/statusbar/doom_sbar.txt | 103 ++------ wadsrc/static/zscript/statusbar/statusbar.txt | 171 ++++++------ .../static/zscript/statusbar/strife_sbar.txt | 125 ++++----- 9 files changed, 400 insertions(+), 350 deletions(-) diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index 1f8fb62e4..88860291e 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -356,13 +356,6 @@ public: CENTER_BOTTOM = BOTTOM | HCENTER }; - enum ETextAlign - { - ALIGN_LEFT = 0, - ALIGN_CENTER = 1, - ALIGN_RIGHT = 2 - }; - DBaseStatusBar (); void SetSize(int reltop = 32, int hres = 320, int vres = 200); void OnDestroy() override; @@ -402,10 +395,8 @@ public: void DrawLog(); uint32_t GetTranslation() const; - void DrawGraphic(FTextureID texture, bool animate, double x, double y, double Alpha = 1., bool translatable = false, bool dim = false, - int imgAlign = TOP | LEFT, int screenalign = TOP | LEFT, bool alphamap = false, double width = -1, double height = -1); - - void DrawString(FFont *font, const FString &cstring, double x, double y, double Alpha, int translation, int align, int screenalign, int spacing = 0, bool monospaced = false, int shadowX = 0, int shadowY = 0); + void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY); + void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, bool monospaced, int shadowX, int shadowY); void BeginStatusBar(int resW, int resH, int relTop, bool completeborder = false, bool forceScaled = false); void BeginHUD(int resW, int resH, double Alpha, bool forceScaled = false); @@ -436,8 +427,6 @@ public: double Displacement; bool ShowLog; - FImageCollection Images; - player_t *CPlayer; double Alpha = 1.; @@ -471,6 +460,7 @@ extern FTexture *CrosshairImage; FTextureID GetInventoryIcon(AInventory *item, uint32_t flags, bool *applyscale); + enum DI_Flags { DI_SKIPICON = 0x1, @@ -478,11 +468,68 @@ enum DI_Flags DI_SKIPSPAWN = 0x4, DI_SKIPREADY = 0x8, DI_ALTICONFIRST = 0x10, - - DI_DRAWINBOX = 0x20, // Set when either width or height is not zero - + DI_TRANSLATABLE = 0x20, DI_FORCESCALE = 0x40, - DI_ALTERNATEONFAIL = 0x80 + DI_DIM = 0x80, + DI_DRAWCURSORFIRST = 0x100, // only for DrawInventoryBar. + DI_ALWAYSSHOWCOUNT = 0x200, // only for DrawInventoryBar. + DI_DIMDEPLETED = 0x400, + DI_DONTANIMATE = 0x800, // do not animate the texture + // These 2 flags are only used by SBARINFO + DI_DRAWINBOX = 0x1000, // Set when either width or height is not zero + DI_ALTERNATEONFAIL = 0x2000, + + DI_SCREEN_AUTO = 0, // decide based on given offsets. + DI_SCREEN_MANUAL_ALIGN = 0x4000, // If this is on, the following flags will have an effect + + DI_SCREEN_TOP = DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_VCENTER = 0x8000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_BOTTOM = 0x10000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_VOFFSET = 0x18000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_VMASK = 0x18000 | DI_SCREEN_MANUAL_ALIGN, + + DI_SCREEN_LEFT = DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_HCENTER = 0x20000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_RIGHT = 0x40000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_HOFFSET = 0x60000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_HMASK = 0x60000 | DI_SCREEN_MANUAL_ALIGN, + + DI_SCREEN_LEFT_TOP = DI_SCREEN_TOP|DI_SCREEN_LEFT, + DI_SCREEN_RIGHT_TOP = DI_SCREEN_TOP|DI_SCREEN_RIGHT, + DI_SCREEN_LEFT_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_LEFT, + DI_SCREEN_RIGHT_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_RIGHT, + DI_SCREEN_CENTER = DI_SCREEN_VCENTER|DI_SCREEN_HCENTER, + DI_SCREEN_CENTER_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_HCENTER, + DI_SCREEN_OFFSETS = DI_SCREEN_HOFFSET|DI_SCREEN_VOFFSET, + + DI_ITEM_AUTO = 0, // equivalent with bottom center, which is the default alignment. + + DI_ITEM_TOP = 0x80000, + DI_ITEM_VCENTER = 0x100000, + DI_ITEM_BOTTOM = 0, // this is the default vertical alignment + DI_ITEM_VOFFSET = 0x180000, + DI_ITEM_VMASK = 0x180000, + + DI_ITEM_LEFT = 0x200000, + DI_ITEM_HCENTER = 0, // this is the deafault horizontal alignment + DI_ITEM_RIGHT = 0x400000, + DI_ITEM_HOFFSET = 0x600000, + DI_ITEM_HMASK = 0x600000, + + DI_ITEM_LEFT_TOP = DI_ITEM_TOP|DI_ITEM_LEFT, + DI_ITEM_RIGHT_TOP = DI_ITEM_TOP|DI_ITEM_RIGHT, + DI_ITEM_LEFT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_LEFT, + DI_ITEM_RIGHT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_RIGHT, + DI_ITEM_CENTER = DI_ITEM_VCENTER|DI_ITEM_HCENTER, + DI_ITEM_CENTER_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_HCENTER, + DI_ITEM_OFFSETS = DI_ITEM_HOFFSET|DI_ITEM_VOFFSET, + + DI_TEXT_ALIGN_LEFT = 0, + DI_TEXT_ALIGN_RIGHT = 0x800000, + DI_TEXT_ALIGN_CENTER = 0x1000000, + DI_TEXT_ALIGN = 0x1800000, + + DI_ALPHAMAPPED = 0x2000000, }; #endif /* __SBAR_H__ */ diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index 438c3e3d2..ae97c7c89 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -65,9 +65,7 @@ enum imgSELECTBOX, imgCURSOR, imgINVLFGEM1, - imgINVLFGEM2, imgINVRTGEM1, - imgINVRTGEM2, }; EXTERN_CVAR(Int, fraglimit) @@ -981,8 +979,7 @@ public: static const char *InventoryBarLumps[] = { - "ARTIBOX", "SELECTBO", "INVCURS", "INVGEML1", - "INVGEML2", "INVGEMR1", "INVGEMR2", + "ARTIBOX", "SELECTBO", "INVCURS", "INVGEML1", "INVGEMR1", "USEARTIA", "USEARTIB", "USEARTIC", "USEARTID", }; TArray patchnames; diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index f9b772581..22d9b0f1d 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -2230,16 +2230,14 @@ class CommandDrawInventoryBar : public SBarInfoCommand { int offset = (style != STYLE_Strife ? (style != STYLE_HexenStrict ? -12 : -10) : 14); int yOffset = style != STYLE_HexenStrict ? 0 : -1; - statusBar->DrawGraphic(statusBar->Images[!(gametic & 4) ? - statusBar->invBarOffset + imgINVLFGEM1 : statusBar->invBarOffset + imgINVLFGEM2], x + (!vertical ? offset : yOffset), y + (vertical ? offset : yOffset), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgINVLFGEM1], x + (!vertical ? offset : yOffset), y + (vertical ? offset : yOffset), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); } // Is there something to the right? if (!noArrows && item != NULL) { int offset = (style != STYLE_Strife ? (style != STYLE_HexenStrict ? size*31+2 : size*31) : size*35-4); int yOffset = style != STYLE_HexenStrict ? 0 : -1; - statusBar->DrawGraphic(statusBar->Images[!(gametic & 4) ? - statusBar->invBarOffset + imgINVRTGEM1 : statusBar->invBarOffset + imgINVRTGEM2], x + (!vertical ? offset : yOffset), y + (vertical ? offset : yOffset), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgINVRTGEM1], x + (!vertical ? offset : yOffset), y + (vertical ? offset : yOffset), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); } } } diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 7e8683eb1..382db0c92 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1543,31 +1543,71 @@ uint32_t DBaseStatusBar::GetTranslation() const // //============================================================================ -void DBaseStatusBar::DrawGraphic(FTextureID texture, bool animate, double x, double y, double Alpha, bool translatable, bool dim, - int imgAlign, int screenalign, bool alphamap, double width, double height) +void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY) { if (!texture.isValid()) return; + FTexture *tex = (flags & DI_DONTANIMATE)? TexMan[texture] : TexMan(texture); + + double texwidth = tex->GetScaledWidthDouble() * scaleX; + double texheight = tex->GetScaledHeightDouble() * scaleY; + + if (boxwidth > 0 || boxheight > 0) + { + double scale1 = 1., scale2 = 1.; + + if (boxwidth > 0 && (boxwidth < texwidth || (flags & DI_FORCESCALE))) + { + scale1 = boxwidth / texwidth; + } + if (boxheight != -1 && (boxheight < texheight || (flags & DI_FORCESCALE))) + { + scale2 = boxheight / texheight; + } + + if (flags & DI_FORCESCALE) + { + if (boxwidth <= 0 || (boxheight > 0 && scale2 < scale1)) + scale1 = scale2; + } + else scale1 = MIN(scale1, scale2); + + boxwidth = texwidth * scale1; + boxheight = texheight * scale1; + } + else + { + boxwidth = texwidth; + boxheight = texheight; + } + + // resolve auto-alignment before making any adjustments to the position values. + if (!(flags & DI_SCREEN_MANUAL_ALIGN)) + { + if (x < 0) flags |= DI_SCREEN_RIGHT; + else flags |= DI_SCREEN_LEFT; + if (y < 0) flags |= DI_SCREEN_BOTTOM; + else flags |= DI_SCREEN_TOP; + } + Alpha *= this->Alpha; if (Alpha <= 0) return; x += drawOffset.X; y += drawOffset.Y; - FTexture *tex = animate ? TexMan(texture) : TexMan[texture]; - - switch (imgAlign & HMASK) + switch (flags & DI_ITEM_HMASK) { - case HCENTER: x -= width / 2; break; - case RIGHT: x -= width; break; - case HOFFSET: x -= tex->GetScaledLeftOffsetDouble() * width / tex->GetScaledWidthDouble(); break; + case DI_ITEM_HCENTER: x -= boxwidth / 2; break; + case DI_ITEM_RIGHT: x -= boxwidth; break; + case DI_ITEM_HOFFSET: x -= tex->GetScaledLeftOffsetDouble() * boxwidth / texwidth; break; } - switch (imgAlign & VMASK) + switch (flags & DI_ITEM_VMASK) { - case VCENTER: y -= height / 2; break; - case BOTTOM: y -= height; break; - case VOFFSET: y -= tex->GetScaledTopOffsetDouble() * height / tex->GetScaledHeightDouble(); break; + case DI_ITEM_VCENTER: y -= texheight / 2; break; + case DI_ITEM_BOTTOM: y -= texheight; break; + case DI_ITEM_VOFFSET: y -= tex->GetScaledTopOffsetDouble() * boxheight / texheight; break; } if (!fullscreenOffsets) @@ -1578,89 +1618,139 @@ void DBaseStatusBar::DrawGraphic(FTextureID texture, bool animate, double x, dou // Todo: Allow other scaling values, too. if (Scaled) { - screen->VirtualToRealCoords(x, y, width, height, HorizontalResolution, VerticalResolution, true, true); + screen->VirtualToRealCoords(x, y, boxwidth, boxheight, HorizontalResolution, VerticalResolution, true, true); } } else { double orgx, orgy; - switch (screenalign & HMASK) + switch (flags & DI_SCREEN_HMASK) { default: orgx = 0; break; - case HCENTER: orgx = screen->GetWidth() / 2; break; - case RIGHT: orgx = screen->GetWidth(); break; + case DI_SCREEN_HCENTER: orgx = screen->GetWidth() / 2; break; + case DI_SCREEN_RIGHT: orgx = screen->GetWidth(); break; } - switch (screenalign & VMASK) + switch (flags & DI_SCREEN_VMASK) { default: orgy = 0; break; - case VCENTER: orgy = screen->GetHeight() / 2; break; - case BOTTOM: orgy = screen->GetHeight(); break; + case DI_SCREEN_VCENTER: orgy = screen->GetHeight() / 2; break; + case DI_SCREEN_BOTTOM: orgy = screen->GetHeight(); break; } - if (screenalign == (RIGHT | TOP) && vid_fps) y += 10; + // move stuff in the top right corner a bit down if the fps counter is on. + if ((flags & (DI_SCREEN_HMASK|DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; DVector2 Scale = GetHUDScale(); x *= Scale.X; y *= Scale.Y; - width *= Scale.X; - height *= Scale.Y; + boxwidth *= Scale.X; + boxheight *= Scale.Y; x += orgx; y += orgy; } screen->DrawTexture(tex, x, y, DTA_TopOffset, 0, DTA_LeftOffset, 0, - DTA_DestWidthF, width, - DTA_DestHeightF, height, - DTA_TranslationIndex, translatable ? GetTranslation() : 0, - DTA_ColorOverlay, dim ? MAKEARGB(170, 0, 0, 0) : 0, + DTA_DestWidthF, boxwidth, + DTA_DestHeightF, boxheight, + DTA_TranslationIndex, (flags & DI_TRANSLATABLE) ? GetTranslation() : 0, + DTA_ColorOverlay, (flags & DI_DIM) ? MAKEARGB(170, 0, 0, 0) : 0, DTA_Alpha, Alpha, - DTA_AlphaChannel, alphamap, - DTA_FillColor, alphamap ? 0 : -1); + DTA_AlphaChannel, !!(flags & DI_ALPHAMAPPED), + DTA_FillColor, (flags & DI_ALPHAMAPPED) ? 0 : -1); } -DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawGraphic) +DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawTexture) { PARAM_SELF_PROLOGUE(DBaseStatusBar); PARAM_INT(texid); - PARAM_BOOL(animate); PARAM_FLOAT(x); PARAM_FLOAT(y); - PARAM_FLOAT(alpha); - PARAM_BOOL(translatable); - PARAM_BOOL(dim); - PARAM_INT(ialign); - PARAM_INT(salign); - PARAM_BOOL(alphamap); - PARAM_FLOAT(w); - PARAM_FLOAT(h); - self->DrawGraphic(FSetTextureID(texid), animate, x, y, alpha, translatable, dim, ialign, salign, alphamap, w, h); + PARAM_INT_DEF(flags); + PARAM_FLOAT_DEF(alpha); + PARAM_FLOAT_DEF(w); + PARAM_FLOAT_DEF(h); + PARAM_FLOAT_DEF(scaleX); + PARAM_FLOAT_DEF(scaleY); + self->DrawGraphic(FSetTextureID(texid), x, y, flags, alpha, w, h, scaleX, scaleY); + return 0; +} + +DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawImage) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + PARAM_STRING(texid); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_INT_DEF(flags); + PARAM_FLOAT_DEF(alpha); + PARAM_FLOAT_DEF(w); + PARAM_FLOAT_DEF(h); + PARAM_FLOAT_DEF(scaleX); + PARAM_FLOAT_DEF(scaleY); + self->DrawGraphic(TexMan.CheckForTexture(texid, FTexture::TEX_Any), x, y, flags, alpha, w, h, scaleX, scaleY); return 0; } //============================================================================ // -// draw stuff +// encapsulates all settings a HUD font may need // //============================================================================ -void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, double y, double Alpha, int translation, int align, int screenalign, int spacing, bool monospaced, int shadowX, int shadowY) +class DHUDFont : public DObject { - switch (align) + // this blocks CreateNew on this class which is the intent here. + DECLARE_ABSTRACT_CLASS(DHUDFont, DObject); + +public: + FFont *mFont; + int mSpacing; + bool mMonospaced; + int mShadowX; + int mShadowY; + + DHUDFont(FFont *f, int sp, bool ms, int sx, int sy) + : mFont(f), mSpacing(sp), mMonospaced(ms), mShadowX(sx), mShadowY(sy) + {} +}; + +IMPLEMENT_CLASS(DHUDFont, true, false); + +DEFINE_ACTION_FUNCTION(DHUDFont, Create) +{ + PARAM_PROLOGUE; + PARAM_POINTER(fnt, FFont); + PARAM_INT_DEF(spac); + PARAM_BOOL_DEF(mono); + PARAM_INT_DEF(sx); + PARAM_INT_DEF(sy); + ACTION_RETURN_POINTER(new DHUDFont(fnt, spac, mono, sy, sy)); +} + +//============================================================================ +// +// draw a string +// +//============================================================================ + +void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, bool monospaced, int shadowX, int shadowY) +{ + switch (flags & DI_TEXT_ALIGN) { default: break; - case ALIGN_RIGHT: + case DI_TEXT_ALIGN_RIGHT: if (!monospaced) x -= static_cast (font->StringWidth(cstring) + (spacing * cstring.Len())); else //monospaced, so just multiply the character size x -= static_cast ((spacing) * cstring.Len()); break; - case ALIGN_CENTER: + case DI_TEXT_ALIGN_CENTER: if (!monospaced) x -= static_cast (font->StringWidth(cstring) + (spacing * cstring.Len())) / 2; else //monospaced, so just multiply the character size @@ -1680,21 +1770,22 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d shadowX *= (int)Scale.X; shadowY *= (int)Scale.Y; - switch (screenalign & HMASK) + switch (flags & DI_SCREEN_HMASK) { default: orgx = 0; break; - case HCENTER: orgx = screen->GetWidth() / 2; break; - case RIGHT: orgx = screen->GetWidth(); break; + case DI_SCREEN_HCENTER: orgx = screen->GetWidth() / 2; break; + case DI_SCREEN_RIGHT: orgx = screen->GetWidth(); break; } - switch (screenalign & VMASK) + switch (flags & DI_SCREEN_VMASK) { default: orgy = 0; break; - case VCENTER: orgy = screen->GetHeight() / 2; break; - case BOTTOM: orgy = screen->GetHeight(); break; + case DI_SCREEN_VCENTER: orgy = screen->GetHeight() / 2; break; + case DI_SCREEN_BOTTOM: orgy = screen->GetHeight(); break; } - if (screenalign == (RIGHT | TOP) && vid_fps) orgy += 10; + // move stuff in the top right corner a bit down if the fps counter is on. + if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; } else { @@ -1732,23 +1823,6 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d rw = c->GetScaledWidthDouble(); rh = c->GetScaledHeightDouble(); - if (monospaced) - { - // align the character in the monospaced cell according to the general alignment to ensure that it gets positioned properly - // (i.e. right aligned text aligns to the right edge of the character and not the empty part of the cell.) - switch (align) - { - default: - break; - case ALIGN_CENTER: - rx -= (spacing) / 2; - break; - case ALIGN_RIGHT: - rx -= spacing; - break; - } - } - if (!fullscreenOffsets) { rx += ST_X; @@ -1795,39 +1869,42 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d } - - DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawString) { PARAM_SELF_PROLOGUE(DBaseStatusBar); - PARAM_POINTER(font, FFont); + PARAM_POINTER(font, DHUDFont); PARAM_STRING(string); PARAM_FLOAT(x); PARAM_FLOAT(y); - PARAM_FLOAT(alpha); - PARAM_INT(trans); - PARAM_INT(ialign); - PARAM_INT(salign); - PARAM_INT_DEF(spacing); - PARAM_BOOL_DEF(monospaced); - PARAM_INT_DEF(shadowX); - PARAM_INT_DEF(shadowY); + PARAM_INT_DEF(flags); + PARAM_INT_DEF(trans); + PARAM_FLOAT_DEF(alpha); PARAM_INT_DEF(wrapwidth); PARAM_INT_DEF(linespacing); + + // resolve auto-alignment before making any adjustments to the position values. + if (!(flags & DI_SCREEN_MANUAL_ALIGN)) + { + if (x < 0) flags |= DI_SCREEN_RIGHT; + else flags |= DI_SCREEN_LEFT; + if (y < 0) flags |= DI_SCREEN_BOTTOM; + else flags |= DI_SCREEN_TOP; + } + if (wrapwidth > 0) { - FBrokenLines *brk = V_BreakLines(font, wrapwidth, string, true); + FBrokenLines *brk = V_BreakLines(font->mFont, wrapwidth, string, true); for (int i = 0; brk[i].Width >= 0; i++) { - self->DrawString(font, brk[i].Text, x, y, alpha, trans, ialign, salign, spacing, monospaced, shadowX, shadowY); - y += font->GetHeight() + linespacing; + self->DrawString(font->mFont, brk[i].Text, x, y, flags, alpha, trans, font->mSpacing, font->mMonospaced, font->mShadowX, font->mShadowY); + y += font->mFont->GetHeight() + linespacing; } V_FreeBrokenLines(brk); } else { - self->DrawString(font, string, x, y, alpha, trans, ialign, salign, spacing, monospaced, shadowX, shadowY); + self->DrawString(font->mFont, string, x, y, flags, alpha, trans, font->mSpacing, font->mMonospaced, font->mShadowX, font->mShadowY); } return 0; } @@ -1928,9 +2005,9 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, FormatNumber) { PARAM_PROLOGUE; PARAM_INT(number); - PARAM_INT(minsize); - PARAM_INT(maxsize); - PARAM_INT(flags); + PARAM_INT_DEF(minsize); + PARAM_INT_DEF(maxsize); + PARAM_INT_DEF(flags); PARAM_STRING_DEF(prefix); static int maxvals[] = { 1, 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999 }; diff --git a/wadsrc/static/animdefs.txt b/wadsrc/static/animdefs.txt index a2f844417..e202c5d42 100644 --- a/wadsrc/static/animdefs.txt +++ b/wadsrc/static/animdefs.txt @@ -183,6 +183,14 @@ texture optional FBULB0 // The Wings of Wrath are not included, because they stop spinning when // you stop flying, so they can't be a simple animation. +texture optional INVGEML1 + pic INVGEML1 tics 4 + pic INVGEML2 tics 4 + +texture optional INVGEMR1 + pic INVGEMR1 tics 4 + pic INVGEMR2 tics 4 + switch doom 1 SW1BRCOM on pic SW2BRCOM tics 0 switch doom 1 SW1BRN1 on pic SW2BRN1 tics 0 switch doom 1 SW1BRN2 on pic SW2BRN2 tics 0 diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 6b6922ad3..a312c4688 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -169,7 +169,7 @@ struct Screen native // This is a leftover of the abandoned Inventory.DrawPowerup method. deprecated("2.5") static ui void DrawHUDTexture(TextureID tex, double x, double y) { - statusBar.DrawTexture(tex, (x, y), true, 1., BaseStatusBar.ALIGN_TOP|BaseStatusBar.ALIGN_RIGHT, (32, 32), BaseStatusBar.ALIGN_CENTER_BOTTOM); + statusBar.DrawTexture(tex, (x, y), BaseStatusBar.DI_SCREEN_RIGHT_TOP, 1., (32, 32)); } } diff --git a/wadsrc/static/zscript/statusbar/doom_sbar.txt b/wadsrc/static/zscript/statusbar/doom_sbar.txt index efeac9404..b0d0c5013 100644 --- a/wadsrc/static/zscript/statusbar/doom_sbar.txt +++ b/wadsrc/static/zscript/statusbar/doom_sbar.txt @@ -1,53 +1,29 @@ class DoomStatusBar : BaseStatusBar { - // it is not really needed to precache all textures but should be good practice to reduce execution time. - enum eImg - { - imgMEDIA0, - imgPSTRA0, - imgSTBAR, - imgSTTPRCNT, - imgSTKEYS0, - imgSTKEYS1, - imgSTKEYS2, - imgSTKEYS3, - imgSTKEYS4, - imgSTKEYS5, - imgSTKEYS6, - imgSTKEYS7, - imgSTKEYS8, - imgSTARMS, - imgSTGNUM2, - imgSTGNUM3, - imgSTGNUM4, - imgSTGNUM5, - imgSTGNUM6, - imgSTGNUM7, - imgSTYSNUM2, - imgSTYSNUM3, - imgSTYSNUM4, - imgSTYSNUM5, - imgSTYSNUM6, - imgSTYSNUM7, - imgSTFBANY, - - NUMIMG - } - - TextureID Images[NUMIMG]; - int HUDFontSpacing; + HUDFont mHUDFont; + //DrawInventoryBarParms diparms; override void Init() { Super.Init(); SetSize(32, 320, 200); - DoCommonInit(); + + // set up the inventory bar drawer. + /* + diparms.SetDefaults(HX_SHADOW); + diparms.SetTextures("SELECTBO", "ARTIBOX", "INVGEML1", "INVGEMR1"); + diparms.SetLeftArrow("INVGEML1"); + diparms.SetRightArrow("INVGEMR1"); + */ + + // Create the font used for the fullscreen HUD + Font fnt = "HUDFONT_DOOM"; + mHUDFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true, 1, 1); } override void NewGame () { - DoCommonInit (); if (CPlayer != NULL) { AttachToPlayer (CPlayer); @@ -70,27 +46,6 @@ class DoomStatusBar : BaseStatusBar } } - void DoCommonInit () - { - static const String LumpNames[] = - { - "MEDIA0", "PSTRA0", "STBAR", "STTPRCNT", "STKEYS0", - "STKEYS1", "STKEYS2", "STKEYS3", "STKEYS4", "STKEYS5", "STKEYS6", "STKEYS7", "STKEYS8", - "STARMS", - "STGNUM2", "STGNUM3", "STGNUM4", "STGNUM5", "STGNUM6", "STGNUM7", - "STYSNUM2", "STYSNUM3", "STYSNUM4", "STYSNUM5", "STYSNUM6", "STYSNUM7", - "STFBANY" - }; - - for(int i = 0; i < NUMIMG; i++) - { - Images[i] = TexMan.CheckForTexture(LumpNames[i], TexMan.TYPE_MiscPatch); - } - - Font fnt = "HUDFONT_DOOM"; - if (fnt != null) HudFontSpacing = fnt.GetCharWidth("0"); - } - protected void DrawMainBar (double TicFrac) { //DrawTexture(Images[imgINVBACK], (0, 0), true, 1.0, itemAlign:ALIGN_OFFSETS); @@ -105,39 +60,38 @@ class DoomStatusBar : BaseStatusBar Vector2 iconbox = (40, 20); // Draw health let berserk = CPlayer.mo.FindInventory("PowerStrength"); - DrawTexture(Images[berserk? imgPSTRA0 : imgMEDIA0], (20, -2), true, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.health, 3, 0, 0), (44, -20), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); + DrawImage(berserk? "PSTRA0" : "MEDIA0", (20, -2)); + DrawString(mHUDFont, FormatNumber(CPlayer.health, 3), (44, -20)); let armor = CPlayer.mo.FindInventory("BasicArmor"); if (armor != null) { - DrawInventoryIcon(armor, (20, -22), true, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(armor.Amount, 3, 0, 0), (44, -40), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); + DrawInventoryIcon(armor, (20, -22)); + DrawString(mHUDFont, FormatNumber(armor.Amount, 3), (44, -40)); } Inventory ammotype1, ammotype2; - int ammoamount1, ammoamount2; - [ammotype1, ammotype2, ammoamount1, ammoamount2] = GetCurrentAmmo(); + [ammotype1, ammotype2] = GetCurrentAmmo(); int invY = -20; if (ammotype1 != null) { - DrawInventoryIcon(ammotype1, (-14, -4), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(ammoamount1, 3, 0, 0), (-25, -20), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); + DrawInventoryIcon(ammotype1, (-14, -4)); + DrawString(mHUDFont, FormatNumber(ammotype1.Amount, 3), (-30, -20), DI_TEXT_ALIGN_RIGHT); invY -= 20; } if (ammotype2 != null && ammotype2 != ammotype1) { - DrawInventoryIcon(ammotype2, (-14, invY + 17), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(ammoamount2, 3, 0, 0), (-25, invY), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); + DrawInventoryIcon(ammotype2, (-14, invY + 17)); + DrawString(mHUDFont, FormatNumber(ammotype2.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); invY -= 20; } if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null) { - DrawInventoryIcon(CPlayer.mo.InvSel, (-14, invY + 17), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, iconbox, ALIGN_BOTTOM|ALIGN_HCENTER); - DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.mo.InvSel.Amount, 3, 0, 0), (-25, invY), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_BOTTOM, HUdFontSpacing, true, 1, 1); + DrawInventoryIcon(CPlayer.mo.InvSel, (-14, invY + 17)); + DrawString(mHUDFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); } if (deathmatch) { - DrawString("HUDFONT_DOOM", FormatNumber(CPlayer.fragSum(), 3, 0, 0), (-3, -1), 1., Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_RIGHT|ALIGN_TOP, HUdFontSpacing, true, 1, 1); + DrawString(mHUDFont, FormatNumber(CPlayer.fragSum(), 3), (-3, 1), DI_TEXT_ALIGN_RIGHT); } // Draw the keys. This does not use a special draw function like SBARINFO because the specifics will be different for each mod @@ -149,7 +103,7 @@ class DoomStatusBar : BaseStatusBar { if (i is "Key" && i.Icon.IsValid()) { - DrawTexture(i.Icon, keypos, true, 1., ALIGN_TOP|ALIGN_RIGHT, (-1,-1), ALIGN_TOP|ALIGN_LEFT); + DrawTexture(i.Icon, keypos, DI_SCREEN_RIGHT_TOP|DI_ITEM_LEFT_TOP); Vector2 size = TexMan.GetScaledSize(i.Icon); keypos.Y += size.Y + 2; roww = max(roww, size.X); @@ -164,8 +118,7 @@ class DoomStatusBar : BaseStatusBar } if (CPlayer.inventorytics != 0) { - //DrawInventoryBar("A - //drawinventorybar Doom, translucent, 7, INDEXFONT, -106+center, -31; + //DrawInventoryBar(diparms, (0, 0), 7, ALIGN_CENTER_BOTTOM, ALIGN_CENTER_BOTTOM); } } } diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index dc708e20a..e7c85f615 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -15,6 +15,12 @@ struct MugShot } } +class HUDFont native ui +{ + // This is intentionally opaque to the script side. + native static HUDFont Create(Font fnt, int spacing = 0, bool monospaced = false, int shadowx = 0, int shadowy = 0); +} + class BaseStatusBar native ui { @@ -65,8 +71,66 @@ class BaseStatusBar native ui DI_TRANSLATABLE = 0x20, DI_FORCESCALE = 0x40, DI_DIM = 0x80, - }; + DI_DRAWCURSORFIRST = 0x100, // only for DrawInventoryBar. + DI_ALWAYSSHOWCOUNT = 0x200, // only for DrawInventoryBar. + DI_DIMDEPLETED = 0x400, + DI_DONTANIMATE = 0x800, // do not animate the texture + // These 2 flags are only used by SBARINFO + DI_DRAWINBOX = 0x1000, // Set when either width or height is not zero + DI_ALTERNATEONFAIL = 0x2000, + + DI_SCREEN_AUTO = 0, // decide based on given offsets. + DI_SCREEN_MANUAL_ALIGN = 0x4000, // If this is on, the following flags will have an effect + + DI_SCREEN_TOP = DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_VCENTER = 0x8000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_BOTTOM = 0x10000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_VOFFSET = 0x18000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_VMASK = 0x18000 | DI_SCREEN_MANUAL_ALIGN, + + DI_SCREEN_LEFT = DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_HCENTER = 0x20000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_RIGHT = 0x40000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_HOFFSET = 0x60000 | DI_SCREEN_MANUAL_ALIGN, + DI_SCREEN_HMASK = 0x60000 | DI_SCREEN_MANUAL_ALIGN, + + DI_SCREEN_LEFT_TOP = DI_SCREEN_TOP|DI_SCREEN_LEFT, + DI_SCREEN_RIGHT_TOP = DI_SCREEN_TOP|DI_SCREEN_RIGHT, + DI_SCREEN_LEFT_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_LEFT, + DI_SCREEN_RIGHT_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_RIGHT, + DI_SCREEN_CENTER = DI_SCREEN_VCENTER|DI_SCREEN_HCENTER, + DI_SCREEN_CENTER_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_HCENTER, + DI_SCREEN_OFFSETS = DI_SCREEN_HOFFSET|DI_SCREEN_VOFFSET, + + DI_ITEM_AUTO = 0, // equivalent with bottom center, which is the default alignment. + + DI_ITEM_TOP = 0x80000, + DI_ITEM_VCENTER = 0x100000, + DI_ITEM_BOTTOM = 0, // this is the default vertical alignment + DI_ITEM_VOFFSET = 0x180000, + DI_ITEM_VMASK = 0x180000, + + DI_ITEM_LEFT = 0x200000, + DI_ITEM_HCENTER = 0, // this is the deafault horizontal alignment + DI_ITEM_RIGHT = 0x400000, + DI_ITEM_HOFFSET = 0x600000, + DI_ITEM_HMASK = 0x600000, + + DI_ITEM_LEFT_TOP = DI_ITEM_TOP|DI_ITEM_LEFT, + DI_ITEM_RIGHT_TOP = DI_ITEM_TOP|DI_ITEM_RIGHT, + DI_ITEM_LEFT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_LEFT, + DI_ITEM_RIGHT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_RIGHT, + DI_ITEM_CENTER = DI_ITEM_VCENTER|DI_ITEM_HCENTER, + DI_ITEM_CENTER_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_HCENTER, + DI_ITEM_OFFSETS = DI_ITEM_HOFFSET|DI_ITEM_VOFFSET, + + DI_TEXT_ALIGN_LEFT = 0, + DI_TEXT_ALIGN_RIGHT = 0x800000, + DI_TEXT_ALIGN_CENTER = 0x1000000, + DI_ALPHAMAPPED = 0x2000000, + }; + enum IconType { ITYPE_PLAYERICON = 1000, @@ -87,32 +151,6 @@ class BaseStatusBar native ui HEXENARMOR_AMULET, }; - enum EAlign - { - ALIGN_TOP = 0, - ALIGN_VCENTER = 1, - ALIGN_BOTTOM = 2, - ALIGN_VOFFSET = 3, - ALIGN_VMASK = 3, - - ALIGN_LEFT = 0, - ALIGN_HCENTER = 4, - ALIGN_RIGHT = 8, - ALIGN_HOFFSET = 12, - ALIGN_HMASK = 12, - - ALIGN_CENTER = ALIGN_VCENTER|ALIGN_HCENTER, - ALIGN_CENTER_BOTTOM = ALIGN_BOTTOM|ALIGN_HCENTER, - ALIGN_OFFSETS = ALIGN_HOFFSET|ALIGN_VOFFSET - }; - - enum ETextAlign - { - TEXT_LEFT = 0, - TEXT_CENTER = 1, - TEXT_RIGHT = 2 - }; - enum SBGameModes { GAMEMODE_SINGLEPLAYER = 0x1, @@ -193,9 +231,10 @@ class BaseStatusBar native ui // These functions are kept native solely for performance reasons. They get called repeatedly and can drag down performance easily if they get too slow. native Inventory ValidateInvFirst (int numVisible) const; native static TextureID, bool GetInventoryIcon(Inventory item, int flags); - native void DrawGraphic(TextureID texture, bool animate, Vector2 pos, double Alpha, bool translatable, bool dim, int imgAlign, int screenalign, bool alphamap, Vector2 box); - native void DrawString(Font font, String string, Vector2 pos , double Alpha, int translation, int align, int screenalign, int spacing=0, bool monospaced = false, int shadowX=0, int shadowY=0, int wrapwidth = -1, int linespacing = 4); - native static String FormatNumber(int number, int minsize, int maxsize, int format, String prefix = ""); + native void DrawTexture(TextureID texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1)); + native void DrawImage(String texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1)); + native void DrawString(HUDFont font, String string, Vector2 pos, int flags = 0, int translation = Font.CR_UNTRANSLATED, double Alpha = 1., int wrapwidth = -1, int linespacing = 4); + native static String FormatNumber(int number, int minsize = 0, int maxsize = 0, int format = 0, String prefix = ""); //============================================================================ @@ -535,7 +574,7 @@ class BaseStatusBar native ui if (icon.IsValid()) { // Each icon gets a 32x32 block. - DrawTexture(icon, pos, true, 1.0, ALIGN_TOP|ALIGN_RIGHT, (POWERUPICONSIZE, POWERUPICONSIZE), ALIGN_CENTER_BOTTOM); + DrawTexture(icon, pos, DI_SCREEN_RIGHT_TOP, 1.0, (POWERUPICONSIZE, POWERUPICONSIZE)); pos.x -= POWERUPICONSIZE; if (pos.x < -maxpos) { @@ -560,70 +599,13 @@ class BaseStatusBar native ui return Translation.MakeID(TRANSLATION_Players, CPlayer.mo.PlayerNumber()); } - //============================================================================ - // - // draw stuff - // - //============================================================================ - - void DrawTexture(TextureID texture, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0, Vector2 scale = (1., 1.) ) - { - if (!texture.IsValid()) return; // nothing to draw - - alpha *= self.alpha; - if (alpha <= 0) return; // invisible - - Vector2 texsize = TexMan.GetScaledSize(texture); - texsize.X *= scale.X; - texsize.Y *= scale.Y; - if (boxsize.X > 0 || boxsize.Y > 0) - { - double scale1 = 1., scale2 = 1.; - - if (boxsize.X != -1 && (boxsize.X < texsize.X || (flags & DI_FORCESCALE))) - { - scale1 = boxsize.X / texsize.X; - } - if (boxsize.Y != -1 && (boxsize.Y < texsize.Y || (flags & DI_FORCESCALE))) - { - scale2 = boxsize.Y / texsize.Y; - } - - if (flags & DI_FORCESCALE) - { - if (boxsize.X == -1 || (boxsize.Y != -1 && scale2 < scale1)) - scale1 = scale2; - } - else scale1 = min(scale1, scale2); - - boxsize = texsize * scale1; - } - else - { - boxsize = texsize; - } - DrawGraphic(texture, animated, pos, Alpha, !!(flags & DI_TRANSLATABLE), !!(flags & DI_DIM), itemAlign, screenAlign, false, boxsize); - } - //============================================================================ // // // //============================================================================ - void DrawImage(String imagename, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0, Vector2 scale = (1., 1.) ) - { - let tex = TexMan.CheckForTexture(imagename, TexMan.TYPE_MiscPatch); - DrawTexture(tex, pos, animated, screenalign, alpha, boxsize, itemAlign, flags, scale); - } - - //============================================================================ - // - // - // - //============================================================================ - - void DrawHexenArmor(int armortype, String image, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0) + void DrawHexenArmor(int armortype, String image, Vector2 pos, int flags = 0, double alpha = 1.0, Vector2 boxsize = (-1, -1), Vector2 scale = (1.,1.)) { let harmor = HexenArmor(statusBar.CPlayer.mo.FindInventory("HexenArmor")); if (harmor != NULL) @@ -638,7 +620,7 @@ class BaseStatusBar native ui } else return; } - DrawImage(image, pos, animated, screenalign, alpha, boxsize, itemAlign, flags); + DrawImage(image, pos, flags, alpha, boxsize, scale); } //============================================================================ @@ -647,14 +629,17 @@ class BaseStatusBar native ui // //============================================================================ - void DrawInventoryIcon(Inventory item, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = ALIGN_TOP|ALIGN_LEFT, Vector2 boxsize = (-1, -1), int itemAlign = ALIGN_TOP|ALIGN_LEFT, int flags = 0) + void DrawInventoryIcon(Inventory item, Vector2 pos, int flags = 0, double alpha = 1.0, Vector2 boxsize = (-1, -1), Vector2 scale = (1.,1.)) { TextureID texture; - Vector2 applyscale = (1, 1); + Vector2 applyscale; [texture, applyscale] = GetIcon(item, flags, false); if (texture.IsValid()) { - DrawTexture(texture, pos, animated, alpha, screenalign, boxsize, itemAlign, flags, applyscale); + if ((flags & DI_DIMDEPLETED) && item.Amount <= 0) flags |= DI_DIM; + applyscale.X *= scale.X; + applyscale.Y *= scale.Y; + DrawTexture(texture, pos, flags, alpha, boxsize, applyscale); } } diff --git a/wadsrc/static/zscript/statusbar/strife_sbar.txt b/wadsrc/static/zscript/statusbar/strife_sbar.txt index 59e4cd71f..b90a30a76 100644 --- a/wadsrc/static/zscript/statusbar/strife_sbar.txt +++ b/wadsrc/static/zscript/statusbar/strife_sbar.txt @@ -15,23 +15,10 @@ class StrifeStatusBar : BaseStatusBar { imgINVCURS, imgCURSOR01, - imgINVBACK, - imgINVTOP, imgINVPOP, imgINVPOP2, imgINVPBAK, imgINVPBAK2, - imgFONG0, - imgFONG1, - imgFONG2, - imgFONG3, - imgFONG4, - imgFONG5, - imgFONG6, - imgFONG7, - imgFONG8, - imgFONG9, - imgFONG_PERCENT, imgFONY0, imgFONY1, imgFONY2, @@ -43,10 +30,6 @@ class StrifeStatusBar : BaseStatusBar imgFONY8, imgFONY9, imgFONY_PERCENT, - imgCOMM, - imgMEDI, - imgARM1, - imgARM2, imgNEGATIVE, }; @@ -55,17 +38,40 @@ class StrifeStatusBar : BaseStatusBar int CurrentPop, PendingPop, PopHeight, PopHeightChange; int KeyPopPos, KeyPopScroll; double ItemFlash; + + HUDFont mYelFont, mGrnFont, mBigFont; override void Init() { + static const Name strifeLumpNames[] = + { + "INVCURS", "CURSOR01", "INVPOP", "INVPOP2", + "INVPBAK", "INVPBAK2", + "INVFONY0", "INVFONY1", "INVFONY2", "INVFONY3", "INVFONY4", + "INVFONY5", "INVFONY6", "INVFONY7", "INVFONY8", "INVFONY9", + "INVFONY%", "" + + }; + Super.Init(); SetSize(32, 320, 200); - DoCommonInit(); + Reset(); + + for(int i = 0; i <= imgNEGATIVE; i++) + { + Images[i] = TexMan.CheckForTexture(strifeLumpNames[i], TexMan.TYPE_MiscPatch); + } + + CursorImage = Images[imgINVCURS].IsValid() ? imgINVCURS : imgCURSOR01; + + mYelFont = HUDFont.Create("Indexfont_Strife_Yellow", 7, true, 1, 1); + mGrnFont = HUDFont.Create("Indexfont_Strife_Green", 7, true, 1, 1); + mBigFont = HUDFont.Create("BigFont", 0, false, 2, 2); } override void NewGame () { - DoCommonInit (); + Reset (); if (CPlayer != NULL) { AttachToPlayer (CPlayer); @@ -142,29 +148,8 @@ class StrifeStatusBar : BaseStatusBar return false; } - void DoCommonInit () + void Reset () { - static const String strifeLumpNames[] = - { - "INVCURS", "CURSOR01", "INVBACK", "INVTOP", "INVPOP", "INVPOP2", - "INVPBAK", "INVPBAK2", - "INVFONG0", "INVFONG1", "INVFONG2", "INVFONG3", "INVFONG4", - "INVFONG5", "INVFONG6", "INVFONG7", "INVFONG8", "INVFONG9", - "INVFONG%", - "INVFONY0", "INVFONY1", "INVFONY2", "INVFONY3", "INVFONY4", - "INVFONY5", "INVFONY6", "INVFONY7", "INVFONY8", "INVFONY9", - "INVFONY%", - "I_COMM", "I_MDKT", "I_ARM1", "I_ARM2", "" - - }; - - for(int i = 0; i <= imgNEGATIVE; i++) - { - Images[i] = TexMan.CheckForTexture(strifeLumpNames[i], TexMan.TYPE_MiscPatch); - } - - CursorImage = Images[imgINVCURS].IsValid() ? imgINVCURS : imgCURSOR01; - CurrentPop = POP_None; PendingPop = POP_NoChange; PopHeight = 0; @@ -305,11 +290,11 @@ class StrifeStatusBar : BaseStatusBar DrawPopScreen (Scaled ? (ST_Y - 8) * screen.GetHeight() / 200 : ST_Y - 8, TicFrac); } - DrawTexture(Images[imgINVBACK], (0, 0), true, 1.0, itemAlign:ALIGN_OFFSETS); - DrawTexture(Images[imgINVTOP], (0, -8), true, 1.0, itemAlign:ALIGN_OFFSETS); + DrawImage("INVBACK", (0, 0), DI_ITEM_OFFSETS); + DrawImage("INVTOP", (0, -8), DI_ITEM_OFFSETS); // Health - DrawString("Indexfont_Strife_Green", FormatNumber(CPlayer.health, 3, 5, 0), (86, -6), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, 0, 7, true, 1, 1); + DrawString(mGrnFont, FormatNumber(CPlayer.health, 3, 5), (79, -6), DI_TEXT_ALIGN_RIGHT); int points; if (CPlayer.cheats & CF_GODMODE) { @@ -326,23 +311,23 @@ class StrifeStatusBar : BaseStatusBar item = CPlayer.mo.FindInventory('BasicArmor'); if (item != NULL && item.Amount > 0) { - DrawInventoryIcon(item, (2, 9), true, 1.0, itemAlign:ALIGN_OFFSETS); - DrawString("Indexfont_Strife_Yellow", FormatNumber(item.Amount, 3, 5, 0), (34, 23), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, 0, 7, true, 1, 1); + DrawInventoryIcon(item, (2, 9), DI_ITEM_OFFSETS); + DrawString(mYelFont, FormatNumber(item.Amount, 3, 5), (27, 23), DI_TEXT_ALIGN_RIGHT); } // Ammo - Inventory = GetCurrentAmmo (); + Inventory ammo1 = GetCurrentAmmo (); if (ammo1 != NULL) { - DrawString("Indexfont_Strife_Green", FormatNumber(ammo1.Amount, 3, 5, 0), (318, -6), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, 0, 7, true, 1, 1); - DrawInventoryIcon (ammo1, (290, 13), true, 1.0, itemAlign:ALIGN_OFFSETS); + DrawString(mGrnFont, FormatNumber(ammo1.Amount, 3, 5), (311, -6), DI_TEXT_ALIGN_RIGHT); + DrawInventoryIcon (ammo1, (290, 13), DI_ITEM_OFFSETS); } // Sigil item = CPlayer.mo.FindInventory('Sigil'); if (item != NULL) { - DrawInventoryIcon (item, (253, 7), true, 1.0, itemAlign:ALIGN_OFFSETS); + DrawInventoryIcon (item, (253, 7), DI_ITEM_OFFSETS); } // Inventory @@ -351,29 +336,29 @@ class StrifeStatusBar : BaseStatusBar i = 0; for (item = CPlayer.mo.InvFirst; item != NULL && i < 6; item = item.NextInv()) { + int flags = item.Amount <= 0? DI_ITEM_OFFSETS|DI_DIM : DI_ITEM_OFFSETS; if (item == CPlayer.mo.InvSel) { - DrawTexture (Images[CursorImage], (42 + 35*i, 12), true, 1. - ItemFlash, itemAlign:ALIGN_OFFSETS, item.Amount <= 0? DI_DIM : 0); + DrawTexture (Images[CursorImage], (42 + 35*i, 12), flags, 1. - ItemFlash); } - DrawInventoryIcon (item, (48 + 35*i, 14), true, 1.0, itemAlign:ALIGN_OFFSETS, item.Amount <= 0? DI_DIM : 0); - DrawString("Indexfont_Strife_Yellow", FormatNumber(item.Amount, 3, 5, 0), (81 + 35*i, 23), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, 0, 7, true, 1, 1); + DrawInventoryIcon (item, (48 + 35*i, 14), flags); + DrawString(mYelFont, FormatNumber(item.Amount, 3, 5), (75 + 35*i, 23), DI_TEXT_ALIGN_RIGHT); i++; } } protected void DrawFullScreenStuff () { - // Draw health - - DrawString("Indexfont_Strife_Green", FormatNumber(CPlayer.health, 3, 0, 0), (4, -10), 1., (CPlayer.health < CPlayer.mo.RunHealth)? Font.CR_BRICK : Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, 7, true, 1, 1); - DrawTexture(Images[imgMEDI], (14, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); + // Draw health (use red color if health is below the run health threashold.) + DrawString(mGrnFont, FormatNumber(CPlayer.health, 3), (4, -10), DI_TEXT_ALIGN_LEFT, (CPlayer.health < CPlayer.mo.RunHealth)? Font.CR_BRICK : Font.CR_UNTRANSLATED); + DrawImage("I_MDKT", (14, -17)); // Draw armor let armor = CPlayer.mo.FindInventory('BasicArmor'); if (armor != NULL && armor.Amount != 0) { - DrawString("Indexfont_Strife_Yellow", FormatNumber(armor.Amount, 3, 0, 0), (35, -10), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_LEFT|ALIGN_BOTTOM, 7, true, 1, 1); - DrawInventoryIcon(armor, (45, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_LEFT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString(mYelFont, FormatNumber(armor.Amount, 3), (35, -10)); + DrawInventoryIcon(armor, (45, -17)); } // Draw ammo @@ -384,19 +369,19 @@ class StrifeStatusBar : BaseStatusBar if (ammo1 != NULL) { // Draw primary ammo in the bottom-right corner - DrawString("Indexfont_Strife_Green", FormatNumber(ammo1.Amount, 3, 0, 0), (-23, -10), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_RIGHT|ALIGN_BOTTOM, 7, true, 1, 1); - DrawInventoryIcon(ammo1, (-14, -17), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString(mGrnFont, FormatNumber(ammo1.Amount, 3), (-23, -10)); + DrawInventoryIcon(ammo1, (-14, -17)); if (ammo2 != NULL && ammo1!=ammo2) { // Draw secondary ammo just above the primary ammo - DrawString("Indexfont_Strife_Green", FormatNumber(ammo1.Amount, 3, 0, 0), (-23, -48), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_RIGHT|ALIGN_BOTTOM, 7, true, 1, 1); - DrawInventoryIcon(ammo1, (-14, -55), false, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, itemalign: ALIGN_BOTTOM|ALIGN_HCENTER); + DrawString(mGrnFont, FormatNumber(ammo1.Amount, 3), (-23, -48)); + DrawInventoryIcon(ammo1, (-14, -55)); } } if (deathmatch) { // Draw frags (in DM) - DrawString("BigFont", FormatNumber(CPlayer.FragCount, 3, 0, 0), (-44, 1), 1., Font.CR_UNTRANSLATED, TEXT_LEFT, ALIGN_RIGHT|ALIGN_TOP, 0, false, 2, 2); + DrawString(mBigFont, FormatNumber(CPlayer.FragCount, 3), (4, 1)); } // Draw inventory @@ -406,10 +391,10 @@ class StrifeStatusBar : BaseStatusBar { if (ItemFlash > 0) { - DrawTexture(Images[CursorImage], (-28, -15), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, ItemAlign:ALIGN_BOTTOM|ALIGN_RIGHT); + DrawTexture(Images[CursorImage], (-42, -15)); } - DrawString("Indexfont_Strife_Yellow", FormatNumber(CPlayer.mo.InvSel.Amount, 3, 5, 0), (-23, -10), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_BOTTOM|ALIGN_RIGHT, 7, true, 1, 1); - DrawInventoryIcon(CPlayer.mo.InvSel, (-42, -17), true, 1.0, ALIGN_BOTTOM|ALIGN_RIGHT, ItemAlign:ALIGN_BOTTOM|ALIGN_HCENTER, CPlayer.mo.InvSel.Amount > 0 ? 0 : DI_DIM); + DrawString(mYelFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3, 5), (-30, -10), DI_TEXT_ALIGN_RIGHT); + DrawInventoryIcon(CPlayer.mo.InvSel, (-42, -17), DI_DIMDEPLETED); } } else @@ -424,13 +409,13 @@ class StrifeStatusBar : BaseStatusBar { if (item == CPlayer.mo.InvSel) { - DrawTexture(Images[CursorImage], (-90+i*35, -3), true, 0.75, ALIGN_CENTER_BOTTOM, ItemAlign:ALIGN_CENTER_BOTTOM); + DrawTexture(Images[CursorImage], (-90+i*35, -3), DI_SCREEN_CENTER_BOTTOM, 0.75); } if (item.Icon.isValid()) { - DrawInventoryIcon(item, (-90+i*35, -5), true, 0.75, ALIGN_CENTER_BOTTOM, box, ALIGN_CENTER_BOTTOM, CPlayer.mo.InvSel.Amount > 0 ? 0 : DI_DIM); + DrawInventoryIcon(item, (-90+i*35, -5), DI_SCREEN_CENTER_BOTTOM|DI_DIMDEPLETED, 0.75); } - DrawString("Indexfont_Strife_Yellow", FormatNumber(item.Amount, 3, 5, 0), (-65 + i*35, -8), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, ALIGN_CENTER_BOTTOM, 7, true, 1, 1); + DrawString(mYelFont, FormatNumber(item.Amount, 3, 5), (-72 + i*35, -8), DI_TEXT_ALIGN_RIGHT|DI_SCREEN_CENTER_BOTTOM); ++i; } } From e791c957d9827340952af037685c7f19d9272dfc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 26 Mar 2017 22:04:58 +0200 Subject: [PATCH 04/29] - implemented the regular Doom status bar. The DOOM status bar and HUD are complete, except the inventory bar. --- src/d_main.cpp | 10 +- src/d_player.h | 1 + src/g_inventory/a_keys.cpp | 13 +- src/g_inventory/a_keys.h | 2 +- src/g_statusbar/sbar.h | 1 + src/g_statusbar/sbarinfo.cpp | 1 + src/g_statusbar/shared_sbar.cpp | 7 +- src/p_user.cpp | 18 +++ wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/shared/player.txt | 1 + wadsrc/static/zscript/statusbar/doom_sbar.txt | 143 ++++++++++-------- wadsrc/static/zscript/statusbar/statusbar.txt | 33 ++-- 12 files changed, 131 insertions(+), 100 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 7216881d4..22ba39cfe 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2568,14 +2568,8 @@ void D_DoomMain (void) P_SetupWeapons_ntohton(); - //SBarInfo support. - // This needs special checking because there are two distinct methods of defining status bars. - // SBARINFO should only be picked if it is the most recently defined one, so that both - // methods can override each other if loaded in sequence. - if (gameinfo.statusbarfile > gameinfo.statusbarclassfile) - { - SBarInfo::Load(); - } + //SBarInfo support. Note that the first SBARINFO lump contains the mugshot definition so it even needs to be read when a regular status bar is being used. + SBarInfo::Load(); HUD_InitHud(); if (!batchrun) diff --git a/src/d_player.h b/src/d_player.h index 4a718778b..f9da0d120 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -532,6 +532,7 @@ public: // [Nash] set player FOV void SetFOV(float fov); + bool HasWeaponsInSlot(int slot) const; }; // Bookkeeping on players - state. diff --git a/src/g_inventory/a_keys.cpp b/src/g_inventory/a_keys.cpp index 75d98c2c7..701b98b00 100644 --- a/src/g_inventory/a_keys.cpp +++ b/src/g_inventory/a_keys.cpp @@ -464,7 +464,7 @@ void P_DeinitKeyMessages() // //=========================================================================== -bool P_CheckKeys (AActor *owner, int keynum, bool remote) +bool P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet) { const char *failtext = NULL; FSoundID *failsound; @@ -479,6 +479,7 @@ bool P_CheckKeys (AActor *owner, int keynum, bool remote) if (!locks[keynum]) { + if (quiet) return false; if (keynum == 103 && (gameinfo.flags & GI_SHAREWARE)) failtext = "$TXT_RETAIL_ONLY"; else @@ -490,6 +491,7 @@ bool P_CheckKeys (AActor *owner, int keynum, bool remote) else { if (locks[keynum]->check(owner)) return true; + if (quiet) return false; failtext = remote? locks[keynum]->RemoteMsg : locks[keynum]->Message; failsound = &locks[keynum]->locksound[0]; numfailsounds = locks[keynum]->locksound.Size(); @@ -519,6 +521,15 @@ bool P_CheckKeys (AActor *owner, int keynum, bool remote) return false; } +DEFINE_ACTION_FUNCTION(AActor, CheckKeys) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(locknum); + PARAM_BOOL(remote); + PARAM_BOOL_DEF(quiet); + ACTION_RETURN_BOOL(P_CheckKeys(self, locknum, remote, quiet)); +} + //========================================================================== // // These functions can be used to get color information for diff --git a/src/g_inventory/a_keys.h b/src/g_inventory/a_keys.h index 328ff04a6..05eff1189 100644 --- a/src/g_inventory/a_keys.h +++ b/src/g_inventory/a_keys.h @@ -4,7 +4,7 @@ class AActor; class AInventory; -bool P_CheckKeys (AActor *owner, int keynum, bool remote); +bool P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet = false); void P_InitKeyMessages (); void P_DeinitKeyMessages (); int P_GetMapColorForLock (int lock); diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index 88860291e..cdb191354 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -530,6 +530,7 @@ enum DI_Flags DI_TEXT_ALIGN = 0x1800000, DI_ALPHAMAPPED = 0x2000000, + DI_NOSHADOW = 0x4000000, }; #endif /* __SBAR_H__ */ diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index ae97c7c89..ae39fdca8 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -446,6 +446,7 @@ void SBarInfo::Load() { FreeSBarInfoScript(); MugShotStates.Clear(); + if(gameinfo.statusbar.IsNotEmpty()) { int lump = Wads.CheckNumForFullName(gameinfo.statusbar, true); diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 382db0c92..fd1b914b1 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1846,7 +1846,7 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d } // This is not really such a great way to draw shadows because they can overlap with previously drawn characters. // This may have to be changed to draw the shadow text up front separately. - if (shadowX != 0 || shadowY != 0) + if ((shadowX != 0 || shadowY != 0) && !(flags & DI_NOSHADOW)) { screen->DrawChar(font, CR_UNTRANSLATED, rx + shadowX, ry + shadowY, ch, DTA_DestWidthF, rw, @@ -2033,10 +2033,9 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, ReceivedWeapon) DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetMugshot) { PARAM_SELF_PROLOGUE(DBaseStatusBar); - PARAM_POINTER(player, player_t); - PARAM_STRING(def_face); PARAM_INT(accuracy); PARAM_INT_DEF(stateflags); - auto tex = self->mugshot.GetFace(player, def_face, accuracy, (FMugShot::StateFlags)stateflags); + PARAM_STRING_DEF(def_face); + auto tex = self->mugshot.GetFace(self->CPlayer, def_face, accuracy, (FMugShot::StateFlags)stateflags); ACTION_RETURN_INT(tex ? tex->id.GetIndex() : -1); } diff --git a/src/p_user.cpp b/src/p_user.cpp index 19de4cb18..ae4cfda78 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -707,6 +707,24 @@ void player_t::SendPitchLimits() const } +bool player_t::HasWeaponsInSlot(int slot) const +{ + for (int i = 0; i < weapons.Slots[slot].Size(); i++) + { + PClassActor *weap = weapons.Slots[slot].GetWeapon(i); + if (weap != NULL && mo->FindInventory(weap)) return true; + } + return false; +} + +DEFINE_ACTION_FUNCTION(_PlayerInfo, HasWeaponsInSlot) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_INT(slot); + ACTION_RETURN_BOOL(self->HasWeaponsInSlot(slot)); +} + + DEFINE_ACTION_FUNCTION(_PlayerInfo, GetUserName) { PARAM_SELF_STRUCT_PROLOGUE(player_t); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 71b4a7915..af9ff38d6 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -501,6 +501,7 @@ class Actor : Thinker native native static int FindUniqueTid(int start = 0, int limit = 0); native void SetShade(color col); native clearscope int GetRenderStyle() const; + native clearscope bool CheckKeys(int locknum, bool remote, bool quiet = false); native clearscope string GetTag(string defstr = "") const; native void SetTag(string defstr = ""); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index a37617289..138db474b 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -373,6 +373,7 @@ usercmd_t original_cmd; native float GetAutoaim() const; native bool GetNoAutostartMap() const; native void SetFOV(float fov); + native clearscope bool HasWeaponsInSlot(int slot) const; clearscope int fragSum () const { diff --git a/wadsrc/static/zscript/statusbar/doom_sbar.txt b/wadsrc/static/zscript/statusbar/doom_sbar.txt index b0d0c5013..cd77b7752 100644 --- a/wadsrc/static/zscript/statusbar/doom_sbar.txt +++ b/wadsrc/static/zscript/statusbar/doom_sbar.txt @@ -1,6 +1,7 @@ class DoomStatusBar : BaseStatusBar { HUDFont mHUDFont; + HUDFont mIndexFont; //DrawInventoryBarParms diparms; @@ -20,6 +21,8 @@ class DoomStatusBar : BaseStatusBar // Create the font used for the fullscreen HUD Font fnt = "HUDFONT_DOOM"; mHUDFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true, 1, 1); + fnt = "INDEXFONT_DOOM"; + mIndexFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true); } override void NewGame () @@ -48,11 +51,83 @@ class DoomStatusBar : BaseStatusBar protected void DrawMainBar (double TicFrac) { - //DrawTexture(Images[imgINVBACK], (0, 0), true, 1.0, itemAlign:ALIGN_OFFSETS); - //DrawTexture(Images[imgINVTOP], (0, -8), true, 1.0, itemAlign:ALIGN_OFFSETS); + DrawImage("STBAR", (0, 0), DI_ITEM_OFFSETS); + DrawImage("STTPRCNT", (90, 3), DI_ITEM_OFFSETS); + DrawImage("STTPRCNT", (221, 3), DI_ITEM_OFFSETS); + + Inventory a1, a2; + int amt1; + [a1, a2, amt1] = GetCurrentAmmo(); + DrawString(mHUDFont, FormatNumber(amt1, 3), (44, 3), DI_TEXT_ALIGN_RIGHT|DI_NOSHADOW); + DrawString(mHUDFont, FormatNumber(CPlayer.health, 3), (90, 3), DI_TEXT_ALIGN_RIGHT|DI_NOSHADOW); + DrawString(mHUDFont, FormatNumber(GetArmorAmount(), 3), (221, 3), DI_TEXT_ALIGN_RIGHT|DI_NOSHADOW); - // Health - //DrawString("Indexfont_Strife_Green", FormatNumber(CPlayer.health, 3, 5, 0), (86, -6), 1.0, Font.CR_UNTRANSLATED, TEXT_RIGHT, 0, 7, true, 1, 1); + bool locks[6]; + String image; + for(int i = 0; i < 6; i++) locks[i] = CPlayer.mo.CheckKeys(i + 1, false, true); + // key 1 + if (locks[1] && locks[4]) image = "STKEYS6"; + else if (locks[1]) image = "STKEYS0"; + else if (locks[4]) image = "STKEYS3"; + DrawImage(image, (239, 3), DI_ITEM_OFFSETS); + // key 2 + if (locks[2] && locks[5]) image = "STKEYS7"; + else if (locks[2]) image = "STKEYS1"; + else if (locks[5]) image = "STKEYS4"; + else image = ""; + DrawImage(image, (239, 13), DI_ITEM_OFFSETS); + // key 3 + if (locks[0] && locks[3]) image = "STKEYS8"; + else if (locks[0]) image = "STKEYS2"; + else if (locks[3]) image = "STKEYS5"; + else image = ""; + DrawImage(image, (239, 23), DI_ITEM_OFFSETS); + + int maxamt; + [amt1, maxamt] = GetAmount("Clip"); + DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 5), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 5), DI_TEXT_ALIGN_RIGHT); + + [amt1, maxamt] = GetAmount("Shell"); + DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 11), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 11), DI_TEXT_ALIGN_RIGHT); + + [amt1, maxamt] = GetAmount("RocketAmmo"); + DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 17), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 17), DI_TEXT_ALIGN_RIGHT); + + [amt1, maxamt] = GetAmount("Cell"); + DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 23), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 23), DI_TEXT_ALIGN_RIGHT); + + if (deathmatch || teamplay) + { + DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (138, 3), DI_TEXT_ALIGN_RIGHT); + } + else + { + DrawImage("STARMS", (104, 0), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(2)? "STYSNUM2" : "STGNUM2", (111, 3), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(3)? "STYSNUM3" : "STGNUM3", (123, 3), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(4)? "STYSNUM4" : "STGNUM4", (135, 3), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(5)? "STYSNUM5" : "STGNUM5", (111, 13), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(6)? "STYSNUM6" : "STGNUM6", (123, 13), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(7)? "STYSNUM7" : "STGNUM7", (135, 13), DI_ITEM_OFFSETS); + } + + if (multiplayer) + { + DrawImage("STFBANY", (143, 0), DI_ITEM_OFFSETS|DI_TRANSLATABLE); + } + + if (CPlayer.mo.InvSel != null) + { + //drawinventorybar Doom, 7, INDEXFONT, 50, 170; + } + else + { + DrawTexture(GetMugShot(5), (143, 0), DI_ITEM_OFFSETS); + } } protected void DrawFullScreenStuff () @@ -91,7 +166,7 @@ class DoomStatusBar : BaseStatusBar } if (deathmatch) { - DrawString(mHUDFont, FormatNumber(CPlayer.fragSum(), 3), (-3, 1), DI_TEXT_ALIGN_RIGHT); + DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (-3, 1), DI_TEXT_ALIGN_RIGHT); } // Draw the keys. This does not use a special draw function like SBARINFO because the specifics will be different for each mod @@ -122,61 +197,3 @@ class DoomStatusBar : BaseStatusBar } } } - -/* -statusbar normal // Standard Doom Status bar -{ - drawimage "STBAR", 0, 168; - drawimage "STTPRCNT", 90, 171; - drawimage "STTPRCNT", 221, 171; - drawnumber 3, HUDFONT_DOOM, untranslated, ammo1, 44, 171; - drawnumber 3, HUDFONT_DOOM, untranslated, health, 90, 171; - drawnumber 3, HUDFONT_DOOM, untranslated, armor, 221, 171; - - //keys - drawswitchableimage keyslot 2 && 5, "nullimage", "STKEYS0", "STKEYS3", "STKEYS6", 239, 171; - drawswitchableimage keyslot 3 && 6, "nullimage", "STKEYS1", "STKEYS4", "STKEYS7", 239, 181; - drawswitchableimage keyslot 1 && 4, "nullimage", "STKEYS2", "STKEYS5", "STKEYS8", 239, 191; - - drawnumber 3, INDEXFONT_DOOM, untranslated, ammo(Clip), 288, 173; - drawnumber 3, INDEXFONT_DOOM, untranslated, ammo(Shell), 288, 179; - drawnumber 3, INDEXFONT_DOOM, untranslated, ammo(RocketAmmo), 288, 185; - drawnumber 3, INDEXFONT_DOOM, untranslated, ammo(Cell), 288, 191; - - drawnumber 3, INDEXFONT_DOOM, untranslated, ammocapacity(Clip), 314, 173; - drawnumber 3, INDEXFONT_DOOM, untranslated, ammocapacity(Shell), 314, 179; - drawnumber 3, INDEXFONT_DOOM, untranslated, ammocapacity(RocketAmmo), 314, 185; - drawnumber 3, INDEXFONT_DOOM, untranslated, ammocapacity(Cell), 314, 191; - gamemode deathmatch, teamgame - { - drawnumber 2, HUDFONT_DOOM, untranslated, frags, 138, 171; - } - gamemode cooperative, singleplayer - { - drawimage "STARMS", 104, 168; - drawswitchableimage weaponslot 2, "STGNUM2", "STYSNUM2", 111, 172; - drawswitchableimage weaponslot 3, "STGNUM3", "STYSNUM3", 123, 172; - drawswitchableimage weaponslot 4, "STGNUM4", "STYSNUM4", 135, 172; - drawswitchableimage weaponslot 5, "STGNUM5", "STYSNUM5", 111, 182; - drawswitchableimage weaponslot 6, "STGNUM6", "STYSNUM6", 123, 182; - drawswitchableimage weaponslot 7, "STGNUM7", "STYSNUM7", 135, 182; - } - gamemode cooperative, deathmatch, teamgame - { - drawimage translatable "STFBANY", 143, 169; - } - drawselectedinventory alternateonempty, INDEXFONT, 143, 168 - { - drawmugshot "STF", 5, 143, 168; - } -} - -statusbar inventory // Standard bar overlay (ZDoom Addition) -{ - drawinventorybar Doom, 7, INDEXFONT, 50, 170; -} - -statusbar inventoryfullscreen, fullscreenoffsets // ZDoom HUD overlay. -{ -} -*/ \ No newline at end of file diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index e7c85f615..45d15c0d4 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -129,6 +129,7 @@ class BaseStatusBar native ui DI_TEXT_ALIGN_CENTER = 0x1000000, DI_ALPHAMAPPED = 0x2000000, + DI_NOSHADOW = 0x4000000, }; enum IconType @@ -151,14 +152,6 @@ class BaseStatusBar native ui HEXENARMOR_AMULET, }; - enum SBGameModes - { - GAMEMODE_SINGLEPLAYER = 0x1, - GAMEMODE_COOPERATIVE = 0x2, - GAMEMODE_DEATHMATCH = 0x4, - GAMEMODE_TEAMGAME = 0x8 - }; - enum AmmoModes { AMMO_PRIMARY, @@ -226,7 +219,7 @@ class BaseStatusBar native ui virtual bool MustDrawLog(int state) { return true; } native void RefreshBackground () const; - native TextureID GetMugshot(PlayerInfo player, String default_face, int accuracy, int stateflags=MugShot.STANDARD); + native TextureID GetMugshot(int accuracy, int stateflags=MugShot.STANDARD, String default_face = "STF"); // These functions are kept native solely for performance reasons. They get called repeatedly and can drag down performance easily if they get too slow. native Inventory ValidateInvFirst (int numVisible) const; @@ -338,6 +331,14 @@ class BaseStatusBar native ui return armor? armor.Amount : 0; } + int, int GetAmount(class item) + { + let it = CPlayer.mo.FindInventory(item); + int ret1 = it? it.Amount : GetDefaultByType(item).Amount; + int ret2 = it? it.MaxAmount : GetDefaultByType(item).MaxAmount; + return ret1, ret2; + } + int GetMaxAmount(class item) { let it = CPlayer.mo.FindInventory(item); @@ -393,20 +394,6 @@ class BaseStatusBar native ui // //============================================================================ - //============================================================================ - // - // checks current game mode against a flag mask - // - //============================================================================ - - bool CheckGameMode(int ValidModes) - { - return (!multiplayer && (ValidModes & GAMEMODE_SINGLEPLAYER)) || - (deathmatch && (ValidModes & GAMEMODE_DEATHMATCH)) || - (multiplayer && !deathmatch && (ValidModes & GAMEMODE_COOPERATIVE)) || - (teamplay && (ValidModes & GAMEMODE_TEAMGAME)); - } - //============================================================================ // // checks ammo use of current weapon From a112b29c43de1f54e48df0e158cb0a49e1661cbc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Mar 2017 01:02:10 +0200 Subject: [PATCH 05/29] - implemented the inventory bar. This object is a bit special because it requires a lot of parameters, most of which are easily set to defaults. To make handling easier, most are passed through a container object which does some processing up front. - finished work on the Doom status bar. I also took the opportunity to fix the layout of the inventory bar which is a bit broken in SBARINFO. - tuned the selection rules for deciding what creates the status bar, so that the most recent definition that can be found is chosen. --- src/g_shared/shared_hud.cpp | 10 +- src/g_statusbar/sbarinfo.cpp | 4 +- src/g_statusbar/shared_sbar.cpp | 30 ++-- src/p_mobj.cpp | 6 + wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/statusbar/doom_sbar.txt | 34 +++-- wadsrc/static/zscript/statusbar/statusbar.txt | 130 +++++++++++++++++- 7 files changed, 181 insertions(+), 34 deletions(-) diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index fa5b8a030..ce8a4965e 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -115,7 +115,7 @@ static FFont * IndexFont; // The font for the inventory indices static FTexture * healthpic; // Health icon static FTexture * berserkpic; // Berserk icon (Doom only) static FTexture * fragpic; // Frags icon -static FTexture * invgems[4]; // Inventory arrows +static FTexture * invgems[2]; // Inventory arrows static int hudwidth, hudheight; // current width/height for HUD display static int statspace; @@ -816,7 +816,7 @@ static void DrawInventory(player_t * CPlayer, int x,int y) { if(rover->PrevInv()) { - screen->DrawTexture(invgems[!!(level.time&4)], x-10, y, + screen->DrawTexture(invgems[0], x-10, y, DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.4, TAG_DONE); } @@ -852,7 +852,7 @@ static void DrawInventory(player_t * CPlayer, int x,int y) } if(rover) { - screen->DrawTexture(invgems[2 + !!(level.time&4)], x-10, y, + screen->DrawTexture(invgems[1], x-10, y, DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.4, TAG_DONE); } @@ -1279,9 +1279,7 @@ void HUD_InitHud() if (IndexFont == NULL) IndexFont = ConFont; // Emergency fallback invgems[0] = TexMan.FindTexture("INVGEML1"); - invgems[1] = TexMan.FindTexture("INVGEML2"); - invgems[2] = TexMan.FindTexture("INVGEMR1"); - invgems[3] = TexMan.FindTexture("INVGEMR2"); + invgems[1] = TexMan.FindTexture("INVGEMR1"); fragpic = TexMan.FindTexture("HU_FRAGS"); // Sadly, I don't have anything usable for this. :( diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index ae39fdca8..b7f859442 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -984,13 +984,13 @@ public: "USEARTIA", "USEARTIB", "USEARTIC", "USEARTID", }; TArray patchnames; - patchnames.Resize(script->Images.Size()+10); + patchnames.Resize(script->Images.Size()+9); unsigned int i = 0; for(i = 0;i < script->Images.Size();i++) { patchnames[i] = script->Images[i]; } - for(i = 0;i < 10;i++) + for(i = 0;i < 9;i++) { patchnames[i+script->Images.Size()] = InventoryBarLumps[i]; } diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index fd1b914b1..acb9c4295 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -243,16 +243,24 @@ void ST_CreateStatusBar(bool bTitleLevel) StatusBar = new DBaseStatusBar(); StatusBar->SetSize(0); } - else if (gameinfo.statusbarclassfile >= gameinfo.statusbarfile) + else { - auto cls = PClass::FindClass(gameinfo.statusbarclass); - if (cls != nullptr) + // The old rule of 'what came last wins' goes here, as well. + // If the most recent SBARINFO definition comes before a status bar class definition it will be picked, + // if the class is defined later, this will be picked. If both come from the same file, the class definition will win. + int sbarinfolump = Wads.CheckNumForName("SBARINFO"); + int sbarinfofile = Wads.GetLumpFile(sbarinfolump); + if (gameinfo.statusbarclassfile >= gameinfo.statusbarfile && gameinfo.statusbarclassfile >= sbarinfofile) { - StatusBar = (DBaseStatusBar *)cls->CreateNew(); - IFVIRTUALPTR(StatusBar, DBaseStatusBar, Init) + auto cls = PClass::FindClass(gameinfo.statusbarclass); + if (cls != nullptr) { - VMValue params[] = { StatusBar }; - GlobalVMStack.Call(func, params, 1, nullptr, 0); + StatusBar = (DBaseStatusBar *)cls->CreateNew(); + IFVIRTUALPTR(StatusBar, DBaseStatusBar, Init) + { + VMValue params[] = { StatusBar }; + GlobalVMStack.Call(func, params, 1, nullptr, 0); + } } } } @@ -283,7 +291,6 @@ void ST_CreateStatusBar(bool bTitleLevel) auto cls = PClass::FindClass(defname); if (cls != nullptr) { - StatusBar = (DBaseStatusBar *)cls->CreateNew(); IFVIRTUALPTR(StatusBar, DBaseStatusBar, Init) { @@ -1605,8 +1612,8 @@ void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int fla switch (flags & DI_ITEM_VMASK) { - case DI_ITEM_VCENTER: y -= texheight / 2; break; - case DI_ITEM_BOTTOM: y -= texheight; break; + case DI_ITEM_VCENTER: y -= boxheight / 2; break; + case DI_ITEM_BOTTOM: y -= boxheight; break; case DI_ITEM_VOFFSET: y -= tex->GetScaledTopOffsetDouble() * boxheight / texheight; break; } @@ -1732,6 +1739,8 @@ DEFINE_ACTION_FUNCTION(DHUDFont, Create) ACTION_RETURN_POINTER(new DHUDFont(fnt, spac, mono, sy, sy)); } +DEFINE_FIELD(DHUDFont, mFont); + //============================================================================ // // draw a string @@ -2039,3 +2048,4 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetMugshot) auto tex = self->mugshot.GetFace(self->CPlayer, def_face, accuracy, (FMugShot::StateFlags)stateflags); ACTION_RETURN_INT(tex ? tex->id.GetIndex() : -1); } + diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index c175858de..08a2f922f 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1045,6 +1045,12 @@ AInventory *AActor::FirstInv () return Inventory->NextInv (); } +DEFINE_ACTION_FUNCTION(AActor, FirstInv) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_OBJECT(self->FirstInv()); +} + //============================================================================ // // AActor :: UseInventory diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index af9ff38d6..aae7d6aeb 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -502,6 +502,7 @@ class Actor : Thinker native native void SetShade(color col); native clearscope int GetRenderStyle() const; native clearscope bool CheckKeys(int locknum, bool remote, bool quiet = false); + native clearscope Inventory FirstInv() const; native clearscope string GetTag(string defstr = "") const; native void SetTag(string defstr = ""); diff --git a/wadsrc/static/zscript/statusbar/doom_sbar.txt b/wadsrc/static/zscript/statusbar/doom_sbar.txt index cd77b7752..e9e96307c 100644 --- a/wadsrc/static/zscript/statusbar/doom_sbar.txt +++ b/wadsrc/static/zscript/statusbar/doom_sbar.txt @@ -2,7 +2,8 @@ class DoomStatusBar : BaseStatusBar { HUDFont mHUDFont; HUDFont mIndexFont; - //DrawInventoryBarParms diparms; + HUDFont mAmountFont; + InventoryBarState diparms; override void Init() @@ -10,19 +11,13 @@ class DoomStatusBar : BaseStatusBar Super.Init(); SetSize(32, 320, 200); - // set up the inventory bar drawer. - /* - diparms.SetDefaults(HX_SHADOW); - diparms.SetTextures("SELECTBO", "ARTIBOX", "INVGEML1", "INVGEMR1"); - diparms.SetLeftArrow("INVGEML1"); - diparms.SetRightArrow("INVGEMR1"); - */ - // Create the font used for the fullscreen HUD Font fnt = "HUDFONT_DOOM"; mHUDFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true, 1, 1); fnt = "INDEXFONT_DOOM"; mIndexFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true); + mAmountFont = HUDFont.Create("INDEXFONT"); + diparms = InventoryBarState.Create(); } override void NewGame () @@ -120,14 +115,23 @@ class DoomStatusBar : BaseStatusBar DrawImage("STFBANY", (143, 0), DI_ITEM_OFFSETS|DI_TRANSLATABLE); } - if (CPlayer.mo.InvSel != null) + if (CPlayer.mo.InvSel != null && !level.NoInventoryBar) { - //drawinventorybar Doom, 7, INDEXFONT, 50, 170; + DrawInventoryIcon(CPlayer.mo.InvSel, (160, 30)); + if (CPlayer.mo.InvSel.Amount > 0) + { + DrawString(mAmountFont, FormatNumber(CPlayer.mo.InvSel.Amount), (175, 30-mIndexFont.mFont.GetHeight()), DI_TEXT_ALIGN_RIGHT, Font.CR_GOLD); + } } else { DrawTexture(GetMugShot(5), (143, 0), DI_ITEM_OFFSETS); } + if (CPlayer.inventorytics != 0 && !level.NoInventoryBar) + { + DrawInventoryBar(diparms, (48, 1), 7, DI_ITEM_LEFT_TOP); + } + } protected void DrawFullScreenStuff () @@ -159,14 +163,14 @@ class DoomStatusBar : BaseStatusBar DrawString(mHUDFont, FormatNumber(ammotype2.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); invY -= 20; } - if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null) + if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null && !level.NoInventoryBar) { DrawInventoryIcon(CPlayer.mo.InvSel, (-14, invY + 17)); DrawString(mHUDFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); } if (deathmatch) { - DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (-3, 1), DI_TEXT_ALIGN_RIGHT); + DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (-3, 1), DI_TEXT_ALIGN_RIGHT, Font.CR_GOLD); } // Draw the keys. This does not use a special draw function like SBARINFO because the specifics will be different for each mod @@ -191,9 +195,9 @@ class DoomStatusBar : BaseStatusBar } } } - if (CPlayer.inventorytics != 0) + if (CPlayer.inventorytics != 0 && !level.NoInventoryBar) { - //DrawInventoryBar(diparms, (0, 0), 7, ALIGN_CENTER_BOTTOM, ALIGN_CENTER_BOTTOM); + DrawInventoryBar(diparms, (0, 0), 7, DI_SCREEN_CENTER_BOTTOM, HX_SHADOW); } } } diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index 45d15c0d4..48bc73dd4 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -17,10 +17,57 @@ struct MugShot class HUDFont native ui { - // This is intentionally opaque to the script side. + native Font mFont; native static HUDFont Create(Font fnt, int spacing = 0, bool monospaced = false, int shadowx = 0, int shadowy = 0); } +class InventoryBarState ui +{ + TextureID box; + TextureID selector; + Vector2 boxsize; + Vector2 innersize; + int boxframesize; + + TextureID left; + TextureID right; + Vector2 arrowoffset; + + double itemalpha; + + HUDFont amountfont; + int cr; + int flags; + + // The default settings here are what SBARINFO is using. + static InventoryBarState Create(HUDFont indexfont = null, int cr = Font.CR_UNTRANSLATED, double itemalpha = 1., + String boxgfx = "ARTIBOX", String selgfx = "SELECTBO", int fsize = 2, + String leftgfx = "INVGEML1", String rightgfx = "INVGEMR1", Vector2 arrowoffs = (0, 0), int flags = 0) + { + let me = new ("InventoryBarState"); + me.itemalpha = itemalpha; + me.box = TexMan.CheckForTexture(boxgfx, TexMan.TYPE_MiscPatch); + me.selector = TexMan.CheckForTexture(selgfx, TexMan.TYPE_MiscPatch); + me.boxframesize = fsize; + if (me.box.IsValid() || me.selector.IsValid()) me.boxsize = TexMan.GetScaledSize(me.box.IsValid()? me.box : me.selector); + else me.boxsize = (32., 32.); + me.innersize = me.boxsize - (2.*fsize, 2.*fsize); + me.left = TexMan.CheckForTexture(leftgfx, TexMan.TYPE_MiscPatch); + me.right = TexMan.CheckForTexture(rightgfx, TexMan.TYPE_MiscPatch); + me.arrowoffset = arrowoffs; + me.arrowoffset.Y += me.boxsize.Y/2; // default is centered to the side of the box. + if (indexfont == null) + { + me.amountfont = HUDFont.Create("INDEXFONT"); + if (cr == Font.CR_UNTRANSLATED) cr = Font.CR_GOLD; + } + else me.amountfont = indexfont; + me.cr = cr; + me.flags = flags; + return me; + } +} + class BaseStatusBar native ui { @@ -130,6 +177,7 @@ class BaseStatusBar native ui DI_ALPHAMAPPED = 0x2000000, DI_NOSHADOW = 0x4000000, + DI_ALWAYSSHOWCOUNTERS = 0x8000000, }; enum IconType @@ -630,6 +678,86 @@ class BaseStatusBar native ui } } + //============================================================================ + // + // DrawInventoryBar + // + // This function needs too many parameters, so most have been offloaded to + // a struct to keep code readable and allow initialization somewhere outside + // the actual drawing code. + // + //============================================================================ + + // Except for the placement information this gets all info from the struct that gets passed in. + void DrawInventoryBar(InventoryBarState parms, Vector2 position, int numfields, int flags = 0, double bgalpha = 1.) + { + double width = parms.boxsize.X * numfields; + + // This must be done here, before altered coordinates get sent to the draw functions. + if (!(flags & DI_SCREEN_MANUAL_ALIGN)) + { + if (position.x < 0) flags |= DI_SCREEN_RIGHT; + else flags |= DI_SCREEN_LEFT; + if (position.y < 0) flags |= DI_SCREEN_BOTTOM; + else flags |= DI_SCREEN_TOP; + } + + // placement by offset is not supported because the inventory bar is a composite. + switch (flags & DI_ITEM_HMASK) + { + case DI_ITEM_HCENTER: position.x -= width / 2; break; + case DI_ITEM_RIGHT: position.x -= width; break; + } + + switch (flags & DI_ITEM_VMASK) + { + case DI_ITEM_VCENTER: position.y -= parms.boxsize.Y / 2; break; + case DI_ITEM_BOTTOM: position.y -= parms.boxsize.Y; break; + } + + // clear all alignment flags so that the following code only passed on the rest + flags &= ~(DI_ITEM_VMASK|DI_ITEM_HMASK); + + CPlayer.mo.InvFirst = ValidateInvFirst(numfields); + if (CPlayer.mo.InvFirst == null) return; // Player has no listed inventory items. + + Vector2 boxsize = parms.boxsize; + // First draw all the boxes + for(int i = 0; i < numfields; i++) + { + DrawTexture(parms.box, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP, bgalpha); + } + + // now the items and the rest + + Vector2 itempos = position + (boxsize.X / 2, boxsize.Y - parms.boxframesize); + Vector2 textpos = position + boxsize - (parms.boxframesize*2, parms.boxframesize + parms.amountfont.mFont.GetHeight()); + + int i = 0; + Inventory item; + for(item = CPlayer.mo.InvFirst; item != NULL && i < numfields; item = item.NextInv()) + { + if ((parms.flags & DI_DRAWCURSORFIRST) && item == CPlayer.mo.InvSel) DrawTexture(parms.selector, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP); + DrawInventoryIcon(item, itempos + (boxsize.X * i, 0), flags | DI_ITEM_CENTER_BOTTOM ); + if (!(parms.flags & DI_DRAWCURSORFIRST) && item == CPlayer.mo.InvSel) DrawTexture(parms.selector, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP); + + if (parms.amountfont != null && (item.Amount > 1 || (parms.flags & DI_ALWAYSSHOWCOUNTERS))) + { + DrawString(parms.amountfont, FormatNumber(item.Amount, 0, 5), textpos + (boxsize.X * i, 0), flags | DI_TEXT_ALIGN_RIGHT, parms.cr, parms.itemalpha); + } + i++; + } + // Is there something to the left? + if (CPlayer.mo.FirstInv() != CPlayer.mo.InvFirst) + { + DrawTexture(parms.left, position + (-parms.arrowoffset.X, parms.arrowoffset.Y), flags | DI_ITEM_RIGHT|DI_ITEM_VCENTER); + } + // Is there something to the right? + if (item != NULL) + { + DrawTexture(parms.right, position + parms.arrowoffset + (width, 0), flags | DI_ITEM_LEFT|DI_ITEM_VCENTER); + } + } } //============================================================================ From bc95e5180d1f78ab31d12dca441214936e956902 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Mar 2017 01:55:47 +0200 Subject: [PATCH 06/29] - moved the BarShader textures into the texture manager so that ZScript can use them. ZScript only knows about TextureIDs, but those require the texture to be handled by the texture manager. --- src/CMakeLists.txt | 1 + src/g_statusbar/sbarinfo_commands.cpp | 87 ++--------------- src/textures/shadertexture.cpp | 133 ++++++++++++++++++++++++++ src/textures/texturemanager.cpp | 6 ++ 4 files changed, 146 insertions(+), 81 deletions(-) create mode 100644 src/textures/shadertexture.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3a3efad30..9af325791 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1190,6 +1190,7 @@ set (PCH_SOURCES textures/rawpagetexture.cpp textures/emptytexture.cpp textures/backdroptexture.cpp + textures/shadertexture.cpp textures/texture.cpp textures/texturemanager.cpp textures/tgatexture.cpp diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index 22d9b0f1d..64da7a7d5 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -2032,7 +2032,7 @@ class CommandDrawShader : public SBarInfoCommand void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) { - statusBar->DrawGraphic(&shaders[(vertical<<1) + reverse], x, y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, false, 0, true, width, height); + statusBar->DrawGraphic(shaders[(vertical<<1) + reverse], x, y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, false, 0, true, width, height); } void Parse(FScanner &sc, bool fullScreenOffsets) { @@ -2063,6 +2063,10 @@ class CommandDrawShader : public SBarInfoCommand } GetCoordinates(sc, fullScreenOffsets, x, y); sc.MustGetToken(';'); + shaders[0] = TexMan.FindTexture("BarShaderHF"); + shaders[1] = TexMan.FindTexture("BarShaderHR"); + shaders[2] = TexMan.FindTexture("BarShaderVF"); + shaders[3] = TexMan.FindTexture("BarShaderVR"); } protected: bool vertical; @@ -2072,87 +2076,8 @@ class CommandDrawShader : public SBarInfoCommand SBarInfoCoordinate x; SBarInfoCoordinate y; private: - class FBarShader : public FTexture - { - public: - FBarShader(bool vertical, bool reverse) - { - int i; - Width = vertical ? 2 : 256; - Height = vertical ? 256 : 2; - CalcBitSize(); - - // Fill the column/row with shading values. - // Vertical shaders have have minimum alpha at the top - // and maximum alpha at the bottom, unless flipped by - // setting reverse to true. Horizontal shaders are just - // the opposite. - if (vertical) - { - if (!reverse) - { - for (i = 0; i < 256; ++i) - { - Pixels[i] = i; - Pixels[256+i] = i; - } - } - else - { - for (i = 0; i < 256; ++i) - { - Pixels[i] = 255 - i; - Pixels[256+i] = 255 -i; - } - } - } - else - { - if (!reverse) - { - for (i = 0; i < 256; ++i) - { - Pixels[i*2] = 255 - i; - Pixels[i*2+1] = 255 - i; - } - } - else - { - for (i = 0; i < 256; ++i) - { - Pixels[i*2] = i; - Pixels[i*2+1] = i; - } - } - } - DummySpan[0].TopOffset = 0; - DummySpan[0].Length = vertical ? 256 : 2; - DummySpan[1].TopOffset = 0; - DummySpan[1].Length = 0; - } - const uint8_t *GetColumn(unsigned int column, const Span **spans_out) - { - if (spans_out != NULL) - { - *spans_out = DummySpan; - } - return Pixels + ((column & WidthMask) << HeightBits); - } - const uint8_t *GetPixels() { return Pixels; } - void Unload() {} - private: - uint8_t Pixels[512]; - Span DummySpan[2]; - }; - - static FBarShader shaders[4]; -}; - -CommandDrawShader::FBarShader CommandDrawShader::shaders[4] = -{ - FBarShader(false, false), FBarShader(false, true), - FBarShader(true, false), FBarShader(true, true) + FTexture *shaders[4]; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/src/textures/shadertexture.cpp b/src/textures/shadertexture.cpp new file mode 100644 index 000000000..93e423470 --- /dev/null +++ b/src/textures/shadertexture.cpp @@ -0,0 +1,133 @@ +/* +** shadertexture.cpp +** +** simple shader gradient textures, used by the status bars. +** +**--------------------------------------------------------------------------- +** Copyright 2008 Braden Obrzut +** Copyright 2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "doomtype.h" +#include "doomstat.h" +#include "d_player.h" +#include "templates.h" +#include "menu/menu.h" +#include "colormatcher.h" +#include "textures/textures.h" +#include "w_wad.h" +#include "v_font.h" +#include "v_video.h" +#include "g_level.h" +#include "gi.h" +#include "r_defs.h" +#include "r_state.h" +#include "r_data/r_translate.h" + + +class FBarShader : public FTexture +{ +public: + FBarShader(bool vertical, bool reverse) + { + int i; + + Name.Format("BarShader%c%c", vertical ? 'v' : 'h', reverse ? 'r' : 'f'); + Width = vertical ? 2 : 256; + Height = vertical ? 256 : 2; + CalcBitSize(); + + // Fill the column/row with shading values. + // Vertical shaders have have minimum alpha at the top + // and maximum alpha at the bottom, unless flipped by + // setting reverse to true. Horizontal shaders are just + // the opposite. + if (vertical) + { + if (!reverse) + { + for (i = 0; i < 256; ++i) + { + Pixels[i] = i; + Pixels[256+i] = i; + } + } + else + { + for (i = 0; i < 256; ++i) + { + Pixels[i] = 255 - i; + Pixels[256+i] = 255 -i; + } + } + } + else + { + if (!reverse) + { + for (i = 0; i < 256; ++i) + { + Pixels[i*2] = 255 - i; + Pixels[i*2+1] = 255 - i; + } + } + else + { + for (i = 0; i < 256; ++i) + { + Pixels[i*2] = i; + Pixels[i*2+1] = i; + } + } + } + DummySpan[0].TopOffset = 0; + DummySpan[0].Length = vertical ? 256 : 2; + DummySpan[1].TopOffset = 0; + DummySpan[1].Length = 0; + } + const uint8_t *GetColumn(unsigned int column, const Span **spans_out) + { + if (spans_out != NULL) + { + *spans_out = DummySpan; + } + return Pixels + ((column & WidthMask) << HeightBits); + } + const uint8_t *GetPixels() { return Pixels; } + void Unload() {} +private: + uint8_t Pixels[512]; + Span DummySpan[2]; +}; + + +FTexture *CreateShaderTexture(bool vertical, bool reverse) +{ + return new FBarShader(vertical, reverse); +} diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 1601660c7..2bd779865 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -977,6 +977,7 @@ void FTextureManager::SortTexturesByType(int start, int end) // //========================================================================== FTexture *GetBackdropTexture(); +FTexture *CreateShaderTexture(bool, bool); void FTextureManager::Init() { @@ -988,7 +989,12 @@ void FTextureManager::Init() // Texture 0 is a dummy texture used to indicate "no texture" AddTexture (new FDummyTexture); + // some special textures used in the game. AddTexture(GetBackdropTexture()); + AddTexture(CreateShaderTexture(false, false)); + AddTexture(CreateShaderTexture(false, true)); + AddTexture(CreateShaderTexture(true, false)); + AddTexture(CreateShaderTexture(true, true)); int wadcnt = Wads.GetNumWads(); for(int i = 0; i< wadcnt; i++) From 0fdd118906858a82e04b620c81ffdef4518b8da5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Mar 2017 09:52:30 +0200 Subject: [PATCH 07/29] - change statusbar drawers to use the top left of the virtual screen as origin, not the top left of the actual status bar, to bring this in line with SBARINFO. The Strife status bar which was still native code had it differently and that was used as the initial guideline. --- src/g_statusbar/shared_sbar.cpp | 4 +- wadsrc/static/zscript/statusbar/doom_sbar.txt | 68 ++++++++----------- wadsrc/static/zscript/statusbar/statusbar.txt | 8 ++- .../static/zscript/statusbar/strife_sbar.txt | 31 ++++----- 4 files changed, 51 insertions(+), 60 deletions(-) diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index acb9c4295..919d67848 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1620,7 +1620,7 @@ void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int fla if (!fullscreenOffsets) { x += ST_X; - y += ST_Y; + //y += ST_Y; // Todo: Allow other scaling values, too. if (Scaled) @@ -1835,7 +1835,7 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d if (!fullscreenOffsets) { rx += ST_X; - ry += ST_Y; + //ry += ST_Y; // Todo: Allow other scaling values, too. if (Scaled) diff --git a/wadsrc/static/zscript/statusbar/doom_sbar.txt b/wadsrc/static/zscript/statusbar/doom_sbar.txt index e9e96307c..7cd2ae461 100644 --- a/wadsrc/static/zscript/statusbar/doom_sbar.txt +++ b/wadsrc/static/zscript/statusbar/doom_sbar.txt @@ -20,14 +20,6 @@ class DoomStatusBar : BaseStatusBar diparms = InventoryBarState.Create(); } - override void NewGame () - { - if (CPlayer != NULL) - { - AttachToPlayer (CPlayer); - } - } - override void Draw (int state, double TicFrac) { Super.Draw (state, TicFrac); @@ -46,16 +38,16 @@ class DoomStatusBar : BaseStatusBar protected void DrawMainBar (double TicFrac) { - DrawImage("STBAR", (0, 0), DI_ITEM_OFFSETS); - DrawImage("STTPRCNT", (90, 3), DI_ITEM_OFFSETS); - DrawImage("STTPRCNT", (221, 3), DI_ITEM_OFFSETS); + DrawImage("STBAR", (0, 168), DI_ITEM_OFFSETS); + DrawImage("STTPRCNT", (90, 171), DI_ITEM_OFFSETS); + DrawImage("STTPRCNT", (221, 171), DI_ITEM_OFFSETS); Inventory a1, a2; int amt1; [a1, a2, amt1] = GetCurrentAmmo(); - DrawString(mHUDFont, FormatNumber(amt1, 3), (44, 3), DI_TEXT_ALIGN_RIGHT|DI_NOSHADOW); - DrawString(mHUDFont, FormatNumber(CPlayer.health, 3), (90, 3), DI_TEXT_ALIGN_RIGHT|DI_NOSHADOW); - DrawString(mHUDFont, FormatNumber(GetArmorAmount(), 3), (221, 3), DI_TEXT_ALIGN_RIGHT|DI_NOSHADOW); + DrawString(mHUDFont, FormatNumber(amt1, 3), (44, 171), DI_TEXT_ALIGN_RIGHT|DI_NOSHADOW); + DrawString(mHUDFont, FormatNumber(CPlayer.health, 3), (90, 171), DI_TEXT_ALIGN_RIGHT|DI_NOSHADOW); + DrawString(mHUDFont, FormatNumber(GetArmorAmount(), 3), (221, 171), DI_TEXT_ALIGN_RIGHT|DI_NOSHADOW); bool locks[6]; String image; @@ -64,72 +56,72 @@ class DoomStatusBar : BaseStatusBar if (locks[1] && locks[4]) image = "STKEYS6"; else if (locks[1]) image = "STKEYS0"; else if (locks[4]) image = "STKEYS3"; - DrawImage(image, (239, 3), DI_ITEM_OFFSETS); + DrawImage(image, (239, 171), DI_ITEM_OFFSETS); // key 2 if (locks[2] && locks[5]) image = "STKEYS7"; else if (locks[2]) image = "STKEYS1"; else if (locks[5]) image = "STKEYS4"; else image = ""; - DrawImage(image, (239, 13), DI_ITEM_OFFSETS); + DrawImage(image, (239, 181), DI_ITEM_OFFSETS); // key 3 if (locks[0] && locks[3]) image = "STKEYS8"; else if (locks[0]) image = "STKEYS2"; else if (locks[3]) image = "STKEYS5"; else image = ""; - DrawImage(image, (239, 23), DI_ITEM_OFFSETS); + DrawImage(image, (239, 191), DI_ITEM_OFFSETS); int maxamt; [amt1, maxamt] = GetAmount("Clip"); - DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 5), DI_TEXT_ALIGN_RIGHT); - DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 5), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 173), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 173), DI_TEXT_ALIGN_RIGHT); [amt1, maxamt] = GetAmount("Shell"); - DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 11), DI_TEXT_ALIGN_RIGHT); - DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 11), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 179), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 179), DI_TEXT_ALIGN_RIGHT); [amt1, maxamt] = GetAmount("RocketAmmo"); - DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 17), DI_TEXT_ALIGN_RIGHT); - DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 17), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 185), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 185), DI_TEXT_ALIGN_RIGHT); [amt1, maxamt] = GetAmount("Cell"); - DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 23), DI_TEXT_ALIGN_RIGHT); - DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 23), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(amt1, 3), (288, 191), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(maxamt, 3), (314, 191), DI_TEXT_ALIGN_RIGHT); if (deathmatch || teamplay) { - DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (138, 3), DI_TEXT_ALIGN_RIGHT); + DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (138, 171), DI_TEXT_ALIGN_RIGHT); } else { - DrawImage("STARMS", (104, 0), DI_ITEM_OFFSETS); - DrawImage(CPlayer.HasWeaponsInSlot(2)? "STYSNUM2" : "STGNUM2", (111, 3), DI_ITEM_OFFSETS); - DrawImage(CPlayer.HasWeaponsInSlot(3)? "STYSNUM3" : "STGNUM3", (123, 3), DI_ITEM_OFFSETS); - DrawImage(CPlayer.HasWeaponsInSlot(4)? "STYSNUM4" : "STGNUM4", (135, 3), DI_ITEM_OFFSETS); - DrawImage(CPlayer.HasWeaponsInSlot(5)? "STYSNUM5" : "STGNUM5", (111, 13), DI_ITEM_OFFSETS); - DrawImage(CPlayer.HasWeaponsInSlot(6)? "STYSNUM6" : "STGNUM6", (123, 13), DI_ITEM_OFFSETS); - DrawImage(CPlayer.HasWeaponsInSlot(7)? "STYSNUM7" : "STGNUM7", (135, 13), DI_ITEM_OFFSETS); + DrawImage("STARMS", (104, 168), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(2)? "STYSNUM2" : "STGNUM2", (111, 171), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(3)? "STYSNUM3" : "STGNUM3", (123, 171), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(4)? "STYSNUM4" : "STGNUM4", (135, 171), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(5)? "STYSNUM5" : "STGNUM5", (111, 181), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(6)? "STYSNUM6" : "STGNUM6", (123, 181), DI_ITEM_OFFSETS); + DrawImage(CPlayer.HasWeaponsInSlot(7)? "STYSNUM7" : "STGNUM7", (135, 181), DI_ITEM_OFFSETS); } if (multiplayer) { - DrawImage("STFBANY", (143, 0), DI_ITEM_OFFSETS|DI_TRANSLATABLE); + DrawImage("STFBANY", (143, 168), DI_ITEM_OFFSETS|DI_TRANSLATABLE); } if (CPlayer.mo.InvSel != null && !level.NoInventoryBar) { - DrawInventoryIcon(CPlayer.mo.InvSel, (160, 30)); + DrawInventoryIcon(CPlayer.mo.InvSel, (160, 198)); if (CPlayer.mo.InvSel.Amount > 0) { - DrawString(mAmountFont, FormatNumber(CPlayer.mo.InvSel.Amount), (175, 30-mIndexFont.mFont.GetHeight()), DI_TEXT_ALIGN_RIGHT, Font.CR_GOLD); + DrawString(mAmountFont, FormatNumber(CPlayer.mo.InvSel.Amount), (175, 198-mIndexFont.mFont.GetHeight()), DI_TEXT_ALIGN_RIGHT, Font.CR_GOLD); } } else { - DrawTexture(GetMugShot(5), (143, 0), DI_ITEM_OFFSETS); + DrawTexture(GetMugShot(5), (143, 168), DI_ITEM_OFFSETS); } if (CPlayer.inventorytics != 0 && !level.NoInventoryBar) { - DrawInventoryBar(diparms, (48, 1), 7, DI_ITEM_LEFT_TOP); + DrawInventoryBar(diparms, (48, 169), 7, DI_ITEM_LEFT_TOP); } } diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index 48bc73dd4..e1bdf4d63 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -262,7 +262,7 @@ class BaseStatusBar native ui virtual void FlashItem (class itemtype) {} virtual void AttachToPlayer (PlayerInfo player) { CPlayer = player; } virtual void FlashCrosshair () { CrosshairSize = XHAIRPICKUPSIZE; } - virtual void NewGame () {} + virtual void NewGame () { if (CPlayer != null) AttachToPlayer(CPlayer); } virtual void ShowPop (int popnum) { ShowLog = (popnum == POP_Log && !ShowLog); } virtual bool MustDrawLog(int state) { return true; } @@ -805,14 +805,16 @@ class DynamicValueInterpolator : Object { int mCurrentValue; int mMinChange; + int mMaxChange; double mChangeFactor; - static DynamicValueInterpolator Create(int startval, double changefactor, int minchange) + static DynamicValueInterpolator Create(int startval, double changefactor, int minchange, int maxchange) { let v = new("DynamicValueInterpolator"); v.mCurrentValue = startval; v.mMinChange = minchange; + v.mMaxChange = maxchange; v.mChangeFactor = changefactor; return v; } @@ -821,7 +823,7 @@ class DynamicValueInterpolator : Object // Do not call this in the Draw function because that may skip some frames! void Update(int destvalue) { - int diff = int(max(abs(destvalue - mCurrentValue) * mChangeFactor, mMinChange)); + int diff = int(clamp(abs(destvalue - mCurrentValue) * mChangeFactor, mMinChange, mMaxChange)); if (mCurrentValue > destvalue) { mCurrentValue = max(destvalue, mCurrentValue - diff); diff --git a/wadsrc/static/zscript/statusbar/strife_sbar.txt b/wadsrc/static/zscript/statusbar/strife_sbar.txt index b90a30a76..889842cc3 100644 --- a/wadsrc/static/zscript/statusbar/strife_sbar.txt +++ b/wadsrc/static/zscript/statusbar/strife_sbar.txt @@ -71,11 +71,8 @@ class StrifeStatusBar : BaseStatusBar override void NewGame () { + Super.NewGame(); Reset (); - if (CPlayer != NULL) - { - AttachToPlayer (CPlayer); - } } override void Draw (int state, double TicFrac) @@ -290,11 +287,11 @@ class StrifeStatusBar : BaseStatusBar DrawPopScreen (Scaled ? (ST_Y - 8) * screen.GetHeight() / 200 : ST_Y - 8, TicFrac); } - DrawImage("INVBACK", (0, 0), DI_ITEM_OFFSETS); - DrawImage("INVTOP", (0, -8), DI_ITEM_OFFSETS); + DrawImage("INVBACK", (0, 168), DI_ITEM_OFFSETS); + DrawImage("INVTOP", (0, 160), DI_ITEM_OFFSETS); // Health - DrawString(mGrnFont, FormatNumber(CPlayer.health, 3, 5), (79, -6), DI_TEXT_ALIGN_RIGHT); + DrawString(mGrnFont, FormatNumber(CPlayer.health, 3, 5), (79, 162), DI_TEXT_ALIGN_RIGHT); int points; if (CPlayer.cheats & CF_GODMODE) { @@ -304,30 +301,30 @@ class StrifeStatusBar : BaseStatusBar { points = min(CPlayer.health, 200); } - DrawHealthBar (points, 49, 4); - DrawHealthBar (points, 49, 7); + DrawHealthBar (points, 49, 172); + DrawHealthBar (points, 49, 175); // Armor item = CPlayer.mo.FindInventory('BasicArmor'); if (item != NULL && item.Amount > 0) { - DrawInventoryIcon(item, (2, 9), DI_ITEM_OFFSETS); - DrawString(mYelFont, FormatNumber(item.Amount, 3, 5), (27, 23), DI_TEXT_ALIGN_RIGHT); + DrawInventoryIcon(item, (2, 177), DI_ITEM_OFFSETS); + DrawString(mYelFont, FormatNumber(item.Amount, 3, 5), (27, 191), DI_TEXT_ALIGN_RIGHT); } // Ammo Inventory ammo1 = GetCurrentAmmo (); if (ammo1 != NULL) { - DrawString(mGrnFont, FormatNumber(ammo1.Amount, 3, 5), (311, -6), DI_TEXT_ALIGN_RIGHT); - DrawInventoryIcon (ammo1, (290, 13), DI_ITEM_OFFSETS); + DrawString(mGrnFont, FormatNumber(ammo1.Amount, 3, 5), (311, 162), DI_TEXT_ALIGN_RIGHT); + DrawInventoryIcon (ammo1, (290, 181), DI_ITEM_OFFSETS); } // Sigil item = CPlayer.mo.FindInventory('Sigil'); if (item != NULL) { - DrawInventoryIcon (item, (253, 7), DI_ITEM_OFFSETS); + DrawInventoryIcon (item, (253, 175), DI_ITEM_OFFSETS); } // Inventory @@ -339,10 +336,10 @@ class StrifeStatusBar : BaseStatusBar int flags = item.Amount <= 0? DI_ITEM_OFFSETS|DI_DIM : DI_ITEM_OFFSETS; if (item == CPlayer.mo.InvSel) { - DrawTexture (Images[CursorImage], (42 + 35*i, 12), flags, 1. - ItemFlash); + DrawTexture (Images[CursorImage], (42 + 35*i, 180), flags, 1. - ItemFlash); } - DrawInventoryIcon (item, (48 + 35*i, 14), flags); - DrawString(mYelFont, FormatNumber(item.Amount, 3, 5), (75 + 35*i, 23), DI_TEXT_ALIGN_RIGHT); + DrawInventoryIcon (item, (48 + 35*i, 182), flags); + DrawString(mYelFont, FormatNumber(item.Amount, 3, 5), (75 + 35*i, 191), DI_TEXT_ALIGN_RIGHT); i++; } } From 5f44bc4d5fada75fcd6449c5f947fd083f61c0b0 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 27 Mar 2017 10:55:51 +0300 Subject: [PATCH 08/29] Fixed crash in line portal setup https://mantis.zdoom.org/view.php?id=488 --- src/portal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portal.cpp b/src/portal.cpp index 1ec92799f..acf6e022d 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -167,7 +167,7 @@ static void BuildBlockmap() void FLinePortalTraverse::AddLineIntercepts(int bx, int by) { - if (by < 0 || by >= PortalBlockmap.dx || bx < 0 || bx >= PortalBlockmap.dy) return; + if (by < 0 || by >= PortalBlockmap.dy || bx < 0 || bx >= PortalBlockmap.dx) return; FPortalBlock &block = PortalBlockmap(bx, by); From ad992d2ffd1d1fd1edd17204061d9fc5a827694d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 Mar 2017 10:12:57 +0200 Subject: [PATCH 09/29] - add support for choosing the particle style in the software renderer --- src/swrenderer/drawers/r_draw.cpp | 11 ++++++++--- src/swrenderer/drawers/r_draw.h | 3 ++- src/swrenderer/drawers/r_draw_pal.cpp | 4 +++- src/swrenderer/drawers/r_draw_rgba.cpp | 3 ++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/swrenderer/drawers/r_draw.cpp b/src/swrenderer/drawers/r_draw.cpp index a4467266e..1f7b2d560 100644 --- a/src/swrenderer/drawers/r_draw.cpp +++ b/src/swrenderer/drawers/r_draw.cpp @@ -64,7 +64,7 @@ namespace swrenderer int fuzzpos; int fuzzviewheight; - uint32_t particle_texture[PARTICLE_TEXTURE_SIZE * PARTICLE_TEXTURE_SIZE]; + uint32_t particle_texture[NUM_PARTICLE_TEXTURES][PARTICLE_TEXTURE_SIZE * PARTICLE_TEXTURE_SIZE]; short zeroarray[MAXWIDTH]; short screenheightarray[MAXWIDTH]; @@ -139,6 +139,8 @@ namespace swrenderer void R_InitParticleTexture() { + static_assert(NUM_PARTICLE_TEXTURES == 3, "R_InitParticleTexture must be updated if NUM_PARTICLE_TEXTURES is changed"); + double center = PARTICLE_TEXTURE_SIZE * 0.5f; for (int y = 0; y < PARTICLE_TEXTURE_SIZE; y++) { @@ -147,9 +149,12 @@ namespace swrenderer double dx = (center - x - 0.5f) / center; double dy = (center - y - 0.5f) / center; double dist2 = dx * dx + dy * dy; - double alpha = clamp(1.1f - dist2 * 1.1f, 0.0f, 1.0f); + double round_alpha = clamp(1.7f - dist2 * 1.7f, 0.0f, 1.0f); + double smooth_alpha = clamp(1.1f - dist2 * 1.1f, 0.0f, 1.0f); - particle_texture[x + y * PARTICLE_TEXTURE_SIZE] = (int)(alpha * 128.0f + 0.5f); + particle_texture[0][x + y * PARTICLE_TEXTURE_SIZE] = 128; + particle_texture[1][x + y * PARTICLE_TEXTURE_SIZE] = (int)(round_alpha * 128.0f + 0.5f); + particle_texture[2][x + y * PARTICLE_TEXTURE_SIZE] = (int)(smooth_alpha * 128.0f + 0.5f); } } } diff --git a/src/swrenderer/drawers/r_draw.h b/src/swrenderer/drawers/r_draw.h index 5c37873c8..e9b893aba 100644 --- a/src/swrenderer/drawers/r_draw.h +++ b/src/swrenderer/drawers/r_draw.h @@ -44,8 +44,9 @@ namespace swrenderer extern int fuzzpos; extern int fuzzviewheight; + #define NUM_PARTICLE_TEXTURES 3 #define PARTICLE_TEXTURE_SIZE 64 - extern uint32_t particle_texture[PARTICLE_TEXTURE_SIZE * PARTICLE_TEXTURE_SIZE]; + extern uint32_t particle_texture[NUM_PARTICLE_TEXTURES][PARTICLE_TEXTURE_SIZE * PARTICLE_TEXTURE_SIZE]; class SWPixelFormatDrawers { diff --git a/src/swrenderer/drawers/r_draw_pal.cpp b/src/swrenderer/drawers/r_draw_pal.cpp index 522eb51b1..3f75a30ac 100644 --- a/src/swrenderer/drawers/r_draw_pal.cpp +++ b/src/swrenderer/drawers/r_draw_pal.cpp @@ -48,6 +48,7 @@ // [SP] r_blendmethod - false = rgb555 matching (ZDoom classic), true = rgb666 (refactored) CVAR(Bool, r_blendmethod, false, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) +EXTERN_CVAR(Int, gl_particles_style) /* [RH] This translucency algorithm is based on DOSDoom 0.65's, but uses @@ -2946,7 +2947,8 @@ namespace swrenderer uint8_t *dest = thread->dest_for_thread(_dest_y, pitch, _dest); pitch = pitch * thread->num_cores; - const uint32_t *source = &particle_texture[(_fracposx >> FRACBITS) * PARTICLE_TEXTURE_SIZE]; + int particle_texture_index = MIN(gl_particles_style, NUM_PARTICLE_TEXTURES - 1); + const uint32_t *source = &particle_texture[particle_texture_index][(_fracposx >> FRACBITS) * PARTICLE_TEXTURE_SIZE]; uint32_t particle_alpha = _alpha; uint32_t fracstep = PARTICLE_TEXTURE_SIZE * FRACUNIT / _count; diff --git a/src/swrenderer/drawers/r_draw_rgba.cpp b/src/swrenderer/drawers/r_draw_rgba.cpp index 453071eae..3dbd38f46 100644 --- a/src/swrenderer/drawers/r_draw_rgba.cpp +++ b/src/swrenderer/drawers/r_draw_rgba.cpp @@ -780,7 +780,8 @@ namespace swrenderer uint32_t *dest = thread->dest_for_thread(_dest_y, _pitch, _dest); int pitch = _pitch * thread->num_cores; - const uint32_t *source = &particle_texture[(_fracposx >> FRACBITS) * PARTICLE_TEXTURE_SIZE]; + int particle_texture_index = MIN(gl_particles_style, NUM_PARTICLE_TEXTURES - 1); + const uint32_t *source = &particle_texture[particle_texture_index][(_fracposx >> FRACBITS) * PARTICLE_TEXTURE_SIZE]; uint32_t particle_alpha = _alpha; uint32_t fracstep = PARTICLE_TEXTURE_SIZE * FRACUNIT / _count; From bed559f763110e0e7bc6c27ccf7b065547d87b4c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 27 Mar 2017 11:55:17 +0300 Subject: [PATCH 10/29] Fixed compilation with GCC/Clang src/g_statusbar/sbar.h:399:23: error: extra qualification on member 'DrawString' --- src/g_statusbar/sbar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index cdb191354..aee9f7c16 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -396,7 +396,7 @@ public: uint32_t GetTranslation() const; void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY); - void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, bool monospaced, int shadowX, int shadowY); + void DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, bool monospaced, int shadowX, int shadowY); void BeginStatusBar(int resW, int resH, int relTop, bool completeborder = false, bool forceScaled = false); void BeginHUD(int resW, int resH, double Alpha, bool forceScaled = false); From e865ba60f59f03711558cbd33f3f3bbbbef137c7 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 Mar 2017 11:33:16 +0200 Subject: [PATCH 11/29] - support particle styles in softpoly --- src/polyrenderer/drawers/poly_draw_args.cpp | 8 ++++++ src/polyrenderer/drawers/poly_draw_args.h | 1 + src/polyrenderer/scene/poly_particle.cpp | 32 ++++++++++++++++++++- src/polyrenderer/scene/poly_particle.h | 9 ++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index eaa812dc9..64fe7a882 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -45,6 +45,14 @@ void PolyDrawArgs::SetClipPlane(const PolyClipPlane &plane) mClipPlane[3] = plane.D; } +void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) +{ + mTexturePixels = texels; + mTextureWidth = width; + mTextureHeight = height; + mTranslation = nullptr; +} + void PolyDrawArgs::SetTexture(FTexture *texture) { mTextureWidth = texture->GetWidth(); diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index 20c73ec58..87cd6a191 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -49,6 +49,7 @@ class PolyDrawArgs { public: void SetClipPlane(const PolyClipPlane &plane); + void SetTexture(const uint8_t *texels, int width, int height); void SetTexture(FTexture *texture); void SetTexture(FTexture *texture, uint32_t translationID, bool forcePal = false); void SetLight(FSWColormap *basecolormap, uint32_t lightlevel, double globVis, bool fixed); diff --git a/src/polyrenderer/scene/poly_particle.cpp b/src/polyrenderer/scene/poly_particle.cpp index d4a49334b..53079b6dd 100644 --- a/src/polyrenderer/scene/poly_particle.cpp +++ b/src/polyrenderer/scene/poly_particle.cpp @@ -29,6 +29,8 @@ #include "polyrenderer/poly_renderer.h" #include "polyrenderer/scene/poly_light.h" +EXTERN_CVAR(Int, gl_particles_style) + void RenderPolyParticle::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue) { DVector3 pos = particle->Pos; @@ -76,12 +78,40 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, const PolyClipPlan args.SetSubsectorDepth(subsectorDepth); args.SetSubsectorDepthTest(true); args.SetColor(particle->color | 0xff000000, particle->color >> 24); - args.SetStyle(TriBlendMode::AlphaBlend, particle->alpha, 1.0 - particle->alpha); + args.SetStyle(TriBlendMode::Shaded, particle->alpha, 1.0 - particle->alpha); args.SetTransform(&worldToClip); args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); args.SetWriteStencil(false); args.SetWriteSubsectorDepth(false); args.SetClipPlane(clipPlane); + args.SetTexture(GetParticleTexture(), ParticleTextureSize, ParticleTextureSize); args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); } + +uint8_t *RenderPolyParticle::GetParticleTexture() +{ + static uint8_t particle_texture[NumParticleTextures][ParticleTextureSize * ParticleTextureSize]; + static bool first_call = true; + if (first_call) + { + double center = ParticleTextureSize * 0.5f; + for (int y = 0; y < ParticleTextureSize; y++) + { + for (int x = 0; x < ParticleTextureSize; x++) + { + double dx = (center - x - 0.5f) / center; + double dy = (center - y - 0.5f) / center; + double dist2 = dx * dx + dy * dy; + double round_alpha = clamp(1.7f - dist2 * 1.7f, 0.0f, 1.0f); + double smooth_alpha = clamp(1.1f - dist2 * 1.1f, 0.0f, 1.0f); + + particle_texture[0][x + y * ParticleTextureSize] = 255; + particle_texture[1][x + y * ParticleTextureSize] = (int)(round_alpha * 255.0f + 0.5f); + particle_texture[2][x + y * ParticleTextureSize] = (int)(smooth_alpha * 255.0f + 0.5f); + } + } + first_call = false; + } + return particle_texture[MIN(gl_particles_style, NumParticleTextures)]; +} diff --git a/src/polyrenderer/scene/poly_particle.h b/src/polyrenderer/scene/poly_particle.h index e91174591..a5cc3d0d0 100644 --- a/src/polyrenderer/scene/poly_particle.h +++ b/src/polyrenderer/scene/poly_particle.h @@ -29,4 +29,13 @@ class RenderPolyParticle { public: void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue); + +private: + static uint8_t *GetParticleTexture(); + + enum + { + NumParticleTextures = 3, + ParticleTextureSize = 64 + }; }; From 020c34abfa17e78c085deea6027bd1cdbf1d1481 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 27 Mar 2017 15:09:01 +0300 Subject: [PATCH 12/29] Added workaround for undefined isnan() All our continuous integration targets have no problems with C99 isnan() macro but on Ubuntu 16.04 compilation fails It appeared that some implementation of C++ Standard Library may undefine bunch of C macros to avoid conflicts with own declarations --- src/swrenderer/line/r_walldraw.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index bf8d856e9..d315d5a01 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -42,6 +42,13 @@ #include "swrenderer/r_renderthread.h" #include "swrenderer/r_memory.h" +#ifndef isnan +// Fallback to C++ function if C99 isnan() macro is not undefined +// Most likely it was undefined in C++ library header to avoid conflicts with own function +#include +using std::isnan; +#endif // !isnan + namespace swrenderer { WallSampler::WallSampler(RenderViewport *viewport, int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FTexture *texture) From a6bf93c6240050a9610af6e37e82dcf18d9976c3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Mar 2017 21:01:40 +0200 Subject: [PATCH 13/29] - implemented the Heretic status bar. --- src/g_statusbar/sbar.h | 13 +- src/g_statusbar/sbarinfo.cpp | 11 - src/g_statusbar/sbarinfo_commands.cpp | 28 +-- src/g_statusbar/shared_sbar.cpp | 52 +++-- src/scripting/backend/codegen.h | 4 +- wadsrc/static/mapinfo/heretic.txt | 3 +- wadsrc/static/zscript.txt | 1 + .../static/zscript/statusbar/heretic_sbar.txt | 208 ++++++++++++++++++ .../zscript/statusbar/sbarinfowrapper.txt | 7 - wadsrc/static/zscript/statusbar/statusbar.txt | 168 +++++++++++--- .../static/zscript/statusbar/strife_sbar.txt | 20 +- 11 files changed, 396 insertions(+), 119 deletions(-) create mode 100644 wadsrc/static/zscript/statusbar/heretic_sbar.txt diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index cdb191354..be8b7bb00 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -426,6 +426,8 @@ public: double CrosshairSize; double Displacement; bool ShowLog; + int artiflashTick = 0; + double itemflashFade = 0.75; player_t *CPlayer; @@ -475,9 +477,6 @@ enum DI_Flags DI_ALWAYSSHOWCOUNT = 0x200, // only for DrawInventoryBar. DI_DIMDEPLETED = 0x400, DI_DONTANIMATE = 0x800, // do not animate the texture - // These 2 flags are only used by SBARINFO - DI_DRAWINBOX = 0x1000, // Set when either width or height is not zero - DI_ALTERNATEONFAIL = 0x2000, DI_SCREEN_AUTO = 0, // decide based on given offsets. DI_SCREEN_MANUAL_ALIGN = 0x4000, // If this is on, the following flags will have an effect @@ -531,6 +530,14 @@ enum DI_Flags DI_ALPHAMAPPED = 0x2000000, DI_NOSHADOW = 0x4000000, + DI_ALWAYSSHOWCOUNTERS = 0x8000000, + DI_ARTIFLASH = 0x10000000, + DI_FORCEFILL = 0x20000000, + + // These 2 flags are only used by SBARINFO so these duplicate other flags not used by SBARINFO + DI_DRAWINBOX = DI_TEXT_ALIGN_RIGHT, + DI_ALTERNATEONFAIL = DI_TEXT_ALIGN_CENTER, + }; #endif /* __SBAR_H__ */ diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index b7f859442..c64dbef65 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -1161,9 +1161,6 @@ public: lastInventoryBar->Tick(NULL, this, false); } - // void DSBarInfo::FlashItem(const PClass *itemtype) - Is defined with CommandDrawSelectedInventory - void _FlashItem(const PClass *itemtype); - void _ShowPop(int popnum) { if(popnum != currentPopup) @@ -1604,14 +1601,6 @@ DEFINE_ACTION_FUNCTION(DSBarInfo, Tick) return 0; } -DEFINE_ACTION_FUNCTION(DSBarInfo, FlashItem) -{ - PARAM_SELF_STRUCT_PROLOGUE(DSBarInfo); - PARAM_CLASS(w, AInventory); - self->_FlashItem(w); - return 0; -} - DEFINE_ACTION_FUNCTION(DSBarInfo, ShowPop) { PARAM_SELF_STRUCT_PROLOGUE(DSBarInfo); diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index 64da7a7d5..458208b96 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -1691,16 +1691,16 @@ class CommandDrawSelectedInventory : public CommandDrawImage, private CommandDra if(statusBar->CPlayer->mo->InvSel != NULL && !(level.flags & LEVEL_NOINVENTORYBAR)) { - if(artiflash && artiflashTick) + if(artiflash && statusBar->wrapper->artiflashTick) { - statusBar->DrawGraphic(statusBar->Images[ARTIFLASH_OFFSET+(4-artiflashTick)], imgx, imgy, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), + statusBar->DrawGraphic(statusBar->Images[ARTIFLASH_OFFSET+(4- statusBar->wrapper->artiflashTick)], imgx, imgy, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translatable, false, offset); } else { - if(itemflash && itemflashFade != 0) + if(itemflash && statusBar->wrapper->itemflashFade != 0) { - double flashAlpha = block->Alpha() * itemflashFade; + double flashAlpha = block->Alpha() * statusBar->wrapper->itemflashFade; statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgCURSOR], imgx-4, imgy+2, block->XOffset(), block->YOffset(), flashAlpha, block->FullScreenOffsets(), translatable, false, offset); } @@ -1789,38 +1789,18 @@ class CommandDrawSelectedInventory : public CommandDrawImage, private CommandDra { SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); - if(artiflashTick > 0) - artiflashTick--; - if(itemflashFade > 0) - { - itemflashFade -= 1./14; - if(itemflashFade < 0) - itemflashFade = 0; - } - SetTruth(statusBar->CPlayer->mo->InvSel == NULL || (level.flags & LEVEL_NOINVENTORYBAR), block, statusBar); CommandDrawImage::Tick(block, statusBar, hudChanged); CommandDrawNumber::Tick(block, statusBar, hudChanged); } - static void Flash() { artiflashTick = 4; itemflashFade = 0.75; } protected: bool alternateOnEmpty; bool artiflash; bool alwaysShowCounter; bool itemflash; - - static int artiflashTick; - static double itemflashFade; }; -int CommandDrawSelectedInventory::artiflashTick = 0; -double CommandDrawSelectedInventory::itemflashFade = 0.75; - -void DSBarInfo::_FlashItem(const PClass *itemtype) -{ - CommandDrawSelectedInventory::Flash(); -} //////////////////////////////////////////////////////////////////////////////// diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 919d67848..af294f19d 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -593,6 +593,19 @@ void DBaseStatusBar::Tick () } } } + + if (artiflashTick > 0) + artiflashTick--; + + if (itemflashFade > 0) + { + itemflashFade -= 1 / 14.; + if (itemflashFade < 0) + { + itemflashFade = 0; + } + } + } DEFINE_ACTION_FUNCTION(DBaseStatusBar, Tick) @@ -1562,26 +1575,29 @@ void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int fla if (boxwidth > 0 || boxheight > 0) { - double scale1 = 1., scale2 = 1.; - - if (boxwidth > 0 && (boxwidth < texwidth || (flags & DI_FORCESCALE))) + if (!(flags & DI_FORCEFILL)) { - scale1 = boxwidth / texwidth; - } - if (boxheight != -1 && (boxheight < texheight || (flags & DI_FORCESCALE))) - { - scale2 = boxheight / texheight; - } + double scale1 = 1., scale2 = 1.; - if (flags & DI_FORCESCALE) - { - if (boxwidth <= 0 || (boxheight > 0 && scale2 < scale1)) - scale1 = scale2; - } - else scale1 = MIN(scale1, scale2); + if (boxwidth > 0 && (boxwidth < texwidth || (flags & DI_FORCESCALE))) + { + scale1 = boxwidth / texwidth; + } + if (boxheight != -1 && (boxheight < texheight || (flags & DI_FORCESCALE))) + { + scale2 = boxheight / texheight; + } - boxwidth = texwidth * scale1; - boxheight = texheight * scale1; + if (flags & DI_FORCESCALE) + { + if (boxwidth <= 0 || (boxheight > 0 && scale2 < scale1)) + scale1 = scale2; + } + else scale1 = MIN(scale1, scale2); + + boxwidth = texwidth * scale1; + boxheight = texheight * scale1; + } } else { @@ -1962,6 +1978,8 @@ DEFINE_FIELD(DBaseStatusBar, drawOffset); DEFINE_FIELD(DBaseStatusBar, drawClip); DEFINE_FIELD(DBaseStatusBar, fullscreenOffsets); DEFINE_FIELD(DBaseStatusBar, defaultScale); +DEFINE_FIELD(DBaseStatusBar, artiflashTick); +DEFINE_FIELD(DBaseStatusBar, itemflashFade); DEFINE_GLOBAL(StatusBar); diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 084ff52d7..2974866ca 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -508,7 +508,6 @@ public: FxConstant(PType *type, VMValue &vmval, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { - ValueType = value.Type = type; isresolved = true; switch (vmval.Type) { @@ -522,13 +521,14 @@ public: break; case REGT_STRING: - value = ExpVal(vmval.s()); + new(&value) ExpVal(vmval.s()); break; case REGT_POINTER: value.pointer = vmval.a; break; } + ValueType = value.Type = type; } static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos); diff --git a/wadsrc/static/mapinfo/heretic.txt b/wadsrc/static/mapinfo/heretic.txt index 361bf5cde..af0295ef3 100644 --- a/wadsrc/static/mapinfo/heretic.txt +++ b/wadsrc/static/mapinfo/heretic.txt @@ -25,7 +25,8 @@ gameinfo defaultbloodparticlecolor = "ff 00 00" backpacktype = "BagOfHolding" armoricons = "SHLDA0", 0.75, "SHD2A0" - statusbar = "sbarinfo/heretic.txt" + //statusbar = "sbarinfo/heretic.txt" + statusbarclass = "HereticStatusBar" intermissionmusic = "mus_intr" intermissioncounter = false weaponslot = 1, "Staff", "Gauntlets" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index a8a1d2586..367a9156d 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -34,6 +34,7 @@ version "2.5" #include "zscript/statusbar/statusbar.txt" #include "zscript/statusbar/doom_sbar.txt" +#include "zscript/statusbar/heretic_sbar.txt" #include "zscript/statusbar/strife_sbar.txt" #include "zscript/statusbar/sbarinfowrapper.txt" diff --git a/wadsrc/static/zscript/statusbar/heretic_sbar.txt b/wadsrc/static/zscript/statusbar/heretic_sbar.txt new file mode 100644 index 000000000..4c97a16be --- /dev/null +++ b/wadsrc/static/zscript/statusbar/heretic_sbar.txt @@ -0,0 +1,208 @@ +class HereticStatusBar : BaseStatusBar +{ + DynamicValueInterpolator mHealthInterpolator; + HUDFont mHUDFont; + HUDFont mIndexFont; + HUDFont mBigFont; + InventoryBarState diparms; + + + override void Init() + { + Super.Init(); + SetSize(48, 320, 200); + + // Create the font used for the fullscreen HUD + Font fnt = "HUDFONT_RAVEN"; + mHUDFont = HUDFont.Create(fnt, fnt.GetCharWidth("0") + 1, true, 1, 1); + fnt = "INDEXFONT_RAVEN"; + mIndexFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true); + fnt = "BIGFONT"; + mBigFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true, 2, 2); + diparms = InventoryBarState.Create(mIndexFont); + mHealthInterpolator = DynamicValueInterpolator.Create(0, 0.25, 1, 8); + } + + override void NewGame () + { + Super.NewGame(); + mHealthInterpolator.Reset (0); + } + + override void Tick() + { + Super.Tick(); + mHealthInterpolator.Update(CPlayer.health); + } + + override void Draw (int state, double TicFrac) + { + Super.Draw (state, TicFrac); + + if (state == HUD_StatusBar) + { + BeginStatusBar(320, 200, 42); + DrawMainBar (TicFrac); + } + else if (state == HUD_Fullscreen) + { + BeginHUD(320, 200, 1., false); + DrawFullScreenStuff (); + } + } + + protected void DrawMainBar (double TicFrac) + { + DrawImage("BARBACK", (0, 158), DI_ITEM_OFFSETS); + DrawImage("LTFCTOP", (0, 148), DI_ITEM_OFFSETS); + DrawImage("RTFCTOP", (290, 148), DI_ITEM_OFFSETS); + if (isInvulnerable()) + { + //god mode + DrawImage("GOD1", (16, 167), DI_ITEM_OFFSETS); + DrawImage("GOD2", (287, 167), DI_ITEM_OFFSETS); + } + //health + DrawImage("CHAINCAC", (0, 190), DI_ITEM_OFFSETS); + // wiggle the chain if it moves + int inthealth = mHealthInterpolator.GetValue(); + int wiggle = (inthealth != CPlayer.health) && Random[ChainWiggle](0, 1); + DrawGem("CHAIN", "LIFEGEM2",inthealth, CPlayer.mo.GetMaxHealth(true), (2, 191 + wiggle), 15, 25, 16, (multiplayer? DI_TRANSLATABLE : 0) | DI_ITEM_LEFT_TOP); + DrawImage("LTFACE", (0, 190), DI_ITEM_OFFSETS); + DrawImage("RTFACE", (276, 190), DI_ITEM_OFFSETS); + DrawShader(SHADER_HORZ, (19, 190), (16, 10)); + DrawShader(SHADER_HORZ|SHADER_REVERSE, (278, 190), (16, 10)); + + if (CPlayer.inventorytics == 0 || level.NoInventoryBar) + { + //statbar + if (!deathmatch) + { + DrawImage("LIFEBAR", (34, 160), DI_ITEM_OFFSETS); + DrawImage("ARMCLEAR", (57, 171), DI_ITEM_OFFSETS); + DrawString(mHUDFont, FormatNumber(mHealthInterpolator.GetValue(), 3), (88, 170), DI_TEXT_ALIGN_RIGHT); + } + else + { + DrawImage("STATBAR", (34, 160), DI_ITEM_OFFSETS); + DrawImage("ARMCLEAR", (57, 171), DI_ITEM_OFFSETS); + DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (88, 170), DI_TEXT_ALIGN_RIGHT); + } + DrawString(mHUDFont, FormatNumber(GetArmorAmount(), 3), (255, 170), DI_TEXT_ALIGN_RIGHT); + + //ammo + Ammo ammo1, ammo2; + [ammo1, ammo2] = GetCurrentAmmo(); + if (ammo1 != null && ammo2 == null) + { + DrawString(mHUDFont, FormatNumber(ammo1.Amount, 3), (136, 162), DI_TEXT_ALIGN_RIGHT); + DrawTexture(ammo1.icon, (123, 180), DI_ITEM_CENTER); + } + else if (ammo2 != null) + { + DrawString(mIndexFont, FormatNumber(ammo1.Amount, 3), (137, 165), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(ammo2.Amount, 3), (137, 177), DI_TEXT_ALIGN_RIGHT); + DrawTexture(ammo1.icon, (115, 169), DI_ITEM_CENTER); + DrawTexture(ammo2.icon, (115, 180), DI_ITEM_CENTER); + } + + //keys + if (CPlayer.mo.CheckKeys(3, false, true)) DrawImage("YKEYICON", (153, 164), DI_ITEM_OFFSETS); + if (CPlayer.mo.CheckKeys(1, false, true)) DrawImage("GKEYICON", (153, 172), DI_ITEM_OFFSETS); + if (CPlayer.mo.CheckKeys(2, false, true)) DrawImage("BKEYICON", (153, 180), DI_ITEM_OFFSETS); + + //inventory box + if (CPlayer.mo.InvSel != null) + { + DrawInventoryIcon(CPlayer.mo.InvSel, (194, 175), DI_ARTIFLASH|DI_ITEM_CENTER, boxsize:(28, 28)); + if (CPlayer.mo.InvSel.Amount > 1) + { + DrawString(mIndexFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (209, 182), DI_TEXT_ALIGN_RIGHT); + } + } + + } + else + { + DrawImage("INVBAR", (34, 160), DI_ITEM_OFFSETS); + //drawinventorybar Heretic, noartibox, 7, INDEXFONT_RAVEN, 50, 160, 77, 182, untranslated; + } + } + + protected void DrawFullScreenStuff () + { + + //health + DrawImage("PTN1A0", (51, -3)); + DrawString(mBigFont, FormatNumber(mHealthInterpolator.GetValue()), (41, -21), DI_TEXT_ALIGN_RIGHT); + + //armor + let armor = CPlayer.mo.FindInventory("BasicArmor"); + if (armor != null) + { + DrawInventoryIcon(armor, (58, -24)); + DrawString(mBigFont, FormatNumber(armor.Amount, 3), (41, -43), DI_TEXT_ALIGN_RIGHT); + } + //frags/keys + if (deathmatch) + { + DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (70, -16)); + } + else + { + Vector2 keypos = (60, -1); + int rowc = 0; + double roww = 0; + for(let i = CPlayer.mo.Inv; i != null; i = i.Inv) + { + if (i is "Key" && i.Icon.IsValid()) + { + DrawTexture(i.Icon, keypos, DI_ITEM_LEFT_BOTTOM); + Vector2 size = TexMan.GetScaledSize(i.Icon); + keypos.Y -= size.Y + 2; + roww = max(roww, size.X); + if (++rowc == 3) + { + keypos.Y = -1; + keypos.X += roww + 2; + roww = 0; + rowc = 0; + } + } + } + } + + //ammo + Ammo ammo1, ammo2; + [ammo1, ammo2] = GetCurrentAmmo(); + int y = -22; + if (ammo1 != null) + { + DrawTexture(ammo1.Icon, (-17, y)); + DrawString(mHUDFont, FormatNumber(ammo1.Amount, 3), (-3, y+7), DI_TEXT_ALIGN_RIGHT); + y -= 40; + } + if (ammo2 != null) + { + DrawTexture(ammo2.Icon, (-14, y)); + DrawString(mHUDFont, FormatNumber(ammo2.Amount, 3), (-3, y+7), DI_TEXT_ALIGN_RIGHT); + y -= 40; + } + + if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null && !level.NoInventoryBar) + { + // This code was changed to always fit the item into the box, regardless of alignment or sprite size. + // Heretic's ARTIBOX is 30x30 pixels. + DrawImage("ARTIBOX", (-46, -1), 0, HX_SHADOW); + DrawInventoryIcon(CPlayer.mo.InvSel, (-46, -15), DI_ARTIFLASH|DI_ITEM_CENTER, boxsize:(28, 28)); + if (CPlayer.mo.InvSel.Amount > 1) + { + DrawString(mIndexFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-32, -2 - mIndexFont.mFont.GetHeight()), DI_TEXT_ALIGN_RIGHT); + } + } + if (CPlayer.inventorytics != 0 && !level.NoInventoryBar) + { + DrawInventoryBar(diparms, (0, 0), 7, DI_SCREEN_CENTER_BOTTOM, HX_SHADOW); + } + } +} diff --git a/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt b/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt index d58e175d1..8c8c6bf53 100644 --- a/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt +++ b/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt @@ -8,7 +8,6 @@ struct SBarInfo native ui native void NewGame(); native bool MustDrawLog(int state); native void Tick(); - native void FlashItem(class itemtype); native void ShowPop(int popnum); } @@ -49,7 +48,6 @@ class SBarInfoWrapper : BaseStatusBar Super.NewGame(); if (CPlayer != NULL) { - AttachToPlayer(CPlayer); core.NewGame(); } } @@ -65,11 +63,6 @@ class SBarInfoWrapper : BaseStatusBar core.Tick(); } - override void FlashItem(class itemtype) - { - core.FlashItem(itemtype); - } - override void ShowPop(int popnum) { Super.ShowPop(popnum); diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index e1bdf4d63..3d6c4fe86 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -26,9 +26,9 @@ class InventoryBarState ui TextureID box; TextureID selector; Vector2 boxsize; + Vector2 boxofs; Vector2 innersize; - int boxframesize; - + TextureID left; TextureID right; Vector2 arrowoffset; @@ -41,17 +41,25 @@ class InventoryBarState ui // The default settings here are what SBARINFO is using. static InventoryBarState Create(HUDFont indexfont = null, int cr = Font.CR_UNTRANSLATED, double itemalpha = 1., - String boxgfx = "ARTIBOX", String selgfx = "SELECTBO", int fsize = 2, + String boxgfx = "ARTIBOX", String selgfx = "SELECTBO", Vector2 innersize = (0, 0), String leftgfx = "INVGEML1", String rightgfx = "INVGEMR1", Vector2 arrowoffs = (0, 0), int flags = 0) { let me = new ("InventoryBarState"); me.itemalpha = itemalpha; me.box = TexMan.CheckForTexture(boxgfx, TexMan.TYPE_MiscPatch); me.selector = TexMan.CheckForTexture(selgfx, TexMan.TYPE_MiscPatch); - me.boxframesize = fsize; if (me.box.IsValid() || me.selector.IsValid()) me.boxsize = TexMan.GetScaledSize(me.box.IsValid()? me.box : me.selector); else me.boxsize = (32., 32.); - me.innersize = me.boxsize - (2.*fsize, 2.*fsize); + if (innersize == (0, 0)) + { + me.boxofs = (2, 2); + me.innersize = me.boxsize - (4, 4); // Default is based on Heretic's and Hexens icons. + } + else + { + me.innersize = innersize; + me.boxofs = (me.boxsize - me.innersize) / 2; + } me.left = TexMan.CheckForTexture(leftgfx, TexMan.TYPE_MiscPatch); me.right = TexMan.CheckForTexture(rightgfx, TexMan.TYPE_MiscPatch); me.arrowoffset = arrowoffs; @@ -122,25 +130,22 @@ class BaseStatusBar native ui DI_ALWAYSSHOWCOUNT = 0x200, // only for DrawInventoryBar. DI_DIMDEPLETED = 0x400, DI_DONTANIMATE = 0x800, // do not animate the texture - // These 2 flags are only used by SBARINFO - DI_DRAWINBOX = 0x1000, // Set when either width or height is not zero - DI_ALTERNATEONFAIL = 0x2000, - + DI_SCREEN_AUTO = 0, // decide based on given offsets. DI_SCREEN_MANUAL_ALIGN = 0x4000, // If this is on, the following flags will have an effect - + DI_SCREEN_TOP = DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_VCENTER = 0x8000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_BOTTOM = 0x10000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_VOFFSET = 0x18000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_VMASK = 0x18000 | DI_SCREEN_MANUAL_ALIGN, - + DI_SCREEN_LEFT = DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_HCENTER = 0x20000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_RIGHT = 0x40000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_HOFFSET = 0x60000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_HMASK = 0x60000 | DI_SCREEN_MANUAL_ALIGN, - + DI_SCREEN_LEFT_TOP = DI_SCREEN_TOP|DI_SCREEN_LEFT, DI_SCREEN_RIGHT_TOP = DI_SCREEN_TOP|DI_SCREEN_RIGHT, DI_SCREEN_LEFT_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_LEFT, @@ -148,21 +153,21 @@ class BaseStatusBar native ui DI_SCREEN_CENTER = DI_SCREEN_VCENTER|DI_SCREEN_HCENTER, DI_SCREEN_CENTER_BOTTOM = DI_SCREEN_BOTTOM|DI_SCREEN_HCENTER, DI_SCREEN_OFFSETS = DI_SCREEN_HOFFSET|DI_SCREEN_VOFFSET, - + DI_ITEM_AUTO = 0, // equivalent with bottom center, which is the default alignment. - + DI_ITEM_TOP = 0x80000, DI_ITEM_VCENTER = 0x100000, DI_ITEM_BOTTOM = 0, // this is the default vertical alignment DI_ITEM_VOFFSET = 0x180000, DI_ITEM_VMASK = 0x180000, - + DI_ITEM_LEFT = 0x200000, DI_ITEM_HCENTER = 0, // this is the deafault horizontal alignment DI_ITEM_RIGHT = 0x400000, DI_ITEM_HOFFSET = 0x600000, DI_ITEM_HMASK = 0x600000, - + DI_ITEM_LEFT_TOP = DI_ITEM_TOP|DI_ITEM_LEFT, DI_ITEM_RIGHT_TOP = DI_ITEM_TOP|DI_ITEM_RIGHT, DI_ITEM_LEFT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_LEFT, @@ -170,14 +175,22 @@ class BaseStatusBar native ui DI_ITEM_CENTER = DI_ITEM_VCENTER|DI_ITEM_HCENTER, DI_ITEM_CENTER_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_HCENTER, DI_ITEM_OFFSETS = DI_ITEM_HOFFSET|DI_ITEM_VOFFSET, - + DI_TEXT_ALIGN_LEFT = 0, DI_TEXT_ALIGN_RIGHT = 0x800000, DI_TEXT_ALIGN_CENTER = 0x1000000, + DI_TEXT_ALIGN = 0x1800000, DI_ALPHAMAPPED = 0x2000000, DI_NOSHADOW = 0x4000000, DI_ALWAYSSHOWCOUNTERS = 0x8000000, + DI_ARTIFLASH = 0x10000000, + DI_FORCEFILL = 0x20000000, + + // These 2 flags are only used by SBARINFO so these duplicate other flags not used by SBARINFO + DI_DRAWINBOX = DI_TEXT_ALIGN_RIGHT, + DI_ALTERNATEONFAIL = DI_TEXT_ALIGN_CENTER, + }; enum IconType @@ -220,6 +233,13 @@ class BaseStatusBar native ui FNF_WHENNOTZERO, } + enum EShade + { + SHADER_HORZ = 0, + SHADER_VERT = 2, + SHADER_REVERSE = 1 + } + const XHAIRSHRINKSIZE =(1./18); const XHAIRPICKUPSIZE = (2+XHAIRSHRINKSIZE); const POWERUPICONSIZE = 32; @@ -237,6 +257,8 @@ class BaseStatusBar native ui native PlayerInfo CPlayer; native bool ShowLog; native Vector2 defaultScale; // factor for fully scaled fullscreen display. + native int artiflashTick; + native double itemflashFade; // These are block properties for the drawers. A child class can set them to have a block of items use the same settings. native double Alpha; @@ -259,7 +281,7 @@ class BaseStatusBar native ui native virtual clearscope void ReceivedWeapon (Weapon weapn); native virtual clearscope void SetMugShotState (String state_name, bool wait_till_done=false, bool reset=false); - virtual void FlashItem (class itemtype) {} + virtual void FlashItem (class itemtype) { artiflashTick = 4; itemflashFade = 0.75; } virtual void AttachToPlayer (PlayerInfo player) { CPlayer = player; } virtual void FlashCrosshair () { CrosshairSize = XHAIRPICKUPSIZE; } virtual void NewGame () { if (CPlayer != null) AttachToPlayer(CPlayer); } @@ -287,7 +309,7 @@ class BaseStatusBar native ui // //============================================================================ - Inventory, Inventory, int, int GetCurrentAmmo () const + Ammo, Ammo, int, int GetCurrentAmmo () const { Ammo ammo1, ammo2; if (CPlayer.ReadyWeapon != NULL) @@ -666,10 +688,16 @@ class BaseStatusBar native ui void DrawInventoryIcon(Inventory item, Vector2 pos, int flags = 0, double alpha = 1.0, Vector2 boxsize = (-1, -1), Vector2 scale = (1.,1.)) { + static const String flashimgs[]= { "USEARTID", "USEARTIC", "USEARTIB", "USEARTIA" }; TextureID texture; Vector2 applyscale; [texture, applyscale] = GetIcon(item, flags, false); - if (texture.IsValid()) + + if((flags & DI_ARTIFLASH) && artiflashTick > 0) + { + DrawImage(flashimgs[artiflashTick-1], pos, flags | DI_TRANSLATABLE, alpha, boxsize); + } + else if (texture.IsValid()) { if ((flags & DI_DIMDEPLETED) && item.Amount <= 0) flags |= DI_DIM; applyscale.X *= scale.X; @@ -680,19 +708,24 @@ class BaseStatusBar native ui //============================================================================ // - // DrawInventoryBar // - // This function needs too many parameters, so most have been offloaded to - // a struct to keep code readable and allow initialization somewhere outside - // the actual drawing code. // //============================================================================ - // Except for the placement information this gets all info from the struct that gets passed in. - void DrawInventoryBar(InventoryBarState parms, Vector2 position, int numfields, int flags = 0, double bgalpha = 1.) + void DrawShader(int which, Vector2 pos, Vector2 size, int flags = 0, double alpha = 1.) + { + static const String texnames[] = {"BarShaderHF", "BarShaderHR", "BarShaderVF", "BarShaderVR" }; + DrawImage(texnames[which], pos, DI_ITEM_LEFT_TOP|DI_ALPHAMAPPED|DI_FORCEFILL | (flags & ~(DI_ITEM_HMASK|DI_ITEM_VMASK)), alpha, size); + } + + //============================================================================ + // + // + // + //============================================================================ + + Vector2, int AdjustPosition(Vector2 position, int flags, double width, double height) { - double width = parms.boxsize.X * numfields; - // This must be done here, before altered coordinates get sent to the draw functions. if (!(flags & DI_SCREEN_MANUAL_ALIGN)) { @@ -711,12 +744,52 @@ class BaseStatusBar native ui switch (flags & DI_ITEM_VMASK) { - case DI_ITEM_VCENTER: position.y -= parms.boxsize.Y / 2; break; - case DI_ITEM_BOTTOM: position.y -= parms.boxsize.Y; break; + case DI_ITEM_VCENTER: position.y -= height / 2; break; + case DI_ITEM_BOTTOM: position.y -= height; break; } - // clear all alignment flags so that the following code only passed on the rest + // clear all alignment flags so that the following code only passes on the rest flags &= ~(DI_ITEM_VMASK|DI_ITEM_HMASK); + return position, flags; + } + + //============================================================================ + // + // note that this does not implement chain wiggling, this is because + // it would severely complicate the parameter list. The calling code is + // normally in a better position to do the needed calculations anyway. + // + //============================================================================ + + void DrawGem(String chain, String gem, int displayvalue, int maxrange, Vector2 pos, int leftpadding, int rightpadding, int chainmod, int flags = 0) + { + TextureID chaintex = TexMan.CheckForTexture(chain, TexMan.TYPE_MiscPatch); + if (!chaintex.IsValid()) return; + Vector2 chainsize = TexMan.GetScaledSize(chaintex); + [pos, flags] = AdjustPosition(pos, flags, chainsize.X, chainsize.Y); + + displayvalue = clamp(displayvalue, 0, maxrange); + int offset = int(double(chainsize.X - leftpadding - rightpadding) * displayvalue / maxrange); + + DrawTexture(chaintex, pos + (offset % chainmod, 0), flags | DI_ITEM_LEFT_TOP); + DrawImage(gem, pos + (offset + leftPadding, 0), flags | DI_ITEM_LEFT_TOP); + } + + //============================================================================ + // + // DrawInventoryBar + // + // This function needs too many parameters, so most have been offloaded to + // a struct to keep code readable and allow initialization somewhere outside + // the actual drawing code. + // + //============================================================================ + + // Except for the placement information this gets all info from the struct that gets passed in. + void DrawInventoryBar(InventoryBarState parms, Vector2 position, int numfields, int flags = 0, double bgalpha = 1.) + { + double width = parms.boxsize.X * numfields; + [position, flags] = AdjustPosition(position, flags, width, parms.boxsize.Y); CPlayer.mo.InvFirst = ValidateInvFirst(numfields); if (CPlayer.mo.InvFirst == null) return; // Player has no listed inventory items. @@ -730,16 +803,29 @@ class BaseStatusBar native ui // now the items and the rest - Vector2 itempos = position + (boxsize.X / 2, boxsize.Y - parms.boxframesize); - Vector2 textpos = position + boxsize - (parms.boxframesize*2, parms.boxframesize + parms.amountfont.mFont.GetHeight()); + Vector2 itempos = position + boxsize / 2; + Vector2 textpos = position + boxsize - (1, 1 + parms.amountfont.mFont.GetHeight()); int i = 0; Inventory item; for(item = CPlayer.mo.InvFirst; item != NULL && i < numfields; item = item.NextInv()) { - if ((parms.flags & DI_DRAWCURSORFIRST) && item == CPlayer.mo.InvSel) DrawTexture(parms.selector, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP); - DrawInventoryIcon(item, itempos + (boxsize.X * i, 0), flags | DI_ITEM_CENTER_BOTTOM ); - if (!(parms.flags & DI_DRAWCURSORFIRST) && item == CPlayer.mo.InvSel) DrawTexture(parms.selector, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP); + for(int j = 0; j < 2; j++) + { + if (j ^ !!(parms.flags & DI_DRAWCURSORFIRST)) + { + if (item == CPlayer.mo.InvSel) + { + double flashAlpha = bgalpha; + if (flags & DI_ARTIFLASH) flashAlpha *= itemflashFade; + DrawTexture(parms.selector, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP, flashAlpha); + } + } + else + { + DrawInventoryIcon(item, itempos + (boxsize.X * i, 0), flags | DI_ITEM_CENTER ); + } + } if (parms.amountfont != null && (item.Amount > 1 || (parms.flags & DI_ALWAYSSHOWCOUNTERS))) { @@ -780,6 +866,11 @@ class LinearValueInterpolator : Object return v; } + void Reset(int value) + { + mCurrentValue = value; + } + // This must be called peroiodically in the status bar's Tick function. // Do not call this in the Draw function because that may skip some frames! void Update(int destvalue) @@ -819,6 +910,11 @@ class DynamicValueInterpolator : Object return v; } + void Reset(int value) + { + mCurrentValue = value; + } + // This must be called peroiodically in the status bar's Tick function. // Do not call this in the Draw function because that may skip some frames! void Update(int destvalue) diff --git a/wadsrc/static/zscript/statusbar/strife_sbar.txt b/wadsrc/static/zscript/statusbar/strife_sbar.txt index 889842cc3..fc1862698 100644 --- a/wadsrc/static/zscript/statusbar/strife_sbar.txt +++ b/wadsrc/static/zscript/statusbar/strife_sbar.txt @@ -37,7 +37,6 @@ class StrifeStatusBar : BaseStatusBar int CursorImage; int CurrentPop, PendingPop, PopHeight, PopHeightChange; int KeyPopPos, KeyPopScroll; - double ItemFlash; HUDFont mYelFont, mGrnFont, mBigFont; @@ -152,22 +151,12 @@ class StrifeStatusBar : BaseStatusBar PopHeight = 0; KeyPopPos = 0; KeyPopScroll = 0; - ItemFlash = 0; } override void Tick () { Super.Tick (); - if (ItemFlash > 0) - { - ItemFlash -= 1/14.; - if (ItemFlash < 0) - { - ItemFlash = 0; - } - } - PopHeightChange = 0; if (PendingPop != POP_NoChange) { @@ -211,11 +200,6 @@ class StrifeStatusBar : BaseStatusBar } } - override void FlashItem (Class itemtype) - { - ItemFlash = 0.75; - } - private void FillBar(double x, double y, double start, double stopp, Color color1, Color color2) { Vector2 virt = Scaled? (320., 200.) : (screen.GetWidth(), screen.GetHeight()); @@ -336,7 +320,7 @@ class StrifeStatusBar : BaseStatusBar int flags = item.Amount <= 0? DI_ITEM_OFFSETS|DI_DIM : DI_ITEM_OFFSETS; if (item == CPlayer.mo.InvSel) { - DrawTexture (Images[CursorImage], (42 + 35*i, 180), flags, 1. - ItemFlash); + DrawTexture (Images[CursorImage], (42 + 35*i, 180), flags, 1. - itemflashFade); } DrawInventoryIcon (item, (48 + 35*i, 182), flags); DrawString(mYelFont, FormatNumber(item.Amount, 3, 5), (75 + 35*i, 191), DI_TEXT_ALIGN_RIGHT); @@ -386,7 +370,7 @@ class StrifeStatusBar : BaseStatusBar { if (CPlayer.mo.InvSel != null) { - if (ItemFlash > 0) + if (itemflashFade > 0) { DrawTexture(Images[CursorImage], (-42, -15)); } From 0537e9c1ba1dfd7044d02c26488125ce5b9021a8 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 Mar 2017 21:03:51 +0200 Subject: [PATCH 14/29] - implement all styles for sprites in softpoly --- src/polyrenderer/drawers/poly_draw_args.h | 2 +- src/polyrenderer/drawers/poly_drawer32_sse2.h | 14 ++- src/polyrenderer/drawers/poly_drawer8.h | 35 ++++-- src/polyrenderer/drawers/poly_triangle.cpp | 6 +- src/polyrenderer/drawers/screen_triangle.cpp | 119 +++++++----------- src/polyrenderer/drawers/screen_triangle.h | 48 +++---- src/polyrenderer/scene/poly_plane.cpp | 4 +- src/polyrenderer/scene/poly_scene.cpp | 2 +- src/polyrenderer/scene/poly_sky.cpp | 12 +- src/polyrenderer/scene/poly_sky.h | 2 +- src/polyrenderer/scene/poly_sprite.cpp | 24 ++-- src/polyrenderer/scene/poly_wall.cpp | 7 +- src/polyrenderer/scene/poly_wallsprite.cpp | 2 +- 13 files changed, 139 insertions(+), 138 deletions(-) diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index 87cd6a191..c19bb6492 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -128,7 +128,7 @@ private: uint8_t mStencilWriteValue = 0; const uint8_t *mColormaps = nullptr; float mClipPlane[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - TriBlendMode mBlendMode = TriBlendMode::Copy; + TriBlendMode mBlendMode = TriBlendMode::FillOpaque; uint32_t mLight = 0; uint32_t mSubsectorDepth = 0; uint32_t mColor = 0; diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index a3568b6c1..39a88c47e 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -53,7 +53,7 @@ public: Loop(args, thread); } } - else // no linear filtering for translated, shaded, fill or skycap + else // no linear filtering for translated, shaded, stencil, fill or skycap { if (is_simple_shade) { @@ -453,7 +453,7 @@ private: using namespace TriScreenDrawerModes; uint32_t texel; - if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Fill) + if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill) { return color; } @@ -542,6 +542,14 @@ private: sampleshadeout += sampleshadeout >> 7; // 255 -> 256 return sampleshadeout; } + else if (SamplerT::Mode == (int)Samplers::Stencil) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]); + sampleshadeout += sampleshadeout >> 7; // 255 -> 256 + return sampleshadeout; + } else { return 0; @@ -621,6 +629,8 @@ private: } else if (BlendT::Mode == (int)BlendModes::AddClampShaded) { + ifgshade0 = (ifgshade0 * srcalpha + 128) >> 8; + ifgshade1 = (ifgshade1 * srcalpha + 128) >> 8; __m128i alpha = _mm_set_epi16(ifgshade1, ifgshade1, ifgshade1, ifgshade1, ifgshade0, ifgshade0, ifgshade0, ifgshade0); fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, alpha), 8); diff --git a/src/polyrenderer/drawers/poly_drawer8.h b/src/polyrenderer/drawers/poly_drawer8.h index 2ae40e524..6b02c52c3 100644 --- a/src/polyrenderer/drawers/poly_drawer8.h +++ b/src/polyrenderer/drawers/poly_drawer8.h @@ -272,7 +272,7 @@ private: using namespace TriScreenDrawerModes; uint8_t texel; - if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Fill) + if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill) { return color; } @@ -301,13 +301,14 @@ private: if (a == 256) return texel; + uint32_t capcolor = GPalette.BaseColors[color].d; uint32_t texelrgb = GPalette.BaseColors[texel].d; uint32_t r = RPART(texelrgb); uint32_t g = GPART(texelrgb); uint32_t b = BPART(texelrgb); - uint32_t capcolor_red = RPART(color); - uint32_t capcolor_green = GPART(color); - uint32_t capcolor_blue = BPART(color); + uint32_t capcolor_red = RPART(capcolor); + uint32_t capcolor_green = GPART(capcolor); + uint32_t capcolor_blue = BPART(capcolor); r = (r * a + capcolor_red * inv_a + 127) >> 8; g = (g * a + capcolor_green * inv_a + 127) >> 8; b = (b * a + capcolor_blue * inv_a + 127) >> 8; @@ -331,6 +332,12 @@ private: sampleshadeout += sampleshadeout >> 7; // 255 -> 256 return sampleshadeout; } + else if (SamplerT::Mode == (int)Samplers::Stencil) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + return texPixels[texelX * texHeight + texelY] != 0 ? 256 : 0; + } else { return 0; @@ -372,6 +379,7 @@ private: } else if (BlendT::Mode == (int)BlendModes::Shaded) { + fgshade = (fgshade * srcalpha + 128) >> 8; uint32_t alpha = fgshade; uint32_t inv_alpha = 256 - fgshade; int32_t fg_r = GPalette.BaseColors[shadedfg].r; @@ -390,6 +398,7 @@ private: } else if (BlendT::Mode == (int)BlendModes::AddClampShaded) { + fgshade = (fgshade * srcalpha + 128) >> 8; uint32_t alpha = fgshade; int32_t fg_r = GPalette.BaseColors[shadedfg].r; int32_t fg_g = GPalette.BaseColors[shadedfg].g; @@ -417,21 +426,21 @@ private: if (BlendT::Mode == (int)BlendModes::AddClamp) { - fg_r = MIN((fg_r * srcalpha + bg_r * destalpha + 127) >> 8, 255); - fg_g = MIN((fg_g * srcalpha + bg_g * destalpha + 127) >> 8, 255); - fg_b = MIN((fg_b * srcalpha + bg_b * destalpha + 127) >> 8, 255); + fg_r = MIN(int32_t(fg_r * srcalpha + bg_r * destalpha + 127) >> 8, 255); + fg_g = MIN(int32_t(fg_g * srcalpha + bg_g * destalpha + 127) >> 8, 255); + fg_b = MIN(int32_t(fg_b * srcalpha + bg_b * destalpha + 127) >> 8, 255); } else if (BlendT::Mode == (int)BlendModes::SubClamp) { - fg_r = MAX((fg_r * srcalpha - bg_r * destalpha + 127) >> 8, 0); - fg_g = MAX((fg_g * srcalpha - bg_g * destalpha + 127) >> 8, 0); - fg_b = MAX((fg_b * srcalpha - bg_b * destalpha + 127) >> 8, 0); + fg_r = MAX(int32_t(fg_r * srcalpha - bg_r * destalpha + 127) >> 8, 0); + fg_g = MAX(int32_t(fg_g * srcalpha - bg_g * destalpha + 127) >> 8, 0); + fg_b = MAX(int32_t(fg_b * srcalpha - bg_b * destalpha + 127) >> 8, 0); } else if (BlendT::Mode == (int)BlendModes::RevSubClamp) { - fg_r = MAX((bg_r * srcalpha - fg_r * destalpha + 127) >> 8, 0); - fg_g = MAX((bg_g * srcalpha - fg_g * destalpha + 127) >> 8, 0); - fg_b = MAX((bg_b * srcalpha - fg_b * destalpha + 127) >> 8, 0); + fg_r = MAX(int32_t(bg_r * srcalpha - fg_r * destalpha + 127) >> 8, 0); + fg_g = MAX(int32_t(bg_g * srcalpha - fg_g * destalpha + 127) >> 8, 0); + fg_b = MAX(int32_t(bg_b * srcalpha - fg_b * destalpha + 127) >> 8, 0); } shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)]; diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index d07102f1e..28dd2da1c 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -99,10 +99,8 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadD { int bmode = (int)drawargs.BlendMode(); - if (drawargs.WriteColor() && drawargs.TexturePixels()) - drawfuncs[num_drawfuncs++] = dest_bgra ? ScreenTriangle::TriDraw32[bmode] : ScreenTriangle::TriDraw8[bmode]; - else if (drawargs.WriteColor()) - drawfuncs[num_drawfuncs++] = dest_bgra ? ScreenTriangle::TriFill32[bmode] : ScreenTriangle::TriFill8[bmode]; + if (drawargs.WriteColor()) + drawfuncs[num_drawfuncs++] = dest_bgra ? ScreenTriangle::TriDrawers32[bmode] : ScreenTriangle::TriDrawers8[bmode]; } if (drawargs.WriteStencil()) diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index ab0928d0e..d1fe49513 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -922,87 +922,62 @@ void ScreenTriangle::SubsectorWrite(const TriDrawTriangleArgs *args, WorkerThrea } } -std::vector ScreenTriangle::TriDraw8 = +std::vector ScreenTriangle::TriDrawers8 = { - &TriScreenDrawer8::Execute, // "Copy", "opaque", false - &TriScreenDrawer8::Execute, // "AlphaBlend", "masked", false - &TriScreenDrawer8::Execute, // "AddSolid", "translucent", false - &TriScreenDrawer8::Execute, // "Add", "add", false - &TriScreenDrawer8::Execute, // "Sub", "sub", false - &TriScreenDrawer8::Execute, // "RevSub", "revsub", false - &TriScreenDrawer8::Execute, // "Stencil", "stencil", false - &TriScreenDrawer8::Execute, // "Shaded", "shaded", false - &TriScreenDrawer8::Execute, // "TranslateCopy", "opaque", true - &TriScreenDrawer8::Execute, // "TranslateAlphaBlend", "masked", true - &TriScreenDrawer8::Execute, // "TranslateAdd", "add", true - &TriScreenDrawer8::Execute, // "TranslateSub", "sub", true - &TriScreenDrawer8::Execute, // "TranslateRevSub", "revsub", true - &TriScreenDrawer8::Execute, // "AddSrcColorOneMinusSrcColor", "addsrccolor", false - &TriScreenDrawer8::Execute // "Skycap", "skycap", false -}; - -std::vector ScreenTriangle::TriFill8 = -{ - &TriScreenDrawer8::Execute, // "Copy", "opaque", false - &TriScreenDrawer8::Execute, // "AlphaBlend", "masked", false - &TriScreenDrawer8::Execute, // "AddSolid", "translucent", false - &TriScreenDrawer8::Execute, // "Add", "add", false - &TriScreenDrawer8::Execute, // "Sub", "sub", false - &TriScreenDrawer8::Execute, // "RevSub", "revsub", false - &TriScreenDrawer8::Execute, // "Stencil", "stencil", false - &TriScreenDrawer8::Execute, // "Shaded", "shaded", false - &TriScreenDrawer8::Execute, // "TranslateCopy", "opaque", true - &TriScreenDrawer8::Execute, // "TranslateAlphaBlend", "masked", true - &TriScreenDrawer8::Execute, // "TranslateAdd", "add", true - &TriScreenDrawer8::Execute, // "TranslateSub", "sub", true - &TriScreenDrawer8::Execute, // "TranslateRevSub", "revsub", true - &TriScreenDrawer8::Execute, // "AddSrcColorOneMinusSrcColor", "addsrccolor", false - &TriScreenDrawer8::Execute // "Skycap", "skycap", false + &TriScreenDrawer8::Execute, // TextureOpaque + &TriScreenDrawer8::Execute, // TextureMasked + &TriScreenDrawer8::Execute, // TextureAdd + &TriScreenDrawer8::Execute, // TextureSub + &TriScreenDrawer8::Execute, // TextureRevSub + &TriScreenDrawer8::Execute, // TextureAddSrcColor + &TriScreenDrawer8::Execute, // TranslatedOpaque + &TriScreenDrawer8::Execute, // TranslatedMasked + &TriScreenDrawer8::Execute, // TranslatedAdd + &TriScreenDrawer8::Execute, // TranslatedSub + &TriScreenDrawer8::Execute, // TranslatedRevSub + &TriScreenDrawer8::Execute, // TranslatedAddSrcColor + &TriScreenDrawer8::Execute, // Shaded + &TriScreenDrawer8::Execute, // AddShaded + &TriScreenDrawer8::Execute, // Stencil + &TriScreenDrawer8::Execute, // AddStencil + &TriScreenDrawer8::Execute, // FillOpaque + &TriScreenDrawer8::Execute, // FillAdd + &TriScreenDrawer8::Execute, // FillSub + &TriScreenDrawer8::Execute, // FillRevSub + &TriScreenDrawer8::Execute, // FillAddSrcColor + &TriScreenDrawer8::Execute // Skycap }; #ifdef NO_SSE -std::vector ScreenTriangle::TriDraw32; -std::vector ScreenTriangle::TriFill32; +std::vector ScreenTriangle::TriDrawers32; #else -std::vector ScreenTriangle::TriDraw32 = +std::vector ScreenTriangle::TriDrawers32 = { - &TriScreenDrawer32::Execute, // "Copy", "opaque", false - &TriScreenDrawer32::Execute, // "AlphaBlend", "masked", false - &TriScreenDrawer32::Execute, // "AddSolid", "translucent", false - &TriScreenDrawer32::Execute, // "Add", "add", false - &TriScreenDrawer32::Execute, // "Sub", "sub", false - &TriScreenDrawer32::Execute, // "RevSub", "revsub", false - &TriScreenDrawer32::Execute, // "Stencil", "stencil", false - &TriScreenDrawer32::Execute, // "Shaded", "shaded", false - &TriScreenDrawer32::Execute, // "TranslateCopy", "opaque", true - &TriScreenDrawer32::Execute, // "TranslateAlphaBlend", "masked", true - &TriScreenDrawer32::Execute, // "TranslateAdd", "add", true - &TriScreenDrawer32::Execute, // "TranslateSub", "sub", true - &TriScreenDrawer32::Execute, // "TranslateRevSub", "revsub", true - &TriScreenDrawer32::Execute, // "AddSrcColorOneMinusSrcColor", "addsrccolor", false - &TriScreenDrawer32::Execute // "Skycap", "skycap", false -}; - -std::vector ScreenTriangle::TriFill32 = -{ - &TriScreenDrawer32::Execute, // "Copy", "opaque", false - &TriScreenDrawer32::Execute, // "AlphaBlend", "masked", false - &TriScreenDrawer32::Execute, // "AddSolid", "translucent", false - &TriScreenDrawer32::Execute, // "Add", "add", false - &TriScreenDrawer32::Execute, // "Sub", "sub", false - &TriScreenDrawer32::Execute, // "RevSub", "revsub", false - &TriScreenDrawer32::Execute, // "Stencil", "stencil", false - &TriScreenDrawer32::Execute, // "Shaded", "shaded", false - &TriScreenDrawer32::Execute, // "TranslateCopy", "opaque", true - &TriScreenDrawer32::Execute, // "TranslateAlphaBlend", "masked", true - &TriScreenDrawer32::Execute, // "TranslateAdd", "add", true - &TriScreenDrawer32::Execute, // "TranslateSub", "sub", true - &TriScreenDrawer32::Execute, // "TranslateRevSub", "revsub", true - &TriScreenDrawer32::Execute, // "AddSrcColorOneMinusSrcColor", "addsrccolor", false - &TriScreenDrawer32::Execute // "Skycap", "skycap", false + &TriScreenDrawer32::Execute, // TextureOpaque + &TriScreenDrawer32::Execute, // TextureMasked + &TriScreenDrawer32::Execute, // TextureAdd + &TriScreenDrawer32::Execute, // TextureSub + &TriScreenDrawer32::Execute, // TextureRevSub + &TriScreenDrawer32::Execute, // TextureAddSrcColor + &TriScreenDrawer32::Execute, // TranslatedOpaque + &TriScreenDrawer32::Execute, // TranslatedMasked + &TriScreenDrawer32::Execute, // TranslatedAdd + &TriScreenDrawer32::Execute, // TranslatedSub + &TriScreenDrawer32::Execute, // TranslatedRevSub + &TriScreenDrawer32::Execute, // TranslatedAddSrcColor + &TriScreenDrawer32::Execute, // Shaded + &TriScreenDrawer32::Execute, // AddShaded + &TriScreenDrawer32::Execute, // Stencil + &TriScreenDrawer32::Execute, // AddStencil + &TriScreenDrawer32::Execute, // FillOpaque + &TriScreenDrawer32::Execute, // FillAdd + &TriScreenDrawer32::Execute, // FillSub + &TriScreenDrawer32::Execute, // FillRevSub + &TriScreenDrawer32::Execute, // FillAddSrcColor + &TriScreenDrawer32::Execute // Skycap }; #endif diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index 81d7cdb68..513d6e760 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -88,25 +88,30 @@ struct TriDrawTriangleArgs enum class TriBlendMode { - Copy, // blend_copy(shade(fg)) - AlphaBlend, // blend_alpha_blend(shade(fg), bg) - AddSolid, // blend_add(shade(fg), bg, srcalpha, destalpha) - Add, // blend_add(shade(fg), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) - Sub, // blend_sub(shade(fg), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) - RevSub, // blend_revsub(shade(fg), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) - Stencil, // blend_stencil(shade(color), fg.a, bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) - Shaded, // blend_stencil(shade(color), fg.index, bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) - TranslateCopy, // blend_copy(shade(translate(fg))) - TranslateAlphaBlend, // blend_alpha_blend(shade(translate(fg)), bg) - TranslateAdd, // blend_add(shade(translate(fg)), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) - TranslateSub, // blend_sub(shade(translate(fg)), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) - TranslateRevSub,// blend_revsub(shade(translate(fg)), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) - AddSrcColorOneMinusSrcColor, // glBlendMode(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR) used by GZDoom's fullbright additive sprites - Skycap // Fade to sky color when the V texture coordinate go beyond the [-1, 1] range + TextureOpaque, + TextureMasked, + TextureAdd, + TextureSub, + TextureRevSub, + TextureAddSrcColor, + TranslatedOpaque, + TranslatedMasked, + TranslatedAdd, + TranslatedSub, + TranslatedRevSub, + TranslatedAddSrcColor, + Shaded, + AddShaded, + Stencil, + AddStencil, + FillOpaque, + FillAdd, + FillSub, + FillRevSub, + FillAddSrcColor, + Skycap }; -inline int NumTriBlendModes() { return (int)TriBlendMode::Skycap + 1; } - class ScreenTriangle { public: @@ -115,10 +120,8 @@ public: static void StencilWrite(const TriDrawTriangleArgs *args, WorkerThreadData *thread); static void SubsectorWrite(const TriDrawTriangleArgs *args, WorkerThreadData *thread); - static std::vector TriDraw8; - static std::vector TriDraw32; - static std::vector TriFill8; - static std::vector TriFill32; + static std::vector TriDrawers8; + static std::vector TriDrawers32; }; struct ScreenTriangleStepVariables @@ -147,10 +150,11 @@ namespace TriScreenDrawerModes struct SimpleShade { static const int Mode = (int)ShadeMode::Simple; }; struct AdvancedShade { static const int Mode = (int)ShadeMode::Advanced; }; - enum class Samplers { Texture, Fill, Shaded, Translated, Skycap }; + enum class Samplers { Texture, Fill, Shaded, Stencil, Translated, Skycap }; struct TextureSampler { static const int Mode = (int)Samplers::Texture; }; struct FillSampler { static const int Mode = (int)Samplers::Fill; }; struct ShadedSampler { static const int Mode = (int)Samplers::Shaded; }; + struct StencilSampler { static const int Mode = (int)Samplers::Stencil; }; struct TranslatedSampler { static const int Mode = (int)Samplers::Translated; }; struct SkycapSampler { static const int Mode = (int)Samplers::Skycap; }; } diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index d41328d57..a15e74af4 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -133,7 +133,7 @@ void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, const PolyClip args.SetLight(GetColorTable(sub->sector->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false); args.SetSubsectorDepth(subsectorDepth); args.SetTransform(&worldToClip); - args.SetStyle(TriBlendMode::Copy); + args.SetStyle(TriBlendMode::TextureOpaque); args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); args.SetWriteStencil(true, stencilValue + 1); @@ -312,7 +312,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane & if (!isSky) { args.SetTexture(tex); - args.SetStyle(TriBlendMode::Copy); + args.SetStyle(TriBlendMode::TextureOpaque); args.DrawArray(vertices, sub->numlines, PolyDrawMode::TriangleFan); } else diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 3aeda994c..a655ca845 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -253,7 +253,7 @@ void RenderPolyScene::RenderPortals(int portalDepth) args.SetLight(&NormalLight, 255, PolyRenderer::Instance()->Light.WallGlobVis(foggy), true); args.SetColor(0, 0); args.SetClipPlane(PortalPlane); - args.SetStyle(TriBlendMode::Copy); + args.SetStyle(TriBlendMode::FillOpaque); for (auto &portal : SectorPortals) { diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index 374163f96..9d27d45cb 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -70,18 +70,20 @@ void PolySkyDome::Render(const TriMatrix &worldToClip) uint32_t topcapcolor = frontskytex->GetSkyCapColor(false); uint32_t bottomcapcolor = frontskytex->GetSkyCapColor(true); + uint8_t topcapindex = RGB256k.All[((RPART(topcapcolor) >> 2) << 12) | ((GPART(topcapcolor) >> 2) << 6) | (BPART(topcapcolor) >> 2)]; + uint8_t bottomcapindex = RGB256k.All[((RPART(bottomcapcolor) >> 2) << 12) | ((GPART(bottomcapcolor) >> 2) << 6) | (BPART(bottomcapcolor) >> 2)]; for (int i = 1; i <= mRows; i++) { - RenderRow(args, i, topcapcolor); - RenderRow(args, rc + i, bottomcapcolor); + RenderRow(args, i, topcapcolor, topcapindex); + RenderRow(args, rc + i, bottomcapcolor, bottomcapindex); } } -void PolySkyDome::RenderRow(PolyDrawArgs &args, int row, uint32_t capcolor) +void PolySkyDome::RenderRow(PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex) { args.SetFaceCullCCW(false); - args.SetColor(capcolor, 0); + args.SetColor(capcolor, capcolorindex); args.SetStyle(TriBlendMode::Skycap); args.DrawArray(&mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleStrip); } @@ -93,7 +95,7 @@ void PolySkyDome::RenderCapColorRow(PolyDrawArgs &args, FTexture *skytex, int ro args.SetFaceCullCCW(bottomCap); args.SetColor(solid, palsolid); - args.SetStyle(TriBlendMode::Copy); + args.SetStyle(TriBlendMode::FillOpaque); args.DrawArray(&mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleFan); } diff --git a/src/polyrenderer/scene/poly_sky.h b/src/polyrenderer/scene/poly_sky.h index 1a8cd8ef2..87d6cabce 100644 --- a/src/polyrenderer/scene/poly_sky.h +++ b/src/polyrenderer/scene/poly_sky.h @@ -38,7 +38,7 @@ private: void SkyVertex(int r, int c, bool yflip); void CreateSkyHemisphere(bool zflip); void CreateDome(); - void RenderRow(PolyDrawArgs &args, int row, uint32_t capcolor); + void RenderRow(PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex); void RenderCapColorRow(PolyDrawArgs &args, FTexture *skytex, int row, bool bottomCap); TriVertex SetVertexXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0); diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 2a98af721..5d0587432 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -150,33 +150,33 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const PolyClipPlane if (thing->RenderStyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy])) { - args.SetStyle(args.Translation() ? TriBlendMode::TranslateAdd : TriBlendMode::Add, 1.0, 0.0); + args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 1.0, 0.0); } else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Add] && fullbrightSprite && thing->Alpha == 1.0 && !args.Translation()) { - args.SetStyle(TriBlendMode::AddSrcColorOneMinusSrcColor, 1.0, 1.0); + args.SetStyle(TriBlendMode::TextureAddSrcColor, 1.0, 1.0); } else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Add]) { - args.SetStyle(args.Translation() ? TriBlendMode::TranslateAdd : TriBlendMode::Add, thing->Alpha, 1.0); + args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, thing->Alpha, 1.0); } else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Subtract]) { - args.SetStyle(args.Translation() ? TriBlendMode::TranslateRevSub : TriBlendMode::RevSub, thing->Alpha, 1.0); + args.SetStyle(args.Translation() ? TriBlendMode::TranslatedRevSub : TriBlendMode::TextureRevSub, thing->Alpha, 1.0); } else if (thing->RenderStyle == LegacyRenderStyles[STYLE_SoulTrans]) { - args.SetStyle(args.Translation() ? TriBlendMode::TranslateAdd : TriBlendMode::Add, transsouls, 1.0 - transsouls); + args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, transsouls, 1.0 - transsouls); } else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 2 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy])) { // NYI - Fuzzy - for now, just a copy of "Shadow" - args.SetStyle(args.Translation() ? TriBlendMode::TranslateAdd : TriBlendMode::Add, 0.0, 160 / 255.0); + args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); } else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 1 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy])) { - args.SetStyle(args.Translation() ? TriBlendMode::TranslateAdd : TriBlendMode::Add, 0.0, 160 / 255.0); + args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); } else if (thing->RenderStyle == LegacyRenderStyles[STYLE_TranslucentStencil]) { @@ -186,23 +186,23 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const PolyClipPlane else if (thing->RenderStyle == LegacyRenderStyles[STYLE_AddStencil]) { args.SetColor(0xff000000 | thing->fillcolor, thing->fillcolor >> 24); - args.SetStyle(TriBlendMode::Stencil, thing->Alpha, 1.0 - thing->Alpha); + args.SetStyle(TriBlendMode::AddStencil, thing->Alpha, 1.0); } else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Shaded]) { - args.SetColor(0, 0); + args.SetColor(0xff000000 | thing->fillcolor, thing->fillcolor >> 24); args.SetStyle(TriBlendMode::Shaded, thing->Alpha, 1.0 - thing->Alpha); args.SetTexture(tex, thing->Translation, true); } else if (thing->RenderStyle == LegacyRenderStyles[STYLE_AddShaded]) { - args.SetColor(0, 0); - args.SetStyle(TriBlendMode::Shaded, thing->Alpha, 1.0 - thing->Alpha); + args.SetColor(0xff000000 | thing->fillcolor, thing->fillcolor >> 24); + args.SetStyle(TriBlendMode::AddShaded, thing->Alpha, 1.0); args.SetTexture(tex, thing->Translation, true); } else { - args.SetStyle(args.Translation() ? TriBlendMode::TranslateAdd : TriBlendMode::Add, thing->Alpha, 1.0 - thing->Alpha); + args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, thing->Alpha, 1.0 - thing->Alpha); } args.SetSubsectorDepthTest(true); diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 263487f70..a85dcdc57 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -272,12 +272,15 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c } else if (!Masked) { - args.SetStyle(TriBlendMode::Copy); + args.SetStyle(TriBlendMode::TextureOpaque); args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); } else { - args.SetStyle((Line->flags & ML_ADDTRANS) ? TriBlendMode::Add : TriBlendMode::AlphaBlend, Line->alpha, 1.0); + bool addtrans = !!(Line->flags & ML_ADDTRANS); + double srcalpha = MIN(Line->alpha, 1.0); + double destalpha = addtrans ? 1.0 : 1.0 - srcalpha; + args.SetStyle(TriBlendMode::TextureAdd, srcalpha, destalpha); args.SetSubsectorDepthTest(true); args.SetWriteSubsectorDepth(true); args.SetWriteStencil(false); diff --git a/src/polyrenderer/scene/poly_wallsprite.cpp b/src/polyrenderer/scene/poly_wallsprite.cpp index 8108849b9..a7a1420e5 100644 --- a/src/polyrenderer/scene/poly_wallsprite.cpp +++ b/src/polyrenderer/scene/poly_wallsprite.cpp @@ -109,6 +109,6 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const PolyClipPl args.SetSubsectorDepthTest(true); args.SetWriteSubsectorDepth(false); args.SetWriteStencil(false); - args.SetStyle(TriBlendMode::AlphaBlend); + args.SetStyle(TriBlendMode::TextureMasked); args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan); } From bac464f2b7766b9a6b3aa6e7b125cb319b49f85f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Mar 2017 21:29:31 +0200 Subject: [PATCH 15/29] - added the inventory bar on Heretic's status bar. --- .../static/zscript/statusbar/heretic_sbar.txt | 5 ++- wadsrc/static/zscript/statusbar/statusbar.txt | 37 ++++++++++++++----- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/wadsrc/static/zscript/statusbar/heretic_sbar.txt b/wadsrc/static/zscript/statusbar/heretic_sbar.txt index 4c97a16be..d5191b99a 100644 --- a/wadsrc/static/zscript/statusbar/heretic_sbar.txt +++ b/wadsrc/static/zscript/statusbar/heretic_sbar.txt @@ -5,6 +5,7 @@ class HereticStatusBar : BaseStatusBar HUDFont mIndexFont; HUDFont mBigFont; InventoryBarState diparms; + InventoryBarState diparms_sbar; override void Init() @@ -20,6 +21,7 @@ class HereticStatusBar : BaseStatusBar fnt = "BIGFONT"; mBigFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true, 2, 2); diparms = InventoryBarState.Create(mIndexFont); + diparms_sbar = InventoryBarState.CreateNoBox(mIndexFont, boxsize:(31, 31), arrowoffs:(0,-10)); mHealthInterpolator = DynamicValueInterpolator.Create(0, 0.25, 1, 8); } @@ -120,12 +122,11 @@ class HereticStatusBar : BaseStatusBar DrawString(mIndexFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (209, 182), DI_TEXT_ALIGN_RIGHT); } } - } else { DrawImage("INVBAR", (34, 160), DI_ITEM_OFFSETS); - //drawinventorybar Heretic, noartibox, 7, INDEXFONT_RAVEN, 50, 160, 77, 182, untranslated; + DrawInventoryBar(diparms_sbar, (49, 160), 7, DI_ITEM_LEFT_TOP, HX_SHADOW); } } diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index 3d6c4fe86..7219d7d55 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -39,17 +39,9 @@ class InventoryBarState ui int cr; int flags; - // The default settings here are what SBARINFO is using. - static InventoryBarState Create(HUDFont indexfont = null, int cr = Font.CR_UNTRANSLATED, double itemalpha = 1., - String boxgfx = "ARTIBOX", String selgfx = "SELECTBO", Vector2 innersize = (0, 0), - String leftgfx = "INVGEML1", String rightgfx = "INVGEMR1", Vector2 arrowoffs = (0, 0), int flags = 0) + private static void Init(InventoryBarState me, HUDFont indexfont, int cr, double itemalpha, Vector2 innersize, String leftgfx, String rightgfx, Vector2 arrowoffs, int flags) { - let me = new ("InventoryBarState"); me.itemalpha = itemalpha; - me.box = TexMan.CheckForTexture(boxgfx, TexMan.TYPE_MiscPatch); - me.selector = TexMan.CheckForTexture(selgfx, TexMan.TYPE_MiscPatch); - if (me.box.IsValid() || me.selector.IsValid()) me.boxsize = TexMan.GetScaledSize(me.box.IsValid()? me.box : me.selector); - else me.boxsize = (32., 32.); if (innersize == (0, 0)) { me.boxofs = (2, 2); @@ -72,8 +64,35 @@ class InventoryBarState ui else me.amountfont = indexfont; me.cr = cr; me.flags = flags; + } + + // The default settings here are what SBARINFO is using. + static InventoryBarState Create(HUDFont indexfont = null, int cr = Font.CR_UNTRANSLATED, double itemalpha = 1., + String boxgfx = "ARTIBOX", String selgfx = "SELECTBO", Vector2 innersize = (0, 0), + String leftgfx = "INVGEML1", String rightgfx = "INVGEMR1", Vector2 arrowoffs = (0, 0), int flags = 0) + { + let me = new ("InventoryBarState"); + me.box = TexMan.CheckForTexture(boxgfx, TexMan.TYPE_MiscPatch); + me.selector = TexMan.CheckForTexture(selgfx, TexMan.TYPE_MiscPatch); + if (me.box.IsValid() || me.selector.IsValid()) me.boxsize = TexMan.GetScaledSize(me.box.IsValid()? me.box : me.selector); + else me.boxsize = (32., 32.); + Init(me, indexfont, cr, itemalpha, innersize, leftgfx, rightgfx, arrowoffs, flags); return me; } + + // The default settings here are what SBARINFO is using. + static InventoryBarState CreateNoBox(HUDFont indexfont = null, int cr = Font.CR_UNTRANSLATED, double itemalpha = 1., + Vector2 boxsize = (32, 32), String selgfx = "SELECTBO", Vector2 innersize = (0, 0), + String leftgfx = "INVGEML1", String rightgfx = "INVGEMR1", Vector2 arrowoffs = (0, 0), int flags = 0) + { + let me = new ("InventoryBarState"); + me.box.SetInvalid(); + me.selector = TexMan.CheckForTexture(selgfx, TexMan.TYPE_MiscPatch); + me.boxsize = boxsize; + Init(me, indexfont, cr, itemalpha, innersize, leftgfx, rightgfx, arrowoffs, flags); + return me; + } + } From 5adf7463cddb42c3d1b10d6a4337fc98604d23cf Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 27 Mar 2017 21:59:43 +0200 Subject: [PATCH 16/29] - support render styles on decals --- src/polyrenderer/drawers/poly_draw_args.cpp | 59 ++++++++++++++++++++ src/polyrenderer/drawers/poly_draw_args.h | 1 + src/polyrenderer/scene/poly_decal.cpp | 3 +- src/polyrenderer/scene/poly_sprite.cpp | 61 +-------------------- 4 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index 64fe7a882..a9bfde1f5 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -140,3 +140,62 @@ void PolyDrawArgs::DrawArray(const TriVertex *vertices, int vcount, PolyDrawMode mDrawMode = mode; PolyRenderer::Instance()->DrawQueue->Push(*this, PolyTriangleDrawer::is_mirror()); } + +void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) +{ + bool forcePal = (renderstyle == LegacyRenderStyles[STYLE_Shaded] || renderstyle == LegacyRenderStyles[STYLE_AddShaded]); + SetTexture(tex, translationID, forcePal); + + if (renderstyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 1.0, 0.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Add] && fullbright && alpha == 1.0 && !Translation()) + { + SetStyle(TriBlendMode::TextureAddSrcColor, 1.0, 1.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Add]) + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, alpha, 1.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Subtract]) + { + SetStyle(Translation() ? TriBlendMode::TranslatedRevSub : TriBlendMode::TextureRevSub, alpha, 1.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_SoulTrans]) + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, transsouls, 1.0 - transsouls); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 2 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + { // NYI - Fuzzy - for now, just a copy of "Shadow" + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 1 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_TranslucentStencil]) + { + SetColor(0xff000000 | fillcolor, fillcolor >> 24); + SetStyle(TriBlendMode::Stencil, alpha, 1.0 - alpha); + } + else if (renderstyle == LegacyRenderStyles[STYLE_AddStencil]) + { + SetColor(0xff000000 | fillcolor, fillcolor >> 24); + SetStyle(TriBlendMode::AddStencil, alpha, 1.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Shaded]) + { + SetColor(0xff000000 | fillcolor, fillcolor >> 24); + SetStyle(TriBlendMode::Shaded, alpha, 1.0 - alpha); + } + else if (renderstyle == LegacyRenderStyles[STYLE_AddShaded]) + { + SetColor(0xff000000 | fillcolor, fillcolor >> 24); + SetStyle(TriBlendMode::AddShaded, alpha, 1.0); + } + else + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, alpha, 1.0 - alpha); + } +} diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index c19bb6492..a77ef7c98 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -61,6 +61,7 @@ public: void SetWriteSubsectorDepth(bool enable) { mWriteSubsector = enable; } void SetFaceCullCCW(bool counterclockwise) { mFaceCullCCW = counterclockwise; } void SetStyle(TriBlendMode blendmode, double srcalpha = 1.0, double destalpha = 1.0) { mBlendMode = blendmode; mSrcAlpha = (uint32_t)(srcalpha * 256.0 + 0.5); mDestAlpha = (uint32_t)(destalpha * 256.0 + 0.5); } + void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); void SetTransform(const TriMatrix *objectToClip) { mObjectToClip = objectToClip; } void SetColor(uint32_t bgra, uint8_t palindex); void DrawArray(const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); diff --git a/src/polyrenderer/scene/poly_decal.cpp b/src/polyrenderer/scene/poly_decal.cpp index 829f444b6..255b8e40a 100644 --- a/src/polyrenderer/scene/poly_decal.cpp +++ b/src/polyrenderer/scene/poly_decal.cpp @@ -134,10 +134,9 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, const PolyClipPlane & PolyDrawArgs args; args.SetLight(GetColorTable(front->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), fullbrightSprite); - args.SetTexture(tex, decal->Translation, true); args.SetSubsectorDepth(subsectorDepth); args.SetColor(0xff000000 | decal->AlphaColor, decal->AlphaColor >> 24); - args.SetStyle(TriBlendMode::Shaded, decal->Alpha, 1.0 - decal->Alpha); // R_SetPatchStyle (decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor); + args.SetStyle(decal->RenderStyle, decal->Alpha, decal->AlphaColor, decal->Translation, tex, false); args.SetTransform(&worldToClip); args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index 5d0587432..c67599580 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -144,67 +144,8 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const PolyClipPlane args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); args.SetWriteStencil(true, stencilValue); - args.SetTexture(tex, thing->Translation); args.SetClipPlane(clipPlane); - - if (thing->RenderStyle == LegacyRenderStyles[STYLE_Normal] || - (r_drawfuzz == 0 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { - args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 1.0, 0.0); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Add] && fullbrightSprite && thing->Alpha == 1.0 && !args.Translation()) - { - args.SetStyle(TriBlendMode::TextureAddSrcColor, 1.0, 1.0); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Add]) - { - args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, thing->Alpha, 1.0); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Subtract]) - { - args.SetStyle(args.Translation() ? TriBlendMode::TranslatedRevSub : TriBlendMode::TextureRevSub, thing->Alpha, 1.0); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_SoulTrans]) - { - args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, transsouls, 1.0 - transsouls); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Fuzzy] || - (r_drawfuzz == 2 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { // NYI - Fuzzy - for now, just a copy of "Shadow" - args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Shadow] || - (r_drawfuzz == 1 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy])) - { - args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_TranslucentStencil]) - { - args.SetColor(0xff000000 | thing->fillcolor, thing->fillcolor >> 24); - args.SetStyle(TriBlendMode::Stencil, thing->Alpha, 1.0 - thing->Alpha); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_AddStencil]) - { - args.SetColor(0xff000000 | thing->fillcolor, thing->fillcolor >> 24); - args.SetStyle(TriBlendMode::AddStencil, thing->Alpha, 1.0); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Shaded]) - { - args.SetColor(0xff000000 | thing->fillcolor, thing->fillcolor >> 24); - args.SetStyle(TriBlendMode::Shaded, thing->Alpha, 1.0 - thing->Alpha); - args.SetTexture(tex, thing->Translation, true); - } - else if (thing->RenderStyle == LegacyRenderStyles[STYLE_AddShaded]) - { - args.SetColor(0xff000000 | thing->fillcolor, thing->fillcolor >> 24); - args.SetStyle(TriBlendMode::AddShaded, thing->Alpha, 1.0); - args.SetTexture(tex, thing->Translation, true); - } - else - { - args.SetStyle(args.Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, thing->Alpha, 1.0 - thing->Alpha); - } - + args.SetStyle(thing->RenderStyle, thing->Alpha, thing->fillcolor, thing->Translation, tex, fullbrightSprite); args.SetSubsectorDepthTest(true); args.SetWriteSubsectorDepth(false); args.SetWriteStencil(false); From d15def7d41307332ba34865ae3a93c3491669736 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 28 Mar 2017 10:52:19 +0200 Subject: [PATCH 17/29] - remove TriVertex::NumVaryings as this did not help on readability at all --- src/polyrenderer/drawers/poly_drawer32_sse2.h | 137 ++++++++---------- src/polyrenderer/drawers/poly_drawer8.h | 113 +++++++-------- src/polyrenderer/drawers/poly_triangle.cpp | 15 +- src/polyrenderer/drawers/screen_triangle.h | 8 +- src/polyrenderer/math/tri_matrix.cpp | 4 +- src/polyrenderer/scene/poly_decal.cpp | 6 +- src/polyrenderer/scene/poly_particle.cpp | 4 +- src/polyrenderer/scene/poly_plane.cpp | 4 +- src/polyrenderer/scene/poly_sky.cpp | 4 +- src/polyrenderer/scene/poly_sprite.cpp | 6 +- src/polyrenderer/scene/poly_wall.cpp | 24 +-- src/polyrenderer/scene/poly_wallsprite.cpp | 6 +- 12 files changed, 155 insertions(+), 176 deletions(-) diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index 39a88c47e..20d0a9efc 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -92,13 +92,13 @@ public: ScreenTriangleStepVariables start; gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); + gradientX.U = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.u * v1.w, v2.u * v2.w, v3.u * v3.w); + gradientY.U = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.u * v1.w, v2.u * v2.w, v3.u * v3.w); + gradientX.V = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.v * v1.w, v2.v * v2.w, v3.v * v3.w); + gradientY.V = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.v * v1.w, v2.v * v2.w, v3.v * v3.w); start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } + start.U = v1.u * v1.w + gradientX.U * (startX - v1.x) + gradientY.U * (startY - v1.y); + start.V = v1.v * v1.w + gradientX.V * (startX - v1.x) + gradientY.V * (startY - v1.y); // Output uint32_t * RESTRICT destOrg = (uint32_t*)args->dest; @@ -157,17 +157,16 @@ public: ScreenTriangleStepVariables blockPosY; blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); + blockPosY.U = start.U + gradientX.U * (span.X - startX) + gradientY.U * (span.Y - startY); + blockPosY.V = start.V + gradientX.V * (span.X - startX) + gradientY.V * (span.Y - startY); for (int y = 0; y < height; y++) { ScreenTriangleStepVariables blockPosX = blockPosY; float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + int32_t posU = (int32_t)(blockPosX.U * rcpW); + int32_t posV = (int32_t)(blockPosX.V * rcpW); fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); @@ -175,16 +174,14 @@ public: for (int x = 0; x < width; x++) { blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; + blockPosX.U += gradientX.U * 8; + blockPosX.V += gradientX.V * 8; rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } + int32_t nextU = (int32_t)(blockPosX.U * rcpW); + int32_t nextV = (int32_t)(blockPosX.V * rcpW); + int32_t stepU = (nextU - posU) / 8; + int32_t stepV = (nextV - posV) / 8; fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); fixed_t lightstep = (lightnext - lightpos) / 8; @@ -201,15 +198,15 @@ public: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; - ifgcolor[0] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight); - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; + ifgcolor[0] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[0] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + posU += stepU; + posV += stepV; - ifgcolor[1] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight); - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; + ifgcolor[1] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[1] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + posU += stepU; + posV += stepV; // Setup light int lightpos0 = lightpos >> 8; @@ -240,8 +237,8 @@ public: } blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; + blockPosY.U += gradientY.U; + blockPosY.V += gradientY.V; dest += pitch; } @@ -253,8 +250,8 @@ public: ScreenTriangleStepVariables blockPosY; blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); + blockPosY.U = start.U + gradientX.U * (block.X - startX) + gradientY.U * (block.Y - startY); + blockPosY.V = start.V + gradientX.V * (block.X - startX) + gradientY.V * (block.Y - startY); uint32_t *dest = destOrg + block.X + block.Y * pitch; uint32_t mask0 = block.Mask0; @@ -266,24 +263,21 @@ public: ScreenTriangleStepVariables blockPosX = blockPosY; float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + int32_t posU = (int32_t)(blockPosX.U * rcpW); + int32_t posV = (int32_t)(blockPosX.V * rcpW); fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; + blockPosX.U += gradientX.U * 8; + blockPosX.V += gradientX.V * 8; rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } + int32_t nextU = (int32_t)(blockPosX.U * rcpW); + int32_t nextV = (int32_t)(blockPosX.V * rcpW); + int32_t stepU = (nextU - posU) / 8; + int32_t stepV = (nextV - posV) / 8; fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); fixed_t lightstep = (lightnext - lightpos) / 8; @@ -304,15 +298,15 @@ public: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; - ifgcolor[0] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight); - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; + ifgcolor[0] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[0] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + posU += stepU; + posV += stepV; - ifgcolor[1] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight); - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; + ifgcolor[1] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[1] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + posU += stepU; + posV += stepV; // Setup light int lightpos0 = lightpos >> 8; @@ -346,8 +340,8 @@ public: } blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; + blockPosY.U += gradientY.U; + blockPosY.V += gradientY.V; dest += pitch; } @@ -358,24 +352,21 @@ public: ScreenTriangleStepVariables blockPosX = blockPosY; float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + int32_t posU = (int32_t)(blockPosX.U * rcpW); + int32_t posV = (int32_t)(blockPosX.V * rcpW); fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; + blockPosX.U += gradientX.U * 8; + blockPosX.V += gradientX.V * 8; rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } + int32_t nextU = (int32_t)(blockPosX.U * rcpW); + int32_t nextV = (int32_t)(blockPosX.V * rcpW); + int32_t stepU = (nextU - posU) / 8; + int32_t stepV = (nextV - posV) / 8; fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); fixed_t lightstep = (lightnext - lightpos) / 8; @@ -396,15 +387,15 @@ public: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; - ifgcolor[0] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight); - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; + ifgcolor[0] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[0] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + posU += stepU; + posV += stepV; - ifgcolor[1] = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight); - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; + ifgcolor[1] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[1] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + posU += stepU; + posV += stepV; // Setup light int lightpos0 = lightpos >> 8; @@ -438,8 +429,8 @@ public: } blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; + blockPosY.U += gradientY.U; + blockPosY.V += gradientY.V; dest += pitch; } diff --git a/src/polyrenderer/drawers/poly_drawer8.h b/src/polyrenderer/drawers/poly_drawer8.h index 6b02c52c3..2f5669901 100644 --- a/src/polyrenderer/drawers/poly_drawer8.h +++ b/src/polyrenderer/drawers/poly_drawer8.h @@ -54,13 +54,13 @@ public: ScreenTriangleStepVariables start; gradientX.W = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); gradientY.W = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.w, v2.w, v3.w); + gradientX.U = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.u * v1.w, v2.u * v2.w, v3.u * v3.w); + gradientY.U = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.u * v1.w, v2.u * v2.w, v3.u * v3.w); + gradientX.V = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.v * v1.w, v2.v * v2.w, v3.v * v3.w); + gradientY.V = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.v * v1.w, v2.v * v2.w, v3.v * v3.w); start.W = v1.w + gradientX.W * (startX - v1.x) + gradientY.W * (startY - v1.y); - for (int i = 0; i < TriVertex::NumVarying; i++) - { - gradientX.Varying[i] = FindGradientX(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - gradientY.Varying[i] = FindGradientY(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, v1.varying[i] * v1.w, v2.varying[i] * v2.w, v3.varying[i] * v3.w); - start.Varying[i] = v1.varying[i] * v1.w + gradientX.Varying[i] * (startX - v1.x) + gradientY.Varying[i] * (startY - v1.y); - } + start.U = v1.u * v1.w + gradientX.U * (startX - v1.x) + gradientY.U * (startY - v1.y); + start.V = v1.v * v1.w + gradientX.V * (startX - v1.x) + gradientY.V * (startY - v1.y); // Output uint8_t * RESTRICT destOrg = args->dest; @@ -89,17 +89,16 @@ public: ScreenTriangleStepVariables blockPosY; blockPosY.W = start.W + gradientX.W * (span.X - startX) + gradientY.W * (span.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (span.X - startX) + gradientY.Varying[j] * (span.Y - startY); + blockPosY.U = start.U + gradientX.U * (span.X - startX) + gradientY.U * (span.Y - startY); + blockPosY.V = start.V + gradientX.V * (span.X - startX) + gradientY.V * (span.Y - startY); for (int y = 0; y < height; y++) { ScreenTriangleStepVariables blockPosX = blockPosY; float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + int32_t posU = (int32_t)(blockPosX.U * rcpW); + int32_t posV = (int32_t)(blockPosX.V * rcpW); fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); @@ -107,16 +106,14 @@ public: for (int x = 0; x < width; x++) { blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; + blockPosX.U += gradientX.U * 8; + blockPosX.V += gradientX.V * 8; rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } + int32_t nextU = (int32_t)(blockPosX.U * rcpW); + int32_t nextV = (int32_t)(blockPosX.V * rcpW); + int32_t stepU = (nextU - posU) / 8; + int32_t stepV = (nextV - posV) / 8; fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); fixed_t lightstep = (lightnext - lightpos) / 8; @@ -126,18 +123,18 @@ public: { int lightshade = lightpos >> 8; uint8_t bgcolor = dest[x * 8 + ix]; - uint8_t fgcolor = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight); + uint8_t fgcolor = Sample(posU, posV, texPixels, texWidth, texHeight, color, translation); + uint32_t fgshade = SampleShade(posU, posV, texPixels, texWidth, texHeight); dest[x * 8 + ix] = ShadeAndBlend(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; + posU += stepU; + posV += stepV; lightpos += lightstep; } } blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; + blockPosY.U += gradientY.U; + blockPosY.V += gradientY.V; dest += pitch; } @@ -149,8 +146,8 @@ public: ScreenTriangleStepVariables blockPosY; blockPosY.W = start.W + gradientX.W * (block.X - startX) + gradientY.W * (block.Y - startY); - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] = start.Varying[j] + gradientX.Varying[j] * (block.X - startX) + gradientY.Varying[j] * (block.Y - startY); + blockPosY.U = start.U + gradientX.U * (block.X - startX) + gradientY.U * (block.Y - startY); + blockPosY.V = start.V + gradientX.V * (block.X - startX) + gradientY.V * (block.Y - startY); uint8_t *dest = destOrg + block.X + block.Y * pitch; uint32_t mask0 = block.Mask0; @@ -162,24 +159,21 @@ public: ScreenTriangleStepVariables blockPosX = blockPosY; float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + int32_t posU = (int32_t)(blockPosX.U * rcpW); + int32_t posV = (int32_t)(blockPosX.V * rcpW); fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; + blockPosX.U += gradientX.U * 8; + blockPosX.V += gradientX.V * 8; rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } + int32_t nextU = (int32_t)(blockPosX.U * rcpW); + int32_t nextV = (int32_t)(blockPosX.V * rcpW); + int32_t stepU = (nextU - posU) / 8; + int32_t stepV = (nextV - posV) / 8; fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); fixed_t lightstep = (lightnext - lightpos) / 8; @@ -191,21 +185,21 @@ public: { int lightshade = lightpos >> 8; uint8_t bgcolor = dest[x]; - uint8_t fgcolor = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight); + uint8_t fgcolor = Sample(posU, posV, texPixels, texWidth, texHeight, color, translation); + uint32_t fgshade = SampleShade(posU, posV, texPixels, texWidth, texHeight); dest[x] = ShadeAndBlend(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); } - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; + posU += stepU; + posV += stepV; lightpos += lightstep; mask0 <<= 1; } blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; + blockPosY.U += gradientY.U; + blockPosY.V += gradientY.V; dest += pitch; } @@ -216,24 +210,21 @@ public: ScreenTriangleStepVariables blockPosX = blockPosY; float rcpW = 0x01000000 / blockPosX.W; - int32_t varyingPos[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] = (int32_t)(blockPosX.Varying[j] * rcpW); + int32_t posU = (int32_t)(blockPosX.U * rcpW); + int32_t posV = (int32_t)(blockPosX.V * rcpW); fixed_t lightpos = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosY.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask); blockPosX.W += gradientX.W * 8; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosX.Varying[j] += gradientX.Varying[j] * 8; + blockPosX.U += gradientX.U * 8; + blockPosX.V += gradientX.V * 8; rcpW = 0x01000000 / blockPosX.W; - int32_t varyingStep[TriVertex::NumVarying]; - for (int j = 0; j < TriVertex::NumVarying; j++) - { - int32_t nextPos = (int32_t)(blockPosX.Varying[j] * rcpW); - varyingStep[j] = (nextPos - varyingPos[j]) / 8; - } + int32_t nextU = (int32_t)(blockPosX.U * rcpW); + int32_t nextV = (int32_t)(blockPosX.V * rcpW); + int32_t stepU = (nextU - posU) / 8; + int32_t stepV = (nextV - posV) / 8; fixed_t lightnext = FRACUNIT - (fixed_t)(clamp(shade - MIN(24.0f / 32.0f, globVis * blockPosX.W), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT); fixed_t lightstep = (lightnext - lightpos) / 8; @@ -245,21 +236,21 @@ public: { int lightshade = lightpos >> 8; uint8_t bgcolor = dest[x]; - uint8_t fgcolor = Sample(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade(varyingPos[0], varyingPos[1], texPixels, texWidth, texHeight); + uint8_t fgcolor = Sample(posU, posV, texPixels, texWidth, texHeight, color, translation); + uint32_t fgshade = SampleShade(posU, posV, texPixels, texWidth, texHeight); dest[x] = ShadeAndBlend(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); } - for (int j = 0; j < TriVertex::NumVarying; j++) - varyingPos[j] += varyingStep[j]; + posU += stepU; + posV += stepV; lightpos += lightstep; mask1 <<= 1; } blockPosY.W += gradientY.W; - for (int j = 0; j < TriVertex::NumVarying; j++) - blockPosY.Varying[j] += gradientY.Varying[j]; + blockPosY.U += gradientY.U; + blockPosY.V += gradientY.V; dest += pitch; } diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 28dd2da1c..9df271b24 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -232,13 +232,12 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool // Keep varyings in -128 to 128 range if possible if (numclipvert > 0) { - for (int j = 0; j < TriVertex::NumVarying; j++) + float newOriginU = floorf(clippedvert[0].u * 0.1f) * 10.0f; + float newOriginV = floorf(clippedvert[0].v * 0.1f) * 10.0f; + for (int i = 0; i < numclipvert; i++) { - float newOrigin = floorf(clippedvert[0].varying[j] * 0.1f) * 10.0f; - for (int i = 0; i < numclipvert; i++) - { - clippedvert[i].varying[j] -= newOrigin; - } + clippedvert[i].u -= newOriginU; + clippedvert[i].v -= newOriginV; } } @@ -424,8 +423,8 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe v.y += verts[w].y * weight; v.z += verts[w].z * weight; v.w += verts[w].w * weight; - for (int iv = 0; iv < TriVertex::NumVarying; iv++) - v.varying[iv] += verts[w].varying[iv] * weight; + v.u += verts[w].u * weight; + v.v += verts[w].v * weight; } } return inputverts; diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index 513d6e760..090a398ba 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -61,11 +61,10 @@ struct WorkerThreadData struct TriVertex { TriVertex() { } - TriVertex(float x, float y, float z, float w, float u, float v) : x(x), y(y), z(z), w(w) { varying[0] = u; varying[1] = v; } + TriVertex(float x, float y, float z, float w, float u, float v) : x(x), y(y), z(z), w(w), u(u), v(v) { } - enum { NumVarying = 2 }; float x, y, z, w; - float varying[NumVarying]; + float u, v; }; struct TriDrawTriangleArgs @@ -126,8 +125,7 @@ public: struct ScreenTriangleStepVariables { - float W; - float Varying[TriVertex::NumVarying]; + float W, U, V; }; namespace TriScreenDrawerModes diff --git a/src/polyrenderer/math/tri_matrix.cpp b/src/polyrenderer/math/tri_matrix.cpp index b50e7bb6c..f6bb03a5e 100644 --- a/src/polyrenderer/math/tri_matrix.cpp +++ b/src/polyrenderer/math/tri_matrix.cpp @@ -199,7 +199,7 @@ ShadedTriVertex TriMatrix::operator*(TriVertex v) const ShadedTriVertex sv; _mm_storeu_ps(&sv.x, mv); #endif - for (int i = 0; i < TriVertex::NumVarying; i++) - sv.varying[i] = v.varying[i]; + sv.u = v.u; + sv.v = v.v; return sv; } diff --git a/src/polyrenderer/scene/poly_decal.cpp b/src/polyrenderer/scene/poly_decal.cpp index 255b8e40a..bbda32b04 100644 --- a/src/polyrenderer/scene/poly_decal.cpp +++ b/src/polyrenderer/scene/poly_decal.cpp @@ -123,10 +123,10 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, const PolyClipPlane & vertices[i].y = (float)p.Y; vertices[i].z = (float)(zpos + spriteHeight * offsets[i].second - spriteHeight * 0.5); vertices[i].w = 1.0f; - vertices[i].varying[0] = (float)(offsets[i].first * tex->Scale.X); - vertices[i].varying[1] = (float)((1.0f - offsets[i].second) * tex->Scale.Y); + vertices[i].u = (float)(offsets[i].first * tex->Scale.X); + vertices[i].v = (float)((1.0f - offsets[i].second) * tex->Scale.Y); if (flipTextureX) - vertices[i].varying[0] = 1.0f - vertices[i].varying[0]; + vertices[i].u = 1.0f - vertices[i].u; } bool fullbrightSprite = (decal->RenderFlags & RF_FULLBRIGHT) == RF_FULLBRIGHT; diff --git a/src/polyrenderer/scene/poly_particle.cpp b/src/polyrenderer/scene/poly_particle.cpp index 53079b6dd..ab80400dd 100644 --- a/src/polyrenderer/scene/poly_particle.cpp +++ b/src/polyrenderer/scene/poly_particle.cpp @@ -66,8 +66,8 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, const PolyClipPlan vertices[i].y = (float)p.Y; vertices[i].z = (float)(zpos + psize * (2.0 * offsets[i].second - 1.0)); vertices[i].w = 1.0f; - vertices[i].varying[0] = (float)(offsets[i].first); - vertices[i].varying[1] = (float)(1.0f - offsets[i].second); + vertices[i].u = (float)(offsets[i].first); + vertices[i].v = (float)(1.0f - offsets[i].second); } bool fullbrightSprite = particle->bright != 0; diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index a15e74af4..d4cd0fb02 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -410,8 +410,8 @@ TriVertex RenderPolyPlane::PlaneVertex(vertex_t *v1, double height, const UVTran v.y = (float)v1->fPos().Y; v.z = (float)height; v.w = 1.0f; - v.varying[0] = transform.GetU(v.x, v.y); - v.varying[1] = transform.GetV(v.x, v.y); + v.u = transform.GetU(v.x, v.y); + v.v = transform.GetV(v.x, v.y); return v; } diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index 9d27d45cb..7cb322032 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -139,8 +139,8 @@ TriVertex PolySkyDome::SetVertexXYZ(float xx, float yy, float zz, float uu, floa v.y = zz; v.z = yy; v.w = 1.0f; - v.varying[0] = uu; - v.varying[1] = vv; + v.u = uu; + v.v = vv; return v; } diff --git a/src/polyrenderer/scene/poly_sprite.cpp b/src/polyrenderer/scene/poly_sprite.cpp index c67599580..ae7295f1e 100644 --- a/src/polyrenderer/scene/poly_sprite.cpp +++ b/src/polyrenderer/scene/poly_sprite.cpp @@ -128,10 +128,10 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const PolyClipPlane vertices[i].y = (float)p.Y; vertices[i].z = (float)(pos.Z + spriteHeight * offsets[i].second); vertices[i].w = 1.0f; - vertices[i].varying[0] = (float)(offsets[i].first * tex->Scale.X); - vertices[i].varying[1] = (float)((1.0f - offsets[i].second) * tex->Scale.Y); + vertices[i].u = (float)(offsets[i].first * tex->Scale.X); + vertices[i].v = (float)((1.0f - offsets[i].second) * tex->Scale.Y); if (flipTextureX) - vertices[i].varying[0] = 1.0f - vertices[i].varying[0]; + vertices[i].u = 1.0f - vertices[i].u; } bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index a85dcdc57..ae11577e4 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -230,14 +230,14 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c if (tex) { PolyWallTextureCoords texcoords(tex, LineSeg, Line, Side, Texpart, TopZ, BottomZ, UnpeggedCeil); - vertices[0].varying[0] = (float)texcoords.u1; - vertices[0].varying[1] = (float)texcoords.v1; - vertices[1].varying[0] = (float)texcoords.u2; - vertices[1].varying[1] = (float)texcoords.v1; - vertices[2].varying[0] = (float)texcoords.u2; - vertices[2].varying[1] = (float)texcoords.v2; - vertices[3].varying[0] = (float)texcoords.u1; - vertices[3].varying[1] = (float)texcoords.v2; + vertices[0].u = (float)texcoords.u1; + vertices[0].v = (float)texcoords.v1; + vertices[1].u = (float)texcoords.u2; + vertices[1].v = (float)texcoords.v1; + vertices[2].u = (float)texcoords.u2; + vertices[2].v = (float)texcoords.v2; + vertices[3].u = (float)texcoords.u1; + vertices[3].v = (float)texcoords.v2; } // Masked walls clamp to the 0-1 range (no texture repeat) @@ -294,8 +294,8 @@ void RenderPolyWall::ClampHeight(TriVertex &v1, TriVertex &v2) { float top = v1.z; float bottom = v2.z; - float texv1 = v1.varying[1]; - float texv2 = v2.varying[1]; + float texv1 = v1.v; + float texv2 = v2.v; float delta = (texv2 - texv1); float t1 = texv1 < 0.0f ? -texv1 / delta : 0.0f; @@ -304,10 +304,10 @@ void RenderPolyWall::ClampHeight(TriVertex &v1, TriVertex &v2) float inv_t2 = 1.0f - t2; v1.z = top * inv_t1 + bottom * t1; - v1.varying[1] = texv1 * inv_t1 + texv2 * t1; + v1.v = texv1 * inv_t1 + texv2 * t1; v2.z = top * inv_t2 + bottom * t2; - v2.varying[1] = texv1 * inv_t2 + texv2 * t2; + v2.v = texv1 * inv_t2 + texv2 * t2; } FTexture *RenderPolyWall::GetTexture() diff --git a/src/polyrenderer/scene/poly_wallsprite.cpp b/src/polyrenderer/scene/poly_wallsprite.cpp index a7a1420e5..d00e6d2bd 100644 --- a/src/polyrenderer/scene/poly_wallsprite.cpp +++ b/src/polyrenderer/scene/poly_wallsprite.cpp @@ -90,10 +90,10 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const PolyClipPl vertices[i].y = (float)p.Y; vertices[i].z = (float)(pos.Z + spriteHeight * offsets[i].second); vertices[i].w = 1.0f; - vertices[i].varying[0] = (float)(offsets[i].first * tex->Scale.X); - vertices[i].varying[1] = (float)((1.0f - offsets[i].second) * tex->Scale.Y); + vertices[i].u = (float)(offsets[i].first * tex->Scale.X); + vertices[i].v = (float)((1.0f - offsets[i].second) * tex->Scale.Y); if (flipTextureX) - vertices[i].varying[0] = 1.0f - vertices[i].varying[0]; + vertices[i].u = 1.0f - vertices[i].u; } bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); From b9485d4edfdac0f0b02c6a4838b1b02d3f5e5fb0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 11:00:05 +0200 Subject: [PATCH 18/29] - ported the Hexen status bar to zscript. Note that DrawBar with a background texture does not work yet because the clipping rectangle is not done yet. --- src/am_map.cpp | 2 + src/g_statusbar/sbar.h | 1 + src/g_statusbar/shared_sbar.cpp | 80 ++++++ wadsrc/static/mapinfo/hexen.txt | 3 +- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/base.txt | 1 + wadsrc/static/zscript/statusbar/doom_sbar.txt | 6 +- .../static/zscript/statusbar/heretic_sbar.txt | 9 +- .../static/zscript/statusbar/hexen_sbar.txt | 258 ++++++++++++++++++ wadsrc/static/zscript/statusbar/statusbar.txt | 81 +++++- 10 files changed, 430 insertions(+), 12 deletions(-) create mode 100644 wadsrc/static/zscript/statusbar/hexen_sbar.txt diff --git a/src/am_map.cpp b/src/am_map.cpp index 1922b967c..f4382f0fd 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -734,6 +734,8 @@ static int grid = 0; bool automapactive = false; +DEFINE_GLOBAL(automapactive); + // location of window on screen static int f_x; static int f_y; diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index e4ad4e69b..d7c771767 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -397,6 +397,7 @@ public: void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY); void DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, bool monospaced, int shadowX, int shadowY); + void Fill(PalEntry color, double x, double y, double w, double h, int flags = 0); void BeginStatusBar(int resW, int resH, int relTop, bool completeborder = false, bool forceScaled = false); void BeginHUD(int resW, int resH, double Alpha, bool forceScaled = false); diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index af294f19d..06f5bed40 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1935,6 +1935,86 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawString) } +//============================================================================ +// +// draw stuff +// +//============================================================================ + +void DBaseStatusBar::Fill(PalEntry color, double x, double y, double w, double h, int flags) +{ + // resolve auto-alignment before making any adjustments to the position values. + if (!(flags & DI_SCREEN_MANUAL_ALIGN)) + { + if (x < 0) flags |= DI_SCREEN_RIGHT; + else flags |= DI_SCREEN_LEFT; + if (y < 0) flags |= DI_SCREEN_BOTTOM; + else flags |= DI_SCREEN_TOP; + } + + double Alpha = color.a * this->Alpha / 255; + if (Alpha <= 0) return; + x += drawOffset.X; + y += drawOffset.Y; + + if (!fullscreenOffsets) + { + x += ST_X; + //y += ST_Y; + + // Todo: Allow other scaling values, too. + if (Scaled) + { + screen->VirtualToRealCoords(x, y, w, h, HorizontalResolution, VerticalResolution, true, true); + } + } + else + { + double orgx, orgy; + + switch (flags & DI_SCREEN_HMASK) + { + default: orgx = 0; break; + case DI_SCREEN_HCENTER: orgx = screen->GetWidth() / 2; break; + case DI_SCREEN_RIGHT: orgx = screen->GetWidth(); break; + } + + switch (flags & DI_SCREEN_VMASK) + { + default: orgy = 0; break; + case DI_SCREEN_VCENTER: orgy = screen->GetHeight() / 2; break; + case DI_SCREEN_BOTTOM: orgy = screen->GetHeight(); break; + } + + // move stuff in the top right corner a bit down if the fps counter is on. + if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; + + DVector2 Scale = GetHUDScale(); + + x *= Scale.X; + y *= Scale.Y; + w *= Scale.X; + h *= Scale.Y; + x += orgx; + y += orgy; + } + screen->Dim(color, float(Alpha), int(x), int(y), int(w), int(h)); +} + + +DEFINE_ACTION_FUNCTION(DBaseStatusBar, Fill) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + PARAM_COLOR(color); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(w); + PARAM_FLOAT(h); + PARAM_INT_DEF(flags); + self->Fill(color, x, y, w, h); + return 0; +} + //============================================================================ // // CCMD showpop diff --git a/wadsrc/static/mapinfo/hexen.txt b/wadsrc/static/mapinfo/hexen.txt index 6b17df101..37afe7336 100644 --- a/wadsrc/static/mapinfo/hexen.txt +++ b/wadsrc/static/mapinfo/hexen.txt @@ -27,7 +27,8 @@ gameinfo defaultbloodcolor = "68 00 00" defaultbloodparticlecolor = "ff 00 00" backpacktype = "BagOfHolding" // Hexen doesn't have a backpack so use Heretic's. - statusbar = "sbarinfo/hexen.txt" + //statusbar = "sbarinfo/hexen.txt" + statusbarclass = "HexenStatusBar" intermissionmusic = "hub" intermissioncounter = false weaponslot = 1, "FWeapFist", "CWeapMace", "MWeapWand" diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 367a9156d..99627676d 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -35,6 +35,7 @@ version "2.5" #include "zscript/statusbar/statusbar.txt" #include "zscript/statusbar/doom_sbar.txt" #include "zscript/statusbar/heretic_sbar.txt" +#include "zscript/statusbar/hexen_sbar.txt" #include "zscript/statusbar/strife_sbar.txt" #include "zscript/statusbar/sbarinfowrapper.txt" diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index a312c4688..379e660ce 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -14,6 +14,7 @@ struct _ native // These are the global variables, the struct is only here to av native play @PlayerInfo players[MAXPLAYERS]; native readonly bool playeringame[MAXPLAYERS]; + native readonly bool automapactive; native play uint gameaction; native readonly int gamestate; native readonly TextureID skyflatnum; diff --git a/wadsrc/static/zscript/statusbar/doom_sbar.txt b/wadsrc/static/zscript/statusbar/doom_sbar.txt index 7cd2ae461..2382559e5 100644 --- a/wadsrc/static/zscript/statusbar/doom_sbar.txt +++ b/wadsrc/static/zscript/statusbar/doom_sbar.txt @@ -119,7 +119,7 @@ class DoomStatusBar : BaseStatusBar { DrawTexture(GetMugShot(5), (143, 168), DI_ITEM_OFFSETS); } - if (CPlayer.inventorytics != 0 && !level.NoInventoryBar) + if (isInventoryBarVisible()) { DrawInventoryBar(diparms, (48, 169), 7, DI_ITEM_LEFT_TOP); } @@ -155,7 +155,7 @@ class DoomStatusBar : BaseStatusBar DrawString(mHUDFont, FormatNumber(ammotype2.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); invY -= 20; } - if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null && !level.NoInventoryBar) + if (!isInventoryBarVisible() && !level.NoInventoryBar) { DrawInventoryIcon(CPlayer.mo.InvSel, (-14, invY + 17)); DrawString(mHUDFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); @@ -187,7 +187,7 @@ class DoomStatusBar : BaseStatusBar } } } - if (CPlayer.inventorytics != 0 && !level.NoInventoryBar) + if (isInventoryBarVisible()) { DrawInventoryBar(diparms, (0, 0), 7, DI_SCREEN_CENTER_BOTTOM, HX_SHADOW); } diff --git a/wadsrc/static/zscript/statusbar/heretic_sbar.txt b/wadsrc/static/zscript/statusbar/heretic_sbar.txt index d5191b99a..e2f761501 100644 --- a/wadsrc/static/zscript/statusbar/heretic_sbar.txt +++ b/wadsrc/static/zscript/statusbar/heretic_sbar.txt @@ -11,7 +11,7 @@ class HereticStatusBar : BaseStatusBar override void Init() { Super.Init(); - SetSize(48, 320, 200); + SetSize(42, 320, 200); // Create the font used for the fullscreen HUD Font fnt = "HUDFONT_RAVEN"; @@ -75,7 +75,7 @@ class HereticStatusBar : BaseStatusBar DrawShader(SHADER_HORZ, (19, 190), (16, 10)); DrawShader(SHADER_HORZ|SHADER_REVERSE, (278, 190), (16, 10)); - if (CPlayer.inventorytics == 0 || level.NoInventoryBar) + if (!isInventoryBarVisible()) { //statbar if (!deathmatch) @@ -132,7 +132,6 @@ class HereticStatusBar : BaseStatusBar protected void DrawFullScreenStuff () { - //health DrawImage("PTN1A0", (51, -3)); DrawString(mBigFont, FormatNumber(mHealthInterpolator.GetValue()), (41, -21), DI_TEXT_ALIGN_RIGHT); @@ -190,7 +189,7 @@ class HereticStatusBar : BaseStatusBar y -= 40; } - if (CPlayer.inventorytics == 0 && CPlayer.mo.InvSel != null && !level.NoInventoryBar) + if (!isInventoryBarVisible() && !level.NoInventoryBar) { // This code was changed to always fit the item into the box, regardless of alignment or sprite size. // Heretic's ARTIBOX is 30x30 pixels. @@ -201,7 +200,7 @@ class HereticStatusBar : BaseStatusBar DrawString(mIndexFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-32, -2 - mIndexFont.mFont.GetHeight()), DI_TEXT_ALIGN_RIGHT); } } - if (CPlayer.inventorytics != 0 && !level.NoInventoryBar) + if (isInventoryBarVisible()) { DrawInventoryBar(diparms, (0, 0), 7, DI_SCREEN_CENTER_BOTTOM, HX_SHADOW); } diff --git a/wadsrc/static/zscript/statusbar/hexen_sbar.txt b/wadsrc/static/zscript/statusbar/hexen_sbar.txt new file mode 100644 index 000000000..6f8318b27 --- /dev/null +++ b/wadsrc/static/zscript/statusbar/hexen_sbar.txt @@ -0,0 +1,258 @@ +class HexenStatusBar : BaseStatusBar +{ + DynamicValueInterpolator mHealthInterpolator; + DynamicValueInterpolator mHealthInterpolator2; + HUDFont mHUDFont; + HUDFont mIndexFont; + HUDFont mBigFont; + InventoryBarState diparms; + InventoryBarState diparms_sbar; + + + override void Init() + { + Super.Init(); + SetSize(38, 320, 200); + + // Create the font used for the fullscreen HUD + Font fnt = "HUDFONT_RAVEN"; + mHUDFont = HUDFont.Create(fnt, fnt.GetCharWidth("0") + 1, true, 1, 1); + fnt = "INDEXFONT_RAVEN"; + mIndexFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true); + fnt = "BIGFONT"; + mBigFont = HUDFont.Create(fnt, fnt.GetCharWidth("0"), true, 2, 2); + diparms = InventoryBarState.Create(mIndexFont); + diparms_sbar = InventoryBarState.CreateNoBox(mIndexFont, boxsize:(31, 31), arrowoffs:(0,-10)); + mHealthInterpolator = DynamicValueInterpolator.Create(0, 0.25, 1, 8); + mHealthInterpolator2 = DynamicValueInterpolator.Create(0, 0.25, 1, 6); // the chain uses a maximum of 6, not 8. + } + + override void NewGame () + { + Super.NewGame(); + mHealthInterpolator.Reset (0); + mHealthInterpolator2.Reset (0); + } + + override void Tick() + { + Super.Tick(); + mHealthInterpolator.Update(CPlayer.health); + mHealthInterpolator2.Update(CPlayer.health); + } + + override void Draw (int state, double TicFrac) + { + Super.Draw (state, TicFrac); + + if (state == HUD_StatusBar) + { + BeginStatusBar(320, 200, 38); + DrawMainBar (TicFrac); + } + else if (state == HUD_Fullscreen) + { + BeginHUD(320, 200, 1., false); + DrawFullScreenStuff (); + } + } + + protected void DrawFullScreenStuff () + { + //health + DrawImage("PTN1A0", (51, -3)); + DrawString(mBigFont, FormatNumber(mHealthInterpolator.GetValue()), (41, -21), DI_TEXT_ALIGN_RIGHT); + + //frags/keys + if (deathmatch) + { + DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (70, -16)); + } + + if (!isInventoryBarVisible() && !level.NoInventoryBar) + { + // This code was changed to always fit the item into the box, regardless of alignment or sprite size. + // Heretic's ARTIBOX is 30x30 pixels. + DrawImage("ARTIBOX", (-66, -1), 0, HX_SHADOW); + DrawInventoryIcon(CPlayer.mo.InvSel, (-66, -15), DI_ARTIFLASH|DI_ITEM_CENTER, boxsize:(28, 28)); + if (CPlayer.mo.InvSel.Amount > 1) + { + DrawString(mIndexFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-52, -2 - mIndexFont.mFont.GetHeight()), DI_TEXT_ALIGN_RIGHT); + } + } + + Ammo ammo1, ammo2; + [ammo1, ammo2] = GetCurrentAmmo(); + if ((ammo1 is "Mana1") || (ammo2 is "Mana1")) DrawImage("MANABRT1", (-17, -30), DI_ITEM_OFFSETS); + else DrawImage("MANADIM1", (-17, -30), DI_ITEM_OFFSETS); + if ((ammo1 is "Mana2") || (ammo2 is "Mana2")) DrawImage("MANABRT2", (-17, -15), DI_ITEM_OFFSETS); + else DrawImage("MANADIM2", (-17, -15), DI_ITEM_OFFSETS); + DrawString(mHUDFont, FormatNumber(GetAmount("Mana1"), 3), (-21, -30), DI_TEXT_ALIGN_RIGHT); + DrawString(mHUDFont, FormatNumber(GetAmount("Mana2"), 3), (-21, -15), DI_TEXT_ALIGN_RIGHT); + + if (isInventoryBarVisible()) + { + DrawInventoryBar(diparms, (0, 0), 7, DI_SCREEN_CENTER_BOTTOM, HX_SHADOW); + } + } + + protected void DrawMainBar (double TicFrac) + { + DrawImage("H2BAR", (0, 134), DI_ITEM_OFFSETS); + if (!automapactive) + { + if (isInventoryBarVisible()) + { + DrawImage("INVBAR", (38, 162), DI_ITEM_OFFSETS); + DrawInventoryBar(diparms_sbar, (52, 163), 7, DI_ITEM_LEFT_TOP, HX_SHADOW); + return; + } + else + { + DrawImage("STATBAR", (38, 162), DI_ITEM_OFFSETS); + + //inventory box + if (CPlayer.mo.InvSel != null) + { + DrawInventoryIcon(CPlayer.mo.InvSel, (159.5, 177), DI_ARTIFLASH|DI_ITEM_CENTER, boxsize:(28, 28)); + if (CPlayer.mo.InvSel.Amount > 1) + { + DrawString(mIndexFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (174, 184), DI_TEXT_ALIGN_RIGHT); + } + } + + if (deathmatch || teamplay) + { + DrawImage("KILLS", (38, 163), DI_ITEM_OFFSETS); + DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (66, 176), DI_TEXT_ALIGN_RIGHT); + } + else + { + DrawImage("ARMCLS", (41, 178), DI_ITEM_OFFSETS); + // Note that this has been changed to use red only if the REAL health is below 25, not when an interpolated value is below 25! + DrawString(mHUDFont, FormatNumber(mHealthInterpolator.GetValue(), 3), (66, 176), DI_TEXT_ALIGN_RIGHT, CPlayer.Health < 25? Font.CR_RED : Font.CR_UNTRANSLATED); + } + + //armor + DrawImage("ARMCLS", (255, 178), DI_ITEM_OFFSETS); + DrawString(mHUDFont, FormatNumber(GetArmorSavePercent() / 5, 2), (276, 176), DI_TEXT_ALIGN_RIGHT); + + Ammo ammo1, ammo2; + [ammo1, ammo2] = GetCurrentAmmo(); + + if (ammo1 != null && !(ammo1 is "Mana1") && !(ammo1 is "Mana2")) + { + DrawImage("HAMOBACK", (77, 164), DI_ITEM_OFFSETS); + if (ammo2 != null) + { + DrawTexture(ammo1.icon, (89, 172), DI_ITEM_CENTER); + DrawTexture(ammo2.icon, (113, 172), DI_ITEM_CENTER); + DrawString(mIndexFont, FormatNumber(ammo1.amount, 3), ( 98, 182), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(ammo2.amount, 3), (122, 182), DI_TEXT_ALIGN_RIGHT); + } + else + { + DrawTexture(ammo1.icon, (100, 172), DI_ITEM_CENTER); + DrawString(mIndexFont, FormatNumber(ammo1.amount, 3), (109, 182), DI_TEXT_ALIGN_RIGHT); + } + } + else + { + int amt1, maxamt1, amt2, maxamt2; + [amt1, maxamt1] = GetAmount("Mana1"); + [amt2, maxamt2] = GetAmount("Mana2"); + if ((ammo1 is "Mana1") || (ammo2 is "Mana1")) + { + DrawImage("MANABRT1", (77, 164), DI_ITEM_OFFSETS); + DrawBar("MANAVL1", "", amt1, maxamt1, (94, 164), 1, SHADER_VERT, DI_ITEM_OFFSETS); + } + else + { + DrawImage("MANADIM1", (77, 164), DI_ITEM_OFFSETS); + DrawBar("MANAVL1D", "", amt1, maxamt1, (94, 164), 1, SHADER_VERT, DI_ITEM_OFFSETS); + } + if ((ammo1 is "Mana2") || (ammo2 is "Mana2")) + { + DrawImage("MANABRT2", (110, 164), DI_ITEM_OFFSETS); + DrawBar("MANAVL2", "", amt2, maxamt2, (102, 164), 1, SHADER_VERT, DI_ITEM_OFFSETS); + } + else + { + DrawImage("MANADIM2", (110, 164), DI_ITEM_OFFSETS); + DrawBar("MANAVL2D", "", amt2, maxamt2, (102, 164), 1, SHADER_VERT, DI_ITEM_OFFSETS); + } + DrawString(mIndexFont, FormatNumber(amt1, 3), ( 92, 181), DI_TEXT_ALIGN_RIGHT); + DrawString(mIndexFont, FormatNumber(amt2, 3), (124, 181), DI_TEXT_ALIGN_RIGHT); + } + if (CPlayer.mo is "ClericPlayer") + { + DrawImage("WPSLOT1", (190, 162), DI_ITEM_OFFSETS); + if (CheckInventory("CWeapWraithverge")) DrawImage("WPFULL1", (190, 162), DI_ITEM_OFFSETS); + else + { + int pieces = GetWeaponPieceMask("CWeapWraithverge"); + if (pieces & 1) DrawImage("WPIECEC1", (190, 162), DI_ITEM_OFFSETS); + if (pieces & 2) DrawImage("WPIECEC2", (212, 162), DI_ITEM_OFFSETS); + if (pieces & 4) DrawImage("WPIECEC3", (225, 162), DI_ITEM_OFFSETS); + } + } + else if (CPlayer.mo is "MagePlayer") + { + DrawImage("WPSLOT2", (190, 162), DI_ITEM_OFFSETS); + if (CheckInventory("MWeapBloodscourge")) DrawImage("WPFULL2", (190, 162), DI_ITEM_OFFSETS); + else + { + int pieces = GetWeaponPieceMask("MWeapBloodscourge"); + if (pieces & 1) DrawImage("WPIECEM1", (190, 162), DI_ITEM_OFFSETS); + if (pieces & 2) DrawImage("WPIECEM2", (205, 162), DI_ITEM_OFFSETS); + if (pieces & 4) DrawImage("WPIECEM3", (224, 162), DI_ITEM_OFFSETS); + } + } + else + { + DrawImage("WPSLOT0", (190, 162), DI_ITEM_OFFSETS); + if (CheckInventory("FWeapQuietus")) DrawImage("WPFULL0", (190, 162), DI_ITEM_OFFSETS); + else + { + int pieces = GetWeaponPieceMask("FWeapQuietus"); + if (pieces & 1) DrawImage("WPIECEF1", (190, 162), DI_ITEM_OFFSETS); + if (pieces & 2) DrawImage("WPIECEF2", (225, 162), DI_ITEM_OFFSETS); + if (pieces & 4) DrawImage("WPIECEF3", (234, 162), DI_ITEM_OFFSETS); + } + } + } + } + else // automap + { + DrawImage("H2BAR", (0, 134), DI_ITEM_OFFSETS); + DrawImage("KEYBAR", (38, 162), DI_ITEM_OFFSETS); + int cnt = 0; + Vector2 keypos = (46, 164); + for(let i = CPlayer.mo.Inv; i != null; i = i.Inv) + { + if (i is "Key" && i.Icon.IsValid()) + { + DrawTexture(i.Icon, keypos, DI_ITEM_OFFSETS); + keypos.X += 20; + if (++cnt >= 5) break; + } + } + DrawHexenArmor(HEXENARMOR_ARMOR, "ARMSLOT1", (150, 164), DI_ITEM_OFFSETS); + DrawHexenArmor(HEXENARMOR_SHIELD, "ARMSLOT2", (181, 164), DI_ITEM_OFFSETS); + DrawHexenArmor(HEXENARMOR_HELM, "ARMSLOT3", (212, 164), DI_ITEM_OFFSETS); + DrawHexenArmor(HEXENARMOR_AMULET, "ARMSLOT4", (243, 164), DI_ITEM_OFFSETS); + } + + String Gem; + if (CPlayer.mo is "ClericPlayer") Gem = "LIFEGMC2"; + else if (CPlayer.mo is "MagePlayer") Gem = "LIFEGMM2"; + else Gem = "LIFEGMF2"; + + int inthealth = mHealthInterpolator2.GetValue(); + DrawGem("CHAIN", "LIFEGMF2", inthealth, CPlayer.mo.GetMaxHealth(true), (30, 193), -23, 49, 15, (multiplayer? DI_TRANSLATABLE : 0) | DI_ITEM_LEFT_TOP); + + DrawImage("LFEDGE", (0, 193), DI_ITEM_OFFSETS); + DrawImage("RTEDGE", (277, 193), DI_ITEM_OFFSETS); + } +} + diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index 7219d7d55..01fbcc7ae 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -27,6 +27,7 @@ class InventoryBarState ui TextureID selector; Vector2 boxsize; Vector2 boxofs; + Vector2 selectofs; Vector2 innersize; TextureID left; @@ -52,6 +53,11 @@ class InventoryBarState ui me.innersize = innersize; me.boxofs = (me.boxsize - me.innersize) / 2; } + if (me.selector.IsValid()) + { + Vector2 sel = TexMan.GetScaledSize(me.selector); + me.selectofs = (me.boxsize - sel) / 2; + } me.left = TexMan.CheckForTexture(leftgfx, TexMan.TYPE_MiscPatch); me.right = TexMan.CheckForTexture(rightgfx, TexMan.TYPE_MiscPatch); me.arrowoffset = arrowoffs; @@ -316,6 +322,7 @@ class BaseStatusBar native ui native void DrawTexture(TextureID texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1)); native void DrawImage(String texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1)); native void DrawString(HUDFont font, String string, Vector2 pos, int flags = 0, int translation = Font.CR_UNTRANSLATED, double Alpha = 1., int wrapwidth = -1, int linespacing = 4); + native void Fill(Color col, double x, double y, double w, double h, int flags = 0); native static String FormatNumber(int number, int minsize = 0, int maxsize = 0, int format = 0, String prefix = ""); @@ -513,7 +520,7 @@ class BaseStatusBar native ui bool isInventoryBarVisible() { if (CPlayer == null) return false; - return (CPlayer.inventorytics <= 0 || level.NoInventoryBar); + return (CPlayer.inventorytics > 0 && !level.NoInventoryBar); } //============================================================================ @@ -563,7 +570,7 @@ class BaseStatusBar native ui // //============================================================================ - bool CheckWeaponPiece(class weap, int piecenum) + int CheckWeaponPiece(class weap, int piecenum) { if (CPlayer == null) return false; for(let inv = CPlayer.mo.Inv; inv != NULL; inv = inv.Inv) @@ -583,6 +590,26 @@ class BaseStatusBar native ui // //============================================================================ + int GetWeaponPieceMask(class weap) + { + if (CPlayer == null) return false; + for(let inv = CPlayer.mo.Inv; inv != NULL; inv = inv.Inv) + { + let wh = WeaponHolder(inv); + if (wh != null && wh.PieceWeapon == weap) + { + return wh.PieceMask; + } + } + return 0; + } + + //============================================================================ + // + // checks if player has the given weapon piece + // + //============================================================================ + bool WeaponUsesAmmoType(class ammotype) { if (CPlayer == null) return false; @@ -794,6 +821,54 @@ class BaseStatusBar native ui DrawImage(gem, pos + (offset + leftPadding, 0), flags | DI_ITEM_LEFT_TOP); } + //============================================================================ + // + // DrawBar + // + //============================================================================ + + void DrawBar(String ongfx, String offgfx, double curval, double maxval, Vector2 position, int border, int vertical, int flags = 0, double alpha = 1.) + { + let ontex = TexMan.CheckForTexture(ongfx, TexMan.TYPE_MiscPatch); + if (!ontex.IsValid()) return; + let offtex = TexMan.CheckForTexture(offgfx, TexMan.TYPE_MiscPatch); + + Vector2 texsize = TexMan.GetScaledSize(ontex); + [position, flags] = AdjustPosition(position, flags, texsize.X, texsize.Y); + + double value = clamp(curval / maxval, 0, 1); + if(border != 0) value = 1. - value; //invert since the new drawing method requires drawing the bg on the fg. + + + // {cx, cb, cr, cy} + double Clip[4]; + Clip[0] = Clip[1] = Clip[2] = Clip[3] = 0; + + bool horizontal = !(vertical & SHADER_VERT); + bool reverse = !!(vertical & SHADER_REVERSE); + double sizeOfImage = (horizontal ? texsize.X - border*2 : texsize.Y - border*2); + Clip[(!horizontal) | ((!reverse)<<1)] = sizeOfImage - sizeOfImage *value; + + if(border != 0) + { + for(int i = 0; i < 4; i++) Clip[i] += border; + + //Draw the whole foreground + DrawTexture(ontex, position, flags | DI_ITEM_LEFT_TOP); + // SetClip + } + + if (offtex.IsValid() && TexMan.GetScaledSize(offtex) == texsize) DrawTexture(offtex, position, flags | DI_ITEM_LEFT_TOP); + else Fill(color(255,0,0,0), position.X + Clip[0], position.Y + Clip[1], texsize.X - Clip[0] - Clip[2], texsize.Y - Clip[1] - Clip[3]); + + if (border == 0) + { + // SetClip + DrawTexture(ontex, position, flags | DI_ITEM_LEFT_TOP); + } + // UnsetClip + } + //============================================================================ // // DrawInventoryBar @@ -837,7 +912,7 @@ class BaseStatusBar native ui { double flashAlpha = bgalpha; if (flags & DI_ARTIFLASH) flashAlpha *= itemflashFade; - DrawTexture(parms.selector, position + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP, flashAlpha); + DrawTexture(parms.selector, position + parms.selectofs + (boxsize.X * i, 0), flags | DI_ITEM_LEFT_TOP, flashAlpha); } } else From f3db5f3803815f5ba65886f4c96c1640e4099021 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 13:06:24 +0200 Subject: [PATCH 19/29] - added a clipping rectangle to DCanvas that can be used independently of DrawTexture calls. Currently this is only being used for draw operations that are not automap related, i.e. DrawLine, DrawPixel and FillSimplePoly are not subjected to it. --- src/g_statusbar/shared_sbar.cpp | 1 + src/gl/system/gl_framebuffer.cpp | 5 +- src/gl/system/gl_framebuffer.h | 4 +- src/gl/system/gl_swframebuffer.cpp | 5 +- src/gl/system/gl_swframebuffer.h | 4 +- src/menu/menu.cpp | 1 + src/v_draw.cpp | 108 ++++++++++++++++++++++++----- src/v_video.cpp | 37 +--------- src/v_video.h | 12 +++- src/wi_stuff.cpp | 1 + src/win32/fb_d3d9.cpp | 7 +- src/win32/win32swiface.h | 4 +- 12 files changed, 119 insertions(+), 70 deletions(-) diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 06f5bed40..8b6b23170 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1135,6 +1135,7 @@ void DBaseStatusBar::CallDraw(EHudState state) GlobalVMStack.Call(func, params, countof(params), nullptr, 0); } else Draw(state); + screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. } diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 43c56018a..08afb72ae 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -361,6 +361,7 @@ FNativePalette *OpenGLFrameBuffer::CreatePalette(FRemapTable *remap) //========================================================================== bool OpenGLFrameBuffer::Begin2D(bool) { + ClearClipRect(); gl_RenderState.mViewMatrix.loadIdentity(); gl_RenderState.mProjectionMatrix.ortho(0, GetWidth(), GetHeight(), 0, -1.0f, 1.0f); gl_RenderState.ApplyMatrices(); @@ -428,7 +429,7 @@ void OpenGLFrameBuffer::Dim(PalEntry) Super::Dim(0); } -void OpenGLFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +void OpenGLFrameBuffer::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h) { if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr) GLRenderer->m2DDrawer->AddDim(color, damount, x1, y1, w, h); @@ -451,7 +452,7 @@ void OpenGLFrameBuffer::FlatFill (int left, int top, int right, int bottom, FTex // // //========================================================================== -void OpenGLFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) +void OpenGLFrameBuffer::DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) { if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr) GLRenderer->m2DDrawer->AddClear(left, top, right, bottom, palcolor, color); diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 67d5969e5..72bdb7315 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -63,9 +63,9 @@ public: void DrawTextureParms(FTexture *img, DrawParms &parms); void DrawLine(int x1, int y1, int x2, int y2, int palcolor, uint32_t color); void DrawPixel(int x1, int y1, int palcolor, uint32_t color); - void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color); + void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); void Dim(PalEntry color=0); - void Dim (PalEntry color, float damount, int x1, int y1, int w, int h); + void DoDim (PalEntry color, float damount, int x1, int y1, int w, int h); void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false); void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 6ff2e0943..acf5dc40b 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -2410,6 +2410,7 @@ bool OpenGLSWFrameBuffer::OpenGLPal::Update() bool OpenGLSWFrameBuffer::Begin2D(bool copy3d) { + ClearClipRect(); if (!Accel2D) { return false; @@ -2488,7 +2489,7 @@ FNativePalette *OpenGLSWFrameBuffer::CreatePalette(FRemapTable *remap) // //========================================================================== -void OpenGLSWFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) +void OpenGLSWFrameBuffer::DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) { if (In2D < 2) { @@ -2517,7 +2518,7 @@ void OpenGLSWFrameBuffer::Clear(int left, int top, int right, int bottom, int pa // //========================================================================== -void OpenGLSWFrameBuffer::Dim(PalEntry color, float amount, int x1, int y1, int w, int h) +void OpenGLSWFrameBuffer::DoDim(PalEntry color, float amount, int x1, int y1, int w, int h) { if (amount <= 0) { diff --git a/src/gl/system/gl_swframebuffer.h b/src/gl/system/gl_swframebuffer.h index dc202a05c..03cc5a4e0 100644 --- a/src/gl/system/gl_swframebuffer.h +++ b/src/gl/system/gl_swframebuffer.h @@ -55,8 +55,8 @@ public: FNativeTexture *CreateTexture(FTexture *gametex, bool wrapping) override; FNativePalette *CreatePalette(FRemapTable *remap) override; void DrawTextureParms(FTexture *img, DrawParms &parms) override; - void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) override; - void Dim(PalEntry color, float amount, int x1, int y1, int w, int h) override; + void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) override; + void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h) override; void FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin) override; void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor) override; void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor) override; diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 2050c4834..6d82bd680 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -279,6 +279,7 @@ void DMenu::CallDrawer() { VMValue params[] = { (DObject*)this }; GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. } } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index d06628d43..a2caded53 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -155,6 +155,22 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) } } +void DCanvas::SetClipRect(int x, int y, int w, int h) +{ + clipleft = clamp(x, 0, GetWidth()); + clipwidth = clamp(w, 0, GetWidth() - x); + cliptop = clamp(y, 0, GetHeight()); + clipwidth = clamp(w, 0, GetHeight() - y); +} + +void DCanvas::GetClipRect(int *x, int *y, int *w, int *h) +{ + if (x) *x = clipleft; + if (y) *y = cliptop; + if (w) *w = clipwidth; + if (h) *h = clipheight; +} + bool DCanvas::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy) const { if (img != NULL) @@ -692,6 +708,15 @@ bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t t parms->remap = nullptr; } + // intersect with the canvas's clipping rectangle. + if (clipwidth >= 0 && clipheight >= 0) + { + if (parms->lclip < clipleft) parms->lclip = clipleft; + if (parms->rclip > clipleft + clipwidth) parms->rclip = clipleft + clipwidth; + if (parms->uclip < cliptop) parms->uclip = cliptop; + if (parms->dclip < cliptop + clipheight) parms->uclip = cliptop + clipheight; + } + if (parms->uclip >= parms->dclip || parms->lclip >= parms->rclip) { return false; @@ -800,22 +825,6 @@ DEFINE_ACTION_FUNCTION(_Screen, VirtualToRealCoords) return MIN(numret, 2); } -void DCanvas::VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, - int vwidth, int vheight, bool vbottom, bool handleaspect) const -{ - double dx, dy, dw, dh; - - dx = FIXED2DBL(x); - dy = FIXED2DBL(y); - dw = FIXED2DBL(w); - dh = FIXED2DBL(h); - VirtualToRealCoords(dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect); - x = FLOAT2FIXED(dx); - y = FLOAT2FIXED(dy); - w = FLOAT2FIXED(dw); - h = FLOAT2FIXED(dh); -} - void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom, bool handleaspect) const { @@ -900,7 +909,7 @@ void DCanvas::DrawPixel(int x, int y, int palColor, uint32_t realcolor) // //========================================================================== -void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) +void DCanvas::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color) { #ifndef NO_SWRENDER if (palcolor < 0 && APART(color) != 255) @@ -914,6 +923,33 @@ void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uin #endif } +void DCanvas::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) +{ + if (clipwidth >= 0 && clipheight >= 0) + { + int w = right - left; + int h = bottom - top; + if (left < clipleft) + { + w -= (clipleft - left); + left = clipleft; + } + if (w > clipwidth) w = clipwidth; + if (w <= 0) return; + + if (top < cliptop) + { + h -= (cliptop - top); + top = cliptop; + } + if (h > clipheight) w = clipheight; + if (h <= 0) return; + right = left + w; + bottom = top + h; + } + DoClear(left, top, right, bottom, palcolor, color); +} + DEFINE_ACTION_FUNCTION(_Screen, Clear) { PARAM_PROLOGUE; @@ -935,13 +971,49 @@ DEFINE_ACTION_FUNCTION(_Screen, Clear) // //========================================================================== -void DCanvas::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +void DCanvas::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h) { #ifndef NO_SWRENDER SWCanvas::Dim(this, color, damount, x1, y1, w, h); #endif } +void DCanvas::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +{ + if (clipwidth >= 0 && clipheight >= 0) + { + if (x1 < clipleft) + { + w -= (clipleft - x1); + x1 = clipleft; + } + if (w > clipwidth) w = clipwidth; + if (w <= 0) return; + + if (y1 < cliptop) + { + h -= (cliptop - y1); + y1 = cliptop; + } + if (h > clipheight) w = clipheight; + if (h <= 0) return; + } + DoDim(color, damount, x1, y1, w, h); +} + +DEFINE_ACTION_FUNCTION(_Screen, Dim) +{ + PARAM_PROLOGUE; + PARAM_INT(color); + PARAM_FLOAT(amount); + PARAM_INT(x1); + PARAM_INT(y1); + PARAM_INT(w); + PARAM_INT(h); + screen->Dim(color, float(amount), x1, y1, w, h); + return 0; +} + //========================================================================== // // DCanvas :: FillSimplePoly diff --git a/src/v_video.cpp b/src/v_video.cpp index a6482a90c..3dea831be 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -204,8 +204,6 @@ void V_MarkRect (int x, int y, int width, int height) { } -DCanvas *DCanvas::CanvasChain = NULL; - //========================================================================== // // DCanvas Constructor @@ -220,10 +218,6 @@ DCanvas::DCanvas (int _width, int _height, bool _bgra) Width = _width; Height = _height; Bgra = _bgra; - - // Add to list of active canvases - Next = CanvasChain; - CanvasChain = this; } //========================================================================== @@ -234,22 +228,6 @@ DCanvas::DCanvas (int _width, int _height, bool _bgra) DCanvas::~DCanvas () { - // Remove from list of active canvases - DCanvas *probe = CanvasChain, **prev; - - prev = &CanvasChain; - probe = CanvasChain; - - while (probe != NULL) - { - if (probe == this) - { - *prev = probe->Next; - break; - } - prev = &probe->Next; - probe = probe->Next; - } } //========================================================================== @@ -336,20 +314,6 @@ void DCanvas::Dim (PalEntry color) Dim (dimmer, amount, 0, 0, Width, Height); } -DEFINE_ACTION_FUNCTION(_Screen, Dim) -{ - PARAM_PROLOGUE; - PARAM_INT(color); - PARAM_FLOAT(amount); - PARAM_INT(x1); - PARAM_INT(y1); - PARAM_INT(w); - PARAM_INT(h); - screen->Dim(color, float(amount), x1, y1, w, h); - return 0; -} - - //========================================================================== // // DCanvas :: GetScreenshotBuffer @@ -1168,6 +1132,7 @@ void DFrameBuffer::SetBlendingRect (int x1, int y1, int x2, int y2) bool DFrameBuffer::Begin2D (bool copy3d) { + ClearClipRect(); return false; } diff --git a/src/v_video.h b/src/v_video.h index 444e80f04..56041a228 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -225,7 +225,8 @@ public: virtual void Dim (PalEntry color = 0); // Dim part of the canvas - virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); + virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h) final; + virtual void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h); // Fill an area with a texture virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false); @@ -236,7 +237,8 @@ public: const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip); // Set an area to a specified color - virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color); + virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) final; + virtual void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); // Draws a line virtual void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor); @@ -259,6 +261,10 @@ public: // Text drawing functions ----------------------------------------------- // 2D Texture drawing + void ClearClipRect() { clipleft = cliptop = 0; clipwidth = clipheight = -1; } + void SetClipRect(int x, int y, int w, int h); + void GetClipRect(int *x, int *y, int *w, int *h); + bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const; void DrawTexture (FTexture *img, double x, double y, int tags, ...); void DrawTexture(FTexture *img, double x, double y, VMVa_List &); @@ -266,7 +272,6 @@ public: void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom=false, bool handleaspect=true) const; // Code that uses these (i.e. SBARINFO) should probably be evaluated for using doubles all around instead. - void VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; #ifdef DrawText @@ -285,6 +290,7 @@ protected: int Pitch; int LockCount; bool Bgra; + int clipleft = 0, cliptop = 0, clipwidth = -1, clipheight = -1; void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms); diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 9e2fc7ed7..f9a49eb0d 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -730,6 +730,7 @@ void WI_Drawer() { VMValue self = WI_Screen; GlobalVMStack.Call(func, &self, 1, nullptr, 0); + screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. // The internal handling here is somewhat poor. After being set to 'LeavingIntermission' // the screen is needed for one more draw operation so we cannot delete it right away but only here. diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 3c07b9c14..4fd198a1b 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -2557,6 +2557,7 @@ bool D3DPal::Update() bool D3DFB::Begin2D(bool copy3d) { + ClearClipRect(); if (!Accel2D) { return false; @@ -2635,11 +2636,11 @@ FNativePalette *D3DFB::CreatePalette(FRemapTable *remap) // //========================================================================== -void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) +void D3DFB::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color) { if (In2D < 2) { - Super::Clear(left, top, right, bottom, palcolor, color); + //Super::Clear(left, top, right, bottom, palcolor, color); return; } if (!InScene) @@ -2664,7 +2665,7 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3 // //========================================================================== -void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h) +void D3DFB::DoDim (PalEntry color, float amount, int x1, int y1, int w, int h) { if (amount <= 0) { diff --git a/src/win32/win32swiface.h b/src/win32/win32swiface.h index ecd5a49df..5c0a456e4 100644 --- a/src/win32/win32swiface.h +++ b/src/win32/win32swiface.h @@ -132,8 +132,8 @@ public: FNativeTexture *CreateTexture (FTexture *gametex, bool wrapping); FNativePalette *CreatePalette (FRemapTable *remap); void DrawTextureParms (FTexture *img, DrawParms &parms); - void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color); - void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); + void DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color); + void DoDim (PalEntry color, float amount, int x1, int y1, int w, int h); void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin); void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor); void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor); From e2e17f575c5aeb0f062d74aa77f4c828a01527b8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 13:25:17 +0200 Subject: [PATCH 20/29] - added safeguards to all 2D drawing functions to throw an exception if used outside a valid 2D draw context. This is necessary because the hardware accelerated renderers will hide the problem, but with pure software rendering to a locked hardware surface, like DirectDraw can result in a crash. Note that ANY mod that gets caught in this did something wrong! --- src/g_statusbar/shared_sbar.cpp | 4 ++++ src/v_draw.cpp | 4 ++++ src/v_text.cpp | 2 ++ src/win32/win32gliface.cpp | 2 +- wadsrc/static/zscript/statusbar/heretic_sbar.txt | 2 +- wadsrc/static/zscript/statusbar/hexen_sbar.txt | 2 +- 6 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 8b6b23170..fe4028091 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1700,6 +1700,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawTexture) PARAM_FLOAT_DEF(h); PARAM_FLOAT_DEF(scaleX); PARAM_FLOAT_DEF(scaleY); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); self->DrawGraphic(FSetTextureID(texid), x, y, flags, alpha, w, h, scaleX, scaleY); return 0; } @@ -1716,6 +1717,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawImage) PARAM_FLOAT_DEF(h); PARAM_FLOAT_DEF(scaleX); PARAM_FLOAT_DEF(scaleY); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); self->DrawGraphic(TexMan.CheckForTexture(texid, FTexture::TEX_Any), x, y, flags, alpha, w, h, scaleX, scaleY); return 0; } @@ -1908,6 +1910,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawString) PARAM_INT_DEF(wrapwidth); PARAM_INT_DEF(linespacing); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); // resolve auto-alignment before making any adjustments to the position values. if (!(flags & DI_SCREEN_MANUAL_ALIGN)) @@ -2012,6 +2015,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, Fill) PARAM_FLOAT(w); PARAM_FLOAT(h); PARAM_INT_DEF(flags); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); self->Fill(color, x, y, w, h); return 0; } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index a2caded53..a45cbddac 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -137,6 +137,8 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawTexture) PARAM_FLOAT(x); PARAM_FLOAT(y); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + FTexture *tex = animate ? TexMan(FSetTextureID(texid)) : TexMan[FSetTextureID(texid)]; VMVa_List args = { param + 4, 0, numparam - 4 }; screen->DrawTexture(tex, x, y, args); @@ -959,6 +961,7 @@ DEFINE_ACTION_FUNCTION(_Screen, Clear) PARAM_INT(y2); PARAM_INT(color); PARAM_INT_DEF(palcol); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); screen->Clear(x1, y1, x2, y2, palcol, color); return 0; } @@ -1010,6 +1013,7 @@ DEFINE_ACTION_FUNCTION(_Screen, Dim) PARAM_INT(y1); PARAM_INT(w); PARAM_INT(h); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); screen->Dim(color, float(amount), x1, y1, w, h); return 0; } diff --git a/src/v_text.cpp b/src/v_text.cpp index ca445913f..fa04da365 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -116,6 +116,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawChar) PARAM_FLOAT(y); PARAM_INT(chr); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); VMVa_List args = { param + 5, 0, numparam - 5 }; screen->DrawChar(font, cr, x, y, chr, args); return 0; @@ -241,6 +242,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawText) PARAM_FLOAT(y); PARAM_STRING(chr); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); VMVa_List args = { param + 5, 0, numparam - 5 }; const char *txt = chr[0] == '$' ? GStrings(&chr[1]) : chr.GetChars(); screen->DrawText(font, cr, x, y, txt, args); diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index b8e8cc53a..2074a17d8 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -1153,7 +1153,7 @@ void Win32GLFrameBuffer::Unlock () bool Win32GLFrameBuffer::IsLocked () { - return m_Lock>0;// true; + return m_Lock > 0; } //========================================================================== diff --git a/wadsrc/static/zscript/statusbar/heretic_sbar.txt b/wadsrc/static/zscript/statusbar/heretic_sbar.txt index e2f761501..1273ad4ce 100644 --- a/wadsrc/static/zscript/statusbar/heretic_sbar.txt +++ b/wadsrc/static/zscript/statusbar/heretic_sbar.txt @@ -189,7 +189,7 @@ class HereticStatusBar : BaseStatusBar y -= 40; } - if (!isInventoryBarVisible() && !level.NoInventoryBar) + if (!isInventoryBarVisible() && !level.NoInventoryBar && CPlayer.mo.InvSel != null) { // This code was changed to always fit the item into the box, regardless of alignment or sprite size. // Heretic's ARTIBOX is 30x30 pixels. diff --git a/wadsrc/static/zscript/statusbar/hexen_sbar.txt b/wadsrc/static/zscript/statusbar/hexen_sbar.txt index 6f8318b27..f1ff81693 100644 --- a/wadsrc/static/zscript/statusbar/hexen_sbar.txt +++ b/wadsrc/static/zscript/statusbar/hexen_sbar.txt @@ -69,7 +69,7 @@ class HexenStatusBar : BaseStatusBar DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (70, -16)); } - if (!isInventoryBarVisible() && !level.NoInventoryBar) + if (!isInventoryBarVisible() && !level.NoInventoryBar && CPlayer.mo.InvSel != null) { // This code was changed to always fit the item into the box, regardless of alignment or sprite size. // Heretic's ARTIBOX is 30x30 pixels. From 6816902a09fdfad5fff2a1281f4519735f75054b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 13:27:59 +0200 Subject: [PATCH 21/29] - forgot to save doom_sbar.txt --- wadsrc/static/zscript/statusbar/doom_sbar.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/statusbar/doom_sbar.txt b/wadsrc/static/zscript/statusbar/doom_sbar.txt index 2382559e5..67ea2c620 100644 --- a/wadsrc/static/zscript/statusbar/doom_sbar.txt +++ b/wadsrc/static/zscript/statusbar/doom_sbar.txt @@ -155,7 +155,7 @@ class DoomStatusBar : BaseStatusBar DrawString(mHUDFont, FormatNumber(ammotype2.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); invY -= 20; } - if (!isInventoryBarVisible() && !level.NoInventoryBar) + if (!isInventoryBarVisible() && !level.NoInventoryBar && CPlayer.mo.InvSel != null) { DrawInventoryIcon(CPlayer.mo.InvSel, (-14, invY + 17)); DrawString(mHUDFont, FormatNumber(CPlayer.mo.InvSel.Amount, 3), (-30, invY), DI_TEXT_ALIGN_RIGHT); From 4716b712b1cd5983777247e7e125aeac3870717a Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 28 Mar 2017 17:10:06 +0300 Subject: [PATCH 22/29] Fixed compilation issues with isnan() Need to do it in pure C++ way to avoid C99 macro at all costs Tested with CI targets, on Debian Jessie using GCC 4.9 and on Ubuntu 16.04 using GCC 5.4 --- src/swrenderer/line/r_walldraw.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index d315d5a01..f07a63bb8 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "doomdef.h" #include "doomstat.h" @@ -42,13 +43,6 @@ #include "swrenderer/r_renderthread.h" #include "swrenderer/r_memory.h" -#ifndef isnan -// Fallback to C++ function if C99 isnan() macro is not undefined -// Most likely it was undefined in C++ library header to avoid conflicts with own function -#include -using std::isnan; -#endif // !isnan - namespace swrenderer { WallSampler::WallSampler(RenderViewport *viewport, int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FTexture *texture) @@ -106,7 +100,7 @@ namespace swrenderer v = v - floor(v); double v_step = uv_stepd / texture->GetHeight(); - if (isnan(v) || isnan(v_step)) // this should never happen, but it apparently does.. + if (std::isnan(v) || std::isnan(v_step)) // this should never happen, but it apparently does.. { uv_stepd = 0.0; v = 0.0; From e8ba1156afc718356d8a66b8aef8c3035d430e2f Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 28 Mar 2017 16:46:22 +0200 Subject: [PATCH 23/29] - add rect drawers for softpoly's player sprites --- src/polyrenderer/drawers/poly_draw_args.cpp | 152 ++++ src/polyrenderer/drawers/poly_draw_args.h | 68 ++ src/polyrenderer/drawers/poly_drawer32_sse2.h | 686 +++++++++++------- src/polyrenderer/drawers/poly_drawer8.h | 445 +++++++----- src/polyrenderer/drawers/poly_triangle.cpp | 20 + src/polyrenderer/drawers/poly_triangle.h | 12 + src/polyrenderer/drawers/screen_triangle.cpp | 72 +- src/polyrenderer/drawers/screen_triangle.h | 8 +- src/polyrenderer/scene/poly_playersprite.cpp | 42 +- 9 files changed, 1015 insertions(+), 490 deletions(-) diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index a9bfde1f5..4c526d1ef 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -199,3 +199,155 @@ void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint3 SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, alpha, 1.0 - alpha); } } + +///////////////////////////////////////////////////////////////////////////// + +void RectDrawArgs::SetTexture(const uint8_t *texels, int width, int height) +{ + mTexturePixels = texels; + mTextureWidth = width; + mTextureHeight = height; + mTranslation = nullptr; +} + +void RectDrawArgs::SetTexture(FTexture *texture) +{ + mTextureWidth = texture->GetWidth(); + mTextureHeight = texture->GetHeight(); + if (PolyRenderer::Instance()->RenderTarget->IsBgra()) + mTexturePixels = (const uint8_t *)texture->GetPixelsBgra(); + else + mTexturePixels = texture->GetPixels(); + mTranslation = nullptr; +} + +void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, bool forcePal) +{ + if (translationID != 0xffffffff && translationID != 0) + { + FRemapTable *table = TranslationToTable(translationID); + if (table != nullptr && !table->Inactive) + { + if (PolyRenderer::Instance()->RenderTarget->IsBgra()) + mTranslation = (uint8_t*)table->Palette; + else + mTranslation = table->Remap; + + mTextureWidth = texture->GetWidth(); + mTextureHeight = texture->GetHeight(); + mTexturePixels = texture->GetPixels(); + return; + } + } + + if (forcePal) + { + mTextureWidth = texture->GetWidth(); + mTextureHeight = texture->GetHeight(); + mTexturePixels = texture->GetPixels(); + } + else + { + SetTexture(texture); + } +} + +void RectDrawArgs::SetLight(FSWColormap *base_colormap, uint32_t lightlevel) +{ + mLight = clamp(lightlevel, 0, 255); + mLightRed = base_colormap->Color.r * 256 / 255; + mLightGreen = base_colormap->Color.g * 256 / 255; + mLightBlue = base_colormap->Color.b * 256 / 255; + mLightAlpha = base_colormap->Color.a * 256 / 255; + mFadeRed = base_colormap->Fade.r; + mFadeGreen = base_colormap->Fade.g; + mFadeBlue = base_colormap->Fade.b; + mFadeAlpha = base_colormap->Fade.a; + mDesaturate = MIN(abs(base_colormap->Desaturate), 255) * 255 / 256; + mSimpleShade = (base_colormap->Color.d == 0x00ffffff && base_colormap->Fade.d == 0x00000000 && base_colormap->Desaturate == 0); + mColormaps = base_colormap->Maps; +} + +void RectDrawArgs::SetColor(uint32_t bgra, uint8_t palindex) +{ + if (PolyRenderer::Instance()->RenderTarget->IsBgra()) + { + mColor = bgra; + } + else + { + mColor = palindex; + } +} + +void RectDrawArgs::Draw(double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1) +{ + mX0 = (float)x0; + mX1 = (float)x1; + mY0 = (float)y0; + mY1 = (float)y1; + mU0 = (float)u0; + mU1 = (float)u1; + mV0 = (float)v0; + mV1 = (float)v1; + PolyRenderer::Instance()->DrawQueue->Push(*this); +} + +void RectDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) +{ + bool forcePal = (renderstyle == LegacyRenderStyles[STYLE_Shaded] || renderstyle == LegacyRenderStyles[STYLE_AddShaded]); + SetTexture(tex, translationID, forcePal); + + if (renderstyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 1.0, 0.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Add] && fullbright && alpha == 1.0 && !Translation()) + { + SetStyle(TriBlendMode::TextureAddSrcColor, 1.0, 1.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Add]) + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, alpha, 1.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Subtract]) + { + SetStyle(Translation() ? TriBlendMode::TranslatedRevSub : TriBlendMode::TextureRevSub, alpha, 1.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_SoulTrans]) + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, transsouls, 1.0 - transsouls); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 2 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + { // NYI - Fuzzy - for now, just a copy of "Shadow" + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 1 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, 0.0, 160 / 255.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_TranslucentStencil]) + { + SetColor(0xff000000 | fillcolor, fillcolor >> 24); + SetStyle(TriBlendMode::Stencil, alpha, 1.0 - alpha); + } + else if (renderstyle == LegacyRenderStyles[STYLE_AddStencil]) + { + SetColor(0xff000000 | fillcolor, fillcolor >> 24); + SetStyle(TriBlendMode::AddStencil, alpha, 1.0); + } + else if (renderstyle == LegacyRenderStyles[STYLE_Shaded]) + { + SetColor(0xff000000 | fillcolor, fillcolor >> 24); + SetStyle(TriBlendMode::Shaded, alpha, 1.0 - alpha); + } + else if (renderstyle == LegacyRenderStyles[STYLE_AddShaded]) + { + SetColor(0xff000000 | fillcolor, fillcolor >> 24); + SetStyle(TriBlendMode::AddShaded, alpha, 1.0); + } + else + { + SetStyle(Translation() ? TriBlendMode::TranslatedAdd : TriBlendMode::TextureAdd, alpha, 1.0 - alpha); + } +} diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index a77ef7c98..c90aaadd0 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -149,3 +149,71 @@ private: bool mNearestFilter = true; bool mFixedLight = false; }; + +class RectDrawArgs +{ +public: + void SetTexture(const uint8_t *texels, int width, int height); + void SetTexture(FTexture *texture); + void SetTexture(FTexture *texture, uint32_t translationID, bool forcePal = false); + void SetLight(FSWColormap *basecolormap, uint32_t lightlevel); + void SetStyle(TriBlendMode blendmode, double srcalpha = 1.0, double destalpha = 1.0) { mBlendMode = blendmode; mSrcAlpha = (uint32_t)(srcalpha * 256.0 + 0.5); mDestAlpha = (uint32_t)(destalpha * 256.0 + 0.5); } + void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); + void SetColor(uint32_t bgra, uint8_t palindex); + void Draw(double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1); + + const uint8_t *TexturePixels() const { return mTexturePixels; } + int TextureWidth() const { return mTextureWidth; } + int TextureHeight() const { return mTextureHeight; } + const uint8_t *Translation() const { return mTranslation; } + + TriBlendMode BlendMode() const { return mBlendMode; } + uint32_t Color() const { return mColor; } + uint32_t SrcAlpha() const { return mSrcAlpha; } + uint32_t DestAlpha() const { return mDestAlpha; } + + uint32_t Light() const { return mLight; } + const uint8_t *BaseColormap() const { return mColormaps; } + uint16_t ShadeLightAlpha() const { return mLightAlpha; } + uint16_t ShadeLightRed() const { return mLightRed; } + uint16_t ShadeLightGreen() const { return mLightGreen; } + uint16_t ShadeLightBlue() const { return mLightBlue; } + uint16_t ShadeFadeAlpha() const { return mFadeAlpha; } + uint16_t ShadeFadeRed() const { return mFadeRed; } + uint16_t ShadeFadeGreen() const { return mFadeGreen; } + uint16_t ShadeFadeBlue() const { return mFadeBlue; } + uint16_t ShadeDesaturate() const { return mDesaturate; } + bool SimpleShade() const { return mSimpleShade; } + + float X0() const { return mX0; } + float X1() const { return mX1; } + float Y0() const { return mY0; } + float Y1() const { return mY1; } + float U0() const { return mU0; } + float U1() const { return mU1; } + float V0() const { return mV0; } + float V1() const { return mV1; } + +private: + const uint8_t *mTexturePixels = nullptr; + int mTextureWidth = 0; + int mTextureHeight = 0; + const uint8_t *mTranslation = nullptr; + const uint8_t *mColormaps = nullptr; + TriBlendMode mBlendMode = TriBlendMode::FillOpaque; + uint32_t mLight = 0; + uint32_t mColor = 0; + uint32_t mSrcAlpha = 0; + uint32_t mDestAlpha = 0; + uint16_t mLightAlpha = 0; + uint16_t mLightRed = 0; + uint16_t mLightGreen = 0; + uint16_t mLightBlue = 0; + uint16_t mFadeAlpha = 0; + uint16_t mFadeRed = 0; + uint16_t mFadeGreen = 0; + uint16_t mFadeBlue = 0; + uint16_t mDesaturate = 0; + bool mSimpleShade = true; + float mX0, mX1, mY0, mY1, mU0, mU1, mV0, mV1; +}; diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index 20d0a9efc..bb94632bc 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -24,6 +24,246 @@ #include "screen_triangle.h" +namespace TriScreenDrawerModes +{ + template + FORCEINLINE unsigned int VECTORCALL Sample32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, uint32_t oneU, uint32_t oneV, uint32_t color, const uint32_t *translation) + { + uint32_t texel; + if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill) + { + return color; + } + else if (SamplerT::Mode == (int)Samplers::Translated) + { + const uint8_t *texpal = (const uint8_t *)texPixels; + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + return translation[texpal[texelX * texHeight + texelY]]; + } + else if (FilterModeT::Mode == (int)FilterModes::Nearest) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + texel = texPixels[texelX * texHeight + texelY]; + } + else + { + u -= oneU >> 1; + v -= oneV >> 1; + + unsigned int frac_x0 = (((uint32_t)u << 8) >> FRACBITS) * texWidth; + unsigned int frac_x1 = ((((uint32_t)u << 8) + oneU) >> FRACBITS) * texWidth; + unsigned int frac_y0 = (((uint32_t)v << 8) >> FRACBITS) * texHeight; + unsigned int frac_y1 = ((((uint32_t)v << 8) + oneV) >> FRACBITS) * texHeight; + unsigned int x0 = frac_x0 >> FRACBITS; + unsigned int x1 = frac_x1 >> FRACBITS; + unsigned int y0 = frac_y0 >> FRACBITS; + unsigned int y1 = frac_y1 >> FRACBITS; + + unsigned int p00 = texPixels[x0 * texHeight + y0]; + unsigned int p01 = texPixels[x0 * texHeight + y1]; + unsigned int p10 = texPixels[x1 * texHeight + y0]; + unsigned int p11 = texPixels[x1 * texHeight + y1]; + + unsigned int inv_a = (frac_x1 >> (FRACBITS - 4)) & 15; + unsigned int inv_b = (frac_y1 >> (FRACBITS - 4)) & 15; + unsigned int a = 16 - inv_a; + unsigned int b = 16 - inv_b; + + unsigned int sred = (RPART(p00) * (a * b) + RPART(p01) * (inv_a * b) + RPART(p10) * (a * inv_b) + RPART(p11) * (inv_a * inv_b) + 127) >> 8; + unsigned int sgreen = (GPART(p00) * (a * b) + GPART(p01) * (inv_a * b) + GPART(p10) * (a * inv_b) + GPART(p11) * (inv_a * inv_b) + 127) >> 8; + unsigned int sblue = (BPART(p00) * (a * b) + BPART(p01) * (inv_a * b) + BPART(p10) * (a * inv_b) + BPART(p11) * (inv_a * inv_b) + 127) >> 8; + unsigned int salpha = (APART(p00) * (a * b) + APART(p01) * (inv_a * b) + APART(p10) * (a * inv_b) + APART(p11) * (inv_a * inv_b) + 127) >> 8; + + texel = (salpha << 24) | (sred << 16) | (sgreen << 8) | sblue; + } + + if (SamplerT::Mode == (int)Samplers::Skycap) + { + int start_fade = 2; // How fast it should fade out + + int alpha_top = clamp(v >> (16 - start_fade), 0, 256); + int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); + int a = MIN(alpha_top, alpha_bottom); + int inv_a = 256 - a; + + uint32_t r = RPART(texel); + uint32_t g = GPART(texel); + uint32_t b = BPART(texel); + uint32_t fg_a = APART(texel); + uint32_t bg_red = RPART(color); + uint32_t bg_green = GPART(color); + uint32_t bg_blue = BPART(color); + r = (r * a + bg_red * inv_a + 127) >> 8; + g = (g * a + bg_green * inv_a + 127) >> 8; + b = (b * a + bg_blue * inv_a + 127) >> 8; + return MAKEARGB(fg_a, r, g, b); + } + else + { + return texel; + } + } + + template + FORCEINLINE unsigned int VECTORCALL SampleShade32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight) + { + if (SamplerT::Mode == (int)Samplers::Shaded) + { + const uint8_t *texpal = (const uint8_t *)texPixels; + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + unsigned int sampleshadeout = texpal[texelX * texHeight + texelY]; + sampleshadeout += sampleshadeout >> 7; // 255 -> 256 + return sampleshadeout; + } + else if (SamplerT::Mode == (int)Samplers::Stencil) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]); + sampleshadeout += sampleshadeout >> 7; // 255 -> 256 + return sampleshadeout; + } + else + { + return 0; + } + } + + template + FORCEINLINE __m128i VECTORCALL Shade32(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light) + { + if (ShadeModeT::Mode == (int)ShadeMode::Simple) + { + fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, mlight), 8); + } + else + { + int blue0 = BPART(ifgcolor0); + int green0 = GPART(ifgcolor0); + int red0 = RPART(ifgcolor0); + int intensity0 = ((red0 * 77 + green0 * 143 + blue0 * 37) >> 8) * desaturate; + + int blue1 = BPART(ifgcolor1); + int green1 = GPART(ifgcolor1); + int red1 = RPART(ifgcolor1); + int intensity1 = ((red1 * 77 + green1 * 143 + blue1 * 37) >> 8) * desaturate; + + __m128i intensity = _mm_set_epi16(0, intensity1, intensity1, intensity1, 0, intensity0, intensity0, intensity0); + + fgcolor = _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(fgcolor, inv_desaturate), intensity), 8); + fgcolor = _mm_mullo_epi16(fgcolor, mlight); + fgcolor = _mm_srli_epi16(_mm_add_epi16(shade_fade, fgcolor), 8); + fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, shade_light), 8); + } + return fgcolor; + } + + template + FORCEINLINE __m128i VECTORCALL Blend32(__m128i fgcolor, __m128i bgcolor, unsigned int ifgcolor0, unsigned int ifgcolor1, unsigned int ifgshade0, unsigned int ifgshade1, uint32_t srcalpha, uint32_t destalpha) + { + if (BlendT::Mode == (int)BlendModes::Opaque) + { + __m128i outcolor = fgcolor; + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + return outcolor; + } + else if (BlendT::Mode == (int)BlendModes::Masked) + { + __m128i mask = _mm_cmpeq_epi32(_mm_packus_epi16(fgcolor, _mm_setzero_si128()), _mm_setzero_si128()); + mask = _mm_unpacklo_epi8(mask, _mm_setzero_si128()); + __m128i outcolor = _mm_or_si128(_mm_and_si128(mask, bgcolor), _mm_andnot_si128(mask, fgcolor)); + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); + return outcolor; + } + else if (BlendT::Mode == (int)BlendModes::AddSrcColorOneMinusSrcColor) + { + __m128i inv_srccolor = _mm_sub_epi16(_mm_set1_epi16(256), _mm_add_epi16(fgcolor, _mm_srli_epi16(fgcolor, 7))); + __m128i outcolor = _mm_add_epi16(fgcolor, _mm_srli_epi16(_mm_mullo_epi16(bgcolor, inv_srccolor), 8)); + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + return outcolor; + } + else if (BlendT::Mode == (int)BlendModes::Shaded) + { + ifgshade0 = (ifgshade0 * srcalpha + 128) >> 8; + ifgshade1 = (ifgshade1 * srcalpha + 128) >> 8; + __m128i alpha = _mm_set_epi16(ifgshade1, ifgshade1, ifgshade1, ifgshade1, ifgshade0, ifgshade0, ifgshade0, ifgshade0); + __m128i inv_alpha = _mm_sub_epi16(_mm_set1_epi16(256), alpha); + + fgcolor = _mm_mullo_epi16(fgcolor, alpha); + bgcolor = _mm_mullo_epi16(bgcolor, inv_alpha); + __m128i outcolor = _mm_srli_epi16(_mm_add_epi16(fgcolor, bgcolor), 8); + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); + return outcolor; + } + else if (BlendT::Mode == (int)BlendModes::AddClampShaded) + { + ifgshade0 = (ifgshade0 * srcalpha + 128) >> 8; + ifgshade1 = (ifgshade1 * srcalpha + 128) >> 8; + __m128i alpha = _mm_set_epi16(ifgshade1, ifgshade1, ifgshade1, ifgshade1, ifgshade0, ifgshade0, ifgshade0, ifgshade0); + + fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, alpha), 8); + __m128i outcolor = _mm_add_epi16(fgcolor, bgcolor); + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); + return outcolor; + } + else + { + uint32_t alpha0 = APART(ifgcolor0); + uint32_t alpha1 = APART(ifgcolor1); + alpha0 += alpha0 >> 7; // 255->256 + alpha1 += alpha1 >> 7; // 255->256 + uint32_t inv_alpha0 = 256 - alpha0; + uint32_t inv_alpha1 = 256 - alpha1; + + uint32_t bgalpha0 = (destalpha * alpha0 + (inv_alpha0 << 8) + 128) >> 8; + uint32_t bgalpha1 = (destalpha * alpha1 + (inv_alpha1 << 8) + 128) >> 8; + uint32_t fgalpha0 = (srcalpha * alpha0 + 128) >> 8; + uint32_t fgalpha1 = (srcalpha * alpha1 + 128) >> 8; + + __m128i bgalpha = _mm_set_epi16(bgalpha1, bgalpha1, bgalpha1, bgalpha1, bgalpha0, bgalpha0, bgalpha0, bgalpha0); + __m128i fgalpha = _mm_set_epi16(fgalpha1, fgalpha1, fgalpha1, fgalpha1, fgalpha0, fgalpha0, fgalpha0, fgalpha0); + + fgcolor = _mm_mullo_epi16(fgcolor, fgalpha); + bgcolor = _mm_mullo_epi16(bgcolor, bgalpha); + + __m128i fg_lo = _mm_unpacklo_epi16(fgcolor, _mm_setzero_si128()); + __m128i bg_lo = _mm_unpacklo_epi16(bgcolor, _mm_setzero_si128()); + __m128i fg_hi = _mm_unpackhi_epi16(fgcolor, _mm_setzero_si128()); + __m128i bg_hi = _mm_unpackhi_epi16(bgcolor, _mm_setzero_si128()); + + __m128i out_lo, out_hi; + if (BlendT::Mode == (int)BlendModes::AddClamp) + { + out_lo = _mm_add_epi32(fg_lo, bg_lo); + out_hi = _mm_add_epi32(fg_hi, bg_hi); + } + else if (BlendT::Mode == (int)BlendModes::SubClamp) + { + out_lo = _mm_sub_epi32(fg_lo, bg_lo); + out_hi = _mm_sub_epi32(fg_hi, bg_hi); + } + else if (BlendT::Mode == (int)BlendModes::RevSubClamp) + { + out_lo = _mm_sub_epi32(bg_lo, fg_lo); + out_hi = _mm_sub_epi32(bg_hi, fg_hi); + } + + out_lo = _mm_srai_epi32(out_lo, 8); + out_hi = _mm_srai_epi32(out_hi, 8); + __m128i outcolor = _mm_packs_epi32(out_lo, out_hi); + outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); + outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); + return outcolor; + } + } +} + template class TriScreenDrawer32 { @@ -66,6 +306,7 @@ public: } } +private: template FORCEINLINE static void VECTORCALL Loop(const TriDrawTriangleArgs *args, WorkerThreadData *thread) { @@ -198,13 +439,13 @@ public: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; - ifgcolor[0] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); posU += stepU; posV += stepV; - ifgcolor[1] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + ifgcolor[1] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); posU += stepU; posV += stepV; @@ -228,8 +469,8 @@ public: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); - __m128i outcolor = Blend(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result _mm_storel_epi64((__m128i*)(dest + x * 8 + ix * 2), outcolor); @@ -298,13 +539,13 @@ public: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; - ifgcolor[0] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); posU += stepU; posV += stepV; - ifgcolor[1] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + ifgcolor[1] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); posU += stepU; posV += stepV; @@ -328,8 +569,8 @@ public: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); - __m128i outcolor = Blend(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result _mm_storel_epi64((__m128i*)desttmp, outcolor); @@ -387,13 +628,13 @@ public: // Sample fgcolor unsigned int ifgcolor[2], ifgshade[2]; - ifgcolor[0] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[0] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); posU += stepU; posV += stepV; - ifgcolor[1] = Sample(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); - ifgshade[1] = SampleShade(posU, posV, texPixels, texWidth, texHeight); + ifgcolor[1] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); posU += stepU; posV += stepV; @@ -417,8 +658,8 @@ public: // Shade and blend __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); - fgcolor = Shade(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); - __m128i outcolor = Blend(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); // Store result _mm_storel_epi64((__m128i*)desttmp, outcolor); @@ -437,250 +678,6 @@ public: } } -private: - template - FORCEINLINE static unsigned int VECTORCALL Sample(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, uint32_t oneU, uint32_t oneV, uint32_t color, const uint32_t *translation) - { - using namespace TriScreenDrawerModes; - - uint32_t texel; - if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill) - { - return color; - } - else if (SamplerT::Mode == (int)Samplers::Translated) - { - const uint8_t *texpal = (const uint8_t *)texPixels; - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - return translation[texpal[texelX * texHeight + texelY]]; - } - else if (FilterModeT::Mode == (int)FilterModes::Nearest) - { - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - texel = texPixels[texelX * texHeight + texelY]; - } - else - { - u -= oneU >> 1; - v -= oneV >> 1; - - unsigned int frac_x0 = (((uint32_t)u << 8) >> FRACBITS) * texWidth; - unsigned int frac_x1 = ((((uint32_t)u << 8) + oneU) >> FRACBITS) * texWidth; - unsigned int frac_y0 = (((uint32_t)v << 8) >> FRACBITS) * texHeight; - unsigned int frac_y1 = ((((uint32_t)v << 8) + oneV) >> FRACBITS) * texHeight; - unsigned int x0 = frac_x0 >> FRACBITS; - unsigned int x1 = frac_x1 >> FRACBITS; - unsigned int y0 = frac_y0 >> FRACBITS; - unsigned int y1 = frac_y1 >> FRACBITS; - - unsigned int p00 = texPixels[x0 * texHeight + y0]; - unsigned int p01 = texPixels[x0 * texHeight + y1]; - unsigned int p10 = texPixels[x1 * texHeight + y0]; - unsigned int p11 = texPixels[x1 * texHeight + y1]; - - unsigned int inv_a = (frac_x1 >> (FRACBITS - 4)) & 15; - unsigned int inv_b = (frac_y1 >> (FRACBITS - 4)) & 15; - unsigned int a = 16 - inv_a; - unsigned int b = 16 - inv_b; - - unsigned int sred = (RPART(p00) * (a * b) + RPART(p01) * (inv_a * b) + RPART(p10) * (a * inv_b) + RPART(p11) * (inv_a * inv_b) + 127) >> 8; - unsigned int sgreen = (GPART(p00) * (a * b) + GPART(p01) * (inv_a * b) + GPART(p10) * (a * inv_b) + GPART(p11) * (inv_a * inv_b) + 127) >> 8; - unsigned int sblue = (BPART(p00) * (a * b) + BPART(p01) * (inv_a * b) + BPART(p10) * (a * inv_b) + BPART(p11) * (inv_a * inv_b) + 127) >> 8; - unsigned int salpha = (APART(p00) * (a * b) + APART(p01) * (inv_a * b) + APART(p10) * (a * inv_b) + APART(p11) * (inv_a * inv_b) + 127) >> 8; - - texel = (salpha << 24) | (sred << 16) | (sgreen << 8) | sblue; - } - - if (SamplerT::Mode == (int)Samplers::Skycap) - { - int start_fade = 2; // How fast it should fade out - - int alpha_top = clamp(v >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - uint32_t r = RPART(texel); - uint32_t g = GPART(texel); - uint32_t b = BPART(texel); - uint32_t fg_a = APART(texel); - uint32_t bg_red = RPART(color); - uint32_t bg_green = GPART(color); - uint32_t bg_blue = BPART(color); - r = (r * a + bg_red * inv_a + 127) >> 8; - g = (g * a + bg_green * inv_a + 127) >> 8; - b = (b * a + bg_blue * inv_a + 127) >> 8; - return MAKEARGB(fg_a, r, g, b); - } - else - { - return texel; - } - } - - FORCEINLINE static unsigned int VECTORCALL SampleShade(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight) - { - using namespace TriScreenDrawerModes; - - if (SamplerT::Mode == (int)Samplers::Shaded) - { - const uint8_t *texpal = (const uint8_t *)texPixels; - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - unsigned int sampleshadeout = texpal[texelX * texHeight + texelY]; - sampleshadeout += sampleshadeout >> 7; // 255 -> 256 - return sampleshadeout; - } - else if (SamplerT::Mode == (int)Samplers::Stencil) - { - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]); - sampleshadeout += sampleshadeout >> 7; // 255 -> 256 - return sampleshadeout; - } - else - { - return 0; - } - } - - template - FORCEINLINE static __m128i VECTORCALL Shade(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light) - { - using namespace TriScreenDrawerModes; - - if (ShadeModeT::Mode == (int)ShadeMode::Simple) - { - fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, mlight), 8); - } - else - { - int blue0 = BPART(ifgcolor0); - int green0 = GPART(ifgcolor0); - int red0 = RPART(ifgcolor0); - int intensity0 = ((red0 * 77 + green0 * 143 + blue0 * 37) >> 8) * desaturate; - - int blue1 = BPART(ifgcolor1); - int green1 = GPART(ifgcolor1); - int red1 = RPART(ifgcolor1); - int intensity1 = ((red1 * 77 + green1 * 143 + blue1 * 37) >> 8) * desaturate; - - __m128i intensity = _mm_set_epi16(0, intensity1, intensity1, intensity1, 0, intensity0, intensity0, intensity0); - - fgcolor = _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(fgcolor, inv_desaturate), intensity), 8); - fgcolor = _mm_mullo_epi16(fgcolor, mlight); - fgcolor = _mm_srli_epi16(_mm_add_epi16(shade_fade, fgcolor), 8); - fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, shade_light), 8); - } - return fgcolor; - } - - FORCEINLINE static __m128i VECTORCALL Blend(__m128i fgcolor, __m128i bgcolor, unsigned int ifgcolor0, unsigned int ifgcolor1, unsigned int ifgshade0, unsigned int ifgshade1, uint32_t srcalpha, uint32_t destalpha) - { - using namespace TriScreenDrawerModes; - - if (BlendT::Mode == (int)BlendModes::Opaque) - { - __m128i outcolor = fgcolor; - outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); - return outcolor; - } - else if (BlendT::Mode == (int)BlendModes::Masked) - { - __m128i mask = _mm_cmpeq_epi32(_mm_packus_epi16(fgcolor, _mm_setzero_si128()), _mm_setzero_si128()); - mask = _mm_unpacklo_epi8(mask, _mm_setzero_si128()); - __m128i outcolor = _mm_or_si128(_mm_and_si128(mask, bgcolor), _mm_andnot_si128(mask, fgcolor)); - outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); - outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); - return outcolor; - } - else if (BlendT::Mode == (int)BlendModes::AddSrcColorOneMinusSrcColor) - { - __m128i inv_srccolor = _mm_sub_epi16(_mm_set1_epi16(256), _mm_add_epi16(fgcolor, _mm_srli_epi16(fgcolor, 7))); - __m128i outcolor = _mm_add_epi16(fgcolor, _mm_srli_epi16(_mm_mullo_epi16(bgcolor, inv_srccolor), 8)); - outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); - return outcolor; - } - else if (BlendT::Mode == (int)BlendModes::Shaded) - { - ifgshade0 = (ifgshade0 * srcalpha + 128) >> 8; - ifgshade1 = (ifgshade1 * srcalpha + 128) >> 8; - __m128i alpha = _mm_set_epi16(ifgshade1, ifgshade1, ifgshade1, ifgshade1, ifgshade0, ifgshade0, ifgshade0, ifgshade0); - __m128i inv_alpha = _mm_sub_epi16(_mm_set1_epi16(256), alpha); - - fgcolor = _mm_mullo_epi16(fgcolor, alpha); - bgcolor = _mm_mullo_epi16(bgcolor, inv_alpha); - __m128i outcolor = _mm_srli_epi16(_mm_add_epi16(fgcolor, bgcolor), 8); - outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); - outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); - return outcolor; - } - else if (BlendT::Mode == (int)BlendModes::AddClampShaded) - { - ifgshade0 = (ifgshade0 * srcalpha + 128) >> 8; - ifgshade1 = (ifgshade1 * srcalpha + 128) >> 8; - __m128i alpha = _mm_set_epi16(ifgshade1, ifgshade1, ifgshade1, ifgshade1, ifgshade0, ifgshade0, ifgshade0, ifgshade0); - - fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, alpha), 8); - __m128i outcolor = _mm_add_epi16(fgcolor, bgcolor); - outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); - outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); - return outcolor; - } - else - { - uint32_t alpha0 = APART(ifgcolor0); - uint32_t alpha1 = APART(ifgcolor1); - alpha0 += alpha0 >> 7; // 255->256 - alpha1 += alpha1 >> 7; // 255->256 - uint32_t inv_alpha0 = 256 - alpha0; - uint32_t inv_alpha1 = 256 - alpha1; - - uint32_t bgalpha0 = (destalpha * alpha0 + (inv_alpha0 << 8) + 128) >> 8; - uint32_t bgalpha1 = (destalpha * alpha1 + (inv_alpha1 << 8) + 128) >> 8; - uint32_t fgalpha0 = (srcalpha * alpha0 + 128) >> 8; - uint32_t fgalpha1 = (srcalpha * alpha1 + 128) >> 8; - - __m128i bgalpha = _mm_set_epi16(bgalpha1, bgalpha1, bgalpha1, bgalpha1, bgalpha0, bgalpha0, bgalpha0, bgalpha0); - __m128i fgalpha = _mm_set_epi16(fgalpha1, fgalpha1, fgalpha1, fgalpha1, fgalpha0, fgalpha0, fgalpha0, fgalpha0); - - fgcolor = _mm_mullo_epi16(fgcolor, fgalpha); - bgcolor = _mm_mullo_epi16(bgcolor, bgalpha); - - __m128i fg_lo = _mm_unpacklo_epi16(fgcolor, _mm_setzero_si128()); - __m128i bg_lo = _mm_unpacklo_epi16(bgcolor, _mm_setzero_si128()); - __m128i fg_hi = _mm_unpackhi_epi16(fgcolor, _mm_setzero_si128()); - __m128i bg_hi = _mm_unpackhi_epi16(bgcolor, _mm_setzero_si128()); - - __m128i out_lo, out_hi; - if (BlendT::Mode == (int)BlendModes::AddClamp) - { - out_lo = _mm_add_epi32(fg_lo, bg_lo); - out_hi = _mm_add_epi32(fg_hi, bg_hi); - } - else if (BlendT::Mode == (int)BlendModes::SubClamp) - { - out_lo = _mm_sub_epi32(fg_lo, bg_lo); - out_hi = _mm_sub_epi32(fg_hi, bg_hi); - } - else if (BlendT::Mode == (int)BlendModes::RevSubClamp) - { - out_lo = _mm_sub_epi32(bg_lo, fg_lo); - out_hi = _mm_sub_epi32(bg_hi, fg_hi); - } - - out_lo = _mm_srai_epi32(out_lo, 8); - out_hi = _mm_srai_epi32(out_hi, 8); - __m128i outcolor = _mm_packs_epi32(out_lo, out_hi); - outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128()); - outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000)); - return outcolor; - } - } - static float FindGradientX(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) { float top = (c1 - c2) * (y0 - y2) - (c0 - c2) * (y1 - y2); @@ -695,3 +692,168 @@ private: return top / bottom; } }; + +template +class RectScreenDrawer32 +{ +public: + static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread) + { + using namespace TriScreenDrawerModes; + + if (args->SimpleShade()) + { + Loop(destOrg, destWidth, destHeight, destPitch, args, thread); + } + else + { + Loop(destOrg, destWidth, destHeight, destPitch, args, thread); + } + } + +private: + template + FORCEINLINE static void VECTORCALL Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread) + { + using namespace TriScreenDrawerModes; + + int x0 = clamp((int)(args->X0() + 0.5f), 0, destWidth); + int x1 = clamp((int)(args->X1() + 0.5f), 0, destWidth); + int y0 = clamp((int)(args->Y0() + 0.5f), 0, destHeight); + int y1 = clamp((int)(args->Y1() + 0.5f), 0, destHeight); + + if (x1 <= x0 || y1 <= y0) + return; + + uint32_t srcalpha = args->SrcAlpha(); + uint32_t destalpha = args->DestAlpha(); + + // Setup step variables + float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0()); + float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0()); + uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000); + uint32_t startV = (int32_t)((args->V0() + (y0 + 0.5f - args->Y0()) * fstepV) * 0x1000000); + uint32_t stepU = (int32_t)(fstepU * 0x1000000); + uint32_t stepV = (int32_t)(fstepV * 0x1000000); + + // Sampling stuff + uint32_t color = args->Color(); + const uint32_t * RESTRICT translation = (const uint32_t *)args->Translation(); + const uint32_t * RESTRICT texPixels = (const uint32_t *)args->TexturePixels(); + uint32_t texWidth = args->TextureWidth(); + uint32_t texHeight = args->TextureHeight(); + uint32_t oneU, oneV; + if (SamplerT::Mode != (int)Samplers::Fill) + { + oneU = ((0x800000 + texWidth - 1) / texWidth) * 2 + 1; + oneV = ((0x800000 + texHeight - 1) / texHeight) * 2 + 1; + } + else + { + oneU = 0; + oneV = 0; + } + + // Shade constants + __m128i inv_desaturate, shade_fade, shade_light; + int desaturate; + if (ShadeModeT::Mode == (int)ShadeMode::Advanced) + { + inv_desaturate = _mm_setr_epi16(256, 256 - args->ShadeDesaturate(), 256 - args->ShadeDesaturate(), 256 - args->ShadeDesaturate(), 256, 256 - args->ShadeDesaturate(), 256 - args->ShadeDesaturate(), 256 - args->ShadeDesaturate()); + shade_fade = _mm_set_epi16(args->ShadeFadeAlpha(), args->ShadeFadeRed(), args->ShadeFadeGreen(), args->ShadeFadeBlue(), args->ShadeFadeAlpha(), args->ShadeFadeRed(), args->ShadeFadeGreen(), args->ShadeFadeBlue()); + shade_light = _mm_set_epi16(args->ShadeLightAlpha(), args->ShadeLightRed(), args->ShadeLightGreen(), args->ShadeLightBlue(), args->ShadeLightAlpha(), args->ShadeLightRed(), args->ShadeLightGreen(), args->ShadeLightBlue()); + desaturate = args->ShadeDesaturate(); + } + else + { + inv_desaturate = _mm_setzero_si128(); + shade_fade = _mm_setzero_si128(); + shade_light = _mm_setzero_si128(); + desaturate = 0; + } + + // Setup light + uint32_t lightpos = args->Light(); + lightpos += lightpos >> 7; // 255 -> 256 + __m128i mlight = _mm_set_epi16(256, lightpos, lightpos, lightpos, 256, lightpos, lightpos, lightpos); + __m128i shade_fade_lit; + if (ShadeModeT::Mode == (int)ShadeMode::Advanced) + { + __m128i inv_light = _mm_sub_epi16(_mm_set_epi16(0, 256, 256, 256, 0, 256, 256, 256), mlight); + shade_fade_lit = _mm_mullo_epi16(shade_fade, inv_light); + } + else + { + shade_fade_lit = _mm_setzero_si128(); + } + + int count = x1 - x0; + int sseCount = count / 2; + + uint32_t posV = startV; + for (int y = y0; y < y1; y++, posV += stepV) + { + int coreBlock = y / 8; + if (coreBlock % thread->num_cores != thread->core) + continue; + + uint32_t *dest = ((uint32_t*)destOrg) + y * destPitch + x0; + + uint32_t posU = startU; + for (int i = 0; i < sseCount; i++) + { + // Load bgcolor + __m128i bgcolor; + if (BlendT::Mode != (int)BlendModes::Opaque) + bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)dest), _mm_setzero_si128()); + else + bgcolor = _mm_setzero_si128(); + + // Sample fgcolor + unsigned int ifgcolor[2], ifgshade[2]; + ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + posU += stepU; + + ifgcolor[1] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[1] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + posU += stepU; + + // Shade and blend + __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); + + // Store result + _mm_storel_epi64((__m128i*)dest, outcolor); + dest += 2; + } + + if (sseCount * 2 != count) + { + // Load bgcolor + __m128i bgcolor; + if (BlendT::Mode != (int)BlendModes::Opaque) + bgcolor = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*dest), _mm_setzero_si128()); + else + bgcolor = _mm_setzero_si128(); + + // Sample fgcolor + unsigned int ifgcolor[2], ifgshade[2]; + ifgcolor[0] = Sample32(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation); + ifgshade[0] = SampleShade32(posU, posV, texPixels, texWidth, texHeight); + ifgcolor[1] = 0; + ifgshade[1] = 0; + posU += stepU; + + // Shade and blend + __m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128()); + fgcolor = Shade32(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light); + __m128i outcolor = Blend32(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha); + + // Store result + *dest = _mm_cvtsi128_si32(outcolor); + } + } + } +}; diff --git a/src/polyrenderer/drawers/poly_drawer8.h b/src/polyrenderer/drawers/poly_drawer8.h index 2f5669901..c6f98bd09 100644 --- a/src/polyrenderer/drawers/poly_drawer8.h +++ b/src/polyrenderer/drawers/poly_drawer8.h @@ -24,6 +24,187 @@ #include "screen_triangle.h" +namespace TriScreenDrawerModes +{ + template + FORCEINLINE unsigned int Sample8(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight, uint32_t color, const uint8_t *translation) + { + uint8_t texel; + if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill) + { + return color; + } + else if (SamplerT::Mode == (int)Samplers::Translated) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + return translation[texPixels[texelX * texHeight + texelY]]; + } + else + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + texel = texPixels[texelX * texHeight + texelY]; + } + + if (SamplerT::Mode == (int)Samplers::Skycap) + { + int start_fade = 2; // How fast it should fade out + + int alpha_top = clamp(v >> (16 - start_fade), 0, 256); + int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); + int a = MIN(alpha_top, alpha_bottom); + int inv_a = 256 - a; + + if (a == 256) + return texel; + + uint32_t capcolor = GPalette.BaseColors[color].d; + uint32_t texelrgb = GPalette.BaseColors[texel].d; + uint32_t r = RPART(texelrgb); + uint32_t g = GPART(texelrgb); + uint32_t b = BPART(texelrgb); + uint32_t capcolor_red = RPART(capcolor); + uint32_t capcolor_green = GPART(capcolor); + uint32_t capcolor_blue = BPART(capcolor); + r = (r * a + capcolor_red * inv_a + 127) >> 8; + g = (g * a + capcolor_green * inv_a + 127) >> 8; + b = (b * a + capcolor_blue * inv_a + 127) >> 8; + return RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)]; + } + else + { + return texel; + } + } + + template + FORCEINLINE unsigned int SampleShade8(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight) + { + if (SamplerT::Mode == (int)Samplers::Shaded) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + unsigned int sampleshadeout = texPixels[texelX * texHeight + texelY]; + sampleshadeout += sampleshadeout >> 7; // 255 -> 256 + return sampleshadeout; + } + else if (SamplerT::Mode == (int)Samplers::Stencil) + { + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + return texPixels[texelX * texHeight + texelY] != 0 ? 256 : 0; + } + else + { + return 0; + } + } + + template + FORCEINLINE uint8_t ShadeAndBlend8(uint8_t fgcolor, uint8_t bgcolor, uint32_t fgshade, uint32_t lightshade, const uint8_t *colormaps, uint32_t srcalpha, uint32_t destalpha) + { + lightshade = ((256 - lightshade) * NUMCOLORMAPS) & 0xffffff00; + uint8_t shadedfg = colormaps[lightshade + fgcolor]; + + if (BlendT::Mode == (int)BlendModes::Opaque) + { + return shadedfg; + } + else if (BlendT::Mode == (int)BlendModes::Masked) + { + return (fgcolor != 0) ? shadedfg : bgcolor; + } + else if (BlendT::Mode == (int)BlendModes::AddSrcColorOneMinusSrcColor) + { + int32_t fg_r = GPalette.BaseColors[shadedfg].r; + int32_t fg_g = GPalette.BaseColors[shadedfg].g; + int32_t fg_b = GPalette.BaseColors[shadedfg].b; + int32_t bg_r = GPalette.BaseColors[bgcolor].r; + int32_t bg_g = GPalette.BaseColors[bgcolor].g; + int32_t bg_b = GPalette.BaseColors[bgcolor].b; + int32_t inv_fg_r = 256 - (fg_r + (fg_r >> 7)); + int32_t inv_fg_g = 256 - (fg_g + (fg_g >> 7)); + int32_t inv_fg_b = 256 - (fg_b + (fg_b >> 7)); + fg_r = MIN(fg_r + ((bg_r * inv_fg_r + 127) >> 8), 255); + fg_g = MIN(fg_g + ((bg_g * inv_fg_g + 127) >> 8), 255); + fg_b = MIN(fg_b + ((bg_b * inv_fg_b + 127) >> 8), 255); + + shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)]; + return (fgcolor != 0) ? shadedfg : bgcolor; + } + else if (BlendT::Mode == (int)BlendModes::Shaded) + { + fgshade = (fgshade * srcalpha + 128) >> 8; + uint32_t alpha = fgshade; + uint32_t inv_alpha = 256 - fgshade; + int32_t fg_r = GPalette.BaseColors[shadedfg].r; + int32_t fg_g = GPalette.BaseColors[shadedfg].g; + int32_t fg_b = GPalette.BaseColors[shadedfg].b; + int32_t bg_r = GPalette.BaseColors[bgcolor].r; + int32_t bg_g = GPalette.BaseColors[bgcolor].g; + int32_t bg_b = GPalette.BaseColors[bgcolor].b; + + fg_r = (fg_r * alpha + bg_r * inv_alpha + 127) >> 8; + fg_g = (fg_g * alpha + bg_g * inv_alpha + 127) >> 8; + fg_b = (fg_b * alpha + bg_b * inv_alpha + 127) >> 8; + + shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)]; + return (alpha != 0) ? shadedfg : bgcolor; + } + else if (BlendT::Mode == (int)BlendModes::AddClampShaded) + { + fgshade = (fgshade * srcalpha + 128) >> 8; + uint32_t alpha = fgshade; + int32_t fg_r = GPalette.BaseColors[shadedfg].r; + int32_t fg_g = GPalette.BaseColors[shadedfg].g; + int32_t fg_b = GPalette.BaseColors[shadedfg].b; + int32_t bg_r = GPalette.BaseColors[bgcolor].r; + int32_t bg_g = GPalette.BaseColors[bgcolor].g; + int32_t bg_b = GPalette.BaseColors[bgcolor].b; + + fg_r = MIN(bg_r + ((fg_r * alpha + 127) >> 8), 255); + fg_g = MIN(bg_g + ((fg_g * alpha + 127) >> 8), 255); + fg_b = MIN(bg_b + ((fg_b * alpha + 127) >> 8), 255); + + shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)]; + + return (alpha != 0) ? shadedfg : bgcolor; + } + else + { + int32_t fg_r = GPalette.BaseColors[shadedfg].r; + int32_t fg_g = GPalette.BaseColors[shadedfg].g; + int32_t fg_b = GPalette.BaseColors[shadedfg].b; + int32_t bg_r = GPalette.BaseColors[bgcolor].r; + int32_t bg_g = GPalette.BaseColors[bgcolor].g; + int32_t bg_b = GPalette.BaseColors[bgcolor].b; + + if (BlendT::Mode == (int)BlendModes::AddClamp) + { + fg_r = MIN(int32_t(fg_r * srcalpha + bg_r * destalpha + 127) >> 8, 255); + fg_g = MIN(int32_t(fg_g * srcalpha + bg_g * destalpha + 127) >> 8, 255); + fg_b = MIN(int32_t(fg_b * srcalpha + bg_b * destalpha + 127) >> 8, 255); + } + else if (BlendT::Mode == (int)BlendModes::SubClamp) + { + fg_r = MAX(int32_t(fg_r * srcalpha - bg_r * destalpha + 127) >> 8, 0); + fg_g = MAX(int32_t(fg_g * srcalpha - bg_g * destalpha + 127) >> 8, 0); + fg_b = MAX(int32_t(fg_b * srcalpha - bg_b * destalpha + 127) >> 8, 0); + } + else if (BlendT::Mode == (int)BlendModes::RevSubClamp) + { + fg_r = MAX(int32_t(bg_r * srcalpha - fg_r * destalpha + 127) >> 8, 0); + fg_g = MAX(int32_t(bg_g * srcalpha - fg_g * destalpha + 127) >> 8, 0); + fg_b = MAX(int32_t(bg_b * srcalpha - fg_b * destalpha + 127) >> 8, 0); + } + + shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)]; + return (fgcolor != 0) ? shadedfg : bgcolor; + } + } +} + template class TriScreenDrawer8 { @@ -123,9 +304,9 @@ public: { int lightshade = lightpos >> 8; uint8_t bgcolor = dest[x * 8 + ix]; - uint8_t fgcolor = Sample(posU, posV, texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade(posU, posV, texPixels, texWidth, texHeight); - dest[x * 8 + ix] = ShadeAndBlend(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); + uint8_t fgcolor = Sample8(posU, posV, texPixels, texWidth, texHeight, color, translation); + uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight); + dest[x * 8 + ix] = ShadeAndBlend8(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); posU += stepU; posV += stepV; lightpos += lightstep; @@ -185,9 +366,9 @@ public: { int lightshade = lightpos >> 8; uint8_t bgcolor = dest[x]; - uint8_t fgcolor = Sample(posU, posV, texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade(posU, posV, texPixels, texWidth, texHeight); - dest[x] = ShadeAndBlend(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); + uint8_t fgcolor = Sample8(posU, posV, texPixels, texWidth, texHeight, color, translation); + uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight); + dest[x] = ShadeAndBlend8(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); } posU += stepU; @@ -236,9 +417,9 @@ public: { int lightshade = lightpos >> 8; uint8_t bgcolor = dest[x]; - uint8_t fgcolor = Sample(posU, posV, texPixels, texWidth, texHeight, color, translation); - uint32_t fgshade = SampleShade(posU, posV, texPixels, texWidth, texHeight); - dest[x] = ShadeAndBlend(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); + uint8_t fgcolor = Sample8(posU, posV, texPixels, texWidth, texHeight, color, translation); + uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight); + dest[x] = ShadeAndBlend8(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); } posU += stepU; @@ -258,187 +439,6 @@ public: } private: - FORCEINLINE static unsigned int Sample(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight, uint32_t color, const uint8_t *translation) - { - using namespace TriScreenDrawerModes; - - uint8_t texel; - if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill) - { - return color; - } - else if (SamplerT::Mode == (int)Samplers::Translated) - { - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - return translation[texPixels[texelX * texHeight + texelY]]; - } - else - { - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - texel = texPixels[texelX * texHeight + texelY]; - } - - if (SamplerT::Mode == (int)Samplers::Skycap) - { - int start_fade = 2; // How fast it should fade out - - int alpha_top = clamp(v >> (16 - start_fade), 0, 256); - int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); - int a = MIN(alpha_top, alpha_bottom); - int inv_a = 256 - a; - - if (a == 256) - return texel; - - uint32_t capcolor = GPalette.BaseColors[color].d; - uint32_t texelrgb = GPalette.BaseColors[texel].d; - uint32_t r = RPART(texelrgb); - uint32_t g = GPART(texelrgb); - uint32_t b = BPART(texelrgb); - uint32_t capcolor_red = RPART(capcolor); - uint32_t capcolor_green = GPART(capcolor); - uint32_t capcolor_blue = BPART(capcolor); - r = (r * a + capcolor_red * inv_a + 127) >> 8; - g = (g * a + capcolor_green * inv_a + 127) >> 8; - b = (b * a + capcolor_blue * inv_a + 127) >> 8; - return RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)]; - } - else - { - return texel; - } - } - - FORCEINLINE static unsigned int SampleShade(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight) - { - using namespace TriScreenDrawerModes; - - if (SamplerT::Mode == (int)Samplers::Shaded) - { - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - unsigned int sampleshadeout = texPixels[texelX * texHeight + texelY]; - sampleshadeout += sampleshadeout >> 7; // 255 -> 256 - return sampleshadeout; - } - else if (SamplerT::Mode == (int)Samplers::Stencil) - { - uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; - return texPixels[texelX * texHeight + texelY] != 0 ? 256 : 0; - } - else - { - return 0; - } - } - - FORCEINLINE static uint8_t ShadeAndBlend(uint8_t fgcolor, uint8_t bgcolor, uint32_t fgshade, uint32_t lightshade, const uint8_t *colormaps, uint32_t srcalpha, uint32_t destalpha) - { - using namespace TriScreenDrawerModes; - - lightshade = ((256 - lightshade) * NUMCOLORMAPS) & 0xffffff00; - uint8_t shadedfg = colormaps[lightshade + fgcolor]; - - if (BlendT::Mode == (int)BlendModes::Opaque) - { - return shadedfg; - } - else if (BlendT::Mode == (int)BlendModes::Masked) - { - return (fgcolor != 0) ? shadedfg : bgcolor; - } - else if (BlendT::Mode == (int)BlendModes::AddSrcColorOneMinusSrcColor) - { - int32_t fg_r = GPalette.BaseColors[shadedfg].r; - int32_t fg_g = GPalette.BaseColors[shadedfg].g; - int32_t fg_b = GPalette.BaseColors[shadedfg].b; - int32_t bg_r = GPalette.BaseColors[bgcolor].r; - int32_t bg_g = GPalette.BaseColors[bgcolor].g; - int32_t bg_b = GPalette.BaseColors[bgcolor].b; - int32_t inv_fg_r = 256 - (fg_r + (fg_r >> 7)); - int32_t inv_fg_g = 256 - (fg_g + (fg_g >> 7)); - int32_t inv_fg_b = 256 - (fg_b + (fg_b >> 7)); - fg_r = MIN(fg_r + ((bg_r * inv_fg_r + 127) >> 8), 255); - fg_g = MIN(fg_g + ((bg_g * inv_fg_g + 127) >> 8), 255); - fg_b = MIN(fg_b + ((bg_b * inv_fg_b + 127) >> 8), 255); - - shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)]; - return (fgcolor != 0) ? shadedfg : bgcolor; - } - else if (BlendT::Mode == (int)BlendModes::Shaded) - { - fgshade = (fgshade * srcalpha + 128) >> 8; - uint32_t alpha = fgshade; - uint32_t inv_alpha = 256 - fgshade; - int32_t fg_r = GPalette.BaseColors[shadedfg].r; - int32_t fg_g = GPalette.BaseColors[shadedfg].g; - int32_t fg_b = GPalette.BaseColors[shadedfg].b; - int32_t bg_r = GPalette.BaseColors[bgcolor].r; - int32_t bg_g = GPalette.BaseColors[bgcolor].g; - int32_t bg_b = GPalette.BaseColors[bgcolor].b; - - fg_r = (fg_r * alpha + bg_r * inv_alpha + 127) >> 8; - fg_g = (fg_g * alpha + bg_g * inv_alpha + 127) >> 8; - fg_b = (fg_b * alpha + bg_b * inv_alpha + 127) >> 8; - - shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)]; - return (alpha != 0) ? shadedfg : bgcolor; - } - else if (BlendT::Mode == (int)BlendModes::AddClampShaded) - { - fgshade = (fgshade * srcalpha + 128) >> 8; - uint32_t alpha = fgshade; - int32_t fg_r = GPalette.BaseColors[shadedfg].r; - int32_t fg_g = GPalette.BaseColors[shadedfg].g; - int32_t fg_b = GPalette.BaseColors[shadedfg].b; - int32_t bg_r = GPalette.BaseColors[bgcolor].r; - int32_t bg_g = GPalette.BaseColors[bgcolor].g; - int32_t bg_b = GPalette.BaseColors[bgcolor].b; - - fg_r = MIN(bg_r + ((fg_r * alpha + 127) >> 8), 255); - fg_g = MIN(bg_g + ((fg_g * alpha + 127) >> 8), 255); - fg_b = MIN(bg_b + ((fg_b * alpha + 127) >> 8), 255); - - shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)]; - - return (alpha != 0) ? shadedfg : bgcolor; - } - else - { - int32_t fg_r = GPalette.BaseColors[shadedfg].r; - int32_t fg_g = GPalette.BaseColors[shadedfg].g; - int32_t fg_b = GPalette.BaseColors[shadedfg].b; - int32_t bg_r = GPalette.BaseColors[bgcolor].r; - int32_t bg_g = GPalette.BaseColors[bgcolor].g; - int32_t bg_b = GPalette.BaseColors[bgcolor].b; - - if (BlendT::Mode == (int)BlendModes::AddClamp) - { - fg_r = MIN(int32_t(fg_r * srcalpha + bg_r * destalpha + 127) >> 8, 255); - fg_g = MIN(int32_t(fg_g * srcalpha + bg_g * destalpha + 127) >> 8, 255); - fg_b = MIN(int32_t(fg_b * srcalpha + bg_b * destalpha + 127) >> 8, 255); - } - else if (BlendT::Mode == (int)BlendModes::SubClamp) - { - fg_r = MAX(int32_t(fg_r * srcalpha - bg_r * destalpha + 127) >> 8, 0); - fg_g = MAX(int32_t(fg_g * srcalpha - bg_g * destalpha + 127) >> 8, 0); - fg_b = MAX(int32_t(fg_b * srcalpha - bg_b * destalpha + 127) >> 8, 0); - } - else if (BlendT::Mode == (int)BlendModes::RevSubClamp) - { - fg_r = MAX(int32_t(bg_r * srcalpha - fg_r * destalpha + 127) >> 8, 0); - fg_g = MAX(int32_t(bg_g * srcalpha - fg_g * destalpha + 127) >> 8, 0); - fg_b = MAX(int32_t(bg_b * srcalpha - fg_b * destalpha + 127) >> 8, 0); - } - - shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)]; - return (fgcolor != 0) ? shadedfg : bgcolor; - } - } - static float FindGradientX(float x0, float y0, float x1, float y1, float x2, float y2, float c0, float c1, float c2) { float top = (c1 - c2) * (y0 - y2) - (c0 - c2) * (y1 - y2); @@ -453,3 +453,68 @@ private: return top / bottom; } }; + +template +class RectScreenDrawer8 +{ +public: + static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread) + { + using namespace TriScreenDrawerModes; + + int x0 = clamp((int)(args->X0() + 0.5f), 0, destWidth); + int x1 = clamp((int)(args->X1() + 0.5f), 0, destWidth); + int y0 = clamp((int)(args->Y0() + 0.5f), 0, destHeight); + int y1 = clamp((int)(args->Y1() + 0.5f), 0, destHeight); + + if (x1 <= x0 || y1 <= y0) + return; + + auto colormaps = args->BaseColormap(); + uint32_t srcalpha = args->SrcAlpha(); + uint32_t destalpha = args->DestAlpha(); + + // Setup step variables + float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0()); + float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0()); + uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000); + uint32_t startV = (int32_t)((args->V0() + (y0 + 0.5f - args->Y0()) * fstepV) * 0x1000000); + uint32_t stepU = (int32_t)(fstepU * 0x1000000); + uint32_t stepV = (int32_t)(fstepV * 0x1000000); + + // Sampling stuff + uint32_t color = args->Color(); + const uint8_t * RESTRICT translation = args->Translation(); + const uint8_t * RESTRICT texPixels = args->TexturePixels(); + uint32_t texWidth = args->TextureWidth(); + uint32_t texHeight = args->TextureHeight(); + + // Setup light + uint32_t lightshade = args->Light(); + lightshade += lightshade >> 7; // 255 -> 256 + + int count = x1 - x0; + + uint32_t posV = startV; + for (int y = y0; y < y1; y++, posV += stepV) + { + int coreBlock = y / 8; + if (coreBlock % thread->num_cores != thread->core) + continue; + + uint8_t *dest = ((uint8_t*)destOrg) + y * destPitch + x0; + + uint32_t posU = startU; + for (int i = 0; i < count; i++) + { + uint8_t bgcolor = *dest; + uint8_t fgcolor = Sample8(posU, posV, texPixels, texWidth, texHeight, color, translation); + uint32_t fgshade = SampleShade8(posU, posV, texPixels, texWidth, texHeight); + *dest = ShadeAndBlend8(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha); + + posU += stepU; + dest++; + } + } + } +}; diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 9df271b24..4bf57e12e 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -449,3 +449,23 @@ void DrawPolyTrianglesCommand::Execute(DrawerThread *thread) PolyTriangleDrawer::draw_arrays(args, &thread_data); } + +///////////////////////////////////////////////////////////////////////////// + +void DrawRectCommand::Execute(DrawerThread *thread) +{ + WorkerThreadData thread_data; + thread_data.core = thread->core; + thread_data.num_cores = thread->num_cores; + + auto renderTarget = PolyRenderer::Instance()->RenderTarget; + const void *destOrg = renderTarget->GetBuffer(); + int destWidth = renderTarget->GetWidth(); + int destHeight = renderTarget->GetHeight(); + int destPitch = renderTarget->GetPitch(); + int blendmode = (int)args.BlendMode(); + if (renderTarget->IsBgra()) + ScreenTriangle::RectDrawers32[blendmode](destOrg, destWidth, destHeight, destPitch, &args, &thread_data); + else + ScreenTriangle::RectDrawers8[blendmode](destOrg, destWidth, destHeight, destPitch, &args, &thread_data); +} diff --git a/src/polyrenderer/drawers/poly_triangle.h b/src/polyrenderer/drawers/poly_triangle.h index d3019fc36..7cd6dbe76 100644 --- a/src/polyrenderer/drawers/poly_triangle.h +++ b/src/polyrenderer/drawers/poly_triangle.h @@ -71,3 +71,15 @@ public: private: PolyDrawArgs args; }; + +class DrawRectCommand : public DrawerCommand +{ +public: + DrawRectCommand(const RectDrawArgs &args) : args(args) { } + + void Execute(DrawerThread *thread) override; + FString DebugInfo() override { return "DrawRect"; } + +private: + RectDrawArgs args; +}; diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index d1fe49513..d61bd79a2 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -922,7 +922,7 @@ void ScreenTriangle::SubsectorWrite(const TriDrawTriangleArgs *args, WorkerThrea } } -std::vector ScreenTriangle::TriDrawers8 = +void(*ScreenTriangle::TriDrawers8[])(const TriDrawTriangleArgs *, WorkerThreadData *) = { &TriScreenDrawer8::Execute, // TextureOpaque &TriScreenDrawer8::Execute, // TextureMasked @@ -950,11 +950,14 @@ std::vector ScreenTria #ifdef NO_SSE -std::vector ScreenTriangle::TriDrawers32; +void(*ScreenTriangle::TriDrawers32[])(const TriDrawTriangleArgs *, WorkerThreadData *) = +{ + nullptr +}; #else -std::vector ScreenTriangle::TriDrawers32 = +void(*ScreenTriangle::TriDrawers32[])(const TriDrawTriangleArgs *, WorkerThreadData *) = { &TriScreenDrawer32::Execute, // TextureOpaque &TriScreenDrawer32::Execute, // TextureMasked @@ -981,3 +984,66 @@ std::vector ScreenTria }; #endif + +void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *) = +{ + &RectScreenDrawer8::Execute, // TextureOpaque + &RectScreenDrawer8::Execute, // TextureMasked + &RectScreenDrawer8::Execute, // TextureAdd + &RectScreenDrawer8::Execute, // TextureSub + &RectScreenDrawer8::Execute, // TextureRevSub + &RectScreenDrawer8::Execute, // TextureAddSrcColor + &RectScreenDrawer8::Execute, // TranslatedOpaque + &RectScreenDrawer8::Execute, // TranslatedMasked + &RectScreenDrawer8::Execute, // TranslatedAdd + &RectScreenDrawer8::Execute, // TranslatedSub + &RectScreenDrawer8::Execute, // TranslatedRevSub + &RectScreenDrawer8::Execute, // TranslatedAddSrcColor + &RectScreenDrawer8::Execute, // Shaded + &RectScreenDrawer8::Execute, // AddShaded + &RectScreenDrawer8::Execute, // Stencil + &RectScreenDrawer8::Execute, // AddStencil + &RectScreenDrawer8::Execute, // FillOpaque + &RectScreenDrawer8::Execute, // FillAdd + &RectScreenDrawer8::Execute, // FillSub + &RectScreenDrawer8::Execute, // FillRevSub + &RectScreenDrawer8::Execute, // FillAddSrcColor + &RectScreenDrawer8::Execute // Skycap +}; + +#ifdef NO_SSE + +void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *) = +{ + nullptr +}; + +#else + +void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *) = +{ + &RectScreenDrawer32::Execute, // TextureOpaque + &RectScreenDrawer32::Execute, // TextureMasked + &RectScreenDrawer32::Execute, // TextureAdd + &RectScreenDrawer32::Execute, // TextureSub + &RectScreenDrawer32::Execute, // TextureRevSub + &RectScreenDrawer32::Execute, // TextureAddSrcColor + &RectScreenDrawer32::Execute, // TranslatedOpaque + &RectScreenDrawer32::Execute, // TranslatedMasked + &RectScreenDrawer32::Execute, // TranslatedAdd + &RectScreenDrawer32::Execute, // TranslatedSub + &RectScreenDrawer32::Execute, // TranslatedRevSub + &RectScreenDrawer32::Execute, // TranslatedAddSrcColor + &RectScreenDrawer32::Execute, // Shaded + &RectScreenDrawer32::Execute, // AddShaded + &RectScreenDrawer32::Execute, // Stencil + &RectScreenDrawer32::Execute, // AddStencil + &RectScreenDrawer32::Execute, // FillOpaque + &RectScreenDrawer32::Execute, // FillAdd + &RectScreenDrawer32::Execute, // FillSub + &RectScreenDrawer32::Execute, // FillRevSub + &RectScreenDrawer32::Execute, // FillAddSrcColor + &RectScreenDrawer32::Execute // Skycap +}; + +#endif diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index 090a398ba..ab1364990 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -85,6 +85,8 @@ struct TriDrawTriangleArgs const PolyDrawArgs *uniforms; }; +class RectDrawArgs; + enum class TriBlendMode { TextureOpaque, @@ -119,8 +121,10 @@ public: static void StencilWrite(const TriDrawTriangleArgs *args, WorkerThreadData *thread); static void SubsectorWrite(const TriDrawTriangleArgs *args, WorkerThreadData *thread); - static std::vector TriDrawers8; - static std::vector TriDrawers32; + static void(*TriDrawers8[])(const TriDrawTriangleArgs *, WorkerThreadData *); + static void(*TriDrawers32[])(const TriDrawTriangleArgs *, WorkerThreadData *); + static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *); + static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *); }; struct ScreenTriangleStepVariables diff --git a/src/polyrenderer/scene/poly_playersprite.cpp b/src/polyrenderer/scene/poly_playersprite.cpp index 9920d2dc9..360af43bc 100644 --- a/src/polyrenderer/scene/poly_playersprite.cpp +++ b/src/polyrenderer/scene/poly_playersprite.cpp @@ -576,52 +576,28 @@ fixed_t RenderPolyPlayerSprites::LightLevelToShade(int lightlevel, bool foggy) void PolyNoAccelPlayerSprite::Render() { -#if 0 if (xscale == 0 || fabs(yscale) < (1.0f / 32000.0f)) { // scaled to 0; can't see return; } - SpriteDrawerArgs drawerargs; - drawerargs.SetLight(Light.BaseColormap, 0, Light.ColormapNum << FRACBITS); - - FDynamicColormap *basecolormap = static_cast(Light.BaseColormap); - - bool visible = drawerargs.SetStyle(RenderStyle, Alpha, Translation, FillColor, basecolormap, Light.ColormapNum << FRACBITS); - if (!visible) - return; - - double spryscale = yscale; - bool sprflipvert = false; - fixed_t iscale = FLOAT2FIXED(1 / yscale); + RectDrawArgs args; + args.SetStyle(RenderStyle, Alpha, FillColor, Translation, pic, false); + args.SetLight(Light.BaseColormap, 255 - (Light.ColormapNum << 3)); double centerY = viewheight / 2; - - double sprtopscreen; + double y1, y2; if (renderflags & RF_YFLIP) { - sprflipvert = true; - spryscale = -spryscale; - iscale = -iscale; - sprtopscreen = centerY + (texturemid - pic->GetHeight()) * spryscale; + y1 = centerY + (texturemid - pic->GetHeight()) * (-yscale); + y2 = y1 + pic->GetHeight() * (-yscale); } else { - sprflipvert = false; - sprtopscreen = centerY - texturemid * spryscale; + y1 = centerY - texturemid * yscale; + y2 = y1 + pic->GetHeight() * yscale; } - - // clip to screen bounds - short *mfloorclip = screenheightarray; - short *mceilingclip = zeroarray; - - fixed_t frac = startfrac; - for (int x = x1; x < x2; x++) - { - drawerargs.DrawMaskedColumn(x, iscale, pic, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, false); - frac += xiscale; - } -#endif + args.Draw(x1, x2, y1, y2, 0.0f, 1.0f, 0.0f, 1.0f); } ///////////////////////////////////////////////////////////////////////////// From cd94d0927a7a877c7ae59b94c110d1cd5079038e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 20:49:06 +0200 Subject: [PATCH 24/29] - fixed a problems with BeginHUD clobbering gST_Y. The code involved is a total mess and needs some cleanup. --- src/g_statusbar/shared_sbar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index fe4028091..240c30fac 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -510,7 +510,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, BeginStatusBar) void DBaseStatusBar::BeginHUD(int resW, int resH, double Alpha, bool forcescaled) { - SetSize(0, resW, resH); // this intentionally resets the relative top to force the caller to go through BeginStatusBar and not just reset some variables. + SetSize(RelTop, resW, resH); this->Alpha = Alpha; ForcedScale = forcescaled; CompleteBorder = false; From 71fe4a83c98e94b010b47edefcb3f7fbfedc969f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 21:18:03 +0200 Subject: [PATCH 25/29] - fixed: the translucent flat drawer used a bad condition for dynamic light processing which caused a problem with the GL 3.x lighting method. --- src/gl/scene/gl_flats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 76c6466ab..0d14378af 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -424,7 +424,7 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); gl_SetPlaneTextureRotation(&plane, gltexture); - DrawSubsectors(pass, !gl.legacyMode, true); + DrawSubsectors(pass, !gl.legacyMode && (gl.lightmethod == LM_DIRECT || dynlightindex > -1), true); gl_RenderState.EnableTextureMatrix(false); } if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); From bdf761e45707881629d570b6d015152bfd7c1d91 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 21:29:14 +0200 Subject: [PATCH 26/29] - moved th player resurrection code into a player_t method. --- src/d_player.h | 1 + src/m_cheat.cpp | 30 +---------------- src/namedef.h | 1 + src/p_user.cpp | 43 +++++++++++++++++++++++++ wadsrc/static/zscript/shared/player.txt | 1 + 5 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index f9da0d120..dc5f6cd54 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -533,6 +533,7 @@ public: // [Nash] set player FOV void SetFOV(float fov); bool HasWeaponsInSlot(int slot) const; + bool Resurrect(); }; // Bookkeeping on players - state. diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 5c8607308..437e7ff89 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -339,35 +339,7 @@ void cht_DoCheat (player_t *player, int cheat) } else { - player->mo->Revive(); - player->playerstate = PST_LIVE; - player->health = player->mo->health = player->mo->GetDefault()->health; - player->viewheight = ((APlayerPawn *)player->mo->GetDefault())->ViewHeight; - player->mo->renderflags &= ~RF_INVISIBLE; - player->mo->Height = player->mo->GetDefault()->Height; - player->mo->radius = player->mo->GetDefault()->radius; - player->mo->special1 = 0; // required for the Hexen fighter's fist attack. - // This gets set by AActor::Die as flag for the wimpy death and must be reset here. - player->mo->SetState (player->mo->SpawnState); - if (!(player->mo->flags2 & MF2_DONTTRANSLATE)) - { - player->mo->Translation = TRANSLATION(TRANSLATION_Players, uint8_t(player-players)); - } - if (player->ReadyWeapon != nullptr) - { - P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetUpState()); - } - - if (player->morphTics) - { - P_UndoPlayerMorph(player, player); - } - - // player is now alive. - // fire E_PlayerRespawned and start the ACS SCRIPT_Respawn. - E_PlayerRespawned(int(player - players)); - // - FBehavior::StaticStartTypedScripts(SCRIPT_Respawn, player->mo, true); + player->Resurrect(); } } diff --git a/src/namedef.h b/src/namedef.h index ca99ff650..a193945de 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -901,3 +901,4 @@ xx(Player5) xx(Player6) xx(Player7) xx(Player8) +xx(PlayerChunk) diff --git a/src/p_user.cpp b/src/p_user.cpp index ae4cfda78..694daffa1 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -62,6 +62,8 @@ #include "g_levellocals.h" #include "actorinlines.h" #include "r_data/r_translate.h" +#include "p_acs.h" +#include "events.h" static FRandom pr_skullpop ("SkullPop"); @@ -725,6 +727,47 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, HasWeaponsInSlot) } +bool player_t::Resurrect() +{ + if (mo == nullptr || mo->IsKindOf(NAME_PlayerChunk)) return false; + mo->Revive(); + playerstate = PST_LIVE; + health = mo->health = mo->GetDefault()->health; + viewheight = ((APlayerPawn *)mo->GetDefault())->ViewHeight; + mo->renderflags &= ~RF_INVISIBLE; + mo->Height = mo->GetDefault()->Height; + mo->radius = mo->GetDefault()->radius; + mo->special1 = 0; // required for the Hexen fighter's fist attack. + // This gets set by AActor::Die as flag for the wimpy death and must be reset here. + mo->SetState(mo->SpawnState); + if (!(mo->flags2 & MF2_DONTTRANSLATE)) + { + mo->Translation = TRANSLATION(TRANSLATION_Players, uint8_t(this - players)); + } + if (ReadyWeapon != nullptr) + { + P_SetPsprite(this, PSP_WEAPON, ReadyWeapon->GetUpState()); + } + + if (morphTics) + { + P_UndoPlayerMorph(this, this); + } + + // player is now alive. + // fire E_PlayerRespawned and start the ACS SCRIPT_Respawn. + E_PlayerRespawned(int(this - players)); + // + FBehavior::StaticStartTypedScripts(SCRIPT_Respawn, mo, true); +} + +DEFINE_ACTION_FUNCTION(_PlayerInfo, Resurrect) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + ACTION_RETURN_BOOL(self->Resurrect()); +} + + DEFINE_ACTION_FUNCTION(_PlayerInfo, GetUserName) { PARAM_SELF_STRUCT_PROLOGUE(player_t); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 138db474b..67414c542 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -360,6 +360,7 @@ usercmd_t original_cmd; native void SetLogText (String text); native void DropWeapon(); native void BringUpWeapon(); + native bool Resurrect(); native String GetUserName() const; native Color GetColor() const; From 99d1581c27c2db48bc1e9c60737cb57fb22bc181 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Sat, 25 Mar 2017 14:59:33 +0800 Subject: [PATCH 27/29] Added "DontLightActors" flag for dynamic lights. Actors will not be illuminated by lights that are given this flag. --- src/g_shared/a_dynlight.h | 1 + src/g_shared/a_dynlightdata.cpp | 23 +++++++++++++++++++++-- src/gl/scene/gl_spritelight.cpp | 2 +- src/scripting/thingdef_data.cpp | 1 + src/swrenderer/things/r_sprite.cpp | 2 +- 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/g_shared/a_dynlight.h b/src/g_shared/a_dynlight.h index 1a1862957..893bbfbee 100644 --- a/src/g_shared/a_dynlight.h +++ b/src/g_shared/a_dynlight.h @@ -27,6 +27,7 @@ enum #define MF4_DONTLIGHTSELF MF4_SEESDAGGERS #define MF4_ATTENUATE MF4_INCOMBAT #define MF4_NOSHADOWMAP MF4_STANDSTILL +#define MF4_DONTLIGHTACTORS MF4_EXTREMEDEATH enum ELightType { diff --git a/src/g_shared/a_dynlightdata.cpp b/src/g_shared/a_dynlightdata.cpp index 160ddea5f..7db1f8f7c 100644 --- a/src/g_shared/a_dynlightdata.cpp +++ b/src/g_shared/a_dynlightdata.cpp @@ -127,6 +127,7 @@ public: void SetDontLightSelf(bool add) { m_dontlightself = add; } void SetAttenuate(bool on) { m_attenuate = on; } void SetHalo(bool halo) { m_halo = halo; } + void SetDontLightActors(bool on) { m_dontlightactors = on; } void OrderIntensities() { @@ -144,7 +145,7 @@ protected: DVector3 m_Pos; ELightType m_type; int8_t m_attenuate; - bool m_subtractive, m_additive, m_halo, m_dontlightself; + bool m_subtractive, m_additive, m_halo, m_dontlightself, m_dontlightactors; bool m_swapped = false; }; @@ -187,6 +188,7 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const if (m_subtractive) light->flags4 |= MF4_SUBTRACTIVE; if (m_additive) light->flags4 |= MF4_ADDITIVE; if (m_dontlightself) light->flags4 |= MF4_DONTLIGHTSELF; + if (m_dontlightactors) light->flags4 |= MF4_DONTLIGHTACTORS; light->m_tickCount = 0; if (m_type == PulseLight) { @@ -236,6 +238,7 @@ static const char *LightTags[]= "halo", "dontlightself", "attenuate", + "dontlightactors", NULL }; @@ -256,7 +259,8 @@ enum { LIGHTTAG_ADDITIVE, LIGHTTAG_HALO, LIGHTTAG_DONTLIGHTSELF, - LIGHTTAG_ATTENUATE + LIGHTTAG_ATTENUATE, + LIGHTTAG_DONTLIGHTACTORS, }; @@ -394,6 +398,9 @@ static void ParsePointLight(FScanner &sc) case LIGHTTAG_ATTENUATE: defaults->SetAttenuate(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; default: sc.ScriptError("Unknown tag: %s\n", sc.String); } @@ -476,6 +483,9 @@ static void ParsePulseLight(FScanner &sc) case LIGHTTAG_ATTENUATE: defaults->SetAttenuate(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; default: sc.ScriptError("Unknown tag: %s\n", sc.String); } @@ -560,6 +570,9 @@ void ParseFlickerLight(FScanner &sc) case LIGHTTAG_ATTENUATE: defaults->SetAttenuate(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; default: sc.ScriptError("Unknown tag: %s\n", sc.String); } @@ -643,6 +656,9 @@ void ParseFlickerLight2(FScanner &sc) case LIGHTTAG_ATTENUATE: defaults->SetAttenuate(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; default: sc.ScriptError("Unknown tag: %s\n", sc.String); } @@ -723,6 +739,9 @@ static void ParseSectorLight(FScanner &sc) case LIGHTTAG_ATTENUATE: defaults->SetAttenuate(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTACTORS: + defaults->SetDontLightActors(ParseInt(sc) != 0); + break; default: sc.ScriptError("Unknown tag: %s\n", sc.String); } diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index 3283f0086..793a10c7c 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -62,7 +62,7 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * while (node) { light=node->lightsource; - if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self)) + if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self) && !(light->flags4&MF4_DONTLIGHTACTORS)) { float dist; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 32363abdc..01a79dfc1 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -488,6 +488,7 @@ static FFlagDef DynLightFlagDefs[] = DEFINE_FLAG(MF4, DONTLIGHTSELF, ADynamicLight, flags4), DEFINE_FLAG(MF4, ATTENUATE, ADynamicLight, flags4), DEFINE_FLAG(MF4, NOSHADOWMAP, ADynamicLight, flags4), + DEFINE_FLAG(MF4, DONTLIGHTACTORS, ADynamicLight, flags4), }; static FFlagDef PowerSpeedFlagDefs[] = diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index 2e8a0f3aa..c98e9dcc6 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -237,7 +237,7 @@ namespace swrenderer while (node != nullptr) { ADynamicLight *light = node->lightsource; - if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->flags4&MF4_DONTLIGHTSELF) || light->target != thing)) + if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->flags4&MF4_DONTLIGHTSELF) || light->target != thing) && !(light->flags4&MF4_DONTLIGHTACTORS)) { float lx = (float)(light->X() - thing->X()); float ly = (float)(light->Y() - thing->Y()); From 6870efe134eb0d8a40172038ed402b64b76f3a6d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 21:36:57 +0200 Subject: [PATCH 28/29] - added a GetCVarString ZScript/DECORATE function. - fixed: loading a savegame triggered PlayerEntered events. --- src/g_level.cpp | 5 ++++- src/p_actionfunctions.cpp | 30 ++++++++++++++++++++++++++++++ wadsrc/static/zscript/actor.txt | 1 + 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 1a3d1d073..ecde760f3 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1028,7 +1028,10 @@ void G_DoLoadLevel (int position, bool autosave) { players[ii].camera = players[ii].mo; } - E_PlayerEntered(ii, finishstate == FINISH_SameHub); + if (!savegamerestore) + { + E_PlayerEntered(ii, finishstate == FINISH_SameHub); + } // ENTER scripts are being handled when the player gets spawned, this cannot be changed due to its effect on voodoo dolls. if (level.FromSnapshot && !savegamerestore) FBehavior::StaticStartTypedScripts(SCRIPT_Return, players[ii].mo, true); } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index a0794f1d6..055274d3d 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -654,6 +654,36 @@ DEFINE_ACTION_FUNCTION(AActor, GetCVar) return 0; } +//========================================================================== +// +// GetCVar +// +// NON-ACTION function that works like ACS's GetCVar. +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(AActor, GetCVarString) +{ + if (numret > 0) + { + assert(ret != nullptr); + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(cvarname); + + FBaseCVar *cvar = GetCVar(self, cvarname); + if (cvar == nullptr) + { + ret->SetString(""); + } + else + { + ret->SetString(cvar->GetGenericRep(CVAR_String).String); + } + return 1; + } + return 0; +} + //========================================================================== // // GetPlayerInput diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index aae7d6aeb..daac2f23d 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -671,6 +671,7 @@ class Actor : Thinker native native clearscope int GetSpawnHealth() const; native double GetCrouchFactor(int ptr = AAPTR_PLAYER1); native double GetCVar(string cvar); + native double GetCVarString(string cvar); native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); native int CountProximity(class classname, double distance, int flags = 0, int ptr = AAPTR_DEFAULT); native double GetSpriteAngle(int ptr = AAPTR_DEFAULT); From 224219dd6621615f634667d08860bd2f09a95d5f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 21:39:03 +0200 Subject: [PATCH 29/29] - made ListMenuItem.DrawSelector virtual. --- wadsrc/static/zscript/menu/listmenuitems.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/menu/listmenuitems.txt b/wadsrc/static/zscript/menu/listmenuitems.txt index ee9be6044..5b4a4e549 100644 --- a/wadsrc/static/zscript/menu/listmenuitems.txt +++ b/wadsrc/static/zscript/menu/listmenuitems.txt @@ -35,7 +35,7 @@ class ListMenuItem : MenuItemBase { - void DrawSelector(double xofs, double yofs, TextureID tex) + virtual void DrawSelector(double xofs, double yofs, TextureID tex) { if (tex.isNull()) {