diff --git a/src/common/2d/wipe.cpp b/src/common/2d/wipe.cpp index ffa84b096..f359e3d18 100644 --- a/src/common/2d/wipe.cpp +++ b/src/common/2d/wipe.cpp @@ -208,6 +208,21 @@ private: int BurnTime = 8; }; +class Wiper_Fizzlefade : public Wiper +{ +public: + ~Wiper_Fizzlefade(); + bool Run(int ticks) override; + void SetTextures(FGameTexture* startscreen, FGameTexture* endscreen) override; + +private: + static const int WIDTH = 512, HEIGHT = 256; + uint8_t FizzleArray[WIDTH * HEIGHT] = { 0 }; + FBurnTexture* FizzleTexture = nullptr; + + uint32_t rndval = 1; +}; + //=========================================================================== // // Screen wipes @@ -220,13 +235,16 @@ Wiper *Wiper::Create(int type) { case wipe_Burn: return new Wiper_Burn; - + case wipe_Fade: return new Wiper_Crossfade; case wipe_Melt: return new Wiper_Melt; - + + case wipe_Fizzlefade: + return new Wiper_Fizzlefade; + default: return nullptr; } @@ -418,6 +436,69 @@ bool Wiper_Burn::Run(int ticks) return done || (BurnTime > 40); } +//========================================================================== + +void Wiper_Fizzlefade::SetTextures(FGameTexture* startscreen, FGameTexture* endscreen) +{ + startScreen = startscreen; + endScreen = endscreen; + FizzleTexture = new FBurnTexture(WIDTH, HEIGHT); + auto mat = FMaterial::ValidateTexture(endScreen, false); + mat->ClearLayers(); + mat->AddTextureLayer(FizzleTexture, false, MaterialLayerSampling::Default); +} + +Wiper_Fizzlefade::~Wiper_Fizzlefade() +{ + delete FizzleTexture; +} + +bool Wiper_Fizzlefade::Run(int ticks) +{ + bool done = false; + + ticks *= 5000; + for (int i = 0; i < ticks; i++) + { + uint32_t y = rndval & 0x000FF; + uint32_t x = (rndval & 0x1FF00) >> 8; + uint32_t lsb = rndval & 1; + rndval >>= 1; + if (lsb) + { + rndval ^= 0x00012000; + } + + FizzleArray[x + (y << 9)] = 255; + + if (rndval == 1) + { + done = true; + break; + } + } + + FizzleTexture->CleanHardwareTextures(); + endScreen->CleanHardwareData(false); // this only cleans the descriptor sets for the Vulkan backend. We do not want to delete the wipe screen's hardware texture here. + + uint8_t* src = FizzleArray; + uint32_t* dest = (uint32_t*)FizzleTexture->GetBuffer(); + for (int y = HEIGHT; y != 0; --y) + { + for (int x = WIDTH; x != 0; --x) + { + uint8_t s = *src++; + *dest++ = MAKEARGB(s, 255, 255, 255); + } + } + + DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE); + DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Burn, true, DTA_Masked, false, TAG_DONE); + + return done; +} + +//========================================================================== void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stopsound, std::function overlaydrawer) { diff --git a/src/common/2d/wipe.h b/src/common/2d/wipe.h index 08a7eeb3b..411390643 100644 --- a/src/common/2d/wipe.h +++ b/src/common/2d/wipe.h @@ -12,6 +12,7 @@ enum wipe_Melt, // weird screen melt wipe_Burn, // fade in shape of fire wipe_Fade, // crossfade from old to new + wipe_Fizzlefade, // wolf3d fizzle fade from old to new wipe_NUMWIPES }; diff --git a/src/common/engine/gamestate.h b/src/common/engine/gamestate.h index 5f674a33b..aff8da57c 100644 --- a/src/common/engine/gamestate.h +++ b/src/common/engine/gamestate.h @@ -21,7 +21,8 @@ enum gamestate_t : int GS_FORCEWIPE = -1, GS_FORCEWIPEFADE = -2, GS_FORCEWIPEBURN = -3, - GS_FORCEWIPEMELT = -4 + GS_FORCEWIPEMELT = -4, + GS_FORCEWIPEFIZZLEFADE = -5 }; diff --git a/src/d_main.cpp b/src/d_main.cpp index 720d8f529..52cb16c92 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -984,6 +984,10 @@ void D_Display () case GS_FORCEWIPEMELT: wipe_type = wipe_Melt; break; + + case GS_FORCEWIPEFIZZLEFADE: + wipe_type = wipe_Fizzlefade; + break; } } @@ -3010,7 +3014,25 @@ static void System_StartCutscene(bool blockui) static void System_SetTransition(int type) { - if (type != wipe_None) wipegamestate = type == wipe_Burn? GS_FORCEWIPEBURN : type == wipe_Fade? GS_FORCEWIPEFADE : GS_FORCEWIPEMELT; + if (type != wipe_None) + { + switch (type) + { + case wipe_Burn: + wipegamestate = GS_FORCEWIPEBURN; + break; + case wipe_Fizzlefade: + wipegamestate = GS_FORCEWIPEFIZZLEFADE; + break; + case wipe_Fade: + wipegamestate = GS_FORCEWIPEFADE; + break; + default: + case wipe_Melt: + wipegamestate = GS_FORCEWIPEMELT; + break; + } + } } static void System_HudScaleChanged() diff --git a/src/intermission/intermission_parse.cpp b/src/intermission/intermission_parse.cpp index 4f75c3bcb..5fbb37e3f 100644 --- a/src/intermission/intermission_parse.cpp +++ b/src/intermission/intermission_parse.cpp @@ -255,6 +255,7 @@ bool FIntermissionActionWiper::ParseKey(FScanner &sc) { "Crossfade", GS_FORCEWIPEFADE }, { "Melt", GS_FORCEWIPEMELT }, { "Burn", GS_FORCEWIPEBURN }, + { "Fizzlefade", GS_FORCEWIPEFIZZLEFADE }, { "Default", GS_FORCEWIPE }, { NULL, GS_FORCEWIPE } }; diff --git a/wadsrc/static/language.def b/wadsrc/static/language.def index 337477ba6..0a7549df6 100644 --- a/wadsrc/static/language.def +++ b/wadsrc/static/language.def @@ -408,3 +408,4 @@ OPTVAL_RAYTRACE = "Raytrace"; GLLIGHTMNU_LIGHTSHADOWS = "Light shadows"; GLLIGHTMNU_LIGHTSHADOWFILTER = "Shadow filter"; OPTMNU_SWRENDERER = "$$DSPLYMNU_SWOPT"; +OPTVAL_FIZZLEFADE = "Fizzlefade"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 7638b0b2b..48358d941 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -928,6 +928,7 @@ OptionValue Wipes 1.0, "$OPTVAL_MELT" 2.0, "$OPTVAL_BURN" 3.0, "$OPTVAL_CROSSFADE" + 4.0, "$OPTVAL_FIZZLEFADE" } OptionValue Endoom