Added wrapper states to actors. Wrapping an actor inside a frame when building a screen is now unnecessary.

This commit is contained in:
Kyzentun
2015-01-30 09:05:09 -07:00
parent 0a4902c648
commit 647b361284
6 changed files with 196 additions and 20 deletions
+157 -20
View File
@@ -1,5 +1,6 @@
#include "global.h"
#include "Actor.h"
#include "ActorFrame.h"
#include "RageDisplay.h"
#include "RageUtil.h"
#include "RageMath.h"
@@ -172,6 +173,11 @@ Actor::~Actor()
{
StopTweening();
UnsubscribeAll();
for(size_t i= 0; i < m_WrapperStates.size(); ++i)
{
SAFE_DELETE(m_WrapperStates[i]);
}
m_WrapperStates.clear();
}
Actor::Actor( const Actor &cpy ):
@@ -187,6 +193,12 @@ Actor::Actor( const Actor &cpy ):
CPY( m_FakeParent );
CPY( m_pLuaInstance );
m_WrapperStates.resize(cpy.m_WrapperStates.size());
for(size_t i= 0; i < m_WrapperStates.size(); ++i)
{
m_WrapperStates[i]= new ActorFrame(*dynamic_cast<ActorFrame*>(cpy.m_WrapperStates[i]));
}
CPY( m_baseRotation );
CPY( m_baseScale );
CPY( m_fBaseAlpha );
@@ -296,7 +308,6 @@ void Actor::Draw()
{
return; // early abort
}
bool fake_parent_partially_opaque= true;
if(m_FakeParent)
{
if(!m_FakeParent->m_bVisible || m_FakeParent->m_fHibernateSecondsLeft > 0
@@ -305,31 +316,99 @@ void Actor::Draw()
return;
}
m_FakeParent->PreDraw();
fake_parent_partially_opaque= m_FakeParent->PartiallyOpaque();
}
this->PreDraw();
ASSERT( m_pTempState != NULL );
if(PartiallyOpaque() && fake_parent_partially_opaque)
{
if(m_FakeParent)
if(!m_FakeParent->PartiallyOpaque())
{
m_FakeParent->BeginDraw();
}
// call the most-derived versions
this->BeginDraw();
this->DrawPrimitives(); // call the most-derived version of DrawPrimitives();
this->EndDraw();
if(m_FakeParent)
{
m_FakeParent->EndDraw();
m_FakeParent->PostDraw();
return;
}
}
this->PostDraw();
if(m_FakeParent)
{
m_FakeParent->BeginDraw();
}
size_t wrapper_states_used= 0;
RageColor last_diffuse;
RageColor last_glow;
bool use_last_diffuse= false;
// dont_abort_draw exists because if one of the layers is invisible,
// there's no point in continuing. -Kyz
bool dont_abort_draw= true;
// abort_with_end_draw exists because PreDraw happens before the
// opaqueness test, so if we abort at the opaqueness test, there isn't
// a BeginDraw to match the EndDraw. -Kyz
bool abort_with_end_draw= true;
// It's more intuitive to apply the highest index wrappers first.
// On the lua side, it looks like this:
// wrapper[3] is the outermost frame. wrapper[2] is inside wrapper[3].
// wrapper[1] is inside wrapper[2]. The actor is inside wrapper[1].
// -Kyz
for(size_t i= m_WrapperStates.size(); i > 0 && dont_abort_draw; --i)
{
Actor* state= m_WrapperStates[i-1];
if(!state->m_bVisible || state->m_fHibernateSecondsLeft > 0 ||
state->EarlyAbortDraw())
{
dont_abort_draw= false;
}
else
{
state->PreDraw();
if(state->PartiallyOpaque())
{
state->BeginDraw();
last_diffuse= state->m_pTempState->diffuse[0];
last_glow= state->m_pTempState->glow;
use_last_diffuse= true;
if(i > 1)
{
m_WrapperStates[i-2]->SetInternalDiffuse(last_diffuse);
m_WrapperStates[i-2]->SetInternalGlow(last_glow);
}
}
else
{
dont_abort_draw= false;
abort_with_end_draw= false;
}
++wrapper_states_used;
}
}
// call the most-derived versions
if(dont_abort_draw)
{
if(use_last_diffuse)
{
this->SetInternalDiffuse(last_diffuse);
this->SetInternalGlow(last_glow);
}
this->PreDraw();
ASSERT( m_pTempState != NULL );
if(PartiallyOpaque())
{
this->BeginDraw();
this->DrawPrimitives();
this->EndDraw();
}
this->PostDraw();
}
for(size_t i= 0; i < wrapper_states_used; ++i)
{
Actor* state= m_WrapperStates[i];
if(abort_with_end_draw)
{
state->EndDraw();
}
abort_with_end_draw= true;
state->PostDraw();
state->m_pTempState= NULL;
}
if(m_FakeParent)
{
m_FakeParent->EndDraw();
m_FakeParent->PostDraw();
m_FakeParent->m_pTempState= NULL;
}
m_pTempState = NULL;
}
@@ -728,6 +807,10 @@ void Actor::Update( float fDeltaTime )
fDeltaTime = -m_fHibernateSecondsLeft;
m_fHibernateSecondsLeft = 0;
}
for(size_t i= 0; i < m_WrapperStates.size(); ++i)
{
m_WrapperStates[i]->Update(fDeltaTime);
}
this->UpdateInternal( fDeltaTime );
}
@@ -823,6 +906,26 @@ RString Actor::GetLineage() const
return sPath;
}
void Actor::AddWrapperState()
{
ActorFrame* wrapper= new ActorFrame;
wrapper->InitState();
m_WrapperStates.push_back(wrapper);
}
void Actor::RemoveWrapperState(size_t i)
{
ASSERT(i < m_WrapperStates.size());
SAFE_DELETE(m_WrapperStates[i]);
m_WrapperStates.erase(m_WrapperStates.begin()+i);
}
Actor* Actor::GetWrapperState(size_t i)
{
ASSERT(i < m_WrapperStates.size());
return m_WrapperStates[i];
}
void Actor::BeginTweening( float time, ITween *pTween )
{
ASSERT( time >= 0 );
@@ -1765,6 +1868,36 @@ public:
}
COMMON_RETURN_SELF;
}
static int AddWrapperState(T* p, lua_State* L)
{
p->AddWrapperState();
p->GetWrapperState(p->GetNumWrapperStates()-1)->PushSelf(L);
return 1;
}
static size_t get_state_index(T* p, lua_State* L, int stack_index)
{
// Lua is one indexed.
int i= IArg(stack_index)-1;
const size_t si= static_cast<size_t>(i);
if(i < 0 || si >= p->GetNumWrapperStates())
{
luaL_error(L, "%d is not a valid wrapper state index.", i+1);
}
return si;
}
static int RemoveWrapperState(T* p, lua_State* L)
{
size_t si= get_state_index(p, L, 1);
p->RemoveWrapperState(si);
COMMON_RETURN_SELF;
}
DEFINE_METHOD(GetNumWrapperStates, GetNumWrapperStates());
static int GetWrapperState(T* p, lua_State* L)
{
size_t si= get_state_index(p, L, 1);
p->GetWrapperState(si)->PushSelf(L);
return 1;
}
static int Draw( T* p, lua_State *L )
{
LUA->YieldLua();
@@ -1938,6 +2071,10 @@ public:
ADD_METHOD( GetParent );
ADD_METHOD( GetFakeParent );
ADD_METHOD( SetFakeParent );
ADD_METHOD( AddWrapperState );
ADD_METHOD( RemoveWrapperState );
ADD_METHOD( GetNumWrapperStates );
ADD_METHOD( GetWrapperState );
ADD_METHOD( Draw );
}