/* * The ManaPlus Client * Copyright (C) 2008 Douglas Boffey * Copyright (C) 2009 The Mana World Development Team * Copyright (C) 2009-2010 The Mana Developers * Copyright (C) 2011-2019 The ManaPlus Developers * * This file is part of The ManaPlus Client. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "gui/palette.h" #include "utils/foreach.h" #include "utils/timer.h" #ifndef USE_SDL2 #include #endif // USE_SDL2 #include "debug.h" const Color Palette::BLACK = Color(0, 0, 0, 255); Palette::Palettes Palette::mInstances; const Color Palette::RAINBOW_COLORS[7] = { Color(255, 0, 0, 255), Color(255, 153, 0, 255), Color(255, 255, 0, 255), Color(0, 153, 0, 255), Color(0, 204, 204, 255), Color(51, 0, 153, 255), Color(153, 0, 153, 255) }; const int Palette::RAINBOW_COLOR_COUNT = 7; Palette::Palette(const int size) : mRainbowTime(tick_time), mColors(Colors(size)), mCharColors(), mGradVector() { mInstances.insert(this); } Palette::~Palette() { mInstances.erase(this); } const Color& Palette::getCharColor(const signed char c, bool &valid) const { const CharColors::const_iterator it = mCharColors.find(c); if (it != mCharColors.end()) { valid = true; return mColors[(*it).second].color; } valid = false; return BLACK; } void Palette::advanceGradients() { FOR_EACH (Palettes::const_iterator, it, mInstances) (*it)->advanceGradient(); } void Palette::advanceGradient() { const int time = get_elapsed_time(mRainbowTime); if (time > 5) { // For slower systems, advance can be greater than one (advance > 1 // skips advance-1 steps). Should make gradient look the same // independent of the framerate. const int advance = time / 5; for (size_t i = 0, sz = mGradVector.size(); i < sz; i++) { ColorElem *const elem A_NONNULLPOINTER = mGradVector[i]; if (elem == nullptr) continue; int delay = elem->delay; const GradientTypeT &grad = elem->grad; if (grad == GradientType::PULSE) delay = delay / 20; const int numOfColors = (elem->grad == GradientType::SPECTRUM ? 6 : grad == GradientType::PULSE ? 127 : RAINBOW_COLOR_COUNT); elem->gradientIndex = (elem->gradientIndex + advance) % (delay * numOfColors); const int gradIndex = elem->gradientIndex; const int pos = delay != 0 ? (gradIndex % delay) : gradIndex; int colIndex; if (delay != 0) colIndex = gradIndex / delay; else colIndex = gradIndex; Color &color = elem->color; int colVal; if (grad == GradientType::PULSE) { colVal = CAST_S32(255.0 * sin(M_PI * colIndex / numOfColors)); const Color &col = elem->testColor; color.r = ((colVal * col.r) / 255) % (col.r + 1); color.g = ((colVal * col.g) / 255) % (col.g + 1); color.b = ((colVal * col.b) / 255) % (col.b + 1); } else if (grad == GradientType::SPECTRUM) { if ((colIndex % 2) != 0) { // falling curve if (delay != 0) { colVal = CAST_S32(255.0 * (cos(M_PI * pos / delay) + 1) / 2); } else { colVal = CAST_S32(255.0 * (cos(M_PI * pos) + 1) / 2); } } else { // ascending curve if (delay != 0) { colVal = CAST_S32(255.0 * (cos(M_PI * (delay - pos) / delay) + 1) / 2); } else { colVal = CAST_S32(255.0 * (cos(M_PI * (delay - pos)) + 1) / 2); } } color.r = (colIndex == 0 || colIndex == 5) ? 255 : (colIndex == 1 || colIndex == 4) ? colVal : 0; color.g = (colIndex == 1 || colIndex == 2) ? 255 : (colIndex == 0 || colIndex == 3) ? colVal : 0; color.b = (colIndex == 3 || colIndex == 4) ? 255 : (colIndex == 2 || colIndex == 5) ? colVal : 0; } else if (elem->grad == GradientType::RAINBOW) { const Color &startCol = RAINBOW_COLORS[colIndex]; const Color &destCol = RAINBOW_COLORS[(colIndex + 1) % numOfColors]; double startColVal; double destColVal; if (delay != 0) startColVal = (cos(M_PI * pos / delay) + 1) / 2; else startColVal = 0; destColVal = 1 - startColVal; color.r = CAST_S32(startColVal * startCol.r + destColVal * destCol.r); color.g = CAST_S32(startColVal * startCol.g + destColVal * destCol.g); color.b = CAST_S32(startColVal * startCol.b + destColVal * destCol.b); } } mRainbowTime = tick_time; } }