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); |