Parcourir la source

Added Fading Functionality

FadeTo allows any SceneObject to dynamically change its BlendColor over
a period of time!  It includes support functions like cancelFadeTo()
that were modeled after moveTo() and rotateTo().  When the fade is
complete an onFadeToComplete() callback is called.  This has all been
thoroughly tested and is ready to move to other dev environments.
Peter Robinson il y a 10 ans
Parent
commit
83931dfec9

+ 88 - 0
engine/source/2d/sceneobject/SceneObject.cc

@@ -150,6 +150,14 @@ SceneObject::SceneObject() :
     mBlendColor(ColorF(1.0f,1.0f,1.0f,1.0f)),
     mAlphaTest(-1.0f),
 
+	// Fading.
+	mFadeActive(false),
+	mTargetColor(ColorF(1.0f, 1.0f, 1.0f, 1.0f)),
+	mDeltaRed(1.0f),
+	mDeltaGreen(1.0f),
+	mDeltaBlue(1.0f),
+	mDeltaAlpha(1.0f),
+
     /// Render sorting.
     mSortPoint(0.0f,0.0f),
 
@@ -610,6 +618,12 @@ void SceneObject::integrateObject( const F32 totalTime, const F32 elapsedTime, D
         // Yes, so calculate camera mount.
         mpAttachedCamera->calculateCameraMount( elapsedTime );
     }
+
+	// Update the BlendColor.
+	if ( mFadeActive )
+	{
+		updateBlendColor( elapsedTime );
+	}
 }
 
 //-----------------------------------------------------------------------------
@@ -633,6 +647,15 @@ void SceneObject::postIntegrate(const F32 totalTime, const F32 elapsedTime, Debu
         Con::executef(this, 1, "onUpdate");
     }
 
