mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-17 20:58:07 +02:00
Implemented bloodlust, clone, and petrify effects for xbrz mode
This commit is contained in:
parent
de3b7e3cc6
commit
28a8d4f4a1
@ -594,16 +594,19 @@ void ColorTransformAnimation::tick(uint32_t msPassed)
|
||||
if (index == timePoints.size())
|
||||
{
|
||||
//end of animation. Apply ColorShifter using final values and die
|
||||
const auto & shifter = steps[index - 1];
|
||||
owner.stacksController->setStackColorFilter(shifter, stack, spell, false);
|
||||
const auto & lastColor = effectColors[index - 1];
|
||||
const auto & lastAlpha = transparency[index - 1];
|
||||
owner.stacksController->setStackColorFilter(lastColor, lastAlpha, stack, spell, false);
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(index != 0);
|
||||
|
||||
const auto & prevShifter = steps[index - 1];
|
||||
const auto & nextShifter = steps[index];
|
||||
const auto & prevColor = effectColors[index - 1];
|
||||
const auto & nextColor = effectColors[index];
|
||||
const auto & prevAlpha = transparency[index - 1];
|
||||
const auto & nextAlpha = transparency[index];
|
||||
|
||||
float prevPoint = timePoints[index-1];
|
||||
float nextPoint = timePoints[index];
|
||||
@ -611,9 +614,10 @@ void ColorTransformAnimation::tick(uint32_t msPassed)
|
||||
float stepDuration = (nextPoint - prevPoint);
|
||||
float factor = localProgress / stepDuration;
|
||||
|
||||
auto shifter = ColorFilter::genInterpolated(prevShifter, nextShifter, factor);
|
||||
const auto & currColor = vstd::lerp(prevColor, nextColor, factor);
|
||||
const auto & currAlpha = vstd::lerp(prevAlpha, nextAlpha, factor);
|
||||
|
||||
owner.stacksController->setStackColorFilter(shifter, stack, spell, true);
|
||||
owner.stacksController->setStackColorFilter(currColor, currAlpha, stack, spell, true);
|
||||
}
|
||||
|
||||
ColorTransformAnimation::ColorTransformAnimation(BattleInterface & owner, const CStack * _stack, const std::string & colorFilterName, const CSpell * spell):
|
||||
@ -622,10 +626,11 @@ ColorTransformAnimation::ColorTransformAnimation(BattleInterface & owner, const
|
||||
totalProgress(0.f)
|
||||
{
|
||||
auto effect = owner.effectsController->getMuxerEffect(colorFilterName);
|
||||
steps = effect.filters;
|
||||
effectColors = effect.effectColors;
|
||||
transparency = effect.transparency;
|
||||
timePoints = effect.timePoints;
|
||||
|
||||
assert(!steps.empty() && steps.size() == timePoints.size());
|
||||
assert(!effectColors.empty() && effectColors.size() == timePoints.size());
|
||||
|
||||
logAnim->debug("Created ColorTransformAnimation for %s", stack->getName());
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../../lib/battle/BattleHexArray.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
#include "../../lib/Color.h"
|
||||
#include "BattleConstants.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@ -113,8 +114,10 @@ public:
|
||||
|
||||
class ColorTransformAnimation : public BattleStackAnimation
|
||||
{
|
||||
std::vector<ColorFilter> steps;
|
||||
std::vector<ColorRGBA> effectColors;
|
||||
std::vector<float> transparency;
|
||||
std::vector<float> timePoints;
|
||||
|
||||
const CSpell * spell;
|
||||
|
||||
float totalProgress;
|
||||
|
@ -143,7 +143,8 @@ void BattleEffectsController::loadColorMuxers()
|
||||
for (const JsonNode & entry : muxer.second.Vector() )
|
||||
{
|
||||
effect.timePoints.push_back(entry["time"].Float());
|
||||
effect.filters.push_back(ColorFilter::genFromJson(entry));
|
||||
effect.effectColors.push_back(ColorRGBA(255*entry["color"][0].Float(), 255*entry["color"][1].Float(), 255*entry["color"][2].Float(), 255*entry["color"][3].Float()));
|
||||
effect.transparency.push_back(entry["alpha"].Float() * 255);
|
||||
}
|
||||
colorMuxerEffects[identifier] = effect;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../../lib/battle/BattleHex.h"
|
||||
#include "../../lib/Point.h"
|
||||
#include "../../lib/Color.h"
|
||||
#include "../../lib/filesystem/ResourcePath.h"
|
||||
#include "BattleConstants.h"
|
||||
|
||||
@ -21,13 +22,19 @@ struct BattleTriggerEffect;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
struct ColorMuxerEffect;
|
||||
class CAnimation;
|
||||
class Canvas;
|
||||
class BattleInterface;
|
||||
class BattleRenderer;
|
||||
class EffectAnimation;
|
||||
|
||||
struct ColorMuxerEffect
|
||||
{
|
||||
std::vector<ColorRGBA> effectColors;
|
||||
std::vector<float> transparency;
|
||||
std::vector<float> timePoints;
|
||||
};
|
||||
|
||||
/// Struct for battle effect animation e.g. morale, prayer, armageddon, bless,...
|
||||
struct BattleEffect
|
||||
{
|
||||
|
@ -204,8 +204,7 @@ void BattleStacksController::stackAdded(const CStack * stack, bool instant)
|
||||
if (!instant)
|
||||
{
|
||||
// immediately make stack transparent, giving correct shifter time to start
|
||||
auto shifterFade = ColorFilter::genAlphaShifter(0);
|
||||
setStackColorFilter(shifterFade, stack, nullptr, true);
|
||||
setStackColorFilter(Colors::TRANSPARENCY, 0, stack, nullptr, true);
|
||||
|
||||
owner.addToAnimationStage(EAnimationEvents::HIT, [=]()
|
||||
{
|
||||
@ -324,14 +323,18 @@ void BattleStacksController::showStackAmountBox(Canvas & canvas, const CStack *
|
||||
|
||||
void BattleStacksController::showStack(Canvas & canvas, const CStack * stack)
|
||||
{
|
||||
ColorFilter fullFilter = ColorFilter::genEmptyShifter();
|
||||
ColorRGBA effectColor = Colors::TRANSPARENCY;
|
||||
uint8_t transparency = 255;
|
||||
for(const auto & filter : stackFilterEffects)
|
||||
{
|
||||
if (filter.target == stack)
|
||||
fullFilter = ColorFilter::genCombined(fullFilter, filter.effect);
|
||||
{
|
||||
effectColor = filter.effectColor;
|
||||
transparency = static_cast<int>(filter.transparency) * transparency / 255;
|
||||
}
|
||||
}
|
||||
|
||||
stackAnimation[stack->unitId()]->nextFrame(canvas, fullFilter, facingRight(stack)); // do actual blit
|
||||
stackAnimation[stack->unitId()]->nextFrame(canvas, effectColor, transparency, facingRight(stack)); // do actual blit
|
||||
}
|
||||
|
||||
void BattleStacksController::tick(uint32_t msPassed)
|
||||
@ -769,18 +772,19 @@ Point BattleStacksController::getStackPositionAtHex(const BattleHex & hexNum, co
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BattleStacksController::setStackColorFilter(const ColorFilter & effect, const CStack * target, const CSpell * source, bool persistent)
|
||||
void BattleStacksController::setStackColorFilter(const ColorRGBA & effectColor, uint8_t transparency, const CStack * target, const CSpell * source, bool persistent)
|
||||
{
|
||||
for (auto & filter : stackFilterEffects)
|
||||
{
|
||||
if (filter.target == target && filter.source == source)
|
||||
{
|
||||
filter.effect = effect;
|
||||
filter.effectColor = effectColor;
|
||||
filter.transparency = transparency;
|
||||
filter.persistent = persistent;
|
||||
return;
|
||||
}
|
||||
}
|
||||
stackFilterEffects.push_back({ effect, target, source, persistent });
|
||||
stackFilterEffects.push_back({ target, source, effectColor, transparency, persistent });
|
||||
}
|
||||
|
||||
void BattleStacksController::removeExpiredColorFilters()
|
||||
@ -791,7 +795,7 @@ void BattleStacksController::removeExpiredColorFilters()
|
||||
{
|
||||
if (filter.source && !filter.target->hasBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(filter.source->id)), Selector::all))
|
||||
return true;
|
||||
if (filter.effect == ColorFilter::genEmptyShifter())
|
||||
if (filter.effectColor == Colors::TRANSPARENCY && filter.transparency == 255)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../render/ColorFilter.h"
|
||||
#include "../../lib/Color.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -37,9 +37,10 @@ class IImage;
|
||||
|
||||
struct BattleStackFilterEffect
|
||||
{
|
||||
ColorFilter effect;
|
||||
const CStack * target;
|
||||
const CSpell * source;
|
||||
ColorRGBA effectColor;
|
||||
uint8_t transparency;
|
||||
bool persistent;
|
||||
};
|
||||
|
||||
@ -134,7 +135,7 @@ public:
|
||||
/// Adds new color filter effect targeting stack
|
||||
/// Effect will last as long as stack is affected by specified spell (unless effect is persistent)
|
||||
/// If effect from same (target, source) already exists, it will be updated
|
||||
void setStackColorFilter(const ColorFilter & effect, const CStack * target, const CSpell *source, bool persistent);
|
||||
void setStackColorFilter(const ColorRGBA & effect, uint8_t transparency, const CStack * target, const CSpell *source, bool persistent);
|
||||
void addNewAnim(BattleAnimation *anim); //adds new anim to pendingAnims
|
||||
|
||||
const CStack* getActiveStack() const;
|
||||
|
@ -24,11 +24,6 @@ static const ColorRGBA creatureBlueBorder = { 0, 255, 255, 255 };
|
||||
static const ColorRGBA creatureGoldBorder = { 255, 255, 0, 255 };
|
||||
static const ColorRGBA creatureNoBorder = { 0, 0, 0, 0 };
|
||||
|
||||
static ColorRGBA genShadow(ui8 alpha)
|
||||
{
|
||||
return ColorRGBA(0, 0, 0, alpha);
|
||||
}
|
||||
|
||||
ColorRGBA AnimationControls::getBlueBorder()
|
||||
{
|
||||
return creatureBlueBorder;
|
||||
@ -192,7 +187,6 @@ void CreatureAnimation::setType(ECreatureAnimType type)
|
||||
CreatureAnimation::CreatureAnimation(const AnimationPath & name_, TSpeedController controller)
|
||||
: name(name_),
|
||||
speed(0.1f),
|
||||
shadowAlpha(128),
|
||||
currentFrame(0),
|
||||
animationEnd(-1),
|
||||
elapsedTime(0),
|
||||
@ -324,11 +318,8 @@ static ColorRGBA genBorderColor(ui8 alpha, const ColorRGBA & base)
|
||||
return ColorRGBA(base.r, base.g, base.b, ui8(base.a * alpha / 256));
|
||||
}
|
||||
|
||||
void CreatureAnimation::nextFrame(Canvas & canvas, const ColorFilter & shifter, bool facingRight)
|
||||
void CreatureAnimation::nextFrame(Canvas & canvas, const ColorRGBA & effectColor, uint8_t transparency, bool facingRight)
|
||||
{
|
||||
ColorRGBA shadowTest = shifter.shiftColor(genShadow(128));
|
||||
shadowAlpha = shadowTest.a;
|
||||
|
||||
size_t frame = static_cast<size_t>(floor(currentFrame));
|
||||
|
||||
std::shared_ptr<IImage> image;
|
||||
@ -345,7 +336,8 @@ void CreatureAnimation::nextFrame(Canvas & canvas, const ColorFilter & shifter,
|
||||
else
|
||||
image->setOverlayColor(Colors::TRANSPARENCY);
|
||||
|
||||
image->adjustPalette(shifter, 0);
|
||||
image->setEffectColor(effectColor);
|
||||
image->setAlpha(transparency);
|
||||
|
||||
canvas.draw(image, pos.topLeft(), Rect(0, 0, pos.w, pos.h));
|
||||
}
|
||||
|
@ -94,9 +94,6 @@ private:
|
||||
///type of animation being displayed
|
||||
ECreatureAnimType type;
|
||||
|
||||
/// current value of shadow transparency
|
||||
uint8_t shadowAlpha;
|
||||
|
||||
/// border color, disabled if alpha = 0
|
||||
ColorRGBA border;
|
||||
|
||||
@ -127,7 +124,7 @@ public:
|
||||
/// returns currently rendered type of animation
|
||||
ECreatureAnimType getType() const;
|
||||
|
||||
void nextFrame(Canvas & canvas, const ColorFilter & shifter, bool facingRight);
|
||||
void nextFrame(Canvas & canvas, const ColorRGBA & effectColor, uint8_t transparency, bool facingRight);
|
||||
|
||||
/// should be called every frame, return true when animation was reset to beginning
|
||||
bool incrementFrame(float timePassed);
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
void setAlpha(uint8_t value) override{};
|
||||
void playerColored(const PlayerColor & player) override{};
|
||||
void setOverlayColor(const ColorRGBA & color) override{};
|
||||
void setEffectColor(const ColorRGBA & color) override{};
|
||||
void shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) override{};
|
||||
void adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) override{};
|
||||
|
||||
|
@ -129,40 +129,3 @@ ColorFilter ColorFilter::genCombined(const ColorFilter & left, const ColorFilter
|
||||
float a = left.a * right.a;
|
||||
return genMuxerShifter(r,g,b,a);
|
||||
}
|
||||
|
||||
ColorFilter ColorFilter::genFromJson(const JsonNode & entry)
|
||||
{
|
||||
ChannelMuxer r{ 1.f, 0.f, 0.f, 0.f };
|
||||
ChannelMuxer g{ 0.f, 1.f, 0.f, 0.f };
|
||||
ChannelMuxer b{ 0.f, 0.f, 1.f, 0.f };
|
||||
float a{ 1.0};
|
||||
|
||||
if (!entry["red"].isNull())
|
||||
{
|
||||
r.r = entry["red"].Vector()[0].Float();
|
||||
r.g = entry["red"].Vector()[1].Float();
|
||||
r.b = entry["red"].Vector()[2].Float();
|
||||
r.a = entry["red"].Vector()[3].Float();
|
||||
}
|
||||
|
||||
if (!entry["green"].isNull())
|
||||
{
|
||||
g.r = entry["green"].Vector()[0].Float();
|
||||
g.g = entry["green"].Vector()[1].Float();
|
||||
g.b = entry["green"].Vector()[2].Float();
|
||||
g.a = entry["green"].Vector()[3].Float();
|
||||
}
|
||||
|
||||
if (!entry["blue"].isNull())
|
||||
{
|
||||
b.r = entry["blue"].Vector()[0].Float();
|
||||
b.g = entry["blue"].Vector()[1].Float();
|
||||
b.b = entry["blue"].Vector()[2].Float();
|
||||
b.a = entry["blue"].Vector()[3].Float();
|
||||
}
|
||||
|
||||
if (!entry["alpha"].isNull())
|
||||
a = entry["alpha"].Float();
|
||||
|
||||
return genMuxerShifter(r,g,b,a);
|
||||
}
|
||||
|
@ -54,13 +54,4 @@ public:
|
||||
|
||||
/// Scales down strength of a shifter to a specified factor
|
||||
static ColorFilter genInterpolated(const ColorFilter & left, const ColorFilter & right, float power);
|
||||
|
||||
/// Generates object using supplied Json config
|
||||
static ColorFilter genFromJson(const JsonNode & entry);
|
||||
};
|
||||
|
||||
struct ColorMuxerEffect
|
||||
{
|
||||
std::vector<ColorFilter> filters;
|
||||
std::vector<float> timePoints;
|
||||
};
|
||||
|
@ -51,6 +51,7 @@ enum class EImageBlitMode : uint8_t
|
||||
WITH_SHADOW_AND_FLAG_COLOR,
|
||||
|
||||
/// RGBA, contains only body, with shadow and overlay disabled
|
||||
GRAYSCALE_BODY_HIDE_SELECTION,
|
||||
ONLY_BODY_HIDE_SELECTION,
|
||||
ONLY_BODY_HIDE_FLAG_COLOR,
|
||||
|
||||
@ -104,8 +105,8 @@ public:
|
||||
|
||||
virtual void setAlpha(uint8_t value) = 0;
|
||||
|
||||
//only indexed bitmaps with 7 special colors
|
||||
virtual void setOverlayColor(const ColorRGBA & color) = 0;
|
||||
virtual void setEffectColor(const ColorRGBA & color) = 0;
|
||||
|
||||
virtual ~IImage() = default;
|
||||
};
|
||||
|
@ -103,6 +103,10 @@ void ScalableImageParameters::preparePalette(const SDL_Palette * originalPalette
|
||||
case EImageBlitMode::ONLY_SELECTION:
|
||||
adjustPalette(originalPalette, blitMode, ColorFilter::genAlphaShifter(0), 0);
|
||||
break;
|
||||
case EImageBlitMode::GRAYSCALE_BODY_HIDE_SELECTION:
|
||||
adjustPalette(originalPalette, blitMode, ColorFilter::genMuxerShifter( { 0.299, 0.587, 0.114, 0}, { 0.299, 0.587, 0.114, 0}, { 0.299, 0.587, 0.114, 0}, 1), 0);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
switch(blitMode)
|
||||
@ -120,6 +124,7 @@ void ScalableImageParameters::preparePalette(const SDL_Palette * originalPalette
|
||||
case EImageBlitMode::ONLY_BODY_IGNORE_OVERLAY:
|
||||
case EImageBlitMode::ONLY_FLAG_COLOR:
|
||||
case EImageBlitMode::ONLY_SELECTION:
|
||||
case EImageBlitMode::GRAYSCALE_BODY_HIDE_SELECTION:
|
||||
setShadowTransparency(originalPalette, 0.0);
|
||||
break;
|
||||
}
|
||||
@ -140,6 +145,7 @@ void ScalableImageParameters::preparePalette(const SDL_Palette * originalPalette
|
||||
break;
|
||||
case EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION:
|
||||
case EImageBlitMode::ONLY_BODY_HIDE_SELECTION:
|
||||
case EImageBlitMode::GRAYSCALE_BODY_HIDE_SELECTION:
|
||||
setOverlayColor(originalPalette, Colors::TRANSPARENCY, true);
|
||||
break;
|
||||
}
|
||||
@ -273,11 +279,15 @@ void ScalableImageShared::draw(SDL_Surface * where, const Point & dest, const Re
|
||||
bool shadowLoading = scaled.at(scalingFactor).shadow.at(0) && scaled.at(scalingFactor).shadow.at(0)->isLoading();
|
||||
bool bodyLoading = scaled.at(scalingFactor).body.at(0) && scaled.at(scalingFactor).body.at(0)->isLoading();
|
||||
bool overlayLoading = scaled.at(scalingFactor).overlay.at(0) && scaled.at(scalingFactor).overlay.at(0)->isLoading();
|
||||
bool grayscaleLoading = scaled.at(scalingFactor).bodyGrayscale.at(0) && scaled.at(scalingFactor).bodyGrayscale.at(0)->isLoading();
|
||||
bool playerLoading = parameters.player != PlayerColor::CANNOT_DETERMINE && scaled.at(scalingFactor).playerColored.at(1+parameters.player.getNum()) && scaled.at(scalingFactor).playerColored.at(1+parameters.player.getNum())->isLoading();
|
||||
|
||||
if (shadowLoading || bodyLoading || overlayLoading || playerLoading)
|
||||
if (shadowLoading || bodyLoading || overlayLoading || playerLoading || grayscaleLoading)
|
||||
{
|
||||
getFlippedImage(scaled[1].body)->scaledDraw(where, parameters.palette, dimensions() * scalingFactor, dest, src, parameters.colorMultiplier, parameters.alphaValue, locator.layer);
|
||||
|
||||
if (parameters.effectColorMultiplier.a != ColorRGBA::ALPHA_TRANSPARENT)
|
||||
getFlippedImage(scaled[1].body)->scaledDraw(where, parameters.palette, dimensions() * scalingFactor, dest, src, parameters.effectColorMultiplier, parameters.alphaValue, locator.layer);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -292,6 +302,9 @@ void ScalableImageShared::draw(SDL_Surface * where, const Point & dest, const Re
|
||||
{
|
||||
if (scaled.at(scalingFactor).body.at(0))
|
||||
flipAndDraw(scaled.at(scalingFactor).body, parameters.colorMultiplier, parameters.alphaValue);
|
||||
|
||||
if (scaled.at(scalingFactor).bodyGrayscale.at(0) && parameters.effectColorMultiplier.a != ColorRGBA::ALPHA_TRANSPARENT)
|
||||
flipAndDraw(scaled.at(scalingFactor).bodyGrayscale, parameters.effectColorMultiplier, parameters.alphaValue);
|
||||
}
|
||||
|
||||
if (scaled.at(scalingFactor).overlay.at(0))
|
||||
@ -370,6 +383,24 @@ void ScalableImageInstance::setOverlayColor(const ColorRGBA & color)
|
||||
parameters.setOverlayColor(image->getPalette(), color, blitMode == EImageBlitMode::WITH_SHADOW_AND_SELECTION);
|
||||
}
|
||||
|
||||
void ScalableImageInstance::setEffectColor(const ColorRGBA & color)
|
||||
{
|
||||
parameters.effectColorMultiplier = color;
|
||||
|
||||
if (parameters.palette)
|
||||
{
|
||||
const auto grayscaleFilter = ColorFilter::genMuxerShifter( { 0.299, 0.587, 0.114, 0}, { 0.299, 0.587, 0.114, 0}, { 0.299, 0.587, 0.114, 0}, 1);
|
||||
const auto effectStrengthFilter = ColorFilter::genRangeShifter( 0, 0, 0, color.r / 255.f, color.g / 255.f, color.b / 255.f);
|
||||
const auto effectFilter = ColorFilter::genCombined(grayscaleFilter, effectStrengthFilter);
|
||||
const auto effectiveFilter = ColorFilter::genInterpolated(ColorFilter::genEmptyShifter(), effectFilter, color.a / 255.f);
|
||||
|
||||
parameters.adjustPalette(image->getPalette(), blitMode, effectiveFilter, 0);
|
||||
}
|
||||
|
||||
if (color.a != ColorRGBA::ALPHA_TRANSPARENT)
|
||||
image->prepareEffectImage();
|
||||
}
|
||||
|
||||
void ScalableImageInstance::playerColored(const PlayerColor & player)
|
||||
{
|
||||
parameters.player = player;
|
||||
@ -424,11 +455,19 @@ std::shared_ptr<const ISharedImage> ScalableImageShared::loadOrGenerateImage(EIm
|
||||
if (loadedImage)
|
||||
return loadedImage;
|
||||
|
||||
// optional images for 1x resolution - only try load them, don't attempt to generate
|
||||
bool optionalImage =
|
||||
mode == EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR ||
|
||||
mode == EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION ||
|
||||
mode == EImageBlitMode::ONLY_FLAG_COLOR ||
|
||||
mode == EImageBlitMode::ONLY_SELECTION ||
|
||||
mode == EImageBlitMode::GRAYSCALE_BODY_HIDE_SELECTION ||
|
||||
color != PlayerColor::CANNOT_DETERMINE;
|
||||
|
||||
if (scalingFactor == 1)
|
||||
{
|
||||
// optional images for 1x resolution - only try load them, don't attempt to generate
|
||||
// this block should never be called for 'body' layer - that image is loaded unconditionally before construction
|
||||
assert(mode == EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR || mode == EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION || mode == EImageBlitMode::ONLY_FLAG_COLOR || mode == EImageBlitMode::ONLY_SELECTION || color != PlayerColor::CANNOT_DETERMINE);
|
||||
assert(optionalImage);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -441,7 +480,7 @@ std::shared_ptr<const ISharedImage> ScalableImageShared::loadOrGenerateImage(EIm
|
||||
{
|
||||
if (scaling == 1)
|
||||
{
|
||||
if (mode == EImageBlitMode::ONLY_SHADOW_HIDE_FLAG_COLOR || mode == EImageBlitMode::ONLY_SHADOW_HIDE_SELECTION || mode == EImageBlitMode::ONLY_FLAG_COLOR || mode == EImageBlitMode::ONLY_SELECTION || color != PlayerColor::CANNOT_DETERMINE)
|
||||
if (optionalImage)
|
||||
{
|
||||
ScalableImageParameters parameters(getPalette(), mode);
|
||||
return loadedImage->scaleInteger(scalingFactor, parameters.palette, mode);
|
||||
@ -560,3 +599,20 @@ void ScalableImageShared::preparePlayerColoredImage(PlayerColor color)
|
||||
{
|
||||
loadScaledImages(GH.screenHandler().getScalingFactor(), color);
|
||||
}
|
||||
|
||||
void ScalableImageShared::prepareEffectImage()
|
||||
{
|
||||
int scalingFactor = GH.screenHandler().getScalingFactor();
|
||||
|
||||
if (scaled[scalingFactor].bodyGrayscale[0] == nullptr)
|
||||
{
|
||||
switch(locator.layer)
|
||||
{
|
||||
case EImageBlitMode::WITH_SHADOW_AND_SELECTION:
|
||||
scaled[scalingFactor].bodyGrayscale[0] = loadOrGenerateImage(EImageBlitMode::GRAYSCALE_BODY_HIDE_SELECTION, scalingFactor, PlayerColor::CANNOT_DETERMINE, scaled[1].bodyGrayscale[0]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ struct ScalableImageParameters : boost::noncopyable
|
||||
|
||||
ColorRGBA colorMultiplier = Colors::WHITE_TRUE;
|
||||
ColorRGBA ovelayColorMultiplier = Colors::WHITE_TRUE;
|
||||
ColorRGBA effectColorMultiplier = Colors::TRANSPARENCY;
|
||||
|
||||
PlayerColor player = PlayerColor::CANNOT_DETERMINE;
|
||||
uint8_t alphaValue = 255;
|
||||
@ -64,6 +65,9 @@ class ScalableImageShared final : public std::enable_shared_from_this<ScalableIm
|
||||
/// Upscaled overlay (player color, selection highlight) of our image, may be null
|
||||
FlippedImages overlay;
|
||||
|
||||
/// Upscaled grayscale version of body, for special effects in combat (e.g clone / petrify / berserk)
|
||||
FlippedImages bodyGrayscale;
|
||||
|
||||
/// player-colored images of this particular scale, mostly for UI. These are never flipped in h3
|
||||
PlayerColoredImages playerColored;
|
||||
};
|
||||
@ -91,6 +95,7 @@ public:
|
||||
|
||||
std::shared_ptr<ScalableImageInstance> createImageReference();
|
||||
|
||||
void prepareEffectImage();
|
||||
void preparePlayerColoredImage(PlayerColor color);
|
||||
};
|
||||
|
||||
@ -115,6 +120,7 @@ public:
|
||||
void setAlpha(uint8_t value) override;
|
||||
void draw(SDL_Surface * where, const Point & pos, const Rect * src, int scalingFactor) const override;
|
||||
void setOverlayColor(const ColorRGBA & color) override;
|
||||
void setEffectColor(const ColorRGBA & color) override;
|
||||
void playerColored(const PlayerColor & player) override;
|
||||
void shiftPalette(uint32_t firstColorID, uint32_t colorsToMove, uint32_t distanceToMove) override;
|
||||
void adjustPalette(const ColorFilter & shifter, uint32_t colorsToSkipMask) override;
|
||||
|
@ -10,12 +10,8 @@
|
||||
// Note that actual speed of animation is subject to changes from in-game animation speed setting
|
||||
"time" : 0.0,
|
||||
|
||||
// Optional. Transformation filter for red, green and blue components of a color
|
||||
// Applies transformation with specified parameters to each channel. Formula:
|
||||
// result = red * (value 1) + green * (value 2) + blue * (value 3) + (value 4)
|
||||
"red" : [ 1.0, 0.0, 0.0, 0.0 ],
|
||||
"green" : [ 0.0, 1.0, 0.0, 0.0 ],
|
||||
"blue" : [ 0.0, 0.0, 1.0, 0.0 ],
|
||||
// Optional. Adds grayscale overlay on top of creature, multiplied by specified color per channel (rgba order)
|
||||
"color" : [ 1.0, 0.0, 0.0, 1.0 ],
|
||||
|
||||
/// Optional. Transparency filter, makes stack appear semi-transparent, used mostly for fade-in effects
|
||||
/// Value 0 = full transparency, 1 = fully opaque
|
||||
@ -25,23 +21,21 @@
|
||||
|
||||
"petrification" : [
|
||||
{
|
||||
"time" : 0.0
|
||||
"time" : 0.0,
|
||||
"alpha" : 1.0
|
||||
},
|
||||
{
|
||||
"time" : 1.0,
|
||||
// Conversion to grayscale, using human eye perception factor for channels
|
||||
"red" : [ 0.299, 0.587, 0.114, 0.0 ],
|
||||
"green" : [ 0.299, 0.587, 0.114, 0.0 ],
|
||||
"blue" : [ 0.299, 0.587, 0.114, 0.0 ],
|
||||
"color" : [ 1.0, 1.0, 1.0, 1.0 ], //grayscale
|
||||
"alpha" : 1.0
|
||||
}
|
||||
],
|
||||
"cloning" : [
|
||||
{
|
||||
// No fade in - will be handled by summonFadeIn effect
|
||||
"time" : 0.0,
|
||||
"red" : [ 0.5, 0.0, 0.0, 0.0 ],
|
||||
"green" : [ 0.0, 0.5, 0.0, 0.0 ],
|
||||
"blue" : [ 0.0, 0.0, 0.5, 0.5 ],
|
||||
"color" : [ 0.0, 0.0, 1.0, 1.0 ], //blue
|
||||
"alpha" : 1.0
|
||||
}
|
||||
],
|
||||
"summonFadeIn" : [
|
||||
@ -50,12 +44,14 @@
|
||||
"alpha" : 0.0
|
||||
},
|
||||
{
|
||||
"time" : 1.0
|
||||
"time" : 1.0,
|
||||
"alpha" : 1.0
|
||||
},
|
||||
],
|
||||
"summonFadeOut" : [
|
||||
{
|
||||
"time" : 0.0
|
||||
"time" : 0.0,
|
||||
"alpha" : 1.0
|
||||
},
|
||||
{
|
||||
"time" : 1.0,
|
||||
@ -68,12 +64,14 @@
|
||||
"alpha" : 0.0
|
||||
},
|
||||
{
|
||||
"time" : 0.5
|
||||
"time" : 0.5,
|
||||
"alpha" : 1.0
|
||||
},
|
||||
],
|
||||
"teleportFadeOut" : [
|
||||
{
|
||||
"time" : 0.0
|
||||
"time" : 0.0,
|
||||
"alpha" : 1.0
|
||||
},
|
||||
{
|
||||
"time" : 0.5,
|
||||
@ -82,31 +80,17 @@
|
||||
],
|
||||
"bloodlust" : [
|
||||
{
|
||||
"time" : 0.0
|
||||
},
|
||||
{
|
||||
"time" : 0.25,
|
||||
"red" : [ 0.5, 0.0, 0.5, 0.4 ],
|
||||
"green" : [ 0.0, 1.0, 0.0, 0.0 ],
|
||||
"blue" : [ 0.0, 0.0, 1.0, 0.0 ],
|
||||
"time" : 0.0,
|
||||
"alpha" : 1.0
|
||||
},
|
||||
{
|
||||
"time" : 0.5,
|
||||
"red" : [ 0.6, 0.6, 0.6, 0.0 ],
|
||||
"green" : [ 0.0, 0.5, 0.0, 0.0 ],
|
||||
"blue" : [ 0.0, 0.0, 0.5, 0.0 ],
|
||||
"alpha" : 1.0
|
||||
},
|
||||
{
|
||||
"time" : 0.75,
|
||||
"red" : [ 0.5, 0.0, 0.5, 0.4 ],
|
||||
"green" : [ 0.0, 1.0, 0.0, 0.0 ],
|
||||
"blue" : [ 0.0, 0.0, 1.0, 0.0 ],
|
||||
"time" : 0.5,
|
||||
"color" : [ 1.0, 0.0, 0.0, 1.0 ], //red
|
||||
"alpha" : 1.0
|
||||
},
|
||||
{
|
||||
"time" : 1.0,
|
||||
"alpha" : 1.0
|
||||
},
|
||||
],
|
||||
}
|
||||
|
14
lib/Color.h
14
lib/Color.h
@ -64,4 +64,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
namespace vstd
|
||||
{
|
||||
template<typename Floating>
|
||||
ColorRGBA lerp(const ColorRGBA & left, const ColorRGBA & right, const Floating & factor)
|
||||
{
|
||||
return ColorRGBA(
|
||||
vstd::lerp(left.r, right.r, factor),
|
||||
vstd::lerp(left.g, right.g, factor),
|
||||
vstd::lerp(left.b, right.b, factor),
|
||||
vstd::lerp(left.a, right.a, factor)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
Loading…
x
Reference in New Issue
Block a user