From cf2fdbf6851843281294c1ddc84300dc06550e39 Mon Sep 17 00:00:00 2001
From: Carsten Teibes <dev@f4ke.de>
Date: Sun, 20 Jan 2019 18:24:07 +0100
Subject: [PATCH 31/36] Allow stopping palette effects. Properly fix #9 Earlier
 solution was bad, when returning from setup menu the sky was missing.

---
 src/io/gfx/paletteeffects.cpp | 130 +++++++++++++++++++---------------
 src/io/gfx/paletteeffects.h   |  26 +++----
 src/io/gfx/video.cpp          |   9 +--
 src/io/gfx/video.h            |   2 +-
 src/level/level.cpp           |   3 +-
 src/loop.h                    |   2 +-
 src/main.cpp                  |   5 +-
 7 files changed, 94 insertions(+), 83 deletions(-)

--- a/src/io/gfx/paletteeffects.cpp
+++ b/src/io/gfx/paletteeffects.cpp
@@ -68,11 +68,12 @@ PaletteEffect::~PaletteEffect () {
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void PaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void PaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 	return;
 
@@ -102,20 +103,20 @@ WhiteInPaletteEffect::WhiteInPaletteEffe
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void WhiteInPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void WhiteInPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	int count;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
-
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 	if (whiteness > F1) {
 
 		memset(shownPalette, 255, sizeof(SDL_Color) * 256);
 
-		whiteness -= ITOF(mspf) / duration;
+		if (!isStatic) whiteness -= ITOF(mspf) / duration;
 
 	} else if (whiteness > 0) {
 
@@ -130,7 +131,7 @@ void WhiteInPaletteEffect::apply (SDL_Co
 
 		}
 
-		whiteness -= ITOF(mspf) / duration;
+		if (!isStatic) whiteness -= ITOF(mspf) / duration;
 
 	}
 
@@ -164,20 +165,21 @@ FadeInPaletteEffect::FadeInPaletteEffect
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void FadeInPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void FadeInPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	int count;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 
 	if (blackness > F1) {
 
 		memset(shownPalette, 0, sizeof(SDL_Color) * 256);
 
-		blackness -= ITOF(mspf) / duration;
+		if (!isStatic) blackness -= ITOF(mspf) / duration;
 
 	} else if (blackness > 0) {
 
@@ -192,7 +194,7 @@ void FadeInPaletteEffect::apply (SDL_Col
 
 		}
 
-		blackness -= ITOF(mspf) / duration;
+		if (!isStatic) blackness -= ITOF(mspf) / duration;
 
 	}
 
@@ -226,35 +228,39 @@ WhiteOutPaletteEffect::WhiteOutPaletteEf
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void WhiteOutPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void WhiteOutPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	int count;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 
 	if (whiteness > F1) {
 
 		memset(shownPalette, 255, sizeof(SDL_Color) * 256);
 
-	} else if (whiteness > 0) {
+	} else {
 
-		for (count = 0; count < 256; count++) {
+		if (whiteness > 0) {
 
-			shownPalette[count].r = 255 -
-				FTOI((255 - shownPalette[count].r) * (F1 - whiteness));
-			shownPalette[count].g = 255 -
-				FTOI((255 - shownPalette[count].g) * (F1 - whiteness));
-			shownPalette[count].b = 255 -
-				FTOI((255 - shownPalette[count].b) * (F1 - whiteness));
+			for (count = 0; count < 256; count++) {
+
+				shownPalette[count].r = 255 -
+					FTOI((255 - shownPalette[count].r) * (F1 - whiteness));
+				shownPalette[count].g = 255 -
+					FTOI((255 - shownPalette[count].g) * (F1 - whiteness));
+				shownPalette[count].b = 255 -
+					FTOI((255 - shownPalette[count].b) * (F1 - whiteness));
 
+			}
 		}
 
-		whiteness += ITOF(mspf) / duration;
+		if (!isStatic) whiteness += ITOF(mspf) / duration;
 
-	} else whiteness += ITOF(mspf) / duration;
+	}
 
 	if (direct) video.changePalette(shownPalette, 0, 256);
 
@@ -286,34 +292,39 @@ FadeOutPaletteEffect::FadeOutPaletteEffe
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void FadeOutPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void FadeOutPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	int count;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 	if (blackness > F1) {
 
 		memset(shownPalette, 0, sizeof(SDL_Color) * 256);
 
-	} else if (blackness > 0) {
+	} else {
 
-		for (count = 0; count < 256; count++) {
+		if (blackness > 0) {
 
-			shownPalette[count].r =
-				FTOI(shownPalette[count].r * (F1 - blackness));
-			shownPalette[count].g =
-				FTOI(shownPalette[count].g * (F1 - blackness));
-			shownPalette[count].b =
-				FTOI(shownPalette[count].b * (F1 - blackness));
+			for (count = 0; count < 256; count++) {
+
+				shownPalette[count].r =
+					FTOI(shownPalette[count].r * (F1 - blackness));
+				shownPalette[count].g =
+					FTOI(shownPalette[count].g * (F1 - blackness));
+				shownPalette[count].b =
+					FTOI(shownPalette[count].b * (F1 - blackness));
+
+			}
 
 		}
 
-		blackness += ITOF(mspf) / duration;
+		if (!isStatic) blackness += ITOF(mspf) / duration;
 
-	} else blackness += ITOF(mspf) / duration;
+	}
 
 	if (direct) video.changePalette(shownPalette, 0, 256);
 
@@ -353,13 +364,14 @@ FlashPaletteEffect::FlashPaletteEffect
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void FlashPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void FlashPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	int count;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 	if (progress < 0) {
 
@@ -374,7 +386,7 @@ void FlashPaletteEffect::apply (SDL_Colo
 
 		}
 
-		progress += ITOF(mspf) / duration;
+		if (!isStatic) progress += ITOF(mspf) / duration;
 
 	} else if (progress < F1) {
 
@@ -389,7 +401,7 @@ void FlashPaletteEffect::apply (SDL_Colo
 
 		}
 
-		progress += ITOF(mspf) / duration;
+		if (!isStatic) progress += ITOF(mspf) / duration;
 
 	}
 
@@ -428,15 +440,15 @@ RotatePaletteEffect::RotatePaletteEffect
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void RotatePaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void RotatePaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	SDL_Color* currentPalette;
 	int count;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
-
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 	currentPalette = video.getPalette();
 
@@ -448,8 +460,12 @@ void RotatePaletteEffect::apply (SDL_Col
 
 	}
 
-	position -= (mspf * speed) >> 10;
-	while (position < 0) position += ITOF(amount);
+	if (!isStatic) {
+
+		position -= (mspf * speed) >> 10;
+		while (position < 0) position += ITOF(amount);
+
+	}
 
 	if (direct) video.changePalette(shownPalette + first, first, amount);
 
@@ -488,14 +504,14 @@ SkyPaletteEffect::SkyPaletteEffect
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void SkyPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void SkyPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	int position, count, y;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
-
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 	position = viewY + ((canvasH - 33) << 9) - F4;
 	y = ((canvasH - 34) / 100) + 1;
@@ -564,15 +580,15 @@ P2DPaletteEffect::P2DPaletteEffect
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void P2DPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void P2DPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	SDL_Color* currentPalette;
 	int count, x, y, j;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
-
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 	currentPalette = video.getPalette();
 	x = FTOI(((256 * 32) - FTOI(viewX)) * speed);
@@ -624,16 +640,16 @@ P1DPaletteEffect::P1DPaletteEffect
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void P1DPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void P1DPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	SDL_Color* currentPalette;
 	fixed position;
 	int count;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
-
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 	currentPalette = video.getPalette();
 	position = viewX + viewY;
@@ -676,15 +692,15 @@ WaterPaletteEffect::WaterPaletteEffect (
  * @param shownPalette The palette the effect will be applied to
  * @param direct Whether or not to apply the effect directly
  * @param mspf Ticks per frame
+ * @param isStatic Whether the effect should advance after applying
  */
-void WaterPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf) {
+void WaterPaletteEffect::apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic) {
 
 	SDL_Color* currentPalette;
 	int position, count;
 
 	// Apply the next palette effect
-	if (next) next->apply(shownPalette, direct, mspf);
-
+	if (next) next->apply(shownPalette, direct, mspf, isStatic);
 
 	currentPalette = video.getPalette();
 
@@ -714,5 +730,3 @@ void WaterPaletteEffect::apply (SDL_Colo
 	return;
 
 }
-
-
--- a/src/io/gfx/paletteeffects.h
+++ b/src/io/gfx/paletteeffects.h
@@ -26,7 +26,6 @@
 #ifndef _PALETTE_H
 #define _PALETTE_H
 
-
 #include "OpenJazz.h"
 
 #include <SDL.h>
@@ -58,7 +57,7 @@ class PaletteEffect {
 		PaletteEffect          (PaletteEffect* nextPE);
 		virtual ~PaletteEffect ();
 
-		virtual void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		virtual void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -72,7 +71,7 @@ class WhiteInPaletteEffect : public Pale
 	public:
 		WhiteInPaletteEffect (int newDuration, PaletteEffect* nextPE);
 
-		void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -86,7 +85,7 @@ class FadeInPaletteEffect : public Palet
 	public:
 		FadeInPaletteEffect (int newDuration, PaletteEffect* nextPE);
 
-		void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -100,7 +99,7 @@ class WhiteOutPaletteEffect : public Pal
 	public:
 		WhiteOutPaletteEffect (int newDuration, PaletteEffect* nextPE);
 
-		void apply  (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -114,7 +113,7 @@ class FadeOutPaletteEffect : public Pale
 	public:
 		FadeOutPaletteEffect (int newDuration, PaletteEffect* nextPE);
 
-		void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -129,7 +128,7 @@ class FlashPaletteEffect : public Palett
 	public:
 		FlashPaletteEffect (unsigned char newRed, unsigned char newGreen, unsigned char newBlue, int newDuration, PaletteEffect* nextPE);
 
-		void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -145,7 +144,7 @@ class RotatePaletteEffect : public Palet
 	public:
 		RotatePaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, PaletteEffect* nextPE);
 
-		void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -161,7 +160,7 @@ class SkyPaletteEffect : public PaletteE
 	public:
 		SkyPaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, SDL_Color* newSkyPalette, PaletteEffect* nextPE);
 
-		void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -176,7 +175,7 @@ class P2DPaletteEffect : public PaletteE
 	public:
 		P2DPaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, PaletteEffect* nextPE);
 
-		void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -191,7 +190,7 @@ class P1DPaletteEffect : public PaletteE
 	public:
 		P1DPaletteEffect (unsigned char newFirst, int newAmount, fixed newSpeed, PaletteEffect* nextPE);
 
-		void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
@@ -204,11 +203,8 @@ class WaterPaletteEffect : public Palett
 	public:
 		WaterPaletteEffect (fixed newDepth, PaletteEffect* nextPE);
 
-		void apply (SDL_Color* shownPalette, bool direct, int mspf);
+		void apply (SDL_Color* shownPalette, bool direct, int mspf, bool isStatic);
 
 };
 
