diff options
| -rw-r--r-- | engines/sword1/animation.cpp | 125 | ||||
| -rw-r--r-- | engines/sword1/animation.h | 11 | 
2 files changed, 121 insertions, 15 deletions
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp index d55a08293e..be9e02f64f 100644 --- a/engines/sword1/animation.cpp +++ b/engines/sword1/animation.cpp @@ -72,7 +72,7 @@ MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::  	_decoderType = decoderType;  	_decoder = decoder; -	_white = 255; +	_c1Color = _c2Color = _c3Color = _c4Color = 255;  	_black = 0;  } @@ -127,8 +127,16 @@ bool MoviePlayer::load(uint32 id) {  					warning("%s:%d startFrame (%d) <= lastEnd (%d)", filename.c_str(), lineNo, startFrame, lastEnd);  					continue;  				} - -				_movieTexts.push_back(MovieText(startFrame, endFrame, ptr)); +				 +				int color = 0; +				if (*ptr == '@') { +					++ptr; +					color = strtoul(ptr, const_cast<char **>(&ptr), 10); +					while (*ptr && isspace(static_cast<unsigned char>(*ptr))) +						ptr++; +				}  + +				_movieTexts.push_back(MovieText(startFrame, endFrame, ptr, color));  				lastEnd = endFrame;  			}  			f.close(); @@ -188,6 +196,7 @@ void MoviePlayer::performPostProcessing(byte *screen) {  			_textHeight = _resMan->toUint16(frame->height);  			_textX = 320 - _textWidth / 2;  			_textY = 420 - _textHeight; +			_textColor = _movieTexts.front()._color;  		}  		if (_decoder->getCurFrame() == _movieTexts.front()._endFrame) {  			_textMan->releaseText(2, false); @@ -209,7 +218,7 @@ void MoviePlayer::performPostProcessing(byte *screen) {  					dst[x] = findBlackPalIndex();  					break;  				case LETTER_COL: -					dst[x] = findWhitePalIndex(); +					dst[x] = findTextColorPalIndex();  					break;  				}  			} @@ -258,12 +267,29 @@ bool MoviePlayer::playVideo() {  			if (_decoder->hasDirtyPalette()) {  				_decoder->setSystemPalette(); -				uint32 maxWeight = 0;  				uint32 minWeight = 0xFFFFFFFF;  				uint32 weight; +				float c1Weight = 1e+30; +				float c2Weight = 1e+30; +				float c3Weight = 1e+30; +				float c4Weight = 1e+30;  				byte r, g, b; +				float h, s, v, hd, hsvWeight;  				const byte *palette = _decoder->getPalette(); +				 +				// Color comparaison for the subtitles colors is done in HSL +				// C1 color is used for George and is almost white (R = 248, G = 252, B = 248) +				const float h1 = 0.333333f, s1 = 0.02f, v1 = 0.99f; + +				// C2 color is used for George as a narrator and is grey (R = 184, G = 188, B = 184) +				const float h2 = 0.333333f, s2 = 0.02f, v2 = 0.74f; + +				// C3 color is used for Nicole and is rose (R = 200, G = 120, B = 184) +				const float h3 = 0.866667f, s3 = 0.4f, v3 = 0.78f; + +				// C4 color is used for Maguire and is blue (R = 80, G = 152, B = 184) +				const float h4 = 0.55f, s4 = 0.57f, v4 = 0.72f;  				for (int i = 0; i < 256; i++) {  					r = *palette++; @@ -272,15 +298,55 @@ bool MoviePlayer::playVideo() {  					weight = 3 * r * r + 6 * g * g + 2 * b * b; -					if (weight >= maxWeight) { -						maxWeight = weight; -						_white = i; -					} -  					if (weight <= minWeight) {  						minWeight = weight;  						_black = i;  					} + +					convertColor(r, g, b, h, s, v); + +					// C1 color +					// It is almost achromatic (very low saturation) so the hue as litle impact on the color. +					// Therefore use a low weight on hue and high weight on saturation. +					hd = h - h1; +					hd += hd < -0.5f ? 1.0f : hd > 0.5f ? -1.0f : 0.0f; +					hsvWeight = 1.0f * hd * hd + 4.0f * (s - s1) * (s - s1) + 3.0f * (v - v1) * (v - v1); +					if (hsvWeight <= c1Weight) { +						c1Weight = hsvWeight; +						_c1Color = i; +					} + +					// C2 color +					// Also an almost achromatic color so use the same weights as for C1 color. +					hd = h - h2; +					hd += hd < -0.5f ? 1.0f : hd > 0.5f ? -1.0f : 0.0f; +					hsvWeight = 1.0f * hd * hd + 4.0f * (s - s2) * (s - s2) + 3.0f * (v - v2) * (v - v2); +					if (hsvWeight <= c2Weight) { +						c2Weight = hsvWeight; +						_c2Color = i; +					} + +					// C3 color +					// A light rose. Use a high weight on the hue to get a rose. +					// The color is a bit gray and the saturation has not much impact so use a low weight. +					hd = h - h3; +					hd += hd < -0.5f ? 1.0f : hd > 0.5f ? -1.0f : 0.0f; +					hsvWeight = 4.0f * hd * hd + 1.0f * (s - s3) * (s - s3) + 2.0f * (v - v3) * (v - v3); +					if (hsvWeight <= c3Weight) { +						c3Weight = hsvWeight; +						_c3Color = i; +					} + +					// C4 color +					// Blue. Use a hight weight on the hue to get a blue. +					// The color is darker and more saturated than C3 and the saturation has more impact. +					hd = h - h4; +					hd += hd < -0.5f ? 1.0f : hd > 0.5f ? -1.0f : 0.0f; +					hsvWeight = 5.0f * hd * hd + 3.0f * (s - s4) * (s - s4) + 2.0f * (v - v4) * (v - v4); +					if (hsvWeight <= c4Weight) { +						c4Weight = hsvWeight; +						_c4Color = i; +					}  				}  			} @@ -304,9 +370,44 @@ bool MoviePlayer::playVideo() {  byte MoviePlayer::findBlackPalIndex() {  	return _black;  } +	 +byte MoviePlayer::findTextColorPalIndex() { +	switch (_textColor) { +	case 1: +		return _c1Color; +	case 2: +		return _c2Color; +	case 3: +		return _c3Color; +	case 4: +		return _c4Color; +	} +	return _c1Color; +} -byte MoviePlayer::findWhitePalIndex() { -	return _white; +void MoviePlayer::convertColor(byte r, byte g, byte b, float &h, float &s, float &v) { +	float varR = r / 255.0f; +	float varG = g / 255.0f; +	float varB = b / 255.0f; + +	float min = MIN(varR, MIN(varG, varB)); +	float max = MAX(varR, MAX(varG, varB)); + +	v = max; +	float d = max - min; +	s = max == 0.0f ? 0.0f : d / max; + +	if (min == max) { +		h = 0.0f; // achromatic +	} else { +		if (max == varR) +			h = (varG - varB) / d + (varG < varB ? 6.0f : 0.0f); +		else if (max == varG) +			h = (varB - varR) / d + 2.0f; +		else +			h = (varR - varG) / d + 4.0f; +		h /= 6.0f; +	}  }  DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle) diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h index 1c03c66342..c436607211 100644 --- a/engines/sword1/animation.h +++ b/engines/sword1/animation.h @@ -45,11 +45,13 @@ class MovieText {  public:  	uint16 _startFrame;  	uint16 _endFrame; +	uint16 _color;  	Common::String _text; -	MovieText(int startFrame, int endFrame, const Common::String &text) { +	MovieText(int startFrame, int endFrame, const Common::String &text, int color) {  		_startFrame = startFrame;  		_endFrame = endFrame;  		_text = text; +		_color = color;  	}  }; @@ -80,7 +82,9 @@ protected:  	OSystem *_system;  	Common::List<MovieText> _movieTexts;  	int _textX, _textY, _textWidth, _textHeight; -	byte _white, _black; +	int _textColor; +	byte _black; +	byte _c1Color, _c2Color, _c3Color, _c4Color;  	DecoderType _decoderType;  	Video::VideoDecoder *_decoder; @@ -91,7 +95,8 @@ protected:  	void performPostProcessing(byte *screen);  	byte findBlackPalIndex(); -	byte findWhitePalIndex(); +	byte findTextColorPalIndex(); +	void convertColor(byte r, byte g, byte b, float &h, float &s, float &v);  };  MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system);  | 
