Browse Source

Merge pull request #256 from greenfire27/FadeToBranch

Added Fading Functionality
Peter Robinson 10 years ago
parent
commit
5f78a091b2

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

@@ -150,6 +150,14 @@ SceneObject::SceneObject() :
     mBlendColor(ColorF(1.0f,1.0f,1.0f,1.0f)),
     mBlendColor(ColorF(1.0f,1.0f,1.0f,1.0f)),
     mAlphaTest(-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.
     /// Render sorting.
     mSortPoint(0.0f,0.0f),
     mSortPoint(0.0f,0.0f),
 
 
@@ -610,6 +618,12 @@ void SceneObject::integrateObject( const F32 totalTime, const F32 elapsedTime, D
         // Yes, so calculate camera mount.
         // Yes, so calculate camera mount.
         mpAttachedCamera->calculateCameraMount( elapsedTime );
         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");
         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?
     // Are we using the sleeping callback?
     if ( mSleepingCallback )
     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 )
 void SceneObject::cancelMoveTo( const bool autoStop )
 {
 {
     // Only cancel an active moveTo event
     // 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 )
 static void WriteCircleCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement )
 {
 {
     // Sanity!
     // Sanity!

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

@@ -179,6 +179,14 @@ protected:
     ColorF                  mBlendColor;
     ColorF                  mBlendColor;
     F32                     mAlphaTest;
     F32                     mAlphaTest;
 
 
+	// Fading
+	bool					mFadeActive;
+	ColorF					mTargetColor;
+	F32						mDeltaRed;
+	F32						mDeltaGreen;
+	F32						mDeltaBlue;
+	F32						mDeltaAlpha;
+
     /// Render sorting.
     /// Render sorting.
     Vector2                 mSortPoint;
     Vector2                 mSortPoint;
 
 
@@ -239,6 +247,9 @@ protected:
     virtual void            onTamlCustomWrite( TamlCustomNodes& customNodes );
     virtual void            onTamlCustomWrite( TamlCustomNodes& customNodes );
     virtual void            onTamlCustomRead( const TamlCustomNodes& customNodes );
     virtual void            onTamlCustomRead( const TamlCustomNodes& customNodes );
 
 
+	// Effect Processing.
+	F32					processEffect( const F32 current, const F32 target, const F32 rate );
+
 public:
 public:
     SceneObject();
     SceneObject();
     virtual ~SceneObject();
     virtual ~SceneObject();
@@ -395,6 +406,12 @@ public:
     inline bool             isMoveToComplete( void ) const              { return mMoveToEventId == 0; }
     inline bool             isMoveToComplete( void ) const              { return mMoveToEventId == 0; }
     inline bool             isRotateToComplete( void ) const            { return mRotateToEventId == 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.
     /// Force and impulse.
     void                    applyForce( const Vector2& worldForce, const bool wake = true );
     void                    applyForce( const Vector2& worldForce, const bool wake = true );
     void                    applyForce( const Vector2& worldForce, const Vector2& worldPoint, 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

@@ -1956,6 +1956,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.
 /*! Stop a previous 'moveTo' command.
     @param autoStop? - Whether to automatically set the linear velocity to zero or not
     @param autoStop? - Whether to automatically set the linear velocity to zero or not
     @return No return value.
     @return No return value.
@@ -1994,6 +2080,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.
 /*! Gets whether a previous 'moveTo' command has completed or not.
     @return No return value.
     @return No return value.
 */
 */
@@ -2014,6 +2110,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.
 /*! 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.
     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).
     @param worldForceX/Y - The world force vector in Newtons (N).