-
 #endif
-
-
--- a/src/io/gfx/video.cpp
+++ b/src/io/gfx/video.cpp
@@ -255,7 +255,7 @@ void Video::setPalette (SDL_Color *palet
 
 	// Make palette changes invisible until the next draw. Hopefully.
 	clearScreen(SDL_MapRGB(screen->format, 0, 0, 0));
-	flip(0, NULL);
+	flip(0);
 
 	SDL_SetPalette(screen, SDL_PHYSPAL, palette, 0, 256);
 	currentPalette = palette;
@@ -474,8 +474,9 @@ void Video::update (SDL_Event *event) {
  *
  * @param mspf Ticks per frame
  * @param paletteEffects Palette effects to use
+ * @param effectsStopped Whether the effects should be applied without advancing
  */
-void Video::flip (int mspf, PaletteEffect* paletteEffects) {
+void Video::flip (int mspf, PaletteEffect* paletteEffects, bool effectsStopped) {
 
 	SDL_Color shownPalette[256];
 
@@ -503,13 +504,13 @@ void Video::flip (int mspf, PaletteEffec
 
 			memcpy(shownPalette, currentPalette, sizeof(SDL_Color) * 256);
 
-			paletteEffects->apply(shownPalette, false, mspf);
+			paletteEffects->apply(shownPalette, false, mspf, effectsStopped);
 
 			SDL_SetPalette(screen, SDL_PHYSPAL, shownPalette, 0, 256);
 
 		} else {
 
-			paletteEffects->apply(shownPalette, true, mspf);
+			paletteEffects->apply(shownPalette, true, mspf, effectsStopped);
 
 		}
 
--- a/src/io/gfx/video.h
+++ b/src/io/gfx/video.h
@@ -143,7 +143,7 @@ class Video {
 #endif
 
 		void       update                (SDL_Event *event);
-		void       flip                  (int mspf, PaletteEffect* paletteEffects);
+		void       flip                  (int mspf, PaletteEffect* paletteEffects = NULL, bool effectsStopped = false);
 
 		void       clearScreen           (int index);
 
--- a/src/level/level.cpp
+++ b/src/level/level.cpp
@@ -405,8 +405,7 @@ int Level::loop (bool& menu, int& option
 
 
 	// Main loop
-	if (::loop(NORMAL_LOOP, paused ? NULL : paletteEffects) == E_QUIT)
-		return E_QUIT;
+	if (::loop(NORMAL_LOOP, paletteEffects, paused) == E_QUIT) return E_QUIT;
 
 
 	if (controls.release(C_ESCAPE)) {
--- a/src/loop.h
+++ b/src/loop.h
@@ -57,7 +57,7 @@ enum LoopType {
 
 // Function in main.cpp
 
-EXTERN int loop (LoopType type, PaletteEffect* paletteEffects = NULL);
+EXTERN int loop (LoopType type, PaletteEffect* paletteEffects = NULL, bool effectsStopped = false);
 
 #endif
 
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -480,10 +480,11 @@ int play () {
  *
  * @param type Type of loop. Normal, typing, or input configuration
  * @param paletteEffects Palette effects to apply to video output
+ * @param effectsStopped Whether the effects should be applied without advancing
  *
  * @return Error code
  */
-int loop (LoopType type, PaletteEffect* paletteEffects) {
+int loop (LoopType type, PaletteEffect* paletteEffects, bool effectsStopped) {
 
 	SDL_Event event;
 	int prevTicks, ret;
@@ -502,7 +503,7 @@ int loop (LoopType type, PaletteEffect*
 	}
 
 	// Show what has been drawn
-	video.flip(globalTicks - prevTicks, paletteEffects);
+	video.flip(globalTicks - prevTicks, paletteEffects, effectsStopped);
 
 
 	// Process system events