+	// Check to see if we're done fading.
+	if ( mFadeActive && mBlendColor == mTargetColor )
+	{
+		mFadeActive = false;
+
+		PROFILE_SCOPE(SceneObject_onFadeComplete);
+		Con::executef(this, 1, "onFadeToComplete");
+	}
+
     // Are we using the sleeping callback?
     if ( mSleepingCallback )
     {
@@ -1673,6 +1696,38 @@ bool SceneObject::rotateTo( const F32 targetAngle, const F32 speed, const bool a
 
 //-----------------------------------------------------------------------------
 
+bool SceneObject::fadeTo(const ColorF& targetColor, const F32 deltaRed, const F32 deltaGreen, const F32 deltaBlue, const F32 deltaAlpha)
+{
+	// Check in a scene.
+	if (!getScene())
+	{
+		Con::warnf("SceneObject::fadeTo() - Cannot fade object (%d) to a color as it is not in a scene.", getId());
+		return false;
+	}
+
+	// Check targetColor.
+	if (!targetColor.isValidColor())
+	{
+		Con::warnf("SceneObject::fadeTo() - Cannot fade object (%d) because the color is invalid.", getId());
+		return false;
+	}
+
+	// Only set fading active if the target color is not the blending color.
+	if (targetColor != mBlendColor)
+	{
+		mFadeActive = true;
+		mTargetColor = targetColor;
+		mDeltaRed = deltaRed;
+		mDeltaGreen = deltaGreen;
+		mDeltaBlue = deltaBlue;
+		mDeltaAlpha = deltaAlpha;
+	}
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+
 void SceneObject::cancelMoveTo( const bool autoStop )
 {
     // Only cancel an active moveTo event
@@ -4099,6 +4154,39 @@ const char* SceneObject::getDstBlendFactorDescription(const GLenum factor)
 
 //-----------------------------------------------------------------------------
 
+void SceneObject::updateBlendColor(const F32 elapsedTime)
+{
+	// Apply the color deltas to the blendColor to move it toward the targetColor.
+	mBlendColor.red = processEffect(mBlendColor.red, mTargetColor.red, mDeltaRed * elapsedTime);
+	mBlendColor.green = processEffect(mBlendColor.green, mTargetColor.green, mDeltaGreen * elapsedTime);
+	mBlendColor.blue = processEffect(mBlendColor.blue, mTargetColor.blue, mDeltaBlue * elapsedTime);
+	mBlendColor.alpha = processEffect(mBlendColor.alpha, mTargetColor.alpha, mDeltaAlpha * elapsedTime);
+}
+
+//-----------------------------------------------------------------------------
+
+F32 SceneObject::processEffect(const F32 current, const F32 target, const F32 rate)
+{
+	if (mFabs(current - target) < rate)
+	{
+		return target;
+	}
+	else if (current < target)
+	{
+		return current + rate;
+	}
+	else if (current > target)
+	{
+		return current - rate;
+	}
+	else
+	{
+		return target;
+	}
+}
+
+//-----------------------------------------------------------------------------
+
 static void WriteCircleCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement )
 {
     // Sanity!

+ 17 - 0
engine/source/2d/sceneobject/SceneObject.h

@@ -179,6 +179,14 @@ protected:
     ColorF                  mBlendColor;
     F32                     mAlphaTest;
 
+	// Fading
+	bool					mFadeActive;
+	ColorF					mTargetColor;
+	F32						mDeltaRed;
+	F32						mDeltaGreen;
+	F32						mDeltaBlue;
+	F32						mDeltaAlpha;
+
     /// Render sorting.
     Vector2                 mSortPoint;
 
@@ -239,6 +247,9 @@ protected:
     virtual void            onTamlCustomWrite( TamlCustomNodes& customNodes );
     virtual void            onTamlCustomRead( const TamlCustomNodes& customNodes );
 
+	// Effect Processing.
+	F32					processEffect( const F32 current, const F32 target, const F32 rate );
+
 public:
     SceneObject();
     virtual ~SceneObject();
@@ -395,6 +406,12 @@ public:
     inline bool             isMoveToComplete( void ) const              { return mMoveToEventId == 0; }
     inline bool             isRotateToComplete( void ) const            { return mRotateToEventId == 0; }
 
+	// Fade to
+	bool					fadeTo( const ColorF& targetColor, const F32 deltaRed, const F32 deltaGreen, const F32 deltaBlue, const F32 deltaAlpha );
+	inline void				cancelFadeTo( void )						{ mFadeActive = false; }
+	inline bool				isFadeToComplete( void ) const				{ return !mFadeActive; }
+	void					updateBlendColor( const F32 elapsedTime );
+
     /// Force and impulse.
     void                    applyForce( const Vector2& worldForce, const bool wake = true );
     void                    applyForce( const Vector2& worldForce, const Vector2& worldPoint, const bool wake = true);

+ 106 - 0
engine/source/2d/sceneobject/SceneObject_ScriptBinding.h

@@ -1934,6 +1934,92 @@ ConsoleMethodWithDocs(SceneObject, rotateTo, ConsoleBool, 4, 6, (angle, speed, [
 
 //-----------------------------------------------------------------------------
 
+/*! Fades the object to the target color.
+	The current color of the object will continue to change until it arrives at the target color or the fade is cancelled.
+	The change will continue even if the blendColor is set directly.
+	@param (red / green / blue / alpha) The target color to fade the object to.
+	@param rate The rate per second to change each color value. Must be a number greater than zero.
+	@return Whether the fade started or not.
+*/
+ConsoleMethodWithDocs(SceneObject, fadeTo, ConsoleBool, 4, 4, (targetColor red / green / blue / alpha, rate))
+{
+	if (argc < 3)
+	{
+		Con::warnf("Scene::fadeTo() - Invalid number of parameters!");
+		return false;
+	}
+
+	const U32 colorCount = Utility::mGetStringElementCount(argv[2]);
+	if (colorCount != 4)
+	{
+		Con::warnf("Scene::fadeTo() - Invalid color! Colors require four values (red / green / blue / alpha)!");
+		return false;
+	}
+
+	F32 rate = dAtof(argv[3]);
+	if (rate <= 0.0f)
+	{
+		Con::warnf("Scene::fadeTo() - Rate must be greater than zero!");
+		return false;
+	}
+
+	return object->fadeTo(ColorF(dAtof(Utility::mGetStringElement(argv[2], 0)),
+								 dAtof(Utility::mGetStringElement(argv[2], 1)),
+								 dAtof(Utility::mGetStringElement(argv[2], 2)),
+								 dAtof(Utility::mGetStringElement(argv[2], 3))), 
+								 rate, rate, rate, rate);
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Fades the object to the target color over a period of time.
+	The current color of the object will continue to change until it arrives at the target color or the fade is cancelled.
+	The change will continue even if the blendColor is set directly which will change the amount of time it takes.
+	Unhindered, each of the color values will arrive at the target in approximately the target time.
+	@param (red / green / blue / alpha) The target color to fade the object to.
+	@param time The amount of time in milliseconds that each color value will take to reach the target. Must be a number greater than zero.
+	@return Whether the fade started or not.
+*/
+ConsoleMethodWithDocs(SceneObject, fadeToTime, ConsoleBool, 4, 4, (targetColor red / green / blue / alpha, time))
+{
+	if (argc < 3)
+	{
+		Con::warnf("Scene::fadeToTime() - Invalid number of parameters!");
+		return false;
+	}
+
+	const U32 colorCount = Utility::mGetStringElementCount(argv[2]);
+	if (colorCount != 4)
+	{
+		Con::warnf("Scene::fadeToTime() - Invalid color! Colors require four values (red / green / blue / alpha)!");
+		return false;
+	}
+
+	F32 time = dAtof(argv[3]);
+	if (time <= 0.0f)
+	{
+		Con::warnf("Scene::fadeToTime() - Time must be greater than zero!");
+		return false;
+	}
+
+	// Get the target color values.
+	const F32 tRed = dAtof(Utility::mGetStringElement(argv[2], 0));
+	const F32 tGreen = dAtof(Utility::mGetStringElement(argv[2], 1));
+	const F32 tBlue = dAtof(Utility::mGetStringElement(argv[2], 2));
+	const F32 tAlpha = dAtof(Utility::mGetStringElement(argv[2], 3));
+
+	// Get the rate to change each value. The rate will be change per second.
+	const ColorF currentColor = object->getBlendColor();
+	F32 rRed = (1000.0f * fabs(tRed - currentColor.red)) / time;
+	F32 rGreen = (1000.0f * fabs(tGreen - currentColor.green)) / time;
+	F32 rBlue = (1000.0f * fabs(tBlue - currentColor.blue)) / time;
+	F32 rAlpha = (1000.0f * fabs(tAlpha - currentColor.alpha)) / time;
+
+	return object->fadeTo(ColorF(tRed, tGreen, tBlue, tAlpha), rRed, rGreen, rBlue, rAlpha);
+}
+
+//-----------------------------------------------------------------------------
+
 /*! Stop a previous 'moveTo' command.
     @param autoStop? - Whether to automatically set the linear velocity to zero or not
     @return No return value.
@@ -1972,6 +2058,16 @@ ConsoleMethodWithDocs(SceneObject, cancelRotateTo, ConsoleVoid, 2, 3, ([autoStop
 
 //-----------------------------------------------------------------------------
 
+/*! Stop a previous 'fadeTo' command.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(SceneObject, cancelFadeTo, ConsoleVoid, 2, 2, ())
+{
+	object->cancelFadeTo();
+}
+
+//-----------------------------------------------------------------------------
+
 /*! Gets whether a previous 'moveTo' command has completed or not.
     @return No return value.
 */
@@ -1992,6 +2088,16 @@ ConsoleMethodWithDocs(SceneObject, isRotateToComplete, ConsoleBool, 2, 2, ())
 
 //-----------------------------------------------------------------------------
 
+/*! Gets whether a previous 'fadeTo' command has completed or not.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(SceneObject, isFadeToComplete, ConsoleBool, 2, 2, ())
+{
+	return object->isFadeToComplete();
+}
+
+//-----------------------------------------------------------------------------
+
 /*! Applies a force at a world point.
     If the force is not applied at the center of mass, it will generate a torque and affect the angular velocity.
     @param worldForceX/Y - The world force vector in Newtons (N).