/* ** a_decalfx.h ** Decal animation thinkers ** **--------------------------------------------------------------------------- ** Copyright 1998-2006 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: ** ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** 3. The name of the author may not be used to endorse or promote products ** derived from this software without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **--------------------------------------------------------------------------- ** */ #include "decallib.h" #include "a_decalfx.h" #include "serializer.h" #include "a_sharedglobal.h" #include "g_levellocals.h" #include "m_fixed.h" IMPLEMENT_CLASS(DDecalThinker, false, true) IMPLEMENT_POINTERS_START(DDecalThinker) IMPLEMENT_POINTER(TheDecal) IMPLEMENT_POINTERS_END void DDecalThinker::Serialize(FSerializer &arc) { Super::Serialize (arc); arc("thedecal", TheDecal); } IMPLEMENT_CLASS(DDecalFader, false, false) void DDecalFader::Serialize(FSerializer &arc) { Super::Serialize (arc); arc("starttime", TimeToStartDecay) ("endtime", TimeToEndDecay) ("starttrans", StartTrans); } void DDecalFader::Tick () { if (TheDecal == nullptr) { Destroy (); } else { if (Level->maptime < TimeToStartDecay || Level->isFrozen()) { return; } else if (Level->maptime >= TimeToEndDecay) { TheDecal->Expired(); // for impact decal bookkeeping. TheDecal->Destroy (); // remove the decal Destroy (); // remove myself return; } if (StartTrans == -1) { StartTrans = TheDecal->Alpha; } int distanceToEnd = TimeToEndDecay - Level->maptime; int fadeDistance = TimeToEndDecay - TimeToStartDecay; TheDecal->Alpha = StartTrans * distanceToEnd / fadeDistance; } } IMPLEMENT_CLASS(DDecalStretcher, false, false) void DDecalStretcher::Serialize(FSerializer &arc) { Super::Serialize (arc); arc("starttime", TimeToStart) ("endtime", TimeToStop) ("goalx", GoalX) ("startx", StartX) ("stretchx", bStretchX) ("goaly", GoalY) ("starty", StartY) ("stretchy", bStretchY) ("started", bStarted); } void DDecalStretcher::Tick () { if (TheDecal == nullptr) { Destroy (); return; } if (Level->maptime < TimeToStart || Level->isFrozen()) { return; } if (Level->maptime >= TimeToStop) { if (bStretchX) { TheDecal->ScaleX = GoalX; } if (bStretchY) { TheDecal->ScaleY = GoalY; } Destroy (); return; } if (!bStarted) { bStarted = true; StartX = TheDecal->ScaleX; StartY = TheDecal->ScaleY; } int distance = Level->maptime - TimeToStart; int maxDistance = TimeToStop - TimeToStart; if (bStretchX) { TheDecal->ScaleX = StartX + (GoalX - StartX) * distance / maxDistance; } if (bStretchY) { TheDecal->ScaleY = StartY + (GoalY - StartY) * distance / maxDistance; } } IMPLEMENT_CLASS(DDecalSlider, false, false) void DDecalSlider::Serialize(FSerializer &arc) { Super::Serialize (arc); arc("starttime", TimeToStart) ("endtime", TimeToStop) ("disty", DistY) ("starty", StartY) ("started", bStarted); } void DDecalSlider::Tick () { if (TheDecal == nullptr) { Destroy (); return; } if (Level->maptime < TimeToStart || Level->isFrozen()) { return; } if (!bStarted) { bStarted = true; /*StartX = TheDecal->LeftDistance;*/ StartY = TheDecal->Z; } if (Level->maptime >= TimeToStop) { /*TheDecal->LeftDistance = StartX + DistX;*/ TheDecal->Z = StartY + DistY; Destroy (); return; } int distance = Level->maptime - TimeToStart; int maxDistance = TimeToStop - TimeToStart; /*TheDecal->LeftDistance = StartX + DistX * distance / maxDistance);*/ TheDecal->Z = StartY + DistY * distance / maxDistance; } IMPLEMENT_CLASS(DDecalColorer, false, false) void DDecalColorer::Serialize(FSerializer &arc) { Super::Serialize (arc); arc("starttime", TimeToStartDecay) ("endtime", TimeToEndDecay) ("startcolor", StartColor) ("goalcolor", GoalColor); } void DDecalColorer::Tick () { if (TheDecal == nullptr || !(TheDecal->RenderStyle.Flags & STYLEF_ColorIsFixed)) { Destroy (); } else { if (Level->maptime < TimeToStartDecay || Level->isFrozen()) { return; } else if (Level->maptime >= TimeToEndDecay) { TheDecal->SetShade (GoalColor); Destroy (); // remove myself } if (StartColor.a == 255) { StartColor = TheDecal->AlphaColor & 0xffffff; if (StartColor == GoalColor) { Destroy (); return; } } if (Level->maptime & 0) { // Changing the shade can be expensive, so don't do it too often. return; } int distance = Level->maptime - TimeToStartDecay; int maxDistance = TimeToEndDecay - TimeToStartDecay; int r = StartColor.r + Scale (GoalColor.r - StartColor.r, distance, maxDistance); int g = StartColor.g + Scale (GoalColor.g - StartColor.g, distance, maxDistance); int b = StartColor.b + Scale (GoalColor.b - StartColor.b, distance, maxDistance); TheDecal->SetShade (r, g, b); } }