Files
itgmania212121/stepmania/src/Actor.cpp
T

1367 lines
45 KiB
C++
Raw Normal View History

2004-06-08 00:47:53 +00:00
#include "global.h"
2001-11-03 10:52:42 +00:00
#include "Actor.h"
2002-05-19 01:59:48 +00:00
#include "RageDisplay.h"
#include "RageUtil.h"
#include "RageMath.h"
#include "GameConstantsAndTypes.h"
2003-03-02 01:43:33 +00:00
#include "RageLog.h"
2004-06-10 22:47:51 +00:00
#include "arch/Dialog/Dialog.h"
#include "Foreach.h"
#include "XmlFile.h"
2005-01-24 02:26:55 +00:00
#include "LuaBinding.h"
2005-01-26 11:21:43 +00:00
#include "Command.h"
#include "ActorCommands.h"
2005-02-12 22:54:15 +00:00
#include "ThemeManager.h"
#include "LuaReference.h"
#include "MessageManager.h"
#include "LightsManager.h" // for NUM_CABINET_LIGHTS
2005-01-24 02:26:55 +00:00
float Actor::g_fCurrentBGMTime = 0, Actor::g_fCurrentBGMBeat;
2003-12-18 10:31:42 +00:00
2005-04-29 00:07:33 +00:00
static float g_fCabinetLights[NUM_CABINET_LIGHTS];
2005-04-28 23:55:47 +00:00
void Actor::SetBGMTime( float fTime, float fBeat )
{
g_fCurrentBGMTime = fTime;
g_fCurrentBGMBeat = fBeat;
}
2005-04-29 00:07:33 +00:00
void Actor::SetBGMLight( int iLightNumber, float fCabinetLights )
2005-04-28 23:55:47 +00:00
{
2005-04-29 00:07:33 +00:00
ASSERT( iLightNumber < NUM_CABINET_LIGHTS );
g_fCabinetLights[iLightNumber] = fCabinetLights;
2005-04-28 23:55:47 +00:00
}
2003-04-02 05:41:22 +00:00
/* This is Reset instead of Init since many derived classes have Init() functions
* that shouldn't change the position of the actor. */
void Actor::Reset()
2001-11-03 10:52:42 +00:00
{
2005-01-16 04:35:47 +00:00
m_Tweens.clear();
2003-10-07 04:26:14 +00:00
m_pTempState = NULL;
m_baseRotation = RageVector3( 0, 0, 0 );
m_baseScale = RageVector3( 1, 1, 1 );
2005-04-30 07:48:10 +00:00
m_fBaseAlpha = 1;
m_start.Init();
m_current.Init();
m_HorizAlign = align_center;
m_VertAlign = align_middle;
2003-02-17 12:19:42 +00:00
m_Effect = no_effect;
m_fSecsIntoEffect = 0;
2004-10-18 04:19:20 +00:00
m_fEffectDelta = 0;
2003-02-17 12:19:42 +00:00
m_fEffectPeriodSeconds = 1;
2004-01-20 23:25:38 +00:00
m_fEffectDelay = 0;
m_fEffectOffset = 0;
2003-12-18 10:31:42 +00:00
m_EffectClock = CLOCK_TIMER;
2003-03-02 01:43:33 +00:00
m_vEffectMagnitude = RageVector3(0,0,10);
m_effectColor1 = RageColor(1,1,1,1);
m_effectColor2 = RageColor(1,1,1,1);
m_bVisible = true;
m_fShadowLength = 0;
2003-03-05 02:52:40 +00:00
m_bIsAnimating = true;
m_fHibernateSecondsLeft = 0;
2004-05-02 03:01:27 +00:00
m_iDrawOrder = 0;
m_bTextureWrapping = false;
m_BlendMode = BLEND_NORMAL;
m_fZBias = 0;
2003-07-07 20:24:51 +00:00
m_bClearZBuffer = false;
2004-05-15 09:26:21 +00:00
m_ZTestMode = ZTEST_OFF;
2003-11-18 20:33:18 +00:00
m_bZWrite = false;
2004-02-04 11:05:33 +00:00
m_CullMode = CULL_NONE;
2005-01-04 10:41:32 +00:00
UnsubcribeAndClearCommands();
2001-11-03 10:52:42 +00:00
}
static bool GetMessageNameFromCommandName( const CString &sCommandName, CString &sMessageNameOut )
{
if( sCommandName.Right(7) == "Message" )
{
sMessageNameOut = sCommandName.Left(sCommandName.size()-7);
return true;
}
else
{
return false;
}
}
void Actor::UnsubcribeAndClearCommands()
{
2005-03-08 16:54:48 +00:00
FOREACH_CONST( CString, m_vsSubscribedTo, s )
MESSAGEMAN->Unsubscribe( this, *s );
m_vsSubscribedTo.clear();
}
2005-06-21 05:23:25 +00:00
Actor::Actor()
{
2005-07-04 21:45:16 +00:00
m_pLuaInstance = new LuaClass;
2005-06-21 05:23:25 +00:00
m_size = RageVector2( 1, 1 );
Reset();
m_bFirstUpdate = true;
}
Actor::~Actor()
{
UnsubcribeAndClearCommands();
}
void Actor::LoadFromNode( const CString& sDir, const XNode* pNode )
{
// Load Name, if any.
pNode->GetAttrValue( "Name", m_sName );
float f;
if( pNode->GetAttrValue( "BaseRotationXDegrees", f ) ) SetBaseRotationX( f );
if( pNode->GetAttrValue( "BaseRotationYDegrees", f ) ) SetBaseRotationY( f );
if( pNode->GetAttrValue( "BaseRotationZDegrees", f ) ) SetBaseRotationZ( f );
if( pNode->GetAttrValue( "BaseZoomX", f ) ) SetBaseZoomX( f );
if( pNode->GetAttrValue( "BaseZoomY", f ) ) SetBaseZoomY( f );
if( pNode->GetAttrValue( "BaseZoomZ", f ) ) SetBaseZoomZ( f );
//
// Load commands
//
FOREACH_CONST_Attr( pNode, a )
{
CString sKeyName = a->m_sName; /* "OnCommand" */
if( sKeyName.Right(7).CompareNoCase("Command") != 0 )
continue; /* not a command */
2005-02-12 22:54:15 +00:00
CString sValue = a->m_sValue;
THEME->EvaluateString( sValue );
2005-02-23 20:58:07 +00:00
apActorCommands apac( new ActorCommands( sValue ) );
2005-01-26 11:21:43 +00:00
CString sCmdName;
/* Special case: "Command=foo" -> "OnCommand=foo" */
if( sKeyName.size() == 7 )
sCmdName="On";
else
sCmdName = sKeyName.Left( sKeyName.size()-7 );
AddCommand( sCmdName, apac );
}
/* There's an InitCommand. Run it now. This can be used to eg. change Z to
* modify draw order between BGAs in a Foreground. */
PlayCommand( "Init" );
}
2002-08-19 20:02:30 +00:00
void Actor::Draw()
{
if( !m_bVisible )
return; // early abort
if( m_fHibernateSecondsLeft > 0 )
return; // early abort
if( this->EarlyAbortDraw() )
return;
2002-08-19 20:02:30 +00:00
// call the most-derived versions
this->BeginDraw();
this->DrawPrimitives(); // call the most-derived version of DrawPrimitives();
this->EndDraw();
}
void Actor::BeginDraw() // set the world matrix and calculate actor properties
2001-11-28 20:26:45 +00:00
{
2002-05-19 01:59:48 +00:00
DISPLAY->PushMatrix(); // we're actually going to do some drawing in this function
2002-01-16 10:01:32 +00:00
2005-04-30 07:48:10 +00:00
// Somthing below may set m_pTempState to m_tempState
m_pTempState = &m_current;
//
// set temporary drawing properties based on Effects
//
2003-10-07 04:26:14 +00:00
if( m_Effect == no_effect )
2001-11-28 20:26:45 +00:00
{
}
else if( m_Effect == effect_lua )
{
/* Allow a Lua function to set the frame's draw state. This may be expensive
* and has not been well-benchmarked yet; use wisely. This allows arbitrary
* effects, instead of the mess of parameters below. (In fact, all this does
* is run a command, but to avoid calling RunCommand() all the time, and due
* to the fact that this is the only place where the TempState is meaningful,
* we treat this as an effect.) */
m_pTempState = &m_tempState;
m_tempState = m_current;
PlayCommand( m_sEffectCommand );
}
2003-10-07 04:26:14 +00:00
else
{
m_pTempState = &m_tempState;
m_tempState = m_current;
2004-01-20 23:25:38 +00:00
/* EffectPeriodSeconds is the total time of the effect (including delay).
* m_fEffectDelay is the amount of time to stick on 0%. Offset shifts the
* entire thing forwards. For example, if m_fEffectPeriodSeconds is 1,
* the effect can happen from .40 to .55 by setting offset to .40 and
* delay to .85. */
const float fTotalPeriod = m_fEffectPeriodSeconds + m_fEffectDelay;
2004-08-08 18:12:28 +00:00
CHECKPOINT_M( ssprintf("%f = %f + %f", fTotalPeriod, m_fEffectPeriodSeconds, m_fEffectDelay) );
2004-01-20 23:25:38 +00:00
const float fSecsIntoPeriod = fmodfp( m_fSecsIntoEffect+m_fEffectOffset, fTotalPeriod );
2004-08-08 18:12:28 +00:00
CHECKPOINT_M( ssprintf("%f = fmodfp(%f + %f, %f)", fSecsIntoPeriod, m_fSecsIntoEffect, m_fEffectOffset, fTotalPeriod) );
2003-12-18 10:31:42 +00:00
2004-01-20 23:25:38 +00:00
float fPercentThroughEffect = SCALE( fSecsIntoPeriod, 0, m_fEffectPeriodSeconds, 0, 1 );
2004-08-08 18:12:28 +00:00
CHECKPOINT_M( ssprintf("%f = SCALE(%f, 0, %f, 0, 1)", fPercentThroughEffect, fSecsIntoPeriod, m_fEffectPeriodSeconds) );
2004-01-20 23:25:38 +00:00
fPercentThroughEffect = clamp( fPercentThroughEffect, 0, 1 );
2004-08-08 18:12:28 +00:00
ASSERT_M( fPercentThroughEffect >= 0 && fPercentThroughEffect <= 1,
ssprintf("%f", fPercentThroughEffect) );
2004-01-20 23:25:38 +00:00
bool bBlinkOn = fPercentThroughEffect > 0.5f;
float fPercentBetweenColors = RageFastSin( (fPercentThroughEffect + 0.25f) * 2 * PI ) / 2 + 0.5f;
2004-08-08 18:12:28 +00:00
ASSERT_M( fPercentBetweenColors >= 0 && fPercentBetweenColors <= 1,
ssprintf("%f, %f", fPercentBetweenColors, fPercentThroughEffect) );
2003-10-07 04:26:14 +00:00
float fOriginalAlpha = m_tempState.diffuse[0].a;
2001-11-28 20:26:45 +00:00
2003-10-07 04:26:14 +00:00
switch( m_Effect )
{
case diffuse_blink:
/* XXX: Should diffuse_blink and diffuse_shift multiply the tempState color?
* (That would have the same effect with 1,1,1,1, and allow tweening the diffuse
* while blinking and shifting.) */
2004-09-21 07:53:39 +00:00
for(int i=0; i<4; i++)
{
2003-10-07 04:26:14 +00:00
m_tempState.diffuse[i] = bBlinkOn ? m_effectColor1 : m_effectColor2;
m_tempState.diffuse[i].a *= fOriginalAlpha; // multiply the alphas so we can fade even while an effect is playing
}
2003-10-07 04:26:14 +00:00
break;
case diffuse_shift:
2004-09-21 07:53:39 +00:00
for(int i=0; i<4; i++)
{
2003-10-07 04:26:14 +00:00
m_tempState.diffuse[i] = m_effectColor1*fPercentBetweenColors + m_effectColor2*(1.0f-fPercentBetweenColors);
m_tempState.diffuse[i].a *= fOriginalAlpha; // multiply the alphas so we can fade even while an effect is playing
}
2003-10-07 04:26:14 +00:00
break;
2005-03-21 10:49:51 +00:00
case diffuse_ramp:
for(int i=0; i<4; i++)
{
2005-03-21 10:49:51 +00:00
m_tempState.diffuse[i] = m_effectColor1*fPercentThroughEffect + m_effectColor2*(1.0f-fPercentThroughEffect);
m_tempState.diffuse[i].a *= fOriginalAlpha; // multiply the alphas so we can fade even while an effect is playing
}
2005-03-21 10:49:51 +00:00
break;
2003-10-07 04:26:14 +00:00
case glow_blink:
m_tempState.glow = bBlinkOn ? m_effectColor1 : m_effectColor2;
m_tempState.glow.a *= fOriginalAlpha; // don't glow if the Actor is transparent!
break;
case glow_shift:
m_tempState.glow = m_effectColor1*fPercentBetweenColors + m_effectColor2*(1.0f-fPercentBetweenColors);
m_tempState.glow.a *= fOriginalAlpha; // don't glow if the Actor is transparent!
break;
case rainbow:
m_tempState.diffuse[0] = RageColor(
RageFastCos( fPercentBetweenColors*2*PI ) * 0.5f + 0.5f,
RageFastCos( fPercentBetweenColors*2*PI + PI * 2.0f / 3.0f ) * 0.5f + 0.5f,
RageFastCos( fPercentBetweenColors*2*PI + PI * 4.0f / 3.0f) * 0.5f + 0.5f,
2003-10-07 04:26:14 +00:00
fOriginalAlpha );
2004-09-21 07:53:39 +00:00
for( int i=1; i<4; i++ )
2003-10-07 04:26:14 +00:00
m_tempState.diffuse[i] = m_tempState.diffuse[0];
break;
case wag:
m_tempState.rotation += m_vEffectMagnitude * RageFastSin( fPercentThroughEffect * 2.0f * PI );
2003-10-07 04:26:14 +00:00
break;
case spin:
// nothing needs to be here
break;
case vibrate:
m_tempState.pos.x += m_vEffectMagnitude.x * randomf(-1.0f, 1.0f) * GetZoom();
m_tempState.pos.y += m_vEffectMagnitude.y * randomf(-1.0f, 1.0f) * GetZoom();
m_tempState.pos.z += m_vEffectMagnitude.z * randomf(-1.0f, 1.0f) * GetZoom();
break;
case bounce:
{
float fPercentOffset = RageFastSin( fPercentThroughEffect*PI );
2003-10-07 04:26:14 +00:00
m_tempState.pos += m_vEffectMagnitude * fPercentOffset;
m_tempState.pos.x = roundf( m_tempState.pos.x );
m_tempState.pos.y = roundf( m_tempState.pos.y );
m_tempState.pos.z = roundf( m_tempState.pos.z );
}
break;
case bob:
{
float fPercentOffset = RageFastSin( fPercentThroughEffect*PI*2 );
2003-10-07 04:26:14 +00:00
m_tempState.pos += m_vEffectMagnitude * fPercentOffset;
m_tempState.pos.x = roundf( m_tempState.pos.x );
m_tempState.pos.y = roundf( m_tempState.pos.y );
m_tempState.pos.z = roundf( m_tempState.pos.z );
}
break;
case pulse:
{
float fMinZoom = m_vEffectMagnitude[0];
float fMaxZoom = m_vEffectMagnitude[1];
float fPercentOffset = RageFastSin( fPercentThroughEffect*PI );
2003-10-07 04:26:14 +00:00
float fZoom = SCALE( fPercentOffset, 0.f, 1.f, fMinZoom, fMaxZoom );
m_tempState.scale *= fZoom;
// Use the color as a Vector3 to scale the effect for added control
RageColor c = SCALE( fPercentOffset, 0.f, 1.f, m_effectColor1, m_effectColor2 );
m_tempState.scale.x *= c.r;
m_tempState.scale.y *= c.g;
m_tempState.scale.z *= c.b;
2003-10-07 04:26:14 +00:00
}
break;
default:
ASSERT(0); // invalid Effect
}
}
2002-01-16 10:01:32 +00:00
2005-04-30 07:48:10 +00:00
if( m_fBaseAlpha != 1 )
{
if( m_pTempState != &m_tempState )
{
m_pTempState = &m_tempState;
m_tempState = m_current;
}
for( int i=0; i<4; i++ )
m_tempState.diffuse[i].a *= m_fBaseAlpha;
}
{
RageMatrix m;
RageMatrixTranslateAndScale( &m,
m_pTempState->pos.x,
m_pTempState->pos.y,
m_pTempState->pos.z,
m_pTempState->scale.x * m_baseScale.x,
m_pTempState->scale.y * m_baseScale.y,
m_pTempState->scale.z * m_baseScale.z );
DISPLAY->PreMultMatrix( m );
}
{
/* The only time rotation and quat should normally be used simultaneously
* is for m_baseRotation. Most objects aren't rotated at all, so optimize
* that case. */
const float fRotateX = m_pTempState->rotation.x + m_baseRotation.x;
const float fRotateY = m_pTempState->rotation.y + m_baseRotation.y;
const float fRotateZ = m_pTempState->rotation.z + m_baseRotation.z;
if( fRotateX != 0 || fRotateY != 0 || fRotateZ != 0 )
{
RageMatrix m;
RageMatrixRotationXYZ( &m, fRotateX, fRotateY, fRotateZ );
DISPLAY->PreMultMatrix( m );
}
}
2003-10-07 04:26:14 +00:00
if( m_pTempState->quat.x != 0 || m_pTempState->quat.y != 0 || m_pTempState->quat.z != 0 || m_pTempState->quat.w != 1 )
{
RageMatrix mat;
2003-10-07 04:26:14 +00:00
RageMatrixFromQuat( &mat, m_pTempState->quat );
DISPLAY->MultMatrix(mat);
}
2005-05-02 21:43:27 +00:00
if( m_pTempState->fSkewX != 0 )
{
DISPLAY->SkewX( m_pTempState->fSkewX );
}
2002-08-19 20:02:30 +00:00
}
2002-01-16 10:01:32 +00:00
2005-02-27 08:31:41 +00:00
void Actor::SetGlobalRenderStates()
{
// set Actor-defined render states
DISPLAY->SetBlendMode( m_BlendMode );
2003-11-18 20:33:18 +00:00
DISPLAY->SetZWrite( m_bZWrite );
2004-05-15 09:26:21 +00:00
DISPLAY->SetZTestMode( m_ZTestMode );
2005-05-06 03:24:41 +00:00
// BLEND_NO_EFFECT is used to draw masks to the Z-buffer, which always wants
// Z-bias enabled.
if( m_fZBias == 0 && m_BlendMode == BLEND_NO_EFFECT )
DISPLAY->SetZBias( 1.0f );
else
DISPLAY->SetZBias( m_fZBias );
2005-05-06 03:24:41 +00:00
2003-07-07 20:24:51 +00:00
if( m_bClearZBuffer )
DISPLAY->ClearZBuffer();
2004-02-04 11:05:33 +00:00
DISPLAY->SetCullMode( m_CullMode );
}
2005-02-27 08:31:41 +00:00
void Actor::SetTextureRenderStates()
{
DISPLAY->SetTextureWrapping( m_bTextureWrapping );
}
2002-08-19 20:02:30 +00:00
void Actor::EndDraw()
{
2002-05-19 01:59:48 +00:00
DISPLAY->PopMatrix();
m_pTempState = NULL;
2001-11-28 20:26:45 +00:00
}
2002-09-04 21:53:43 +00:00
void Actor::UpdateTweening( float fDeltaTime )
{
2003-05-16 21:09:26 +00:00
while( 1 )
{
2005-01-16 04:35:47 +00:00
if( m_Tweens.empty() ) // nothing to do
2003-05-16 21:09:26 +00:00
return;
2002-09-04 21:53:43 +00:00
2003-05-16 21:09:26 +00:00
if( fDeltaTime == 0 ) // nothing will change
return;
2002-09-04 21:53:43 +00:00
2003-05-16 21:09:26 +00:00
// update current tween state
2005-01-16 04:35:47 +00:00
// earliest tween
TweenState &TS = m_Tweens[0].state;
TweenInfo &TI = m_Tweens[0].info;
2002-09-04 21:53:43 +00:00
2003-05-16 21:09:26 +00:00
if( TI.m_fTimeLeftInTween == TI.m_fTweenTime ) // we are just beginning this tween
2004-04-24 18:38:18 +00:00
{
2003-05-16 21:09:26 +00:00
m_start = m_current; // set the start position
2002-09-04 21:53:43 +00:00
2004-04-24 18:38:18 +00:00
// Execute the command in this tween (if any).
2005-01-26 11:21:43 +00:00
if( TS.sCommandName.size() )
{
2005-02-27 03:21:18 +00:00
if( TS.sCommandName.Left(1) == "!" )
MESSAGEMAN->Broadcast( TS.sCommandName.substr(1) );
else
this->PlayCommand( TS.sCommandName );
2005-01-26 11:21:43 +00:00
}
2004-04-24 18:38:18 +00:00
}
2003-05-16 21:09:26 +00:00
float fSecsToSubtract = min( TI.m_fTimeLeftInTween, fDeltaTime );
TI.m_fTimeLeftInTween -= fSecsToSubtract;
fDeltaTime -= fSecsToSubtract;
if( TI.m_fTimeLeftInTween == 0 ) // Current tween is over. Stop.
2002-09-04 21:53:43 +00:00
{
2003-05-16 21:09:26 +00:00
m_current = TS;
// don't inherit the queued state's command. We keep having to do this.
// Does sCommandName belong in TweenInfo, instead of TweenState?
m_current.sCommandName = "";
2003-05-16 21:09:26 +00:00
// delete the head tween
2005-01-16 04:35:47 +00:00
m_Tweens.pop_front();
2003-05-16 21:09:26 +00:00
}
else // in the middle of tweening. Recalcute the current position.
{
const float fPercentThroughTween = 1-(TI.m_fTimeLeftInTween / TI.m_fTweenTime);
// distort the percentage if appropriate
float fPercentAlongPath = 0.f;
switch( TI.m_TweenType )
{
case TWEEN_LINEAR: fPercentAlongPath = fPercentThroughTween; break;
case TWEEN_ACCELERATE: fPercentAlongPath = fPercentThroughTween * fPercentThroughTween; break;
case TWEEN_DECELERATE: fPercentAlongPath = 1 - (1-fPercentThroughTween) * (1-fPercentThroughTween); break;
case TWEEN_BOUNCE_BEGIN:fPercentAlongPath = 1 - RageFastSin( 1.1f + fPercentThroughTween*(PI-1.1f) ) / 0.89f; break;
case TWEEN_BOUNCE_END: fPercentAlongPath = RageFastSin( 1.1f + (1-fPercentThroughTween)*(PI-1.1f) ) / 0.89f; break;
case TWEEN_SPRING: fPercentAlongPath = 1 - RageFastCos( fPercentThroughTween*PI*2.5f )/(1+fPercentThroughTween*3); break;
2003-05-16 21:09:26 +00:00
default: ASSERT(0);
}
TweenState::MakeWeightedAverage( m_current, m_start, TS, fPercentAlongPath );
2002-09-04 21:53:43 +00:00
}
}
}
2001-11-28 20:26:45 +00:00
2004-12-27 22:30:51 +00:00
bool Actor::IsFirstUpdate() const
{
return m_bFirstUpdate;
}
2002-01-16 10:01:32 +00:00
void Actor::Update( float fDeltaTime )
2001-11-03 10:52:42 +00:00
{
// LOG->Trace( "Actor::Update( %f )", fDeltaTime );
ASSERT_M( fDeltaTime >= 0, ssprintf("%f",fDeltaTime) );
2001-11-03 10:52:42 +00:00
2005-02-28 18:16:41 +00:00
if( m_fHibernateSecondsLeft > 0 )
{
m_fHibernateSecondsLeft -= fDeltaTime;
2005-02-28 18:16:41 +00:00
if( m_fHibernateSecondsLeft > 0 )
return;
2005-02-28 18:16:41 +00:00
/* Grab the leftover time. */
fDeltaTime = -m_fHibernateSecondsLeft;
m_fHibernateSecondsLeft = 0;
}
this->UpdateInternal( fDeltaTime );
}
void Actor::UpdateInternal( float fDeltaTime )
{
if( m_bFirstUpdate )
m_bFirstUpdate = false;
2004-10-18 04:19:20 +00:00
switch( m_EffectClock )
{
case CLOCK_TIMER:
m_fSecsIntoEffect += fDeltaTime;
m_fEffectDelta = fDeltaTime;
2005-02-28 18:16:41 +00:00
/* Wrap the counter, so it doesn't increase indefinitely (causing loss of
* precision if a screen is left to sit for a day). */
if( m_fSecsIntoEffect >= m_fEffectPeriodSeconds + m_fEffectDelay )
m_fSecsIntoEffect -= m_fEffectPeriodSeconds + m_fEffectDelay;
2004-10-18 04:19:20 +00:00
break;
case CLOCK_BGM_BEAT:
m_fEffectDelta = g_fCurrentBGMBeat - m_fSecsIntoEffect;
m_fSecsIntoEffect = g_fCurrentBGMBeat;
break;
case CLOCK_BGM_TIME:
m_fEffectDelta = g_fCurrentBGMTime - m_fSecsIntoEffect;
m_fSecsIntoEffect = g_fCurrentBGMTime;
break;
2005-04-28 23:55:47 +00:00
default:
if( m_EffectClock >= CLOCK_LIGHT_1 && m_EffectClock <= CLOCK_LIGHT_LAST )
{
int i = m_EffectClock - CLOCK_LIGHT_1;
2005-04-29 00:07:33 +00:00
m_fEffectDelta = g_fCabinetLights[i] - m_fSecsIntoEffect;
m_fSecsIntoEffect = g_fCabinetLights[i];
2005-04-28 23:55:47 +00:00
}
break;
2004-10-18 04:19:20 +00:00
}
2001-11-28 20:26:45 +00:00
// update effect
switch( m_Effect )
{
2003-03-02 01:43:33 +00:00
case spin:
2005-05-04 05:25:53 +00:00
m_current.rotation += m_fEffectDelta*m_vEffectMagnitude;
wrap( m_current.rotation.x, 360 );
wrap( m_current.rotation.y, 360 );
wrap( m_current.rotation.z, 360 );
2001-11-28 20:26:45 +00:00
break;
}
2002-09-04 21:53:43 +00:00
UpdateTweening( fDeltaTime );
2001-11-03 10:52:42 +00:00
}
2002-01-16 10:01:32 +00:00
void Actor::BeginTweening( float time, TweenType tt )
2001-11-03 10:52:42 +00:00
{
2002-04-16 17:31:00 +00:00
ASSERT( time >= 0 );
2002-01-16 10:01:32 +00:00
2003-03-09 00:55:49 +00:00
time = max( time, 0 );
2005-03-20 20:37:24 +00:00
// If the number of tweens to ever gets this large, there's probably an infinitely
// recursing ActorCommand.
if( m_Tweens.size() > 50 )
{
2005-03-23 21:04:40 +00:00
CString sError = ssprintf( "Tween overflow: size = %u. infinitely recursing ActorCommand?", unsigned(m_Tweens.size()) );
2005-03-20 20:37:24 +00:00
LOG->Warn( sError );
Dialog::OK( sError );
FinishTweening();
}
2002-03-09 06:19:40 +00:00
// add a new TweenState to the tail, and initialize it
2005-01-16 04:35:47 +00:00
m_Tweens.resize( m_Tweens.size()+1 );
2003-02-25 02:51:04 +00:00
2005-01-16 04:35:47 +00:00
// latest
TweenState &TS = m_Tweens.back().state;
TweenInfo &TI = m_Tweens.back().info;
2002-01-16 10:01:32 +00:00
2005-01-16 04:35:47 +00:00
if( m_Tweens.size() >= 2 ) // if there was already a TS on the stack
2002-03-09 06:19:40 +00:00
{
// initialize the new TS from the last TS in the list
2005-01-16 04:35:47 +00:00
TS = m_Tweens[m_Tweens.size()-2].state;
// don't inherit the queued state's command
2005-01-26 11:21:43 +00:00
TS.sCommandName = "";
2002-03-09 06:19:40 +00:00
}
else
{
// This new TS is the only TS.
// Set our tween starting and ending values to the current position.
TS = m_current;
2002-03-09 06:19:40 +00:00
}
2002-01-16 10:01:32 +00:00
TI.m_TweenType = tt;
TI.m_fTweenTime = time;
TI.m_fTimeLeftInTween = time;
2001-11-03 10:52:42 +00:00
}
2002-05-28 20:01:22 +00:00
void Actor::StopTweening()
{
2005-01-16 04:35:47 +00:00
m_Tweens.clear();
2002-05-28 20:01:22 +00:00
}
2003-06-16 17:33:28 +00:00
void Actor::FinishTweening()
{
m_current = DestTweenState();
StopTweening();
}
2002-05-28 20:01:22 +00:00
2003-11-18 17:50:50 +00:00
void Actor::HurryTweening( float factor )
{
2005-01-16 04:35:47 +00:00
for( unsigned i = 0; i < m_Tweens.size(); ++i )
2003-11-18 17:50:50 +00:00
{
2005-01-16 04:35:47 +00:00
m_Tweens[i].info.m_fTimeLeftInTween *= factor;
m_Tweens[i].info.m_fTweenTime *= factor;
2003-11-18 17:50:50 +00:00
}
}
2001-11-03 10:52:42 +00:00
2004-09-22 02:20:50 +00:00
void Actor::ScaleTo( const RectF &rect, StretchType st )
2001-11-03 10:52:42 +00:00
{
// width and height of rectangle
2004-09-22 02:20:50 +00:00
float rect_width = rect.GetWidth();
float rect_height = rect.GetHeight();
2001-11-03 10:52:42 +00:00
2003-04-02 06:02:55 +00:00
if( rect_width < 0 ) SetRotationY( 180 );
if( rect_height < 0 ) SetRotationX( 180 );
2001-11-25 10:49:31 +00:00
2001-11-03 10:52:42 +00:00
// center of the rectangle
2002-11-01 20:01:59 +00:00
float rect_cx = rect.left + rect_width/2;
float rect_cy = rect.top + rect_height/2;
2001-11-03 10:52:42 +00:00
2002-01-16 10:01:32 +00:00
// zoom fActor needed to scale the Actor to fill the rectangle
2002-02-24 01:43:11 +00:00
float fNewZoomX = fabsf(rect_width / m_size.x);
float fNewZoomY = fabsf(rect_height / m_size.y);
2001-11-03 10:52:42 +00:00
float fNewZoom = 0.f;
2001-11-03 10:52:42 +00:00
switch( st )
{
case cover:
fNewZoom = fNewZoomX>fNewZoomY ? fNewZoomX : fNewZoomY; // use larger zoom
break;
case fit_inside:
fNewZoom = fNewZoomX>fNewZoomY ? fNewZoomY : fNewZoomX; // use smaller zoom
break;
}
2001-11-25 04:31:44 +00:00
SetXY( rect_cx, rect_cy );
2001-11-03 10:52:42 +00:00
SetZoom( fNewZoom );
}
2005-01-26 11:21:43 +00:00
void Actor::SetHorizAlignString( const CString &s )
2003-04-02 05:41:22 +00:00
{
2005-01-26 11:21:43 +00:00
if (s.CompareNoCase("left")==0) this->SetHorizAlign( align_left ); /* call derived */
else if(s.CompareNoCase("center")==0) this->SetHorizAlign( align_center );
else if(s.CompareNoCase("right")==0) this->SetHorizAlign( align_right );
2003-04-02 05:41:22 +00:00
else ASSERT(0);
}
2005-01-26 11:21:43 +00:00
void Actor::SetVertAlignString( const CString &s )
2003-04-02 05:41:22 +00:00
{
2005-01-26 11:21:43 +00:00
if (s.CompareNoCase("top")==0) this->SetVertAlign( align_top ); /* call derived */
else if(s.CompareNoCase("middle")==0) this->SetVertAlign( align_middle );
else if(s.CompareNoCase("bottom")==0) this->SetVertAlign( align_bottom );
2003-04-02 05:41:22 +00:00
else ASSERT(0);
}
2005-01-26 11:21:43 +00:00
void Actor::SetEffectClockString( const CString &s )
2003-12-18 10:31:42 +00:00
{
2005-01-26 11:21:43 +00:00
if (s.CompareNoCase("timer")==0) this->SetEffectClock( CLOCK_TIMER );
else if(s.CompareNoCase("beat")==0) this->SetEffectClock( CLOCK_BGM_BEAT );
else if(s.CompareNoCase("music")==0) this->SetEffectClock( CLOCK_BGM_TIME );
else if(s.CompareNoCase("bgm")==0) this->SetEffectClock( CLOCK_BGM_BEAT ); // compat, deprecated
2005-04-28 23:55:47 +00:00
else
{
CabinetLight cl = StringToCabinetLight( s );
if( cl != LIGHT_INVALID )
{
this->SetEffectClock( (EffectClock) (cl + CLOCK_LIGHT_1) );
return;
}
else
ASSERT(0);
}
2003-12-18 10:31:42 +00:00
}
void Actor::StretchTo( const RectF &r )
2001-11-03 10:52:42 +00:00
{
// width and height of rectangle
float width = r.GetWidth();
float height = r.GetHeight();
2001-11-03 10:52:42 +00:00
// center of the rectangle
float cx = r.left + width/2.0f;
float cy = r.top + height/2.0f;
2001-11-03 10:52:42 +00:00
2002-01-16 10:01:32 +00:00
// zoom fActor needed to scale the Actor to fill the rectangle
float fNewZoomX = width / m_size.x;
float fNewZoomY = height / m_size.y;
2001-11-03 10:52:42 +00:00
SetXY( cx, cy );
2002-01-16 10:01:32 +00:00
SetZoomX( fNewZoomX );
SetZoomY( fNewZoomY );
2001-11-03 10:52:42 +00:00
}
2001-11-28 20:26:45 +00:00
2003-03-02 01:43:33 +00:00
// effect "macros"
2001-11-28 20:26:45 +00:00
void Actor::SetEffectLua( const CString &sCommand )
{
m_Effect = effect_lua;
m_sEffectCommand = sCommand;
}
2003-03-02 01:43:33 +00:00
void Actor::SetEffectDiffuseBlink( float fEffectPeriodSeconds, RageColor c1, RageColor c2 )
2001-11-28 20:26:45 +00:00
{
if( m_Effect != diffuse_blink )
{
m_Effect = diffuse_blink;
m_fEffectPeriodSeconds = fEffectPeriodSeconds;
m_fSecsIntoEffect = 0;
}
2003-02-17 12:19:42 +00:00
m_effectColor1 = c1;
m_effectColor2 = c2;
2001-11-28 20:26:45 +00:00
}
2003-02-18 23:15:38 +00:00
void Actor::SetEffectDiffuseShift( float fEffectPeriodSeconds, RageColor c1, RageColor c2 )
2001-11-28 20:26:45 +00:00
{
if( m_Effect != diffuse_shift )
{
m_Effect = diffuse_shift;
m_fEffectPeriodSeconds = fEffectPeriodSeconds;
m_fSecsIntoEffect = 0;
}
2003-02-17 12:19:42 +00:00
m_effectColor1 = c1;
m_effectColor2 = c2;
2001-11-28 20:26:45 +00:00
}
2005-03-21 10:49:51 +00:00
void Actor::SetEffectDiffuseRamp( float fEffectPeriodSeconds, RageColor c1, RageColor c2 )
{
if( m_Effect != diffuse_ramp )
{
m_Effect = diffuse_ramp;
m_fEffectPeriodSeconds = fEffectPeriodSeconds;
m_fSecsIntoEffect = 0;
}
m_effectColor1 = c1;
m_effectColor2 = c2;
}
2003-03-02 01:43:33 +00:00
void Actor::SetEffectGlowBlink( float fEffectPeriodSeconds, RageColor c1, RageColor c2 )
2001-11-28 20:26:45 +00:00
{
if( m_Effect != glow_blink )
{
m_Effect = glow_blink;
m_fEffectPeriodSeconds = fEffectPeriodSeconds;
m_fSecsIntoEffect = 0;
}
2003-02-17 12:19:42 +00:00
m_effectColor1 = c1;
m_effectColor2 = c2;
}
2002-01-16 10:01:32 +00:00
2003-02-18 23:15:38 +00:00
void Actor::SetEffectGlowShift( float fEffectPeriodSeconds, RageColor c1, RageColor c2 )
2003-02-17 12:19:42 +00:00
{
if( m_Effect != glow_shift )
{
m_Effect = glow_shift;
m_fEffectPeriodSeconds = fEffectPeriodSeconds;
m_fSecsIntoEffect = 0;
}
2003-02-17 12:19:42 +00:00
m_effectColor1 = c1;
m_effectColor2 = c2;
2001-11-28 20:26:45 +00:00
}
2003-03-05 02:52:40 +00:00
void Actor::SetEffectRainbow( float fEffectPeriodSeconds )
{
m_Effect = rainbow;
m_fEffectPeriodSeconds = fEffectPeriodSeconds;
m_fSecsIntoEffect = 0;
}
2003-03-02 01:43:33 +00:00
void Actor::SetEffectWag( float fPeriod, RageVector3 vect )
2001-11-28 20:26:45 +00:00
{
2005-02-11 02:56:08 +00:00
if( m_Effect != wag )
{
m_Effect = wag;
m_fSecsIntoEffect = 0;
}
2003-03-02 01:43:33 +00:00
m_fEffectPeriodSeconds = fPeriod;
m_vEffectMagnitude = vect;
2002-01-16 10:01:32 +00:00
}
2003-03-02 01:43:33 +00:00
void Actor::SetEffectBounce( float fPeriod, RageVector3 vect )
2002-01-16 10:01:32 +00:00
{
2003-03-02 01:43:33 +00:00
m_Effect = bounce;
2003-02-17 12:19:42 +00:00
m_fEffectPeriodSeconds = fPeriod;
2003-03-02 01:43:33 +00:00
m_vEffectMagnitude = vect;
2003-02-17 12:19:42 +00:00
m_fSecsIntoEffect = 0;
2002-07-27 19:29:51 +00:00
}
2003-03-02 01:43:33 +00:00
void Actor::SetEffectBob( float fPeriod, RageVector3 vect )
2002-07-27 19:29:51 +00:00
{
2003-04-21 22:26:07 +00:00
if( m_Effect!=bob || m_fEffectPeriodSeconds!=fPeriod )
{
m_Effect = bob;
m_fEffectPeriodSeconds = fPeriod;
m_fSecsIntoEffect = 0;
}
2003-03-02 01:43:33 +00:00
m_vEffectMagnitude = vect;
}
2003-03-02 01:43:33 +00:00
void Actor::SetEffectSpin( RageVector3 vect )
{
2003-03-02 01:43:33 +00:00
m_Effect = spin;
m_vEffectMagnitude = vect;
}
2003-03-02 01:43:33 +00:00
void Actor::SetEffectVibrate( RageVector3 vect )
{
m_Effect = vibrate;
m_vEffectMagnitude = vect;
}
2003-03-05 02:52:40 +00:00
void Actor::SetEffectPulse( float fPeriod, float fMinZoom, float fMaxZoom )
{
m_Effect = pulse;
m_fEffectPeriodSeconds = fPeriod;
m_vEffectMagnitude[0] = fMinZoom;
m_vEffectMagnitude[1] = fMaxZoom;
}
2003-04-02 05:41:22 +00:00
void Actor::SetShadowLength( float fLength )
{
m_fShadowLength = fLength;
2003-04-02 05:41:22 +00:00
}
void Actor::AddRotationH( float rot )
{
RageQuatMultiply( &DestTweenState().quat, DestTweenState().quat, RageQuatFromH(rot) );
}
void Actor::AddRotationP( float rot )
{
RageQuatMultiply( &DestTweenState().quat, DestTweenState().quat, RageQuatFromP(rot) );
}
void Actor::AddRotationR( float rot )
{
RageQuatMultiply( &DestTweenState().quat, DestTweenState().quat, RageQuatFromR(rot) );
}
void Actor::RunCommands( const LuaReference& cmds, Actor *pParent )
2005-03-01 21:56:28 +00:00
{
2005-06-16 22:10:24 +00:00
Lua *L = LUA->Get();
2005-03-01 21:56:28 +00:00
// function
2005-06-16 22:10:24 +00:00
cmds.PushSelf( L );
ASSERT( !lua_isnil(L, -1) );
2005-03-01 21:56:28 +00:00
// 1st parameter
2005-06-16 22:10:24 +00:00
this->PushSelf( L );
2005-03-01 21:56:28 +00:00
// 2nd parameter
if( pParent )
2005-06-16 22:10:24 +00:00
pParent->PushSelf( L );
2005-03-01 21:56:28 +00:00
else
2005-06-16 22:10:24 +00:00
lua_pushnil( L );
2005-03-01 21:56:28 +00:00
// call function with 1 argument and 0 results
2005-06-16 22:10:24 +00:00
lua_call( L, 2, 0 );
LUA->Release(L);
}
float Actor::GetCommandsLengthSeconds( const LuaReference& cmds )
2003-03-19 19:56:27 +00:00
{
Actor temp;
2005-01-04 10:41:32 +00:00
temp.RunCommands(cmds);
2003-03-19 19:56:27 +00:00
return temp.GetTweenTimeLeft();
}
2003-03-02 01:43:33 +00:00
float Actor::GetTweenTimeLeft() const
2003-01-01 09:05:21 +00:00
{
float tot = 0;
tot += m_fHibernateSecondsLeft;
2005-01-16 04:35:47 +00:00
for( unsigned i=0; i<m_Tweens.size(); ++i )
tot += m_Tweens[i].info.m_fTimeLeftInTween;
2003-01-01 09:05:21 +00:00
return tot;
}
2003-04-02 05:41:22 +00:00
2005-02-13 20:10:27 +00:00
/*
* This is a hack to change all tween states while leaving existing tweens alone.
*
2005-02-13 20:10:27 +00:00
* Hmm. Most commands actually act on a TweenStateAndInfo, not the Actor itself.
* Conceptually, it wouldn't be hard to give TweenState a presence in Lua, so
* we can simply say eg. "for x in states(Actor) do x.SetDiffuseColor(c) end".
* However, we'd then have to give every TweenState a userdata in Lua while it's
* being manipulated, which would add overhead ...
*/
void Actor::SetGlobalDiffuseColor( RageColor c )
{
for(int i=0; i<4; i++) /* color, not alpha */
{
2005-01-16 04:35:47 +00:00
for( unsigned ts = 0; ts < m_Tweens.size(); ++ts )
{
2005-01-16 04:35:47 +00:00
m_Tweens[ts].state.diffuse[i].r = c.r;
m_Tweens[ts].state.diffuse[i].g = c.g;
m_Tweens[ts].state.diffuse[i].b = c.b;
}
m_current.diffuse[i].r = c.r;
m_current.diffuse[i].g = c.g;
m_current.diffuse[i].b = c.b;
m_start.diffuse[i].r = c.r;
m_start.diffuse[i].g = c.g;
m_start.diffuse[i].b = c.b;
}
}
void Actor::SetGlobalX( float x )
{
2005-01-16 04:35:47 +00:00
for( unsigned ts = 0; ts < m_Tweens.size(); ++ts )
m_Tweens[ts].state.pos.x = x;
m_current.pos.x = x;
m_start.pos.x = x;
}
void Actor::SetDiffuseColor( RageColor c )
{
for(int i=0; i<4; i++)
{
DestTweenState().diffuse[i].r = c.r;
DestTweenState().diffuse[i].g = c.g;
DestTweenState().diffuse[i].b = c.b;
}
}
2003-04-02 05:41:22 +00:00
void Actor::TweenState::Init()
{
pos = RageVector3( 0, 0, 0 );
rotation = RageVector3( 0, 0, 0 );
quat = RageVector4( 0, 0, 0, 1 );
2003-04-02 05:41:22 +00:00
scale = RageVector3( 1, 1, 1 );
2005-05-02 21:43:27 +00:00
fSkewX = 0;
crop = RectF( 0,0,0,0 );
2003-11-08 19:23:40 +00:00
fade = RectF( 0,0,0,0 );
2003-04-02 05:41:22 +00:00
for(int i=0; i<4; i++)
diffuse[i] = RageColor( 1, 1, 1, 1 );
glow = RageColor( 1, 1, 1, 0 );
2005-05-03 20:27:50 +00:00
aux = 0;
2003-04-02 05:41:22 +00:00
}
void Actor::TweenState::MakeWeightedAverage( TweenState& average_out, const TweenState& ts1, const TweenState& ts2, float fPercentBetween )
{
average_out.pos = ts1.pos + (ts2.pos - ts1.pos )*fPercentBetween;
average_out.scale = ts1.scale + (ts2.scale - ts1.scale )*fPercentBetween;
average_out.rotation = ts1.rotation + (ts2.rotation - ts1.rotation)*fPercentBetween;
RageQuatSlerp(&average_out.quat, ts1.quat, ts2.quat, fPercentBetween);
2005-05-02 21:43:27 +00:00
average_out.fSkewX = ts1.fSkewX + (ts2.fSkewX - ts1.fSkewX)*fPercentBetween;
average_out.crop.left = ts1.crop.left + (ts2.crop.left - ts1.crop.left )*fPercentBetween;
average_out.crop.top = ts1.crop.top + (ts2.crop.top - ts1.crop.top )*fPercentBetween;
average_out.crop.right = ts1.crop.right + (ts2.crop.right - ts1.crop.right )*fPercentBetween;
average_out.crop.bottom = ts1.crop.bottom+ (ts2.crop.bottom - ts1.crop.bottom)*fPercentBetween;
2003-11-08 19:23:40 +00:00
average_out.fade.left = ts1.fade.left + (ts2.fade.left - ts1.fade.left )*fPercentBetween;
average_out.fade.top = ts1.fade.top + (ts2.fade.top - ts1.fade.top )*fPercentBetween;
average_out.fade.right = ts1.fade.right + (ts2.fade.right - ts1.fade.right )*fPercentBetween;
average_out.fade.bottom = ts1.fade.bottom+ (ts2.fade.bottom - ts1.fade.bottom)*fPercentBetween;
2003-04-02 05:41:22 +00:00
for(int i=0; i<4; i++)
average_out.diffuse[i] = ts1.diffuse[i]+ (ts2.diffuse[i] - ts1.diffuse[i])*fPercentBetween;
average_out.glow = ts1.glow + (ts2.glow - ts1.glow )*fPercentBetween;
2005-05-03 20:27:50 +00:00
average_out.aux = ts1.aux + (ts2.aux - ts1.aux )*fPercentBetween;
2003-04-02 05:41:22 +00:00
}
2003-07-05 21:36:47 +00:00
2005-01-26 11:21:43 +00:00
void Actor::SetBlendModeString( const CString &s )
2003-07-05 21:36:47 +00:00
{
2005-01-26 11:21:43 +00:00
if (s.CompareNoCase("normal")==0) this->SetBlendMode( BLEND_NORMAL );
else if(s.CompareNoCase("add")==0) this->SetBlendMode( BLEND_ADD );
else if(s.CompareNoCase("noeffect")==0) this->SetBlendMode( BLEND_NO_EFFECT );
2003-07-05 21:36:47 +00:00
else ASSERT(0);
}
2005-01-26 11:21:43 +00:00
void Actor::SetCullModeString( const CString &s )
2004-02-04 11:05:33 +00:00
{
2005-01-26 11:21:43 +00:00
if (s.CompareNoCase("back")==0) this->SetCullMode( CULL_BACK );
else if(s.CompareNoCase("front")==0) this->SetCullMode( CULL_FRONT );
else if(s.CompareNoCase("none")==0) this->SetCullMode( CULL_NONE );
2004-02-04 11:05:33 +00:00
else ASSERT(0);
}
2005-01-26 11:21:43 +00:00
void Actor::SetZTestModeString( const CString &s )
2004-05-15 09:26:21 +00:00
{
// for metrics backward compatibility
2005-01-26 11:21:43 +00:00
if(s.CompareNoCase("off")==0) this->SetZTestMode( ZTEST_OFF );
else if(s.CompareNoCase("writeonpass")==0) this->SetZTestMode( ZTEST_WRITE_ON_PASS );
else if(s.CompareNoCase("writeonfail")==0) this->SetZTestMode( ZTEST_WRITE_ON_FAIL );
2004-05-15 09:26:21 +00:00
else ASSERT(0);
}
void Actor::CopyTweening( const Actor &from )
{
m_current = from.m_current;
m_start = from.m_start;
2005-01-16 04:35:47 +00:00
m_Tweens = from.m_Tweens;
}
2004-04-24 18:38:18 +00:00
void Actor::Sleep( float time )
{
BeginTweening( time, TWEEN_LINEAR );
BeginTweening( 0, TWEEN_LINEAR );
}
2005-01-26 11:21:43 +00:00
void Actor::QueueCommand( const CString& sCommandName )
2004-04-24 18:38:18 +00:00
{
2005-01-26 11:21:43 +00:00
BeginTweening( 0, TWEEN_LINEAR );
DestTweenState().sCommandName = sCommandName;
2004-04-24 18:38:18 +00:00
}
2004-06-08 00:47:53 +00:00
2005-02-27 03:21:18 +00:00
void Actor::QueueMessage( const CString& sMessageName )
{
// Hack: use "!" as a marker to broadcast a command, instead of playing a
// command, so we don't have to add yet another element to every tween
// state for this rarely-used command.
BeginTweening( 0, TWEEN_LINEAR );
DestTweenState().sCommandName = "!" + sMessageName;
}
void Actor::AddCommand( const CString &sCmdName, apActorCommands apac )
{
2005-05-04 19:19:22 +00:00
if( HasCommand(sCmdName) )
{
CString sWarning = m_sName+"'s command '"+sCmdName+"' defined twice";
Dialog::OK( sWarning, "COMMAND_DEFINED_TWICE" );
}
2005-05-04 09:59:41 +00:00
CString sMessage;
if( GetMessageNameFromCommandName(sCmdName, sMessage) )
2005-03-08 16:54:48 +00:00
{
2005-03-27 05:54:26 +00:00
SubscribeToMessage( sMessage );
2005-03-08 16:54:48 +00:00
m_mapNameToCommands[sMessage] = apac; // sCmdName w/o "Message" at the end
}
else
{
m_mapNameToCommands[sCmdName] = apac;
}
}
2005-03-13 20:34:52 +00:00
bool Actor::HasCommand( const CString &sCmdName )
{
map<CString, apActorCommands>::const_iterator it = m_mapNameToCommands.find( sCmdName );
return it != m_mapNameToCommands.end();
}
const apActorCommands& Actor::GetCommand( const CString &sCommandName ) const
{
map<CString, apActorCommands>::const_iterator it = m_mapNameToCommands.find( sCommandName );
ASSERT( it != m_mapNameToCommands.end() );
return it->second;
}
void Actor::PlayCommand( const CString &sCommandName, Actor *pParent )
2005-01-04 10:41:32 +00:00
{
2005-03-13 20:34:52 +00:00
map<CString, apActorCommands>::const_iterator it = m_mapNameToCommands.find( sCommandName );
2005-01-04 10:41:32 +00:00
if( it == m_mapNameToCommands.end() )
return;
2005-01-26 11:21:43 +00:00
RunCommands( *it->second );
}
void Actor::HandleMessage( const CString& sMessage )
{
2005-03-08 16:54:48 +00:00
PlayCommand( sMessage );
}
2005-03-27 05:54:26 +00:00
void Actor::SubscribeToMessage( const CString &sMessageName )
{
MESSAGEMAN->Subscribe( this, sMessageName );
m_vsSubscribedTo.push_back( sMessageName );
}
2005-01-04 10:41:32 +00:00
2005-05-01 22:59:00 +00:00
void Actor::SubscribeToMessage( Message message )
{
MESSAGEMAN->Subscribe( this, message );
m_vsSubscribedTo.push_back( MessageToString(message) );
}
2005-06-20 04:23:36 +00:00
// lua start
#include "LuaBinding.h"
2005-06-20 05:02:03 +00:00
class LunaActor : public Luna<Actor>
2005-06-20 04:23:36 +00:00
{
public:
LunaActor() { LUA->Register( Register ); }
static int sleep( T* p, lua_State *L ) { p->Sleep(FArg(1)); return 0; }
static int linear( T* p, lua_State *L ) { p->BeginTweening(FArg(1),Actor::TWEEN_LINEAR); return 0; }
static int accelerate( T* p, lua_State *L ) { p->BeginTweening(FArg(1),Actor::TWEEN_ACCELERATE); return 0; }
static int decelerate( T* p, lua_State *L ) { p->BeginTweening(FArg(1),Actor::TWEEN_DECELERATE); return 0; }
static int bouncebegin( T* p, lua_State *L ) { p->BeginTweening(FArg(1),Actor::TWEEN_BOUNCE_BEGIN); return 0; }
static int bounceend( T* p, lua_State *L ) { p->BeginTweening(FArg(1),Actor::TWEEN_BOUNCE_END); return 0; }
static int spring( T* p, lua_State *L ) { p->BeginTweening(FArg(1),Actor::TWEEN_SPRING); return 0; }
static int stoptweening( T* p, lua_State *L ) { p->StopTweening(); p->BeginTweening( 0.0001f, Actor::TWEEN_LINEAR ); return 0; }
static int finishtweening( T* p, lua_State *L ) { p->FinishTweening(); return 0; }
static int hurrytweening( T* p, lua_State *L ) { p->HurryTweening(FArg(1)); return 0; }
static int x( T* p, lua_State *L ) { p->SetX(FArg(1)); return 0; }
static int y( T* p, lua_State *L ) { p->SetY(FArg(1)); return 0; }
static int z( T* p, lua_State *L ) { p->SetZ(FArg(1)); return 0; }
static int addx( T* p, lua_State *L ) { p->AddX(FArg(1)); return 0; }
static int addy( T* p, lua_State *L ) { p->AddY(FArg(1)); return 0; }
static int addz( T* p, lua_State *L ) { p->AddZ(FArg(1)); return 0; }
static int zoom( T* p, lua_State *L ) { p->SetZoom(FArg(1)); return 0; }
static int zoomx( T* p, lua_State *L ) { p->SetZoomX(FArg(1)); return 0; }
static int zoomy( T* p, lua_State *L ) { p->SetZoomY(FArg(1)); return 0; }
static int zoomz( T* p, lua_State *L ) { p->SetZoomZ(FArg(1)); return 0; }
static int zoomto( T* p, lua_State *L ) { p->ZoomTo(FArg(1), FArg(2)); return 0; }
static int zoomtowidth( T* p, lua_State *L ) { p->ZoomToWidth(FArg(1)); return 0; }
static int zoomtoheight( T* p, lua_State *L ) { p->ZoomToHeight(FArg(1)); return 0; }
static int basezoomx( T* p, lua_State *L ) { p->SetBaseZoomX(FArg(1)); return 0; }
static int basezoomy( T* p, lua_State *L ) { p->SetBaseZoomY(FArg(1)); return 0; }
static int stretchto( T* p, lua_State *L ) { p->StretchTo( RectF(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int cropleft( T* p, lua_State *L ) { p->SetCropLeft(FArg(1)); return 0; }
static int croptop( T* p, lua_State *L ) { p->SetCropTop(FArg(1)); return 0; }
static int cropright( T* p, lua_State *L ) { p->SetCropRight(FArg(1)); return 0; }
static int cropbottom( T* p, lua_State *L ) { p->SetCropBottom(FArg(1)); return 0; }
static int fadeleft( T* p, lua_State *L ) { p->SetFadeLeft(FArg(1)); return 0; }
static int fadetop( T* p, lua_State *L ) { p->SetFadeTop(FArg(1)); return 0; }
static int faderight( T* p, lua_State *L ) { p->SetFadeRight(FArg(1)); return 0; }
static int fadebottom( T* p, lua_State *L ) { p->SetFadeBottom(FArg(1)); return 0; }
static int diffuse( T* p, lua_State *L ) { p->SetDiffuse( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int diffuseupperleft( T* p, lua_State *L ) { p->SetDiffuseUpperLeft( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int diffuseupperright( T* p, lua_State *L ) { p->SetDiffuseUpperRight( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int diffuselowerleft( T* p, lua_State *L ) { p->SetDiffuseLowerLeft( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int diffuselowerright( T* p, lua_State *L ) { p->SetDiffuseLowerRight( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int diffuseleftedge( T* p, lua_State *L ) { p->SetDiffuseLeftEdge( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int diffuserightedge( T* p, lua_State *L ) { p->SetDiffuseRightEdge( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int diffusetopedge( T* p, lua_State *L ) { p->SetDiffuseTopEdge( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int diffusebottomedge( T* p, lua_State *L ) { p->SetDiffuseBottomEdge( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int diffusealpha( T* p, lua_State *L ) { p->SetDiffuseAlpha(FArg(1)); return 0; }
static int diffusecolor( T* p, lua_State *L ) { p->SetDiffuseColor( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int glow( T* p, lua_State *L ) { p->SetGlow( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int aux( T* p, lua_State *L ) { p->SetAux( FArg(1) ); return 0; }
static int getaux( T* p, lua_State *L ) { lua_pushnumber( L, p->GetAux() ); return 1; }
static int rotationx( T* p, lua_State *L ) { p->SetRotationX(FArg(1)); return 0; }
static int rotationy( T* p, lua_State *L ) { p->SetRotationY(FArg(1)); return 0; }
static int rotationz( T* p, lua_State *L ) { p->SetRotationZ(FArg(1)); return 0; }
static int getrotation( T* p, lua_State *L ) { lua_pushnumber(L, p->GetRotationX()); lua_pushnumber(L, p->GetRotationY()); lua_pushnumber(L, p->GetRotationZ()); return 3; }
static int skewx( T* p, lua_State *L ) { p->SetSkewX(FArg(1)); return 0; }
static int heading( T* p, lua_State *L ) { p->AddRotationH(FArg(1)); return 0; }
static int pitch( T* p, lua_State *L ) { p->AddRotationP(FArg(1)); return 0; }
static int roll( T* p, lua_State *L ) { p->AddRotationR(FArg(1)); return 0; }
static int shadowlength( T* p, lua_State *L ) { p->SetShadowLength(FArg(1)); return 0; }
static int horizalign( T* p, lua_State *L ) { p->SetHorizAlignString(SArg(1)); return 0; }
static int vertalign( T* p, lua_State *L ) { p->SetVertAlignString(SArg(1)); return 0; }
static int luaeffect( T* p, lua_State *L ) { p->SetEffectLua(SArg(1)); return 0; }
static int diffuseblink( T* p, lua_State *L ) { p->SetEffectDiffuseBlink(); return 0; }
static int diffuseshift( T* p, lua_State *L ) { p->SetEffectDiffuseShift(); return 0; }
static int diffuseramp( T* p, lua_State *L ) { p->SetEffectDiffuseRamp(); return 0; }
static int glowblink( T* p, lua_State *L ) { p->SetEffectGlowBlink(); return 0; }
static int glowshift( T* p, lua_State *L ) { p->SetEffectGlowShift(); return 0; }
static int rainbow( T* p, lua_State *L ) { p->SetEffectRainbow(); return 0; }
static int wag( T* p, lua_State *L ) { p->SetEffectWag(); return 0; }
static int bounce( T* p, lua_State *L ) { p->SetEffectBounce(); return 0; }
static int bob( T* p, lua_State *L ) { p->SetEffectBob(); return 0; }
static int pulse( T* p, lua_State *L ) { p->SetEffectPulse(); return 0; }
static int spin( T* p, lua_State *L ) { p->SetEffectSpin(); return 0; }
static int vibrate( T* p, lua_State *L ) { p->SetEffectVibrate(); return 0; }
static int stopeffect( T* p, lua_State *L ) { p->SetEffectNone(); return 0; }
static int effectcolor1( T* p, lua_State *L ) { p->SetEffectColor1( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int effectcolor2( T* p, lua_State *L ) { p->SetEffectColor2( RageColor(FArg(1),FArg(2),FArg(3),FArg(4)) ); return 0; }
static int effectperiod( T* p, lua_State *L ) { p->SetEffectPeriod(FArg(1)); return 0; }
static int effectoffset( T* p, lua_State *L ) { p->SetEffectOffset(FArg(1)); return 0; }
static int effectdelay( T* p, lua_State *L ) { p->SetEffectDelay(FArg(1)); return 0; }
static int effectclock( T* p, lua_State *L ) { p->SetEffectClockString(SArg(1)); return 0; }
static int effectmagnitude( T* p, lua_State *L ) { p->SetEffectMagnitude( RageVector3(FArg(1),FArg(2),FArg(3)) ); return 0; }
static int geteffectmagnitude( T* p, lua_State *L ) { RageVector3 v = p->GetEffectMagnitude(); lua_pushnumber(L, v[0]); lua_pushnumber(L, v[1]); lua_pushnumber(L, v[2]); return 3; }
static int scaletocover( T* p, lua_State *L ) { p->ScaleToCover( RectF(FArg(1), FArg(2), FArg(3), FArg(4)) ); return 0; }
static int scaletofit( T* p, lua_State *L ) { p->ScaleToFitInside( RectF(FArg(1), FArg(2), FArg(3), FArg(4)) ); return 0; }
static int animate( T* p, lua_State *L ) { p->EnableAnimation(!!IArg(1)); return 0; }
static int play( T* p, lua_State *L ) { p->EnableAnimation(true); return 0; }
static int pause( T* p, lua_State *L ) { p->EnableAnimation(false); return 0; }
static int setstate( T* p, lua_State *L ) { p->SetState(IArg(1)); return 0; }
static int texturewrapping( T* p, lua_State *L ) { p->SetTextureWrapping(!!IArg(1)); return 0; }
static int additiveblend( T* p, lua_State *L ) { p->SetBlendMode(!!IArg(1) ? BLEND_ADD : BLEND_NORMAL); return 0; }
static int blend( T* p, lua_State *L ) { p->SetBlendModeString(SArg(1)); return 0; }
static int zbuffer( T* p, lua_State *L ) { p->SetUseZBuffer(!!IArg(1)); return 0; }
static int ztest( T* p, lua_State *L ) { p->SetZTestMode((!!IArg(1))?ZTEST_WRITE_ON_PASS:ZTEST_OFF); return 0; }
static int ztestmode( T* p, lua_State *L ) { p->SetZTestModeString(SArg(1)); return 0; }
static int zwrite( T* p, lua_State *L ) { p->SetZWrite(!!IArg(1)); return 0; }
static int zbias( T* p, lua_State *L ) { p->SetZBias(FArg(1)); return 0; }
static int clearzbuffer( T* p, lua_State *L ) { p->SetClearZBuffer(!!IArg(1)); return 0; }
static int backfacecull( T* p, lua_State *L ) { p->SetCullMode((!!IArg(1)) ? CULL_BACK : CULL_NONE); return 0; }
static int cullmode( T* p, lua_State *L ) { p->SetCullModeString(SArg(1)); return 0; }
static int visible( T* p, lua_State *L ) { p->SetVisible(!!IArg(1)); return 0; }
static int hidden( T* p, lua_State *L ) { p->SetHidden(!!IArg(1)); return 0; }
static int hibernate( T* p, lua_State *L ) { p->SetHibernate(FArg(1)); return 0; }
static int draworder( T* p, lua_State *L ) { p->SetDrawOrder(IArg(1)); return 0; }
static int playcommand( T* p, lua_State *L ) { p->PlayCommand(SArg(1),NULL); return 0; }
static int queuecommand( T* p, lua_State *L ) { p->QueueCommand(SArg(1)); return 0; }
static int queuemessage( T* p, lua_State *L ) { p->QueueMessage(SArg(1)); return 0; }
static int GetX( T* p, lua_State *L ) { lua_pushnumber( L, p->GetX() ); return 1; }
static int GetY( T* p, lua_State *L ) { lua_pushnumber( L, p->GetY() ); return 1; }
static int GetZ( T* p, lua_State *L ) { lua_pushnumber( L, p->GetZ() ); return 1; }
static int GetWidth( T* p, lua_State *L ) { lua_pushnumber( L, p->GetUnzoomedWidth() ); return 1; }
static int GetHeight( T* p, lua_State *L ) { lua_pushnumber( L, p->GetUnzoomedHeight() ); return 1; }
static int GetZoom( T* p, lua_State *L ) { lua_pushnumber( L, p->GetZoom() ); return 1; }
static int GetZoomX( T* p, lua_State *L ) { lua_pushnumber( L, p->GetZoomX() ); return 1; }
static int GetZoomY( T* p, lua_State *L ) { lua_pushnumber( L, p->GetZoomY() ); return 1; }
static int GetZoomZ( T* p, lua_State *L ) { lua_pushnumber( L, p->GetZoomZ() ); return 1; }
static int GetBaseZoomX( T* p, lua_State *L ) { lua_pushnumber( L, p->GetBaseZoomX() ); return 1; }
static int GetSecsIntoEffect( T* p, lua_State *L ) { lua_pushnumber( L, p->GetSecsIntoEffect() ); return 1; }
static int GetEffectDelta( T* p, lua_State *L ) { lua_pushnumber( L, p->GetEffectDelta() ); return 1; }
static void Register(lua_State *L) {
ADD_METHOD( sleep )
ADD_METHOD( linear )
ADD_METHOD( accelerate )
ADD_METHOD( decelerate )
ADD_METHOD( bouncebegin )
ADD_METHOD( bounceend )
ADD_METHOD( spring )
ADD_METHOD( stoptweening )
ADD_METHOD( finishtweening )
ADD_METHOD( hurrytweening )
ADD_METHOD( x )
ADD_METHOD( y )
ADD_METHOD( z )
ADD_METHOD( addx )
ADD_METHOD( addy )
ADD_METHOD( addz )
ADD_METHOD( zoom )
ADD_METHOD( zoomx )
ADD_METHOD( zoomy )
ADD_METHOD( zoomz )
ADD_METHOD( zoomto )
ADD_METHOD( zoomtowidth )
ADD_METHOD( zoomtoheight )
ADD_METHOD( basezoomx )
ADD_METHOD( basezoomy )
ADD_METHOD( stretchto )
ADD_METHOD( cropleft )
ADD_METHOD( croptop )
ADD_METHOD( cropright )
ADD_METHOD( cropbottom )
ADD_METHOD( fadeleft )
ADD_METHOD( fadetop )
ADD_METHOD( faderight )
ADD_METHOD( fadebottom )
ADD_METHOD( diffuse )
ADD_METHOD( diffuseupperleft )
ADD_METHOD( diffuseupperright )
ADD_METHOD( diffuselowerleft )
ADD_METHOD( diffuselowerright )
ADD_METHOD( diffuseleftedge )
ADD_METHOD( diffuserightedge )
ADD_METHOD( diffusetopedge )
ADD_METHOD( diffusebottomedge )
ADD_METHOD( diffusealpha )
ADD_METHOD( diffusecolor )
ADD_METHOD( glow )
ADD_METHOD( aux )
ADD_METHOD( getaux )
ADD_METHOD( rotationx )
ADD_METHOD( rotationy )
ADD_METHOD( rotationz )
ADD_METHOD( getrotation )
ADD_METHOD( skewx )
ADD_METHOD( heading )
ADD_METHOD( pitch )
ADD_METHOD( roll )
ADD_METHOD( shadowlength )
ADD_METHOD( horizalign )
ADD_METHOD( vertalign )
ADD_METHOD( luaeffect )
ADD_METHOD( diffuseblink )
ADD_METHOD( diffuseshift )
ADD_METHOD( diffuseramp )
ADD_METHOD( glowblink )
ADD_METHOD( glowshift )
ADD_METHOD( rainbow )
ADD_METHOD( wag )
ADD_METHOD( bounce )
ADD_METHOD( bob )
ADD_METHOD( pulse )
ADD_METHOD( spin )
ADD_METHOD( vibrate )
ADD_METHOD( stopeffect )
ADD_METHOD( effectcolor1 )
ADD_METHOD( effectcolor2 )
ADD_METHOD( effectperiod )
ADD_METHOD( effectoffset )
ADD_METHOD( effectdelay )
ADD_METHOD( effectclock )
ADD_METHOD( effectmagnitude )
ADD_METHOD( geteffectmagnitude )
ADD_METHOD( scaletocover )
ADD_METHOD( scaletofit )
ADD_METHOD( animate )
ADD_METHOD( play )
ADD_METHOD( pause )
ADD_METHOD( setstate )
ADD_METHOD( texturewrapping )
ADD_METHOD( additiveblend )
ADD_METHOD( blend )
ADD_METHOD( zbuffer )
ADD_METHOD( ztest )
ADD_METHOD( ztestmode )
ADD_METHOD( zwrite )
ADD_METHOD( zbias )
ADD_METHOD( clearzbuffer )
ADD_METHOD( backfacecull )
ADD_METHOD( cullmode )
ADD_METHOD( visible )
ADD_METHOD( hidden )
ADD_METHOD( hibernate )
ADD_METHOD( draworder )
ADD_METHOD( playcommand )
ADD_METHOD( queuecommand )
ADD_METHOD( queuemessage )
ADD_METHOD( GetX )
ADD_METHOD( GetY )
ADD_METHOD( GetZ )
ADD_METHOD( GetWidth )
ADD_METHOD( GetHeight )
ADD_METHOD( GetZoom )
ADD_METHOD( GetZoomX )
ADD_METHOD( GetZoomY )
ADD_METHOD( GetZoomZ )
ADD_METHOD( GetBaseZoomX )
ADD_METHOD( GetSecsIntoEffect )
ADD_METHOD( GetEffectDelta )
Luna<T>::Register( L );
}
};
2005-07-04 21:45:16 +00:00
LUA_REGISTER_INSTANCED_BASE_CLASS( Actor )
2005-06-20 04:23:36 +00:00
// lua end
2004-06-08 00:47:53 +00:00
/*
* (c) 2001-2004 Chris Danford
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/