added ActorMultiVertex

AMV is an actor which can have a variable number of vertices that can
each be given their own pos, color, and coords. They can be drawn using
any of the RageSpriteVertex draw functions in RageDisplay.cpp. The
vertex properties can be tweened.
This commit is contained in:
sigatrev
2014-04-14 21:29:19 -05:00
parent 0263b11fc5
commit 70c5209e76
6 changed files with 878 additions and 14 deletions
+12 -12
View File
@@ -84,7 +84,7 @@ void Actor::SetBGMLight( int iLightNumber, float fCabinetLights )
void Actor::InitState()
{
StopTweening();
this->StopTweening();
m_pTempState = NULL;
@@ -615,14 +615,9 @@ void Actor::EndDraw()
void Actor::UpdateTweening( float fDeltaTime )
{
while( 1 )
while( !m_Tweens.empty() // something to do
&& fDeltaTime > 0 ) // something will change
{
if( m_Tweens.empty() ) // nothing to do
return;
if( fDeltaTime == 0 ) // nothing will change
return;
// update current tween state
// earliest tween
TweenState &TS = m_Tweens[0]->state;
@@ -636,7 +631,10 @@ void Actor::UpdateTweening( float fDeltaTime )
RString sCommand = TI.m_sCommandName;
if( bBeginning ) // we are just beginning this tween
{
m_start = m_current; // set the start position
SetCurrentTweenStart();
}
if( TI.m_fTimeLeftInTween == 0 ) // Current tween is over. Stop.
{
@@ -645,6 +643,7 @@ void Actor::UpdateTweening( float fDeltaTime )
// delete the head tween
delete m_Tweens.front();
m_Tweens.erase( m_Tweens.begin() );
EraseHeadTween();
}
else // in the middle of tweening. Recalcute the current position.
{
@@ -653,6 +652,7 @@ void Actor::UpdateTweening( float fDeltaTime )
// distort the percentage if appropriate
float fPercentAlongPath = TI.m_pTween->Tween( fPercentThroughTween );
TweenState::MakeWeightedAverage( m_current, m_start, TS, fPercentAlongPath );
UpdatePercentThroughTween(fPercentAlongPath);
}
if( bBeginning )
@@ -772,7 +772,7 @@ void Actor::UpdateInternal( float fDeltaTime )
default: break;
}
UpdateTweening( fDeltaTime );
this->UpdateTweening( fDeltaTime );
}
RString Actor::GetLineage() const
@@ -797,7 +797,7 @@ void Actor::BeginTweening( float time, ITween *pTween )
LOG->Warn( "%s", sError.c_str() );
Dialog::OK( sError );
FinishTweening();
this->FinishTweening();
}
// add a new TweenState to the tail, and initialize it
@@ -829,7 +829,7 @@ void Actor::BeginTweening( float time, TweenType tt )
ASSERT( time >= 0 );
ITween *pTween = ITween::CreateFromType( tt );
BeginTweening( time, pTween );
this->BeginTweening( time, pTween );
}
void Actor::StopTweening()
@@ -843,7 +843,7 @@ void Actor::FinishTweening()
{
if( !m_Tweens.empty() )
m_current = DestTweenState();
StopTweening();
this->StopTweening();
}
void Actor::HurryTweening( float factor )
+6 -2
View File
@@ -270,6 +270,10 @@ public:
virtual void Update( float fDeltaTime ); // this can short circuit UpdateInternal
virtual void UpdateInternal( float fDeltaTime ); // override this
void UpdateTweening( float fDeltaTime );
// These next functions should all be overridden by a derived class that has its own tweening states to handl.
virtual void SetCurrentTweenStart() {}
virtual void EraseHeadTween() {}
virtual void UpdatePercentThroughTween( float PercentThroughTween ) {}
/**
* @brief Retrieve the Actor's name.
@@ -449,9 +453,9 @@ public:
void SetAux( float f ) { DestTweenState().aux = f; }
float GetAux() const { return m_current.aux; }
void BeginTweening( float time, ITween *pInterp );
virtual void BeginTweening( float time, ITween *pInterp );
void BeginTweening( float time, TweenType tt = TWEEN_LINEAR );
void StopTweening();
virtual void StopTweening();
void Sleep( float time );
void QueueCommand( const RString& sCommandName );
void QueueMessage( const RString& sMessageName );
+701
View File
@@ -0,0 +1,701 @@
#include "global.h"
#include <cassert>
#include "ActorMultiVertex.h"
#include "RageTextureManager.h"
#include "XmlFile.h"
#include "RageLog.h"
#include "RageDisplay.h"
#include "RageTexture.h"
#include "RageUtil.h"
#include "ActorUtil.h"
#include "Foreach.h"
#include "LuaBinding.h"
#include "LuaManager.h"
#include "LocalizedString.h"
static const char *DrawModeNames[] = {
"Quads",
"QuadStrip",
"Fan",
"Strip",
"Triangles",
"LineStrip",
"SymmetricQuadStrip",
};
static const int DrawModeVertexGroupSizes[] = {
4, // Quads
2, // QuadStrip
1, // Fan
1, // Strip
3, // Triangles
1, // LineStrip
3, // SymmetricQuadStrip
1, // NUM_DrawMode
1, // DrawMode_Invalid
};
static const int DrawModeMinimumToDraw[] = {
4, // Quads
4, // QuadStrip
3, // Fan
3, // Strip
3, // Triangles
2, // LineStrip
6, // SymmetricQuadStrip
1, // NUM_DrawMode
1, // DrawMode_Invalid
};
XToString( DrawMode );
XToLocalizedString( DrawMode );
LuaXType( DrawMode );
REGISTER_ACTOR_CLASS( ActorMultiVertex );
ActorMultiVertex::ActorMultiVertex()
{
// Use blank texture by default.
RageTextureID ID = TEXTUREMAN->GetDefaultTextureID();
_Texture = TEXTUREMAN->LoadTexture( ID );
_EffectMode = EffectMode_Normal;
_TextureMode = TextureMode_Modulate;
}
ActorMultiVertex::~ActorMultiVertex()
{
UnloadTexture();
}
ActorMultiVertex::ActorMultiVertex( const ActorMultiVertex &cpy ):
Actor( cpy )
{
#define CPY(a) a = cpy.a
CPY( AMV_Tweens );
CPY( AMV_current );
CPY( AMV_start );
CPY( _EffectMode );
CPY( _TextureMode );
#undef CPY
if( cpy._Texture != NULL )
{
_Texture = TEXTUREMAN->CopyTexture( cpy._Texture );
}
else
{
_Texture = NULL;
}
}
void ActorMultiVertex::LoadFromNode( const XNode* Node )
{
RString path;
Node->GetAttrValue( "Texture", path );
if( !path.empty() && !TEXTUREMAN->IsTextureRegistered( RageTextureID(path) ) )
{
ActorUtil::GetAttrPath( Node, "Texture", path );
}
if( !path.empty() )
{
LoadFromTexture( path );
}
Actor::LoadFromNode( Node );
}
void ActorMultiVertex::SetTexture( RageTexture *Texture )
{
if( _Texture != Texture )
{
UnloadTexture();
_Texture = Texture;
}
}
void ActorMultiVertex::LoadFromTexture( RageTextureID ID )
{
RageTexture *Texture = NULL;
if( _Texture && _Texture->GetID() == ID )
{
return;
}
Texture = TEXTUREMAN->LoadTexture( ID );
SetTexture( Texture );
}
void ActorMultiVertex::UnloadTexture()
{
if( _Texture != NULL )
{
TEXTUREMAN->UnloadTexture( _Texture );
_Texture = NULL;
}
}
void ActorMultiVertex::SetNumVertices( size_t n )
{
if( n == 0 )
{
for( size_t i = 0; i < AMV_Tweens.size(); ++i )
{
AMV_Tweens[i].vertices.clear();
}
AMV_current.vertices.clear();
AMV_start.vertices.clear();
}
else
{
for( size_t i = 0; i < AMV_Tweens.size(); ++i )
{
AMV_Tweens[i].vertices.resize( n );
}
AMV_current.vertices.resize( n );
AMV_start.vertices.resize( n );
}
}
void ActorMultiVertex::AddVertex()
{
for( size_t i = 0; i < AMV_Tweens.size(); ++i )
{
AMV_Tweens[i].vertices.push_back( RageSpriteVertex() );
}
AMV_current.vertices.push_back( RageSpriteVertex() );
AMV_start.vertices.push_back( RageSpriteVertex() );
}
void ActorMultiVertex::AddVertices( int Add )
{
int size = AMV_DestTweenState().vertices.size();
size += Add;
for( size_t i = 0; i < AMV_Tweens.size(); ++i )
{
AMV_Tweens[i].vertices.resize( size );
}
AMV_current.vertices.resize( size );
AMV_start.vertices.resize( size );
}
void ActorMultiVertex::SetVertexPos( int index, float x, float y, float z )
{
AMV_DestTweenState().vertices[index].p = RageVector3( x, y, z );
}
void ActorMultiVertex::SetVertexColor( int index, RageColor c )
{
AMV_DestTweenState().vertices[index].c = c;
}
void ActorMultiVertex::SetVertexCoords( int index, float TexCoordX, float TexCoordY )
{
AMV_DestTweenState().vertices[index].t = RageVector2( TexCoordX, TexCoordY );
}
void ActorMultiVertex::DrawPrimitives()
{
Actor::SetGlobalRenderStates(); // set Actor-specified render states
DISPLAY->ClearAllTextures();
DISPLAY->SetTexture( TextureUnit_1, _Texture->GetTexHandle() );
Actor::SetTextureRenderStates();
DISPLAY->SetEffectMode( _EffectMode );
// set temporary diffuse and glow
static AMV_TweenState TS;
AMV_TempState = &TS;
TS = AMV_current;
// skip if no change or fully transparent
if( m_pTempState->diffuse[0] != RageColor(1, 1, 1, 1) && m_pTempState->diffuse[0].a > 0 )
{
for( size_t i=0; i < TS.vertices.size(); i++ )
{
// RageVColor * RageColor
TS.vertices[i].c.b *= m_pTempState->diffuse[0].b;
TS.vertices[i].c.r *= m_pTempState->diffuse[0].r;
TS.vertices[i].c.g *= m_pTempState->diffuse[0].g;
TS.vertices[i].c.a *= m_pTempState->diffuse[0].a;
}
}
// Draw diffuse pass.
if( m_pTempState->diffuse[0].a > 0 )
{
DISPLAY->SetTextureMode( TextureUnit_1, _TextureMode );
DrawInternal( AMV_TempState );
}
// Draw the glow pass
if( m_pTempState->glow.a > 0 )
{
for( size_t i=0; i < TS.vertices.size(); i++ )
{
TS.vertices[i].c = m_pTempState->glow;
}
DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Glow );
DrawInternal( AMV_TempState );
}
}
void ActorMultiVertex::DrawInternal( const AMV_TweenState *TS )
{
int FirstToDraw = TS->FirstToDraw;
int NumToDraw = TS->GetSafeNumToDraw(TS->_DrawMode, TS->NumToDraw);
if( NumToDraw == 0 )
{
// Nothing to draw.
return;
}
switch( TS->_DrawMode )
{
case DrawMode_Quads:
{
DISPLAY->DrawQuads( &TS->vertices[FirstToDraw], NumToDraw );
break;
}
case DrawMode_QuadStrip:
{
DISPLAY->DrawQuadStrip( &TS->vertices[FirstToDraw], NumToDraw );
break;
}
case DrawMode_Fan:
{
DISPLAY->DrawFan( &TS->vertices[FirstToDraw], NumToDraw );
break;
}
case DrawMode_Strip:
{
DISPLAY->DrawStrip( &TS->vertices[FirstToDraw], NumToDraw );
break;
}
case DrawMode_Triangles:
{
DISPLAY->DrawTriangles( &TS->vertices[FirstToDraw], NumToDraw );
break;
}
case DrawMode_LineStrip:
{
DISPLAY->DrawLineStrip( &TS->vertices[FirstToDraw], NumToDraw, TS->line_width );
break;
}
case DrawMode_SymmetricQuadStrip:
{
DISPLAY->DrawSymmetricQuadStrip( &TS->vertices[FirstToDraw], NumToDraw );
break;
}
}
DISPLAY->SetEffectMode( EffectMode_Normal );
}
bool ActorMultiVertex::EarlyAbortDraw() const
{
if( AMV_current.FirstToDraw >= (int) AMV_current.vertices.size() || AMV_current._DrawMode >= NUM_DrawMode )
{
return true;
}
return false;
}
void ActorMultiVertex::SetCurrentTweenStart()
{
AMV_start= AMV_current;
}
void ActorMultiVertex::EraseHeadTween()
{
AMV_current= AMV_Tweens[0];
AMV_Tweens.erase(AMV_Tweens.begin());
}
void ActorMultiVertex::UpdatePercentThroughTween( float PercentThroughTween )
{
AMV_TweenState::MakeWeightedAverage( AMV_current, AMV_start, AMV_Tweens[0], PercentThroughTween );
}
void ActorMultiVertex::BeginTweening( float time, ITween *pTween )
{
Actor::BeginTweening( time, pTween );
if( AMV_Tweens.size() >= 1 ) // if there was already a TS on the stack
{
AMV_Tweens.push_back( AMV_Tweens.back() );
}
else
{
AMV_Tweens.push_back( AMV_current );
}
}
void ActorMultiVertex::StopTweening()
{
AMV_Tweens.clear();
Actor::StopTweening();
}
void ActorMultiVertex::FinishTweening()
{
if( !AMV_Tweens.empty() )
{
AMV_current = AMV_DestTweenState();
}
Actor::FinishTweening();
}
void ActorMultiVertex::AMV_TweenState::SetDrawState( DrawMode dm, int first, int num )
{
if(first >= (int)vertices.size() && vertices.size() > 0)
{
LOG->Warn("ActorMultiVertex:SetDrawState: FirstToDraw > vertices.size(), %d > %u", FirstToDraw + 1, (unsigned int)vertices.size() );
return;
}
int safe_num= GetSafeNumToDraw( dm, num );
if( num != safe_num && num != -1 )
{
LOG->Warn("ActorMultiVertex:SetDrawState: NumToDraw %d is not valid for %u vertices with DrawMode %s", num, (unsigned int)vertices.size(), DrawModeNames[dm] );
return;
}
_DrawMode= dm;
FirstToDraw= first;
NumToDraw= num;
}
void ActorMultiVertex::AMV_TweenState::MakeWeightedAverage(AMV_TweenState& average_out, const AMV_TweenState& ts1, const AMV_TweenState& ts2, float percent_between)
{
average_out.line_width= lerp(percent_between, ts1.line_width, ts2.line_width);
for(size_t v= 0; v < average_out.vertices.size(); ++v)
{
WeightedAvergeOfRSVs(average_out.vertices[v], ts1.vertices[v], ts2.vertices[v], percent_between);
}
}
int ActorMultiVertex::AMV_TweenState::GetSafeNumToDraw( DrawMode dm, int num ) const
{
int max = vertices.size() - FirstToDraw;
// NumToDraw == -1 draws all vertices
if( num == -1 || num > max )
{
num = max;
}
num -= ( num % DrawModeVertexGroupSizes[dm]);
if( num < DrawModeMinimumToDraw[dm])
{
num = 0;
}
return num;
}
// lua start
#include "LuaBinding.h"
/** @brief Allow Lua to have access to the ActorMultiVertex. */
class LunaActorMultiVertex: public Luna<ActorMultiVertex>
{
public:
static int SetNumVertices( T* p, lua_State *L )
{
p->SetNumVertices( IArg(1) );
return 0;
}
static int GetNumVertices( T* p, lua_State *L ) { lua_pushnumber( L, p->GetNumVertices() ); return 1; }
static void SetVertexFromStack(T* p, lua_State* L, size_t VertexIndex, int DataStackIndex)
{
// Use the number of arguments to determine which property a table is for
if(lua_type(L, DataStackIndex) != LUA_TTABLE)
{
LOG->Warn("ActorMultiVertex::SetVertex: non-table parameter supplied. Table of tables of vertex data expected.");
return;
}
size_t NumDataParts = lua_objlen(L, DataStackIndex);
for(size_t i = 0; i < NumDataParts; ++i)
{
lua_pushnumber(L, i+1);
lua_gettable(L, DataStackIndex);
int DataPieceIndex = lua_gettop(L);
size_t DataPieceElements = lua_objlen(L, DataPieceIndex);
if(lua_type(L, DataPieceIndex) != LUA_TTABLE)
{
LOG->Warn( "ActorMultiVertex::SetVertex: non-table parameter %u supplied inside table of parameters, table expected.", (unsigned int)i );
return;
}
int pushes = 1;
if(DataPieceElements == 2)
{
pushes += 2;
lua_rawgeti(L, DataPieceIndex, 1);
float x= FArg(-1);
lua_rawgeti(L, DataPieceIndex, 2);
float y= FArg(-1);
p->SetVertexCoords(VertexIndex, x, y);
}
else if(DataPieceElements == 3)
{
pushes += 3;
lua_rawgeti(L, DataPieceIndex, 1);
float x= FArg(-1);
lua_rawgeti(L, DataPieceIndex, 2);
float y= FArg(-1);
lua_rawgeti(L, DataPieceIndex, 3);
float z= FArg(-1);
p->SetVertexPos(VertexIndex, x, y, z);
}
else if(DataPieceElements == 4)
{
// RageColor pops the things it pushes onto the stack, so we don't need to.
RageColor c;
// Does not use FromStackCompat because we are not compatible with passing a color in non-table form.
c.FromStack(L, DataPieceIndex);
p->SetVertexColor(VertexIndex, c);
}
else
{
LOG->Warn( "ActorMultiVertex::SetVertex: Parameter %u has %u elements supplied. 2, 3, or 4 expected.", (unsigned int)i, (unsigned int)DataPieceElements );
}
// Avoid a stack underflow by only popping the amount we pushed.
lua_pop(L, pushes);
}
return;
}
static int SetVertex(T* p, lua_State* L)
{
// Indices from Lua are one-indexed. -1 to adjust.
int Index = IArg(1)-1;
if( Index < 0 )
{
LOG->Warn( "ActorMultiVertex::SetVertex: index %d provided, cannot set Index < 1", Index+1 );
return 0;
}
else if( Index == (int) p->GetNumVertices() )
{
p->AddVertices( 1 );
}
else if( Index > (int) p->GetNumVertices() )
{
LOG->Warn( "ActorMultiVertex::SetVertex: Cannot set vertex %d if there is no vertex %d, only %u vertices.", Index+1 , Index, (unsigned int)p->GetNumVertices() );
return 0;
}
SetVertexFromStack(p, L, Index, lua_gettop(L));
return 0;
}
static int SetVertices(T* p, lua_State* L)
{
int First = 0;
int StackIndex = lua_gettop(L);
// Allow the user to just pass a table without specifying a starting point.
if(lua_type(L, 1) == LUA_TNUMBER)
{
// Indices from Lua are one-indexed. -1 to adjust.
First = IArg(1)-1;
if( First < 0 )
{
LOG->Warn( "ActorMultiVertex::SetVertices: index %d provided, cannot set Index < 1", First+1 );
return 0;
}
}
int Last = First + lua_objlen(L, StackIndex );
if( Last > (int) p->GetNumVertices())
{
p->AddVertices( Last - p->GetNumVertices() );
}
for(int n = First; n < Last; ++n)
{
lua_pushnumber(L, n-First+1);
lua_gettable(L, StackIndex);
SetVertexFromStack(p, L, n, lua_gettop(L));
lua_pop(L, 1);
}
return 0;
}
static int SetEffectMode( T* p, lua_State *L )
{
EffectMode em = Enum::Check<EffectMode>(L, 1);
p->SetEffectMode( em );
return 0;
}
static int SetTextureMode( T* p, lua_State *L )
{
TextureMode tm = Enum::Check<TextureMode>(L, 1);
p->SetTextureMode( tm );
return 0;
}
static int SetLineWidth( T* p, lua_State *L )
{
float Width = FArg(1);
if( Width < 0 )
{
LOG->Warn( "ActorMultiVertex::SetLineWidth: cannot set negative width." );
return 0;
}
p->SetLineWidth(Width);
return 0;
}
static int SetDrawState( T* p, lua_State* L )
{
DrawMode dm= p->GetDestDrawMode();
int first= p->GetDestFirstToDraw();
int num= p->GetDestNumToDraw();
int ArgsIndex= 1;
if( !lua_istable(L, ArgsIndex) )
{
LOG->Warn( "ActorMultiVertex:SetDrawState: Table expected, something else recieved. Doing nothing.");
return 0;
}
// Fetch the draw mode, if provided.
lua_getfield(L, ArgsIndex, "Mode");
if( !lua_isnil(L, -1) )
{
dm= Enum::Check<DrawMode>(L, -1);
}
lua_pop(L, 1);
// Fetch FirstToDraw, if provided.
lua_getfield(L, ArgsIndex, "First");
if( !lua_isnil(L, -1) )
{
// Indices from Lua are one-indexed. -1 to adjust.
first= IArg(-1)-1;
}
lua_pop(L, 1);
// Fetch NumToDraw, if provided.
lua_getfield(L, ArgsIndex, "Num");
if( !lua_isnil(L, -1) )
{
num= IArg(-1);
}
lua_pop(L, 1);
p->SetDrawState(dm, first, num);
return 0;
}
static int GetDestDrawMode( T* p, lua_State* L )
{
Enum::Push(L, p->GetDestDrawMode());
return 1;
}
static int GetDestFirstToDraw( T* p, lua_State* L )
{
// Indices in Lua are one-indexed. +1 to adjust.
lua_pushnumber(L, p->GetDestFirstToDraw()+1);
return 1;
}
static int GetDestNumToDraw( T* p, lua_State* L )
{
lua_pushnumber(L, p->GetDestNumToDraw());
return 1;
}
static int GetCurrDrawMode( T* p, lua_State* L )
{
Enum::Push(L, p->GetCurrDrawMode());
return 1;
}
static int GetCurrFirstToDraw( T* p, lua_State* L )
{
// Indices in Lua are one-indexed. +1 to adjust.
lua_pushnumber(L, p->GetCurrFirstToDraw()+1);
return 1;
}
static int GetCurrNumToDraw( T* p, lua_State* L )
{
lua_pushnumber(L, p->GetCurrNumToDraw());
return 1;
}
static int LoadTexture( T* p, lua_State *L )
{
if( lua_isnil(L, 1) )
{
p->UnloadTexture();
}
else
{
RageTextureID ID( SArg(1) );
p->LoadFromTexture( ID );
}
return 0;
}
static int SetTexture( T* p, lua_State *L )
{
RageTexture *Texture = Luna<RageTexture>::check(L, 1);
Texture = TEXTUREMAN->CopyTexture( Texture );
p->SetTexture( Texture );
return 0;
}
LunaActorMultiVertex()
{
ADD_METHOD( SetVertex );
ADD_METHOD( SetVertices );
ADD_METHOD( SetEffectMode );
ADD_METHOD( SetTextureMode );
ADD_METHOD( SetLineWidth );
ADD_METHOD( SetDrawState );
ADD_METHOD( SetNumVertices );
ADD_METHOD( GetNumVertices );
ADD_METHOD( GetDestDrawMode );
ADD_METHOD( GetDestFirstToDraw );
ADD_METHOD( GetDestNumToDraw );
ADD_METHOD( GetCurrDrawMode );
ADD_METHOD( GetCurrFirstToDraw );
ADD_METHOD( GetCurrNumToDraw );
// Copy from RageTexture
ADD_METHOD( SetTexture );
// Load from file path
ADD_METHOD( LoadTexture );
}
};
LUA_REGISTER_DERIVED_CLASS( ActorMultiVertex, Actor )
/*
* (c) 2014 Matthew Gardner and Eric Reese
* 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.
*/
+146
View File
@@ -0,0 +1,146 @@
/** @brief ActorMultiVertex - A texture created from multiple textures. */
#include "Actor.h"
#include "RageDisplay.h"
#include "RageTextureID.h"
enum DrawMode
{
DrawMode_Quads = 0,
DrawMode_QuadStrip,
DrawMode_Fan,
DrawMode_Strip,
DrawMode_Triangles,
DrawMode_LineStrip,
DrawMode_SymmetricQuadStrip,
NUM_DrawMode,
DrawMode_Invalid
};
const RString& DrawModeToString( DrawMode cat );
const RString& DrawModeToLocalizedString( DrawMode cat );
LuaDeclareType( DrawMode );
class RageTexture;
class ActorMultiVertex: public Actor
{
public:
ActorMultiVertex();
ActorMultiVertex( const ActorMultiVertex &cpy );
virtual ~ActorMultiVertex();
void LoadFromNode( const XNode* Node );
virtual ActorMultiVertex *Copy() const;
struct AMV_TweenState
{
AMV_TweenState(): _DrawMode(DrawMode_Invalid), FirstToDraw(0), NumToDraw(-1), line_width(1.0f) {}
static void MakeWeightedAverage(AMV_TweenState& average_out, const AMV_TweenState& ts1, const AMV_TweenState& ts2, float percent_between);
bool operator==(const AMV_TweenState& other) const;
bool operator!=(const AMV_TweenState& other) const { return !operator==(other); }
void SetDrawState( DrawMode dm, int first, int num );
int GetSafeNumToDraw( DrawMode dm, int num ) const;
vector<RageSpriteVertex> vertices;
DrawMode _DrawMode;
int FirstToDraw;
int NumToDraw;
// needed for DrawMode_LineStrip
float line_width;
};
AMV_TweenState& AMV_DestTweenState()
{
if(AMV_Tweens.empty())
{ return AMV_current; }
else
{ return AMV_Tweens.back(); }
}
const AMV_TweenState& AMV_DestTweenState() const { return const_cast<ActorMultiVertex*>(this)->AMV_DestTweenState(); }
virtual bool EarlyAbortDraw() const;
virtual void DrawPrimitives();
virtual void DrawInternal( const AMV_TweenState *TS );
void SetCurrentTweenStart();
void EraseHeadTween();
void UpdatePercentThroughTween( float PercentThroughTween );
void BeginTweening( float time, ITween *pInterp );
void StopTweening();
void FinishTweening();
void SetTexture( RageTexture *Texture );
void LoadFromTexture( RageTextureID ID );
void UnloadTexture();
void SetNumVertices( size_t n );
void AddVertex();
void AddVertices( int Add );
void SetEffectMode( EffectMode em) { _EffectMode = em; }
void SetTextureMode( TextureMode tm) { _TextureMode = tm; }
void SetLineWidth( float width) { AMV_DestTweenState().line_width = width; }
void SetDrawState( DrawMode dm, int first, int num ) { AMV_DestTweenState().SetDrawState(dm, first, num); }
DrawMode GetDestDrawMode() const { return AMV_DestTweenState()._DrawMode; }
int GetDestFirstToDraw() const { return AMV_DestTweenState().FirstToDraw; }
int GetDestNumToDraw() const { return AMV_DestTweenState().NumToDraw; }
DrawMode GetCurrDrawMode() const { return AMV_current._DrawMode; }
int GetCurrFirstToDraw() const { return AMV_current.FirstToDraw; }
int GetCurrNumToDraw() const { return AMV_current.NumToDraw; }
size_t GetNumVertices() { return AMV_DestTweenState().vertices.size(); }
void SetVertexPos( int index , float x , float y , float z );
void SetVertexColor( int index , RageColor c );
void SetVertexCoords( int index , float TexCoordX , float TexCoordY );
virtual void PushSelf( lua_State *L );
private:
RageTexture* _Texture;
vector<RageSpriteVertex> _Vertices;
vector<AMV_TweenState> AMV_Tweens;
AMV_TweenState AMV_current;
AMV_TweenState AMV_start;
// required to handle diffuse and glow
AMV_TweenState *AMV_TempState;
EffectMode _EffectMode;
TextureMode _TextureMode;
};
/**
* @file
* @author Matthew Gardner and Eric Reese (c) 2014
* @section LICENSE
* 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.
*/
+12
View File
@@ -73,6 +73,18 @@ RString RageColor::NormalizeColorString( RString sColor )
return "";
return c.ToString();
}
void WeightedAvergeOfRSVs(RageSpriteVertex& average_out, RageSpriteVertex const& rsv1, RageSpriteVertex const& rsv2, float percent_between)
{
average_out.p= lerp(percent_between, rsv1.p, rsv2.p);
average_out.n= lerp(percent_between, rsv1.n, rsv2.n);
average_out.c.b= lerp(percent_between, rsv1.c.b, rsv2.c.b);
average_out.c.g= lerp(percent_between, rsv1.c.g, rsv2.c.g);
average_out.c.r= lerp(percent_between, rsv1.c.r, rsv2.c.r);
average_out.c.a= lerp(percent_between, rsv1.c.a, rsv2.c.a);
average_out.t= lerp(percent_between, rsv1.t, rsv2.t);
}
/** @brief Utilities for working with Lua. */
namespace LuaHelpers
{
+1
View File
@@ -342,6 +342,7 @@ struct RageSpriteVertex // has color
RageVector2 t; // texture coordinates
};
void WeightedAvergeOfRSVs(RageSpriteVertex& average_out, RageSpriteVertex const& rsv1, RageSpriteVertex const& rsv2, float percent_between);
struct RageModelVertex // doesn't have color. Relies on material color
{