The big NULL replacement party part 2.
This may take a bit. Trying to do this by operator/command.
This commit is contained in:
+1
-1
@@ -111,7 +111,7 @@ std::string valueToString( bool value )
|
||||
std::string valueToQuotedString( const char *value )
|
||||
{
|
||||
// Not sure how to handle unicode...
|
||||
if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
|
||||
if (strpbrk(value, "\"\\\b\f\n\r\t") == nullptr && !containsControlCharacter( value ))
|
||||
return std::string("\"") + value + "\"";
|
||||
// We have to walk value and escape any special characters.
|
||||
// Appending to std::string is not efficient, but this should be rare.
|
||||
|
||||
+4
-4
@@ -175,7 +175,7 @@ Actor::Actor( const Actor &cpy ):
|
||||
MessageSubscriber( cpy )
|
||||
{
|
||||
/* Don't copy an Actor in the middle of rendering. */
|
||||
ASSERT( cpy.m_pTempState == NULL );
|
||||
ASSERT( cpy.m_pTempState == nullptr );
|
||||
m_pTempState = NULL;
|
||||
|
||||
#define CPY(x) x = cpy.x
|
||||
@@ -1081,7 +1081,7 @@ void Actor::RunCommands( const LuaReference& cmds, const LuaReference *pParamTab
|
||||
this->PushSelf( L );
|
||||
|
||||
// 2nd parameter
|
||||
if( pParamTable == NULL )
|
||||
if( pParamTable == nullptr )
|
||||
lua_pushnil( L );
|
||||
else
|
||||
pParamTable->PushSelf( L );
|
||||
@@ -1482,7 +1482,7 @@ public:
|
||||
static int GetCommand( T* p, lua_State *L )
|
||||
{
|
||||
const apActorCommands *pCommand = p->GetCommand(SArg(1));
|
||||
if( pCommand == NULL )
|
||||
if( pCommand == nullptr )
|
||||
lua_pushnil( L );
|
||||
else
|
||||
(*pCommand)->PushSelf(L);
|
||||
@@ -1537,7 +1537,7 @@ public:
|
||||
static int GetParent( T* p, lua_State *L )
|
||||
{
|
||||
Actor *pParent = p->GetParent();
|
||||
if( pParent == NULL )
|
||||
if( pParent == nullptr )
|
||||
lua_pushnil( L );
|
||||
else
|
||||
pParent->PushSelf(L);
|
||||
|
||||
+2
-2
@@ -118,7 +118,7 @@ void ActorFrame::LoadChildrenFromNode( const XNode* pNode )
|
||||
// Load children
|
||||
const XNode* pChildren = pNode->GetChild("children");
|
||||
bool bArrayOnly = false;
|
||||
if( pChildren == NULL )
|
||||
if( pChildren == nullptr )
|
||||
{
|
||||
bArrayOnly = true;
|
||||
pChildren = pNode;
|
||||
@@ -544,7 +544,7 @@ public:
|
||||
{
|
||||
// this one is tricky, we need to get an Actor from Lua.
|
||||
Actor *pActor = ActorUtil::MakeActor( SArg(1) );
|
||||
if ( pActor == NULL )
|
||||
if ( pActor == nullptr )
|
||||
{
|
||||
lua_pushboolean( L, 0 );
|
||||
return 1;
|
||||
|
||||
+127
-127
@@ -1,127 +1,127 @@
|
||||
#include "global.h"
|
||||
#include "ActorFrameTexture.h"
|
||||
#include "RageTextureRenderTarget.h"
|
||||
#include "RageTextureManager.h"
|
||||
#include "ActorUtil.h"
|
||||
|
||||
REGISTER_ACTOR_CLASS_WITH_NAME( ActorFrameTextureAutoDeleteChildren, ActorFrameTexture );
|
||||
ActorFrameTexture *ActorFrameTexture::Copy() const { return new ActorFrameTexture(*this); }
|
||||
|
||||
ActorFrameTexture::ActorFrameTexture()
|
||||
{
|
||||
m_bDepthBuffer = false;
|
||||
m_bAlphaBuffer = false;
|
||||
m_bFloat = false;
|
||||
m_bPreserveTexture = false;
|
||||
static uint64_t i = 0;
|
||||
++i;
|
||||
m_sTextureName = ssprintf( ConvertI64FormatString("ActorFrameTexture %lli"), i );
|
||||
|
||||
m_pRenderTarget = NULL;
|
||||
}
|
||||
|
||||
ActorFrameTexture::ActorFrameTexture( const ActorFrameTexture &cpy ):
|
||||
ActorFrame(cpy)
|
||||
{
|
||||
FAIL_M( "ActorFrameTexture copy not implemented" );
|
||||
}
|
||||
|
||||
ActorFrameTexture::~ActorFrameTexture()
|
||||
{
|
||||
/* Release our reference to the texture. */
|
||||
TEXTUREMAN->UnloadTexture( m_pRenderTarget );
|
||||
}
|
||||
|
||||
void ActorFrameTexture::Create()
|
||||
{
|
||||
ASSERT( m_pRenderTarget == NULL );
|
||||
RageTextureID id( m_sTextureName );
|
||||
id.Policy = RageTextureID::TEX_VOLATILE;
|
||||
|
||||
RenderTargetParam param;
|
||||
param.bWithDepthBuffer = m_bDepthBuffer;
|
||||
param.bWithAlpha = m_bAlphaBuffer;
|
||||
param.bFloat = m_bFloat;
|
||||
param.iWidth = (int) m_size.x;
|
||||
param.iHeight = (int) m_size.y;
|
||||
m_pRenderTarget = new RageTextureRenderTarget( id, param );
|
||||
m_pRenderTarget->m_bWasUsed = true;
|
||||
|
||||
/* This passes ownership of m_pRenderTarget to TEXTUREMAN, but we retain
|
||||
* our reference to it until we call TEXTUREMAN->UnloadTexture. */
|
||||
TEXTUREMAN->RegisterTexture( id, m_pRenderTarget );
|
||||
}
|
||||
|
||||
void ActorFrameTexture::DrawPrimitives()
|
||||
{
|
||||
if( m_pRenderTarget == NULL )
|
||||
return;
|
||||
|
||||
m_pRenderTarget->BeginRenderingTo( m_bPreserveTexture );
|
||||
|
||||
ActorFrame::DrawPrimitives();
|
||||
|
||||
m_pRenderTarget->FinishRenderingTo();
|
||||
}
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
/** @brief Allow Lua to have access to the ActorFrameTexture. */
|
||||
class LunaActorFrameTexture : public Luna<ActorFrameTexture>
|
||||
{
|
||||
public:
|
||||
static int Create( T* p, lua_State * ) { p->Create(); return 0; }
|
||||
static int EnableDepthBuffer( T* p, lua_State *L ) { p->EnableDepthBuffer(BArg(1)); return 0; }
|
||||
static int EnableAlphaBuffer( T* p, lua_State *L ) { p->EnableAlphaBuffer(BArg(1)); return 0; }
|
||||
static int EnableFloat( T* p, lua_State *L ) { p->EnableFloat(BArg(1)); return 0; }
|
||||
static int EnablePreserveTexture( T* p, lua_State *L ) { p->EnablePreserveTexture(BArg(1)); return 0; }
|
||||
static int SetTextureName( T* p, lua_State *L ) { p->SetTextureName(SArg(1)); return 0; }
|
||||
static int GetTexture( T* p, lua_State *L )
|
||||
{
|
||||
RageTexture *pTexture = p->GetTexture();
|
||||
if( pTexture == NULL )
|
||||
return 0;
|
||||
pTexture->PushSelf(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LunaActorFrameTexture()
|
||||
{
|
||||
ADD_METHOD( Create );
|
||||
ADD_METHOD( EnableDepthBuffer );
|
||||
ADD_METHOD( EnableAlphaBuffer );
|
||||
ADD_METHOD( EnableFloat );
|
||||
ADD_METHOD( EnablePreserveTexture );
|
||||
ADD_METHOD( SetTextureName );
|
||||
ADD_METHOD( GetTexture );
|
||||
}
|
||||
};
|
||||
|
||||
LUA_REGISTER_DERIVED_CLASS( ActorFrameTexture, ActorFrame )
|
||||
// lua end
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "ActorFrameTexture.h"
|
||||
#include "RageTextureRenderTarget.h"
|
||||
#include "RageTextureManager.h"
|
||||
#include "ActorUtil.h"
|
||||
|
||||
REGISTER_ACTOR_CLASS_WITH_NAME( ActorFrameTextureAutoDeleteChildren, ActorFrameTexture );
|
||||
ActorFrameTexture *ActorFrameTexture::Copy() const { return new ActorFrameTexture(*this); }
|
||||
|
||||
ActorFrameTexture::ActorFrameTexture()
|
||||
{
|
||||
m_bDepthBuffer = false;
|
||||
m_bAlphaBuffer = false;
|
||||
m_bFloat = false;
|
||||
m_bPreserveTexture = false;
|
||||
static uint64_t i = 0;
|
||||
++i;
|
||||
m_sTextureName = ssprintf( ConvertI64FormatString("ActorFrameTexture %lli"), i );
|
||||
|
||||
m_pRenderTarget = NULL;
|
||||
}
|
||||
|
||||
ActorFrameTexture::ActorFrameTexture( const ActorFrameTexture &cpy ):
|
||||
ActorFrame(cpy)
|
||||
{
|
||||
FAIL_M( "ActorFrameTexture copy not implemented" );
|
||||
}
|
||||
|
||||
ActorFrameTexture::~ActorFrameTexture()
|
||||
{
|
||||
/* Release our reference to the texture. */
|
||||
TEXTUREMAN->UnloadTexture( m_pRenderTarget );
|
||||
}
|
||||
|
||||
void ActorFrameTexture::Create()
|
||||
{
|
||||
ASSERT( m_pRenderTarget == nullptr );
|
||||
RageTextureID id( m_sTextureName );
|
||||
id.Policy = RageTextureID::TEX_VOLATILE;
|
||||
|
||||
RenderTargetParam param;
|
||||
param.bWithDepthBuffer = m_bDepthBuffer;
|
||||
param.bWithAlpha = m_bAlphaBuffer;
|
||||
param.bFloat = m_bFloat;
|
||||
param.iWidth = (int) m_size.x;
|
||||
param.iHeight = (int) m_size.y;
|
||||
m_pRenderTarget = new RageTextureRenderTarget( id, param );
|
||||
m_pRenderTarget->m_bWasUsed = true;
|
||||
|
||||
/* This passes ownership of m_pRenderTarget to TEXTUREMAN, but we retain
|
||||
* our reference to it until we call TEXTUREMAN->UnloadTexture. */
|
||||
TEXTUREMAN->RegisterTexture( id, m_pRenderTarget );
|
||||
}
|
||||
|
||||
void ActorFrameTexture::DrawPrimitives()
|
||||
{
|
||||
if( m_pRenderTarget == nullptr )
|
||||
return;
|
||||
|
||||
m_pRenderTarget->BeginRenderingTo( m_bPreserveTexture );
|
||||
|
||||
ActorFrame::DrawPrimitives();
|
||||
|
||||
m_pRenderTarget->FinishRenderingTo();
|
||||
}
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
/** @brief Allow Lua to have access to the ActorFrameTexture. */
|
||||
class LunaActorFrameTexture : public Luna<ActorFrameTexture>
|
||||
{
|
||||
public:
|
||||
static int Create( T* p, lua_State * ) { p->Create(); return 0; }
|
||||
static int EnableDepthBuffer( T* p, lua_State *L ) { p->EnableDepthBuffer(BArg(1)); return 0; }
|
||||
static int EnableAlphaBuffer( T* p, lua_State *L ) { p->EnableAlphaBuffer(BArg(1)); return 0; }
|
||||
static int EnableFloat( T* p, lua_State *L ) { p->EnableFloat(BArg(1)); return 0; }
|
||||
static int EnablePreserveTexture( T* p, lua_State *L ) { p->EnablePreserveTexture(BArg(1)); return 0; }
|
||||
static int SetTextureName( T* p, lua_State *L ) { p->SetTextureName(SArg(1)); return 0; }
|
||||
static int GetTexture( T* p, lua_State *L )
|
||||
{
|
||||
RageTexture *pTexture = p->GetTexture();
|
||||
if( pTexture == nullptr )
|
||||
return 0;
|
||||
pTexture->PushSelf(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LunaActorFrameTexture()
|
||||
{
|
||||
ADD_METHOD( Create );
|
||||
ADD_METHOD( EnableDepthBuffer );
|
||||
ADD_METHOD( EnableAlphaBuffer );
|
||||
ADD_METHOD( EnableFloat );
|
||||
ADD_METHOD( EnablePreserveTexture );
|
||||
ADD_METHOD( SetTextureName );
|
||||
ADD_METHOD( GetTexture );
|
||||
}
|
||||
};
|
||||
|
||||
LUA_REGISTER_DERIVED_CLASS( ActorFrameTexture, ActorFrame )
|
||||
// lua end
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ ActorProxy::ActorProxy()
|
||||
|
||||
bool ActorProxy::EarlyAbortDraw() const
|
||||
{
|
||||
return m_pActorTarget == NULL || Actor::EarlyAbortDraw();
|
||||
return m_pActorTarget == nullptr || Actor::EarlyAbortDraw();
|
||||
}
|
||||
|
||||
void ActorProxy::DrawPrimitives()
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ static bool IsRegistered( const RString& sClassName )
|
||||
|
||||
void ActorUtil::Register( const RString& sClassName, CreateActorFn pfn )
|
||||
{
|
||||
if( g_pmapRegistrees == NULL )
|
||||
if( g_pmapRegistrees == nullptr )
|
||||
g_pmapRegistrees = new map<RString,CreateActorFn>;
|
||||
|
||||
map<RString,CreateActorFn>::iterator iter = g_pmapRegistrees->find( sClassName );
|
||||
@@ -211,7 +211,7 @@ Actor* ActorUtil::MakeActor( const RString &sPath_, Actor *pParentActor )
|
||||
case FT_Lua:
|
||||
{
|
||||
auto_ptr<XNode> pNode( LoadXNodeFromLuaShowErrors(sPath) );
|
||||
if( pNode.get() == NULL )
|
||||
if( pNode.get() == nullptr )
|
||||
{
|
||||
// XNode will warn about the error
|
||||
return new Actor;
|
||||
|
||||
+95
-95
@@ -1,95 +1,95 @@
|
||||
#include "global.h"
|
||||
#include "AutoActor.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "Actor.h"
|
||||
#include "ActorUtil.h"
|
||||
|
||||
void AutoActor::Unload()
|
||||
{
|
||||
delete m_pActor;
|
||||
m_pActor=NULL;
|
||||
}
|
||||
|
||||
AutoActor::AutoActor( const AutoActor &cpy )
|
||||
{
|
||||
if( cpy.m_pActor == NULL )
|
||||
m_pActor = NULL;
|
||||
else
|
||||
m_pActor = cpy.m_pActor->Copy();
|
||||
}
|
||||
|
||||
AutoActor &AutoActor::operator=( const AutoActor &cpy )
|
||||
{
|
||||
Unload();
|
||||
|
||||
if( cpy.m_pActor == NULL )
|
||||
m_pActor = NULL;
|
||||
else
|
||||
m_pActor = cpy.m_pActor->Copy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void AutoActor::Load( Actor *pActor )
|
||||
{
|
||||
Unload();
|
||||
m_pActor = pActor;
|
||||
}
|
||||
|
||||
void AutoActor::Load( const RString &sPath )
|
||||
{
|
||||
Unload();
|
||||
m_pActor = ActorUtil::MakeActor( sPath );
|
||||
|
||||
// If a Condition is false, MakeActor will return NULL.
|
||||
if( m_pActor == NULL )
|
||||
m_pActor = new Actor;
|
||||
}
|
||||
|
||||
void AutoActor::LoadB( const RString &sMetricsGroup, const RString &sElement )
|
||||
{
|
||||
ThemeManager::PathInfo pi;
|
||||
bool b = THEME->GetPathInfo( pi, EC_BGANIMATIONS, sMetricsGroup, sElement );
|
||||
ASSERT( b );
|
||||
LuaThreadVariable var1( "MatchingMetricsGroup", pi.sMatchingMetricsGroup );
|
||||
LuaThreadVariable var2( "MatchingElement", pi.sMatchingElement );
|
||||
Load( pi.sResolvedPath );
|
||||
}
|
||||
|
||||
void AutoActor::LoadActorFromNode( const XNode* pNode, Actor *pParent )
|
||||
{
|
||||
Unload();
|
||||
|
||||
m_pActor = ActorUtil::LoadFromNode( pNode, pParent );
|
||||
}
|
||||
|
||||
void AutoActor::LoadAndSetName( const RString &sScreenName, const RString &sActorName )
|
||||
{
|
||||
Load( THEME->GetPathG(sScreenName,sActorName) );
|
||||
m_pActor->SetName( sActorName );
|
||||
ActorUtil::LoadAllCommands( *m_pActor, sScreenName );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "AutoActor.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "Actor.h"
|
||||
#include "ActorUtil.h"
|
||||
|
||||
void AutoActor::Unload()
|
||||
{
|
||||
delete m_pActor;
|
||||
m_pActor=NULL;
|
||||
}
|
||||
|
||||
AutoActor::AutoActor( const AutoActor &cpy )
|
||||
{
|
||||
if( cpy.m_pActor == nullptr )
|
||||
m_pActor = NULL;
|
||||
else
|
||||
m_pActor = cpy.m_pActor->Copy();
|
||||
}
|
||||
|
||||
AutoActor &AutoActor::operator=( const AutoActor &cpy )
|
||||
{
|
||||
Unload();
|
||||
|
||||
if( cpy.m_pActor == nullptr )
|
||||
m_pActor = NULL;
|
||||
else
|
||||
m_pActor = cpy.m_pActor->Copy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void AutoActor::Load( Actor *pActor )
|
||||
{
|
||||
Unload();
|
||||
m_pActor = pActor;
|
||||
}
|
||||
|
||||
void AutoActor::Load( const RString &sPath )
|
||||
{
|
||||
Unload();
|
||||
m_pActor = ActorUtil::MakeActor( sPath );
|
||||
|
||||
// If a Condition is false, MakeActor will return NULL.
|
||||
if( m_pActor == nullptr )
|
||||
m_pActor = new Actor;
|
||||
}
|
||||
|
||||
void AutoActor::LoadB( const RString &sMetricsGroup, const RString &sElement )
|
||||
{
|
||||
ThemeManager::PathInfo pi;
|
||||
bool b = THEME->GetPathInfo( pi, EC_BGANIMATIONS, sMetricsGroup, sElement );
|
||||
ASSERT( b );
|
||||
LuaThreadVariable var1( "MatchingMetricsGroup", pi.sMatchingMetricsGroup );
|
||||
LuaThreadVariable var2( "MatchingElement", pi.sMatchingElement );
|
||||
Load( pi.sResolvedPath );
|
||||
}
|
||||
|
||||
void AutoActor::LoadActorFromNode( const XNode* pNode, Actor *pParent )
|
||||
{
|
||||
Unload();
|
||||
|
||||
m_pActor = ActorUtil::LoadFromNode( pNode, pParent );
|
||||
}
|
||||
|
||||
void AutoActor::LoadAndSetName( const RString &sScreenName, const RString &sActorName )
|
||||
{
|
||||
Load( THEME->GetPathG(sScreenName,sActorName) );
|
||||
m_pActor->SetName( sActorName );
|
||||
ActorUtil::LoadAllCommands( *m_pActor, sScreenName );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-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.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ void BGAnimation::LoadFromAniDir( const RString &_sAniDir )
|
||||
|
||||
XNode* pBGAnimation = ini.GetChild( "BGAnimation" );
|
||||
XNode dummy( "BGAnimation" );
|
||||
if( pBGAnimation == NULL )
|
||||
if( pBGAnimation == nullptr )
|
||||
pBGAnimation = &dummy;
|
||||
|
||||
LoadFromNode( pBGAnimation );
|
||||
|
||||
+671
-671
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -259,7 +259,7 @@ void BPMDisplay::SetFromGameState()
|
||||
}
|
||||
if( GAMESTATE->m_pCurCourse.Get() )
|
||||
{
|
||||
if( GAMESTATE->GetCurrentStyle() == NULL )
|
||||
if( GAMESTATE->GetCurrentStyle() == nullptr )
|
||||
; // This is true when backing out from ScreenSelectCourse to ScreenTitleMenu. So, don't call SetBpmFromCourse where an assert will fire.
|
||||
else
|
||||
SetBpmFromCourse( GAMESTATE->m_pCurCourse );
|
||||
|
||||
@@ -255,7 +255,7 @@ static void GetFilterToFileNames( const RString sBaseDir, const Song *pSong, set
|
||||
}
|
||||
|
||||
XNode *pSection = ini.GetChild( sSection );
|
||||
if( pSection == NULL )
|
||||
if( pSection == nullptr )
|
||||
{
|
||||
ASSERT_M( 0, ssprintf("File '%s' refers to a section '%s' that is missing.", sPath.c_str(), sSection.c_str()) );
|
||||
return;
|
||||
|
||||
+355
-355
@@ -1,355 +1,355 @@
|
||||
#include "global.h"
|
||||
#include "Banner.h"
|
||||
#include "BannerCache.h"
|
||||
#include "SongManager.h"
|
||||
#include "RageUtil.h"
|
||||
#include "Song.h"
|
||||
#include "RageTextureManager.h"
|
||||
#include "Course.h"
|
||||
#include "Character.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "CharacterManager.h"
|
||||
#include "ActorUtil.h"
|
||||
#include "UnlockManager.h"
|
||||
#include "PrefsManager.h"
|
||||
|
||||
REGISTER_ACTOR_CLASS( Banner );
|
||||
|
||||
ThemeMetric<bool> SCROLL_RANDOM ("Banner","ScrollRandom");
|
||||
ThemeMetric<bool> SCROLL_ROULETTE ("Banner","ScrollRoulette");
|
||||
ThemeMetric<bool> SCROLL_MODE ("Banner","ScrollMode");
|
||||
ThemeMetric<bool> SCROLL_SORT_ORDER ("Banner","ScrollSortOrder");
|
||||
ThemeMetric<float> SCROLL_SPEED_DIVISOR ("Banner","ScrollSpeedDivisor");
|
||||
|
||||
Banner::Banner()
|
||||
{
|
||||
m_bScrolling = false;
|
||||
m_fPercentScrolling = 0;
|
||||
}
|
||||
|
||||
// Ugly: if sIsBanner is false, we're actually loading something other than a banner.
|
||||
void Banner::Load( RageTextureID ID, bool bIsBanner )
|
||||
{
|
||||
if( ID.filename == "" )
|
||||
{
|
||||
LoadFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
if( bIsBanner )
|
||||
ID = SongBannerTexture(ID);
|
||||
|
||||
m_fPercentScrolling = 0;
|
||||
m_bScrolling = false;
|
||||
|
||||
TEXTUREMAN->DisableOddDimensionWarning();
|
||||
TEXTUREMAN->VolatileTexture( ID );
|
||||
Sprite::Load( ID );
|
||||
TEXTUREMAN->EnableOddDimensionWarning();
|
||||
};
|
||||
|
||||
void Banner::LoadFromCachedBanner( const RString &sPath )
|
||||
{
|
||||
if( sPath.empty() )
|
||||
{
|
||||
LoadFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
RageTextureID ID;
|
||||
bool bLowRes = (PREFSMAN->m_BannerCache != BNCACHE_FULL);
|
||||
if( !bLowRes )
|
||||
{
|
||||
ID = Sprite::SongBannerTexture( sPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to load the low quality version.
|
||||
ID = BANNERCACHE->LoadCachedBanner( sPath );
|
||||
}
|
||||
|
||||
if( TEXTUREMAN->IsTextureRegistered(ID) )
|
||||
Load( ID );
|
||||
else if( IsAFile(sPath) )
|
||||
Load( sPath );
|
||||
else
|
||||
LoadFallback();
|
||||
}
|
||||
|
||||
void Banner::Update( float fDeltaTime )
|
||||
{
|
||||
Sprite::Update( fDeltaTime );
|
||||
|
||||
if( m_bScrolling )
|
||||
{
|
||||
m_fPercentScrolling += fDeltaTime/(float)SCROLL_SPEED_DIVISOR;
|
||||
m_fPercentScrolling -= (int)m_fPercentScrolling;
|
||||
|
||||
const RectF *pTextureRect = GetCurrentTextureCoordRect();
|
||||
|
||||
float fTexCoords[8] =
|
||||
{
|
||||
0+m_fPercentScrolling, pTextureRect->top, // top left
|
||||
0+m_fPercentScrolling, pTextureRect->bottom, // bottom left
|
||||
1+m_fPercentScrolling, pTextureRect->bottom, // bottom right
|
||||
1+m_fPercentScrolling, pTextureRect->top, // top right
|
||||
};
|
||||
Sprite::SetCustomTextureCoords( fTexCoords );
|
||||
}
|
||||
}
|
||||
|
||||
void Banner::SetScrolling( bool bScroll, float Percent)
|
||||
{
|
||||
m_bScrolling = bScroll;
|
||||
m_fPercentScrolling = Percent;
|
||||
|
||||
// Set up the texture coord rects for the current state.
|
||||
Update(0);
|
||||
}
|
||||
|
||||
void Banner::LoadFromSong( Song* pSong ) // NULL means no song
|
||||
{
|
||||
if( pSong == NULL ) LoadFallback();
|
||||
else if( pSong->HasBanner() ) Load( pSong->GetBannerPath() );
|
||||
else LoadFallback();
|
||||
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadMode()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","Mode") );
|
||||
m_bScrolling = (bool)SCROLL_MODE;
|
||||
}
|
||||
|
||||
void Banner::LoadFromSongGroup( RString sSongGroup )
|
||||
{
|
||||
RString sGroupBannerPath = SONGMAN->GetSongGroupBannerPath( sSongGroup );
|
||||
if( sGroupBannerPath != "" ) Load( sGroupBannerPath );
|
||||
else LoadGroupFallback();
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadFromCourse( const Course *pCourse ) // NULL means no course
|
||||
{
|
||||
if( pCourse == NULL ) LoadFallback();
|
||||
else if( pCourse->GetBannerPath() != "" ) Load( pCourse->GetBannerPath() );
|
||||
else LoadCourseFallback();
|
||||
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadCardFromCharacter( const Character *pCharacter )
|
||||
{
|
||||
if( pCharacter == NULL ) LoadFallback();
|
||||
else if( pCharacter->GetCardPath() != "" ) Load( pCharacter->GetCardPath() );
|
||||
else LoadFallback();
|
||||
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadIconFromCharacter( const Character *pCharacter )
|
||||
{
|
||||
if( pCharacter == NULL ) LoadFallbackCharacterIcon();
|
||||
else if( pCharacter->GetIconPath() != "" ) Load( pCharacter->GetIconPath(), false );
|
||||
else LoadFallbackCharacterIcon();
|
||||
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadBannerFromUnlockEntry( const UnlockEntry* pUE )
|
||||
{
|
||||
if( pUE == NULL )
|
||||
LoadFallback();
|
||||
else
|
||||
{
|
||||
RString sFile = pUE->GetBannerFile();
|
||||
Load( sFile );
|
||||
m_bScrolling = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Banner::LoadBackgroundFromUnlockEntry( const UnlockEntry* pUE )
|
||||
{
|
||||
if( pUE == NULL )
|
||||
LoadFallback();
|
||||
else
|
||||
{
|
||||
RString sFile = pUE->GetBackgroundFile();
|
||||
Load( sFile );
|
||||
m_bScrolling = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Banner::LoadFallback()
|
||||
{
|
||||
Load( THEME->GetPathG("Common","fallback banner") );
|
||||
}
|
||||
|
||||
void Banner::LoadFallbackBG()
|
||||
{
|
||||
Load( THEME->GetPathG("Common","fallback background") );
|
||||
}
|
||||
|
||||
void Banner::LoadGroupFallback()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","group fallback") );
|
||||
}
|
||||
|
||||
void Banner::LoadCourseFallback()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","course fallback") );
|
||||
}
|
||||
|
||||
void Banner::LoadFallbackCharacterIcon()
|
||||
{
|
||||
Character *pCharacter = CHARMAN->GetDefaultCharacter();
|
||||
if( pCharacter && !pCharacter->GetIconPath().empty() )
|
||||
Load( pCharacter->GetIconPath(), false );
|
||||
else
|
||||
LoadFallback();
|
||||
}
|
||||
|
||||
void Banner::LoadRoulette()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","roulette") );
|
||||
m_bScrolling = (bool)SCROLL_ROULETTE;
|
||||
}
|
||||
|
||||
void Banner::LoadRandom()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","random") );
|
||||
m_bScrolling = (bool)SCROLL_RANDOM;
|
||||
}
|
||||
|
||||
void Banner::LoadFromSortOrder( SortOrder so )
|
||||
{
|
||||
// TODO: See if the check for NULL/PREFERRED(?) is needed.
|
||||
if( so == SortOrder_Invalid )
|
||||
{
|
||||
LoadFallback();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( so != SORT_GROUP && so != SORT_RECENT )
|
||||
Load( THEME->GetPathG("Banner",ssprintf("%s",SortOrderToString(so).c_str())) );
|
||||
}
|
||||
m_bScrolling = (bool)SCROLL_SORT_ORDER;
|
||||
}
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
/** @brief Allow Lua to have access to the Banner. */
|
||||
class LunaBanner: public Luna<Banner>
|
||||
{
|
||||
public:
|
||||
static int scaletoclipped( T* p, lua_State *L ) { p->ScaleToClipped(FArg(1),FArg(2)); return 0; }
|
||||
static int ScaleToClipped( T* p, lua_State *L ) { p->ScaleToClipped(FArg(1),FArg(2)); return 0; }
|
||||
static int LoadFromSong( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromSong( NULL ); }
|
||||
else { Song *pS = Luna<Song>::check(L,1); p->LoadFromSong( pS ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromCourse( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromCourse( NULL ); }
|
||||
else { Course *pC = Luna<Course>::check(L,1); p->LoadFromCourse( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromCachedBanner( T* p, lua_State *L )
|
||||
{
|
||||
p->LoadFromCachedBanner( SArg(1) );
|
||||
return 0;
|
||||
}
|
||||
static int LoadIconFromCharacter( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadIconFromCharacter( NULL ); }
|
||||
else { Character *pC = Luna<Character>::check(L,1); p->LoadIconFromCharacter( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadCardFromCharacter( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadIconFromCharacter( NULL ); }
|
||||
else { Character *pC = Luna<Character>::check(L,1); p->LoadIconFromCharacter( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadBannerFromUnlockEntry( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadBannerFromUnlockEntry( NULL ); }
|
||||
else { UnlockEntry *pUE = Luna<UnlockEntry>::check(L,1); p->LoadBannerFromUnlockEntry( pUE ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadBackgroundFromUnlockEntry( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadBackgroundFromUnlockEntry( NULL ); }
|
||||
else { UnlockEntry *pUE = Luna<UnlockEntry>::check(L,1); p->LoadBackgroundFromUnlockEntry( pUE ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromSongGroup( T* p, lua_State *L )
|
||||
{
|
||||
p->LoadFromSongGroup( SArg(1) );
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromSortOrder( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromSortOrder( SortOrder_Invalid ); }
|
||||
else
|
||||
{
|
||||
SortOrder so = Enum::Check<SortOrder>(L, 1);
|
||||
p->LoadFromSortOrder( so );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int GetScrolling( T* p, lua_State *L ){ lua_pushboolean( L, p->GetScrolling() ); return 1; }
|
||||
static int SetScrolling( T* p, lua_State *L ){ p->SetScrolling( BArg(1), FArg(2) ); return 0; }
|
||||
static int GetPercentScrolling( T* p, lua_State *L ){ lua_pushnumber( L, p->ScrollingPercent() ); return 1; }
|
||||
|
||||
LunaBanner()
|
||||
{
|
||||
ADD_METHOD( scaletoclipped );
|
||||
ADD_METHOD( ScaleToClipped );
|
||||
ADD_METHOD( LoadFromSong );
|
||||
ADD_METHOD( LoadFromCourse );
|
||||
ADD_METHOD( LoadFromCachedBanner );
|
||||
ADD_METHOD( LoadIconFromCharacter );
|
||||
ADD_METHOD( LoadCardFromCharacter );
|
||||
ADD_METHOD( LoadBannerFromUnlockEntry );
|
||||
ADD_METHOD( LoadBackgroundFromUnlockEntry );
|
||||
ADD_METHOD( LoadFromSongGroup );
|
||||
ADD_METHOD( LoadFromSortOrder );
|
||||
ADD_METHOD( GetScrolling );
|
||||
ADD_METHOD( SetScrolling );
|
||||
ADD_METHOD( GetPercentScrolling );
|
||||
}
|
||||
};
|
||||
|
||||
LUA_REGISTER_DERIVED_CLASS( Banner, Sprite )
|
||||
// lua end
|
||||
|
||||
|
||||
/*
|
||||
* (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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "Banner.h"
|
||||
#include "BannerCache.h"
|
||||
#include "SongManager.h"
|
||||
#include "RageUtil.h"
|
||||
#include "Song.h"
|
||||
#include "RageTextureManager.h"
|
||||
#include "Course.h"
|
||||
#include "Character.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "CharacterManager.h"
|
||||
#include "ActorUtil.h"
|
||||
#include "UnlockManager.h"
|
||||
#include "PrefsManager.h"
|
||||
|
||||
REGISTER_ACTOR_CLASS( Banner );
|
||||
|
||||
ThemeMetric<bool> SCROLL_RANDOM ("Banner","ScrollRandom");
|
||||
ThemeMetric<bool> SCROLL_ROULETTE ("Banner","ScrollRoulette");
|
||||
ThemeMetric<bool> SCROLL_MODE ("Banner","ScrollMode");
|
||||
ThemeMetric<bool> SCROLL_SORT_ORDER ("Banner","ScrollSortOrder");
|
||||
ThemeMetric<float> SCROLL_SPEED_DIVISOR ("Banner","ScrollSpeedDivisor");
|
||||
|
||||
Banner::Banner()
|
||||
{
|
||||
m_bScrolling = false;
|
||||
m_fPercentScrolling = 0;
|
||||
}
|
||||
|
||||
// Ugly: if sIsBanner is false, we're actually loading something other than a banner.
|
||||
void Banner::Load( RageTextureID ID, bool bIsBanner )
|
||||
{
|
||||
if( ID.filename == "" )
|
||||
{
|
||||
LoadFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
if( bIsBanner )
|
||||
ID = SongBannerTexture(ID);
|
||||
|
||||
m_fPercentScrolling = 0;
|
||||
m_bScrolling = false;
|
||||
|
||||
TEXTUREMAN->DisableOddDimensionWarning();
|
||||
TEXTUREMAN->VolatileTexture( ID );
|
||||
Sprite::Load( ID );
|
||||
TEXTUREMAN->EnableOddDimensionWarning();
|
||||
};
|
||||
|
||||
void Banner::LoadFromCachedBanner( const RString &sPath )
|
||||
{
|
||||
if( sPath.empty() )
|
||||
{
|
||||
LoadFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
RageTextureID ID;
|
||||
bool bLowRes = (PREFSMAN->m_BannerCache != BNCACHE_FULL);
|
||||
if( !bLowRes )
|
||||
{
|
||||
ID = Sprite::SongBannerTexture( sPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to load the low quality version.
|
||||
ID = BANNERCACHE->LoadCachedBanner( sPath );
|
||||
}
|
||||
|
||||
if( TEXTUREMAN->IsTextureRegistered(ID) )
|
||||
Load( ID );
|
||||
else if( IsAFile(sPath) )
|
||||
Load( sPath );
|
||||
else
|
||||
LoadFallback();
|
||||
}
|
||||
|
||||
void Banner::Update( float fDeltaTime )
|
||||
{
|
||||
Sprite::Update( fDeltaTime );
|
||||
|
||||
if( m_bScrolling )
|
||||
{
|
||||
m_fPercentScrolling += fDeltaTime/(float)SCROLL_SPEED_DIVISOR;
|
||||
m_fPercentScrolling -= (int)m_fPercentScrolling;
|
||||
|
||||
const RectF *pTextureRect = GetCurrentTextureCoordRect();
|
||||
|
||||
float fTexCoords[8] =
|
||||
{
|
||||
0+m_fPercentScrolling, pTextureRect->top, // top left
|
||||
0+m_fPercentScrolling, pTextureRect->bottom, // bottom left
|
||||
1+m_fPercentScrolling, pTextureRect->bottom, // bottom right
|
||||
1+m_fPercentScrolling, pTextureRect->top, // top right
|
||||
};
|
||||
Sprite::SetCustomTextureCoords( fTexCoords );
|
||||
}
|
||||
}
|
||||
|
||||
void Banner::SetScrolling( bool bScroll, float Percent)
|
||||
{
|
||||
m_bScrolling = bScroll;
|
||||
m_fPercentScrolling = Percent;
|
||||
|
||||
// Set up the texture coord rects for the current state.
|
||||
Update(0);
|
||||
}
|
||||
|
||||
void Banner::LoadFromSong( Song* pSong ) // NULL means no song
|
||||
{
|
||||
if( pSong == nullptr ) LoadFallback();
|
||||
else if( pSong->HasBanner() ) Load( pSong->GetBannerPath() );
|
||||
else LoadFallback();
|
||||
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadMode()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","Mode") );
|
||||
m_bScrolling = (bool)SCROLL_MODE;
|
||||
}
|
||||
|
||||
void Banner::LoadFromSongGroup( RString sSongGroup )
|
||||
{
|
||||
RString sGroupBannerPath = SONGMAN->GetSongGroupBannerPath( sSongGroup );
|
||||
if( sGroupBannerPath != "" ) Load( sGroupBannerPath );
|
||||
else LoadGroupFallback();
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadFromCourse( const Course *pCourse ) // NULL means no course
|
||||
{
|
||||
if( pCourse == nullptr ) LoadFallback();
|
||||
else if( pCourse->GetBannerPath() != "" ) Load( pCourse->GetBannerPath() );
|
||||
else LoadCourseFallback();
|
||||
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadCardFromCharacter( const Character *pCharacter )
|
||||
{
|
||||
if( pCharacter == nullptr ) LoadFallback();
|
||||
else if( pCharacter->GetCardPath() != "" ) Load( pCharacter->GetCardPath() );
|
||||
else LoadFallback();
|
||||
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadIconFromCharacter( const Character *pCharacter )
|
||||
{
|
||||
if( pCharacter == nullptr ) LoadFallbackCharacterIcon();
|
||||
else if( pCharacter->GetIconPath() != "" ) Load( pCharacter->GetIconPath(), false );
|
||||
else LoadFallbackCharacterIcon();
|
||||
|
||||
m_bScrolling = false;
|
||||
}
|
||||
|
||||
void Banner::LoadBannerFromUnlockEntry( const UnlockEntry* pUE )
|
||||
{
|
||||
if( pUE == nullptr )
|
||||
LoadFallback();
|
||||
else
|
||||
{
|
||||
RString sFile = pUE->GetBannerFile();
|
||||
Load( sFile );
|
||||
m_bScrolling = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Banner::LoadBackgroundFromUnlockEntry( const UnlockEntry* pUE )
|
||||
{
|
||||
if( pUE == nullptr )
|
||||
LoadFallback();
|
||||
else
|
||||
{
|
||||
RString sFile = pUE->GetBackgroundFile();
|
||||
Load( sFile );
|
||||
m_bScrolling = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Banner::LoadFallback()
|
||||
{
|
||||
Load( THEME->GetPathG("Common","fallback banner") );
|
||||
}
|
||||
|
||||
void Banner::LoadFallbackBG()
|
||||
{
|
||||
Load( THEME->GetPathG("Common","fallback background") );
|
||||
}
|
||||
|
||||
void Banner::LoadGroupFallback()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","group fallback") );
|
||||
}
|
||||
|
||||
void Banner::LoadCourseFallback()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","course fallback") );
|
||||
}
|
||||
|
||||
void Banner::LoadFallbackCharacterIcon()
|
||||
{
|
||||
Character *pCharacter = CHARMAN->GetDefaultCharacter();
|
||||
if( pCharacter && !pCharacter->GetIconPath().empty() )
|
||||
Load( pCharacter->GetIconPath(), false );
|
||||
else
|
||||
LoadFallback();
|
||||
}
|
||||
|
||||
void Banner::LoadRoulette()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","roulette") );
|
||||
m_bScrolling = (bool)SCROLL_ROULETTE;
|
||||
}
|
||||
|
||||
void Banner::LoadRandom()
|
||||
{
|
||||
Load( THEME->GetPathG("Banner","random") );
|
||||
m_bScrolling = (bool)SCROLL_RANDOM;
|
||||
}
|
||||
|
||||
void Banner::LoadFromSortOrder( SortOrder so )
|
||||
{
|
||||
// TODO: See if the check for NULL/PREFERRED(?) is needed.
|
||||
if( so == SortOrder_Invalid )
|
||||
{
|
||||
LoadFallback();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( so != SORT_GROUP && so != SORT_RECENT )
|
||||
Load( THEME->GetPathG("Banner",ssprintf("%s",SortOrderToString(so).c_str())) );
|
||||
}
|
||||
m_bScrolling = (bool)SCROLL_SORT_ORDER;
|
||||
}
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
/** @brief Allow Lua to have access to the Banner. */
|
||||
class LunaBanner: public Luna<Banner>
|
||||
{
|
||||
public:
|
||||
static int scaletoclipped( T* p, lua_State *L ) { p->ScaleToClipped(FArg(1),FArg(2)); return 0; }
|
||||
static int ScaleToClipped( T* p, lua_State *L ) { p->ScaleToClipped(FArg(1),FArg(2)); return 0; }
|
||||
static int LoadFromSong( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromSong( NULL ); }
|
||||
else { Song *pS = Luna<Song>::check(L,1); p->LoadFromSong( pS ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromCourse( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromCourse( NULL ); }
|
||||
else { Course *pC = Luna<Course>::check(L,1); p->LoadFromCourse( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromCachedBanner( T* p, lua_State *L )
|
||||
{
|
||||
p->LoadFromCachedBanner( SArg(1) );
|
||||
return 0;
|
||||
}
|
||||
static int LoadIconFromCharacter( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadIconFromCharacter( NULL ); }
|
||||
else { Character *pC = Luna<Character>::check(L,1); p->LoadIconFromCharacter( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadCardFromCharacter( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadIconFromCharacter( NULL ); }
|
||||
else { Character *pC = Luna<Character>::check(L,1); p->LoadIconFromCharacter( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadBannerFromUnlockEntry( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadBannerFromUnlockEntry( NULL ); }
|
||||
else { UnlockEntry *pUE = Luna<UnlockEntry>::check(L,1); p->LoadBannerFromUnlockEntry( pUE ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadBackgroundFromUnlockEntry( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadBackgroundFromUnlockEntry( NULL ); }
|
||||
else { UnlockEntry *pUE = Luna<UnlockEntry>::check(L,1); p->LoadBackgroundFromUnlockEntry( pUE ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromSongGroup( T* p, lua_State *L )
|
||||
{
|
||||
p->LoadFromSongGroup( SArg(1) );
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromSortOrder( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromSortOrder( SortOrder_Invalid ); }
|
||||
else
|
||||
{
|
||||
SortOrder so = Enum::Check<SortOrder>(L, 1);
|
||||
p->LoadFromSortOrder( so );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int GetScrolling( T* p, lua_State *L ){ lua_pushboolean( L, p->GetScrolling() ); return 1; }
|
||||
static int SetScrolling( T* p, lua_State *L ){ p->SetScrolling( BArg(1), FArg(2) ); return 0; }
|
||||
static int GetPercentScrolling( T* p, lua_State *L ){ lua_pushnumber( L, p->ScrollingPercent() ); return 1; }
|
||||
|
||||
LunaBanner()
|
||||
{
|
||||
ADD_METHOD( scaletoclipped );
|
||||
ADD_METHOD( ScaleToClipped );
|
||||
ADD_METHOD( LoadFromSong );
|
||||
ADD_METHOD( LoadFromCourse );
|
||||
ADD_METHOD( LoadFromCachedBanner );
|
||||
ADD_METHOD( LoadIconFromCharacter );
|
||||
ADD_METHOD( LoadCardFromCharacter );
|
||||
ADD_METHOD( LoadBannerFromUnlockEntry );
|
||||
ADD_METHOD( LoadBackgroundFromUnlockEntry );
|
||||
ADD_METHOD( LoadFromSongGroup );
|
||||
ADD_METHOD( LoadFromSortOrder );
|
||||
ADD_METHOD( GetScrolling );
|
||||
ADD_METHOD( SetScrolling );
|
||||
ADD_METHOD( GetPercentScrolling );
|
||||
}
|
||||
};
|
||||
|
||||
LUA_REGISTER_DERIVED_CLASS( Banner, Sprite )
|
||||
// lua end
|
||||
|
||||
|
||||
/*
|
||||
* (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.
|
||||
*/
|
||||
|
||||
+3
-3
@@ -79,7 +79,7 @@ void BannerCache::Demand()
|
||||
|
||||
const RString sCachePath = GetBannerCachePath(sBannerPath);
|
||||
RageSurface *pImage = RageSurfaceUtils::LoadSurface( sCachePath );
|
||||
if( pImage == NULL )
|
||||
if( pImage == nullptr )
|
||||
{
|
||||
continue; /* doesn't exist */
|
||||
}
|
||||
@@ -123,7 +123,7 @@ void BannerCache::LoadBanner( RString sBannerPath )
|
||||
|
||||
CHECKPOINT_M( ssprintf( "BannerCache::LoadBanner: %s", sCachePath.c_str() ) );
|
||||
RageSurface *pImage = RageSurfaceUtils::LoadSurface( sCachePath );
|
||||
if( pImage == NULL )
|
||||
if( pImage == nullptr )
|
||||
{
|
||||
if( tries == 0 )
|
||||
{
|
||||
@@ -368,7 +368,7 @@ void BannerCache::CacheBannerInternal( RString sBannerPath )
|
||||
{
|
||||
RString sError;
|
||||
RageSurface *pImage = RageSurfaceUtils::LoadFile( sBannerPath, sError );
|
||||
if( pImage == NULL )
|
||||
if( pImage == nullptr )
|
||||
{
|
||||
LOG->UserLog( "Cache file", sBannerPath, "couldn't be loaded: %s", sError.c_str() );
|
||||
return;
|
||||
|
||||
+1
-1
@@ -175,7 +175,7 @@ bool BitmapText::LoadFromTextureAndChars( const RString& sTexturePath, const RSt
|
||||
void BitmapText::BuildChars()
|
||||
{
|
||||
// If we don't have a font yet, we'll do this when it loads.
|
||||
if( m_pFont == NULL )
|
||||
if( m_pFont == nullptr )
|
||||
return;
|
||||
|
||||
// calculate line lengths and widths
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ void ComboGraph::Load( RString sMetricsGroup )
|
||||
|
||||
pActor = ActorUtil::MakeActor( THEME->GetPathG(sMetricsGroup,"ComboNumber") );
|
||||
m_pComboNumber = dynamic_cast<BitmapText *>( pActor );
|
||||
if( m_pComboNumber == NULL )
|
||||
if( m_pComboNumber == nullptr )
|
||||
RageException::Throw( "ComboGraph: \"sMetricsGroup\" \"ComboNumber\" must be a BitmapText" );
|
||||
this->AddChild( m_pComboNumber );
|
||||
}
|
||||
|
||||
+2
-2
@@ -669,7 +669,7 @@ void Course::GetTrails( vector<Trail*> &AddTo, StepsType st ) const
|
||||
FOREACH_ShownCourseDifficulty( cd )
|
||||
{
|
||||
Trail *pTrail = GetTrail( st, cd );
|
||||
if( pTrail == NULL )
|
||||
if( pTrail == nullptr )
|
||||
continue;
|
||||
AddTo.push_back( pTrail );
|
||||
}
|
||||
@@ -968,7 +968,7 @@ void Course::CalculateRadarValues()
|
||||
if( AllSongsAreFixed() )
|
||||
{
|
||||
Trail *pTrail = GetTrail( st, cd );
|
||||
if( pTrail == NULL )
|
||||
if( pTrail == nullptr )
|
||||
continue;
|
||||
RadarValues rv = pTrail->GetRadarValues();
|
||||
m_RadarCache[CacheEntry(st, cd)] = rv;
|
||||
|
||||
@@ -25,7 +25,7 @@ void CourseContentsList::LoadFromNode( const XNode* pNode )
|
||||
pNode->GetAttrValue( "MaxSongs", iMaxSongs );
|
||||
|
||||
const XNode *pDisplayNode = pNode->GetChild( "Display" );
|
||||
if( pDisplayNode == NULL )
|
||||
if( pDisplayNode == nullptr )
|
||||
RageException::Throw( "%s: CourseContentsList: missing the Display child", ActorUtil::GetWhere(pNode).c_str() );
|
||||
|
||||
for( int i=0; i<iMaxSongs; i++ )
|
||||
@@ -45,7 +45,7 @@ void CourseContentsList::SetFromGameState()
|
||||
if( GAMESTATE->GetMasterPlayerNumber() == PlayerNumber_Invalid )
|
||||
return;
|
||||
const Trail *pMasterTrail = GAMESTATE->m_pCurTrail[GAMESTATE->GetMasterPlayerNumber()];
|
||||
if( pMasterTrail == NULL )
|
||||
if( pMasterTrail == nullptr )
|
||||
return;
|
||||
unsigned uNumEntriesToShow = pMasterTrail->m_vEntries.size();
|
||||
CLAMP( uNumEntriesToShow, 0, m_vpDisplay.size() );
|
||||
@@ -78,21 +78,21 @@ void CourseContentsList::SetItemFromGameState( Actor *pActor, int iCourseEntryIn
|
||||
FOREACH_HumanPlayer(pn)
|
||||
{
|
||||
const Trail *pTrail = GAMESTATE->m_pCurTrail[pn];
|
||||
if( pTrail == NULL
|
||||
if( pTrail == nullptr
|
||||
|| iCourseEntryIndex >= (int) pTrail->m_vEntries.size()
|
||||
|| iCourseEntryIndex >= (int) pCourse->m_vEntries.size() )
|
||||
continue;
|
||||
|
||||
const TrailEntry *te = &pTrail->m_vEntries[iCourseEntryIndex];
|
||||
const CourseEntry *ce = &pCourse->m_vEntries[iCourseEntryIndex];
|
||||
if( te == NULL )
|
||||
if( te == nullptr )
|
||||
continue;
|
||||
|
||||
RString s;
|
||||
Difficulty dc;
|
||||
if( te->bSecret )
|
||||
{
|
||||
if( ce == NULL )
|
||||
if( ce == nullptr )
|
||||
continue;
|
||||
|
||||
int iLow = ce->stepsCriteria.m_iLowMeter;
|
||||
|
||||
@@ -262,7 +262,7 @@ bool CourseLoaderCRS::LoadFromMsd( const RString &sPath, const MsdFile &msd, Cou
|
||||
}
|
||||
new_entry.songID.FromSong( pSong );
|
||||
|
||||
if( pSong == NULL )
|
||||
if( pSong == nullptr )
|
||||
{
|
||||
LOG->UserLog( "Course file", sPath, "contains a fixed song entry \"%s\" that does not exist. "
|
||||
"This entry will be ignored.", sSong.c_str());
|
||||
|
||||
+3
-3
@@ -110,7 +110,7 @@ void CourseUtil::SortCoursePointerArrayByTotalDifficulty( vector<Course*> &vpCou
|
||||
#if 0
|
||||
RString GetSectionNameFromCourseAndSort( const Course *pCourse, SortOrder so )
|
||||
{
|
||||
if( pCourse == NULL )
|
||||
if( pCourse == nullptr )
|
||||
return RString();
|
||||
// more code here
|
||||
}
|
||||
@@ -552,10 +552,10 @@ Course *CourseID::ToCourse() const
|
||||
Course *pCourse = NULL;
|
||||
if( m_Cache.Get(&pCourse) )
|
||||
return pCourse;
|
||||
if( pCourse == NULL && !sPath2.empty() )
|
||||
if( pCourse == nullptr && !sPath2.empty() )
|
||||
pCourse = SONGMAN->GetCourseFromPath( sPath2 );
|
||||
|
||||
if( pCourse == NULL && !sFullTitle.empty() )
|
||||
if( pCourse == nullptr && !sFullTitle.empty() )
|
||||
pCourse = SONGMAN->GetCourseFromName( sFullTitle );
|
||||
m_Cache.Set( pCourse );
|
||||
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ LuaXType( Difficulty );
|
||||
const RString &CourseDifficultyToLocalizedString( CourseDifficulty x )
|
||||
{
|
||||
static auto_ptr<LocalizedString> g_CourseDifficultyName[NUM_Difficulty];
|
||||
if( g_CourseDifficultyName[0].get() == NULL )
|
||||
if( g_CourseDifficultyName[0].get() == nullptr )
|
||||
{
|
||||
FOREACH_ENUM( Difficulty,i)
|
||||
{
|
||||
|
||||
@@ -61,7 +61,7 @@ void DifficultyIcon::SetPlayer( PlayerNumber pn )
|
||||
void DifficultyIcon::SetFromSteps( PlayerNumber pn, const Steps* pSteps )
|
||||
{
|
||||
SetPlayer( pn );
|
||||
if( pSteps == NULL )
|
||||
if( pSteps == nullptr )
|
||||
Unset();
|
||||
else
|
||||
SetFromDifficulty( pSteps->GetDifficulty() );
|
||||
@@ -70,7 +70,7 @@ void DifficultyIcon::SetFromSteps( PlayerNumber pn, const Steps* pSteps )
|
||||
void DifficultyIcon::SetFromTrail( PlayerNumber pn, const Trail* pTrail )
|
||||
{
|
||||
SetPlayer( pn );
|
||||
if( pTrail == NULL )
|
||||
if( pTrail == nullptr )
|
||||
Unset();
|
||||
else
|
||||
SetFromDifficulty( pTrail->m_CourseDifficulty );
|
||||
|
||||
@@ -50,7 +50,7 @@ void StepsDisplayList::LoadFromNode( const XNode* pNode )
|
||||
FOREACH_ENUM( PlayerNumber, pn )
|
||||
{
|
||||
const XNode *pChild = pNode->GetChild( ssprintf("CursorP%i",pn+1) );
|
||||
if( pChild == NULL )
|
||||
if( pChild == nullptr )
|
||||
RageException::Throw( "%s: StepsDisplayList: missing the node \"CursorP%d\"", ActorUtil::GetWhere(pNode).c_str(), pn+1 );
|
||||
m_Cursors[pn].LoadActorFromNode( pChild, this );
|
||||
|
||||
@@ -61,7 +61,7 @@ void StepsDisplayList::LoadFromNode( const XNode* pNode )
|
||||
* in separate tweening stacks. This means the Cursor command can't change diffuse
|
||||
* colors; I think we do need a diffuse color stack ... */
|
||||
pChild = pNode->GetChild( ssprintf("CursorP%iFrame",pn+1) );
|
||||
if( pChild == NULL )
|
||||
if( pChild == nullptr )
|
||||
RageException::Throw( "%s: StepsDisplayList: missing the node \"CursorP%dFrame\"", ActorUtil::GetWhere(pNode).c_str(), pn+1 );
|
||||
m_CursorFrames[pn].LoadFromNode( pChild );
|
||||
m_CursorFrames[pn].AddChild( m_Cursors[pn] );
|
||||
@@ -88,7 +88,7 @@ int StepsDisplayList::GetCurrentRowIndex( PlayerNumber pn ) const
|
||||
{
|
||||
const Row &row = m_Rows[i];
|
||||
|
||||
if( GAMESTATE->m_pCurSteps[pn] == NULL )
|
||||
if( GAMESTATE->m_pCurSteps[pn] == nullptr )
|
||||
{
|
||||
if( row.m_dc == ClosestDifficulty )
|
||||
return i;
|
||||
@@ -253,7 +253,7 @@ void StepsDisplayList::SetFromGameState()
|
||||
const Song *pSong = GAMESTATE->m_pCurSong;
|
||||
unsigned i = 0;
|
||||
|
||||
if( pSong == NULL )
|
||||
if( pSong == nullptr )
|
||||
{
|
||||
// FIXME: This clamps to between the min and the max difficulty, but
|
||||
// it really should round to the nearest difficulty that's in
|
||||
|
||||
+168
-168
@@ -1,168 +1,168 @@
|
||||
#include "global.h"
|
||||
#include "EnumHelper.h"
|
||||
#include "LuaManager.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
int CheckEnum( lua_State *L, LuaReference &table, int iPos, int iInvalid, const char *szType, bool bAllowInvalid )
|
||||
{
|
||||
luaL_checkany( L, iPos );
|
||||
|
||||
if( lua_isnil(L, iPos) )
|
||||
{
|
||||
if( bAllowInvalid )
|
||||
return iInvalid;
|
||||
|
||||
LuaHelpers::Push( L, ssprintf("Expected %s; got nil", szType) );
|
||||
lua_error( L );
|
||||
}
|
||||
|
||||
iPos = LuaHelpers::AbsIndex( L, iPos );
|
||||
|
||||
table.PushSelf( L );
|
||||
lua_pushvalue( L, iPos );
|
||||
lua_gettable( L, -2 );
|
||||
|
||||
// If the result is nil, then a string was passed that is not a member of this enum. Throw
|
||||
// an error. To specify the invalid value, pass nil. That way, typos will throw an error,
|
||||
// and not silently result in nil, or an out-of-bounds value.
|
||||
if( unlikely(lua_isnil(L, -1)) )
|
||||
{
|
||||
RString sGot;
|
||||
if( lua_isstring(L, iPos) )
|
||||
{
|
||||
/* We were given a string, but it wasn't a valid value for this enum. Show
|
||||
* the string. */
|
||||
lua_pushvalue( L, iPos );
|
||||
LuaHelpers::Pop( L, sGot );
|
||||
sGot = ssprintf( "\"%s\"", sGot.c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We didn't get a string. Show the type. */
|
||||
luaL_pushtype( L, iPos );
|
||||
LuaHelpers::Pop( L, sGot );
|
||||
}
|
||||
LuaHelpers::Push( L, ssprintf("Expected %s; got %s", szType, sGot.c_str() ) );
|
||||
lua_error( L );
|
||||
}
|
||||
int iRet = lua_tointeger( L, -1 );
|
||||
lua_pop( L, 2 );
|
||||
return iRet;
|
||||
}
|
||||
|
||||
// szNameArray is of size iMax; pNameCache is of size iMax+2.
|
||||
const RString &EnumToString( int iVal, int iMax, const char **szNameArray, auto_ptr<RString> *pNameCache )
|
||||
{
|
||||
if( unlikely(pNameCache[0].get() == NULL) )
|
||||
{
|
||||
for( int i = 0; i < iMax; ++i )
|
||||
{
|
||||
auto_ptr<RString> ap( new RString( szNameArray[i] ) );
|
||||
pNameCache[i] = ap;
|
||||
}
|
||||
|
||||
auto_ptr<RString> ap( new RString );
|
||||
pNameCache[iMax+1] = ap;
|
||||
}
|
||||
|
||||
// iMax+1 is "Invalid". iMax+0 is the NUM_ size value, which can not be converted
|
||||
// to a string.
|
||||
// Maybe we should assert on _Invalid? It seems better to make
|
||||
// the caller check that they're supplying a valid enum value instead of
|
||||
// returning an inconspicuous garbage value (empty string). -Chris
|
||||
if (iVal < 0)
|
||||
FAIL_M(ssprintf("Value %i cannot be negative for enums! Enum hint: %s", iVal, szNameArray[0]));
|
||||
if (iVal == iMax)
|
||||
FAIL_M(ssprintf("Value %i cannot be a string with value %i! Enum hint: %s", iVal, iMax, szNameArray[0]));
|
||||
if (iVal > iMax+1)
|
||||
FAIL_M(ssprintf("Value %i is past the invalid value %i! Enum hint: %s", iVal, iMax, szNameArray[0]));
|
||||
return *pNameCache[iVal];
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
int GetName( lua_State *L )
|
||||
{
|
||||
luaL_checktype( L, 1, LUA_TTABLE );
|
||||
|
||||
/* Look up the reverse table. */
|
||||
luaL_getmetafield( L, 1, "name" );
|
||||
|
||||
/* If there was no metafield, then we were called on the wrong type. */
|
||||
if( lua_isnil(L, -1) )
|
||||
luaL_typerror( L, 1, "enum" );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Reverse( lua_State *L )
|
||||
{
|
||||
luaL_checktype( L, 1, LUA_TTABLE );
|
||||
|
||||
/* Look up the reverse table. If there is no metafield, then we were
|
||||
* called on the wrong type. */
|
||||
if( !luaL_getmetafield(L, 1, "reverse") )
|
||||
luaL_typerror( L, 1, "enum" );
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static const luaL_Reg EnumLib[] = {
|
||||
{ "GetName", GetName },
|
||||
{ "Reverse", Reverse },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static void PushEnumMethodTable( lua_State *L )
|
||||
{
|
||||
luaL_register( L, "Enum", EnumLib );
|
||||
}
|
||||
|
||||
/* Set up the enum table on the stack, and pop the table. */
|
||||
void Enum::SetMetatable( lua_State *L, LuaReference &EnumTable, LuaReference &EnumIndexTable, const char *szName )
|
||||
{
|
||||
EnumTable.PushSelf( L );
|
||||
{
|
||||
lua_newtable( L );
|
||||
EnumIndexTable.PushSelf( L );
|
||||
lua_setfield( L, -2, "reverse" );
|
||||
|
||||
lua_pushstring( L, szName );
|
||||
lua_setfield( L, -2, "name" );
|
||||
|
||||
PushEnumMethodTable( L );
|
||||
lua_setfield( L, -2, "__index" );
|
||||
|
||||
lua_pushliteral( L, "Enum" );
|
||||
LuaHelpers::PushValueFunc( L, 1 );
|
||||
lua_setfield( L, -2, "__type" ); // for luaL_pushtype
|
||||
}
|
||||
lua_setmetatable( L, -2 );
|
||||
lua_pop( L, 2 );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "EnumHelper.h"
|
||||
#include "LuaManager.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
int CheckEnum( lua_State *L, LuaReference &table, int iPos, int iInvalid, const char *szType, bool bAllowInvalid )
|
||||
{
|
||||
luaL_checkany( L, iPos );
|
||||
|
||||
if( lua_isnil(L, iPos) )
|
||||
{
|
||||
if( bAllowInvalid )
|
||||
return iInvalid;
|
||||
|
||||
LuaHelpers::Push( L, ssprintf("Expected %s; got nil", szType) );
|
||||
lua_error( L );
|
||||
}
|
||||
|
||||
iPos = LuaHelpers::AbsIndex( L, iPos );
|
||||
|
||||
table.PushSelf( L );
|
||||
lua_pushvalue( L, iPos );
|
||||
lua_gettable( L, -2 );
|
||||
|
||||
// If the result is nil, then a string was passed that is not a member of this enum. Throw
|
||||
// an error. To specify the invalid value, pass nil. That way, typos will throw an error,
|
||||
// and not silently result in nil, or an out-of-bounds value.
|
||||
if( unlikely(lua_isnil(L, -1)) )
|
||||
{
|
||||
RString sGot;
|
||||
if( lua_isstring(L, iPos) )
|
||||
{
|
||||
/* We were given a string, but it wasn't a valid value for this enum. Show
|
||||
* the string. */
|
||||
lua_pushvalue( L, iPos );
|
||||
LuaHelpers::Pop( L, sGot );
|
||||
sGot = ssprintf( "\"%s\"", sGot.c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We didn't get a string. Show the type. */
|
||||
luaL_pushtype( L, iPos );
|
||||
LuaHelpers::Pop( L, sGot );
|
||||
}
|
||||
LuaHelpers::Push( L, ssprintf("Expected %s; got %s", szType, sGot.c_str() ) );
|
||||
lua_error( L );
|
||||
}
|
||||
int iRet = lua_tointeger( L, -1 );
|
||||
lua_pop( L, 2 );
|
||||
return iRet;
|
||||
}
|
||||
|
||||
// szNameArray is of size iMax; pNameCache is of size iMax+2.
|
||||
const RString &EnumToString( int iVal, int iMax, const char **szNameArray, auto_ptr<RString> *pNameCache )
|
||||
{
|
||||
if( unlikely(pNameCache[0].get() == nullptr) )
|
||||
{
|
||||
for( int i = 0; i < iMax; ++i )
|
||||
{
|
||||
auto_ptr<RString> ap( new RString( szNameArray[i] ) );
|
||||
pNameCache[i] = ap;
|
||||
}
|
||||
|
||||
auto_ptr<RString> ap( new RString );
|
||||
pNameCache[iMax+1] = ap;
|
||||
}
|
||||
|
||||
// iMax+1 is "Invalid". iMax+0 is the NUM_ size value, which can not be converted
|
||||
// to a string.
|
||||
// Maybe we should assert on _Invalid? It seems better to make
|
||||
// the caller check that they're supplying a valid enum value instead of
|
||||
// returning an inconspicuous garbage value (empty string). -Chris
|
||||
if (iVal < 0)
|
||||
FAIL_M(ssprintf("Value %i cannot be negative for enums! Enum hint: %s", iVal, szNameArray[0]));
|
||||
if (iVal == iMax)
|
||||
FAIL_M(ssprintf("Value %i cannot be a string with value %i! Enum hint: %s", iVal, iMax, szNameArray[0]));
|
||||
if (iVal > iMax+1)
|
||||
FAIL_M(ssprintf("Value %i is past the invalid value %i! Enum hint: %s", iVal, iMax, szNameArray[0]));
|
||||
return *pNameCache[iVal];
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
int GetName( lua_State *L )
|
||||
{
|
||||
luaL_checktype( L, 1, LUA_TTABLE );
|
||||
|
||||
/* Look up the reverse table. */
|
||||
luaL_getmetafield( L, 1, "name" );
|
||||
|
||||
/* If there was no metafield, then we were called on the wrong type. */
|
||||
if( lua_isnil(L, -1) )
|
||||
luaL_typerror( L, 1, "enum" );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Reverse( lua_State *L )
|
||||
{
|
||||
luaL_checktype( L, 1, LUA_TTABLE );
|
||||
|
||||
/* Look up the reverse table. If there is no metafield, then we were
|
||||
* called on the wrong type. */
|
||||
if( !luaL_getmetafield(L, 1, "reverse") )
|
||||
luaL_typerror( L, 1, "enum" );
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static const luaL_Reg EnumLib[] = {
|
||||
{ "GetName", GetName },
|
||||
{ "Reverse", Reverse },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static void PushEnumMethodTable( lua_State *L )
|
||||
{
|
||||
luaL_register( L, "Enum", EnumLib );
|
||||
}
|
||||
|
||||
/* Set up the enum table on the stack, and pop the table. */
|
||||
void Enum::SetMetatable( lua_State *L, LuaReference &EnumTable, LuaReference &EnumIndexTable, const char *szName )
|
||||
{
|
||||
EnumTable.PushSelf( L );
|
||||
{
|
||||
lua_newtable( L );
|
||||
EnumIndexTable.PushSelf( L );
|
||||
lua_setfield( L, -2, "reverse" );
|
||||
|
||||
lua_pushstring( L, szName );
|
||||
lua_setfield( L, -2, "name" );
|
||||
|
||||
PushEnumMethodTable( L );
|
||||
lua_setfield( L, -2, "__index" );
|
||||
|
||||
lua_pushliteral( L, "Enum" );
|
||||
LuaHelpers::PushValueFunc( L, 1 );
|
||||
lua_setfield( L, -2, "__type" ); // for luaL_pushtype
|
||||
}
|
||||
lua_setmetatable( L, -2 );
|
||||
lua_pop( L, 2 );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
|
||||
+189
-189
@@ -1,189 +1,189 @@
|
||||
#ifndef ENUM_HELPER_H
|
||||
#define ENUM_HELPER_H
|
||||
|
||||
#include "LuaReference.h"
|
||||
#include "RageUtil.h"
|
||||
#include <memory>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "../extern/lua-5.1/src/lua.h"
|
||||
}
|
||||
|
||||
/** @brief A general foreach loop for enumerators, going up to a max value. */
|
||||
#define FOREACH_ENUM_N( e, max, var ) for( e var=(e)0; var<max; enum_add<e>( var, +1 ) )
|
||||
/** @brief A general foreach loop for enumerators. */
|
||||
#define FOREACH_ENUM( e, var ) for( e var=(e)0; var<NUM_##e; enum_add<e>( var, +1 ) )
|
||||
|
||||
int CheckEnum(lua_State *L,
|
||||
LuaReference &table,
|
||||
int iPos,
|
||||
int iInvalid,
|
||||
const char *szType,
|
||||
bool bAllowInvalid);
|
||||
|
||||
template<typename T>
|
||||
struct EnumTraits
|
||||
{
|
||||
static LuaReference StringToEnum;
|
||||
static LuaReference EnumToString;
|
||||
static T Invalid;
|
||||
static const char *szName;
|
||||
};
|
||||
template<typename T> LuaReference EnumTraits<T>::StringToEnum;
|
||||
template<typename T> LuaReference EnumTraits<T>::EnumToString;
|
||||
/** @brief Lua helpers for Enumerators. */
|
||||
namespace Enum
|
||||
{
|
||||
template<typename T>
|
||||
static T Check( lua_State *L, int iPos, bool bAllowInvalid = false )
|
||||
{
|
||||
return (T) CheckEnum(L,
|
||||
EnumTraits<T>::StringToEnum,
|
||||
iPos,
|
||||
EnumTraits<T>::Invalid,
|
||||
EnumTraits<T>::szName,
|
||||
bAllowInvalid);
|
||||
}
|
||||
template<typename T>
|
||||
static void Push( lua_State *L, T iVal )
|
||||
{
|
||||
/* Enum_Invalid values are nil in Lua. */
|
||||
if( iVal == EnumTraits<T>::Invalid )
|
||||
{
|
||||
lua_pushnil( L );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look up the string value. */
|
||||
EnumTraits<T>::EnumToString.PushSelf( L );
|
||||
lua_rawgeti( L, -1, iVal + 1 );
|
||||
lua_remove( L, -2 );
|
||||
}
|
||||
|
||||
void SetMetatable( lua_State *L, LuaReference &EnumTable, LuaReference &EnumIndexTable, const char *szName );
|
||||
};
|
||||
|
||||
const RString &EnumToString( int iVal, int iMax, const char **szNameArray, auto_ptr<RString> *pNameCache ); // XToString helper
|
||||
|
||||
#define XToString(X) \
|
||||
const RString& X##ToString(X x); \
|
||||
COMPILE_ASSERT( NUM_##X == ARRAYLEN(X##Names) ); \
|
||||
const RString& X##ToString( X x ) \
|
||||
{ \
|
||||
static auto_ptr<RString> as_##X##Name[NUM_##X+2]; \
|
||||
return EnumToString( x, NUM_##X, X##Names, as_##X##Name ); \
|
||||
} \
|
||||
namespace StringConversion { template<> RString ToString<X>( const X &value ) { return X##ToString(value); } }
|
||||
|
||||
#define XToLocalizedString(X) \
|
||||
const RString &X##ToLocalizedString(X x); \
|
||||
const RString &X##ToLocalizedString( X x ) \
|
||||
{ \
|
||||
static auto_ptr<LocalizedString> g_##X##Name[NUM_##X]; \
|
||||
if( g_##X##Name[0].get() == NULL ) { \
|
||||
for( unsigned i = 0; i < NUM_##X; ++i ) \
|
||||
{ \
|
||||
auto_ptr<LocalizedString> ap( new LocalizedString(#X, X##ToString((X)i)) ); \
|
||||
g_##X##Name[i] = ap; \
|
||||
} \
|
||||
} \
|
||||
return g_##X##Name[x]->GetValue(); \
|
||||
}
|
||||
|
||||
#define StringToX(X) \
|
||||
X StringTo##X(const RString&); \
|
||||
X StringTo##X( const RString& s ) \
|
||||
{ \
|
||||
for( unsigned i = 0; i < ARRAYLEN(X##Names); ++i ) \
|
||||
if( !s.CompareNoCase(X##Names[i]) ) \
|
||||
return (X)i; \
|
||||
return X##_Invalid; \
|
||||
} \
|
||||
namespace StringConversion \
|
||||
{ \
|
||||
template<> bool FromString<X>( const RString &sValue, X &out ) \
|
||||
{ \
|
||||
out = StringTo##X(sValue); \
|
||||
return out != X##_Invalid; \
|
||||
} \
|
||||
}
|
||||
|
||||
// currently unused
|
||||
#define LuaDeclareType(X)
|
||||
|
||||
#define LuaXType(X) \
|
||||
template struct EnumTraits<X>; \
|
||||
static void Lua##X(lua_State* L) \
|
||||
{ \
|
||||
/* Create the EnumToString table: { "UnlockEntry_ArcadePoints", "UnlockEntry_DancePoints" } */ \
|
||||
lua_newtable( L ); \
|
||||
FOREACH_ENUM( X, i ) \
|
||||
{ \
|
||||
RString s = X##ToString( i ); \
|
||||
lua_pushstring( L, (#X "_")+s ); \
|
||||
lua_rawseti( L, -2, i+1 ); /* 1-based */ \
|
||||
} \
|
||||
EnumTraits<X>::EnumToString.SetFromStack( L ); \
|
||||
EnumTraits<X>::EnumToString.PushSelf( L ); \
|
||||
lua_setglobal( L, #X ); \
|
||||
/* Create the StringToEnum table: { "UnlockEntry_ArcadePoints" = 0, "UnlockEntry_DancePoints" = 1 } */ \
|
||||
lua_newtable( L ); \
|
||||
FOREACH_ENUM( X, i ) \
|
||||
{ \
|
||||
RString s = X##ToString( i ); \
|
||||
lua_pushstring( L, (#X "_")+s ); \
|
||||
lua_pushnumber( L, i ); /* 0-based */ \
|
||||
lua_rawset( L, -3 ); \
|
||||
} \
|
||||
EnumTraits<X>::StringToEnum.SetFromStack( L ); \
|
||||
EnumTraits<X>::StringToEnum.PushSelf( L ); \
|
||||
Enum::SetMetatable( L, EnumTraits<X>::EnumToString, EnumTraits<X>::StringToEnum, #X ); \
|
||||
} \
|
||||
REGISTER_WITH_LUA_FUNCTION( Lua##X ); \
|
||||
template<> X EnumTraits<X>::Invalid = X##_Invalid; \
|
||||
template<> const char *EnumTraits<X>::szName = #X; \
|
||||
namespace LuaHelpers \
|
||||
{ \
|
||||
template<> bool FromStack<X>( lua_State *L, X &Object, int iOffset ) \
|
||||
{ \
|
||||
Object = Enum::Check<X>( L, iOffset, true ); \
|
||||
return Object != EnumTraits<X>::Invalid; \
|
||||
} \
|
||||
} \
|
||||
namespace LuaHelpers \
|
||||
{ \
|
||||
template<> void Push<X>( lua_State *L, const X &Object ) \
|
||||
{ \
|
||||
Enum::Push<X>( L, Object ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Chris Danford, Glenn Maynard (c) 2004-2006
|
||||
* @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.
|
||||
*/
|
||||
#ifndef ENUM_HELPER_H
|
||||
#define ENUM_HELPER_H
|
||||
|
||||
#include "LuaReference.h"
|
||||
#include "RageUtil.h"
|
||||
#include <memory>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "../extern/lua-5.1/src/lua.h"
|
||||
}
|
||||
|
||||
/** @brief A general foreach loop for enumerators, going up to a max value. */
|
||||
#define FOREACH_ENUM_N( e, max, var ) for( e var=(e)0; var<max; enum_add<e>( var, +1 ) )
|
||||
/** @brief A general foreach loop for enumerators. */
|
||||
#define FOREACH_ENUM( e, var ) for( e var=(e)0; var<NUM_##e; enum_add<e>( var, +1 ) )
|
||||
|
||||
int CheckEnum(lua_State *L,
|
||||
LuaReference &table,
|
||||
int iPos,
|
||||
int iInvalid,
|
||||
const char *szType,
|
||||
bool bAllowInvalid);
|
||||
|
||||
template<typename T>
|
||||
struct EnumTraits
|
||||
{
|
||||
static LuaReference StringToEnum;
|
||||
static LuaReference EnumToString;
|
||||
static T Invalid;
|
||||
static const char *szName;
|
||||
};
|
||||
template<typename T> LuaReference EnumTraits<T>::StringToEnum;
|
||||
template<typename T> LuaReference EnumTraits<T>::EnumToString;
|
||||
/** @brief Lua helpers for Enumerators. */
|
||||
namespace Enum
|
||||
{
|
||||
template<typename T>
|
||||
static T Check( lua_State *L, int iPos, bool bAllowInvalid = false )
|
||||
{
|
||||
return (T) CheckEnum(L,
|
||||
EnumTraits<T>::StringToEnum,
|
||||
iPos,
|
||||
EnumTraits<T>::Invalid,
|
||||
EnumTraits<T>::szName,
|
||||
bAllowInvalid);
|
||||
}
|
||||
template<typename T>
|
||||
static void Push( lua_State *L, T iVal )
|
||||
{
|
||||
/* Enum_Invalid values are nil in Lua. */
|
||||
if( iVal == EnumTraits<T>::Invalid )
|
||||
{
|
||||
lua_pushnil( L );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look up the string value. */
|
||||
EnumTraits<T>::EnumToString.PushSelf( L );
|
||||
lua_rawgeti( L, -1, iVal + 1 );
|
||||
lua_remove( L, -2 );
|
||||
}
|
||||
|
||||
void SetMetatable( lua_State *L, LuaReference &EnumTable, LuaReference &EnumIndexTable, const char *szName );
|
||||
};
|
||||
|
||||
const RString &EnumToString( int iVal, int iMax, const char **szNameArray, auto_ptr<RString> *pNameCache ); // XToString helper
|
||||
|
||||
#define XToString(X) \
|
||||
const RString& X##ToString(X x); \
|
||||
COMPILE_ASSERT( NUM_##X == ARRAYLEN(X##Names) ); \
|
||||
const RString& X##ToString( X x ) \
|
||||
{ \
|
||||
static auto_ptr<RString> as_##X##Name[NUM_##X+2]; \
|
||||
return EnumToString( x, NUM_##X, X##Names, as_##X##Name ); \
|
||||
} \
|
||||
namespace StringConversion { template<> RString ToString<X>( const X &value ) { return X##ToString(value); } }
|
||||
|
||||
#define XToLocalizedString(X) \
|
||||
const RString &X##ToLocalizedString(X x); \
|
||||
const RString &X##ToLocalizedString( X x ) \
|
||||
{ \
|
||||
static auto_ptr<LocalizedString> g_##X##Name[NUM_##X]; \
|
||||
if( g_##X##Name[0].get() == nullptr ) { \
|
||||
for( unsigned i = 0; i < NUM_##X; ++i ) \
|
||||
{ \
|
||||
auto_ptr<LocalizedString> ap( new LocalizedString(#X, X##ToString((X)i)) ); \
|
||||
g_##X##Name[i] = ap; \
|
||||
} \
|
||||
} \
|
||||
return g_##X##Name[x]->GetValue(); \
|
||||
}
|
||||
|
||||
#define StringToX(X) \
|
||||
X StringTo##X(const RString&); \
|
||||
X StringTo##X( const RString& s ) \
|
||||
{ \
|
||||
for( unsigned i = 0; i < ARRAYLEN(X##Names); ++i ) \
|
||||
if( !s.CompareNoCase(X##Names[i]) ) \
|
||||
return (X)i; \
|
||||
return X##_Invalid; \
|
||||
} \
|
||||
namespace StringConversion \
|
||||
{ \
|
||||
template<> bool FromString<X>( const RString &sValue, X &out ) \
|
||||
{ \
|
||||
out = StringTo##X(sValue); \
|
||||
return out != X##_Invalid; \
|
||||
} \
|
||||
}
|
||||
|
||||
// currently unused
|
||||
#define LuaDeclareType(X)
|
||||
|
||||
#define LuaXType(X) \
|
||||
template struct EnumTraits<X>; \
|
||||
static void Lua##X(lua_State* L) \
|
||||
{ \
|
||||
/* Create the EnumToString table: { "UnlockEntry_ArcadePoints", "UnlockEntry_DancePoints" } */ \
|
||||
lua_newtable( L ); \
|
||||
FOREACH_ENUM( X, i ) \
|
||||
{ \
|
||||
RString s = X##ToString( i ); \
|
||||
lua_pushstring( L, (#X "_")+s ); \
|
||||
lua_rawseti( L, -2, i+1 ); /* 1-based */ \
|
||||
} \
|
||||
EnumTraits<X>::EnumToString.SetFromStack( L ); \
|
||||
EnumTraits<X>::EnumToString.PushSelf( L ); \
|
||||
lua_setglobal( L, #X ); \
|
||||
/* Create the StringToEnum table: { "UnlockEntry_ArcadePoints" = 0, "UnlockEntry_DancePoints" = 1 } */ \
|
||||
lua_newtable( L ); \
|
||||
FOREACH_ENUM( X, i ) \
|
||||
{ \
|
||||
RString s = X##ToString( i ); \
|
||||
lua_pushstring( L, (#X "_")+s ); \
|
||||
lua_pushnumber( L, i ); /* 0-based */ \
|
||||
lua_rawset( L, -3 ); \
|
||||
} \
|
||||
EnumTraits<X>::StringToEnum.SetFromStack( L ); \
|
||||
EnumTraits<X>::StringToEnum.PushSelf( L ); \
|
||||
Enum::SetMetatable( L, EnumTraits<X>::EnumToString, EnumTraits<X>::StringToEnum, #X ); \
|
||||
} \
|
||||
REGISTER_WITH_LUA_FUNCTION( Lua##X ); \
|
||||
template<> X EnumTraits<X>::Invalid = X##_Invalid; \
|
||||
template<> const char *EnumTraits<X>::szName = #X; \
|
||||
namespace LuaHelpers \
|
||||
{ \
|
||||
template<> bool FromStack<X>( lua_State *L, X &Object, int iOffset ) \
|
||||
{ \
|
||||
Object = Enum::Check<X>( L, iOffset, true ); \
|
||||
return Object != EnumTraits<X>::Invalid; \
|
||||
} \
|
||||
} \
|
||||
namespace LuaHelpers \
|
||||
{ \
|
||||
template<> void Push<X>( lua_State *L, const X &Object ) \
|
||||
{ \
|
||||
Enum::Push<X>( L, Object ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Chris Danford, Glenn Maynard (c) 2004-2006
|
||||
* @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.
|
||||
*/
|
||||
|
||||
+359
-359
@@ -1,359 +1,359 @@
|
||||
#include "global.h"
|
||||
#include "FadingBanner.h"
|
||||
#include "RageTextureManager.h"
|
||||
#include "BannerCache.h"
|
||||
#include "Song.h"
|
||||
#include "RageLog.h"
|
||||
#include "Course.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "SongManager.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "ActorUtil.h"
|
||||
|
||||
REGISTER_ACTOR_CLASS( FadingBanner );
|
||||
|
||||
/* Allow fading from one banner to another. We can handle two fades at once;
|
||||
* this is used to fade from an old banner to a low-quality banner to a high-
|
||||
* quality banner smoothly.
|
||||
*
|
||||
* m_iIndexLatest is the latest banner loaded, and the one that we'll end up
|
||||
* displaying when the fades stop. */
|
||||
FadingBanner::FadingBanner()
|
||||
{
|
||||
m_bMovingFast = false;
|
||||
m_bSkipNextBannerUpdate = false;
|
||||
m_iIndexLatest = 0;
|
||||
for( int i=0; i<NUM_BANNERS; i++ )
|
||||
{
|
||||
m_Banner[i].SetName( "Banner" );
|
||||
ActorUtil::LoadAllCommandsAndOnCommand( m_Banner[i], "FadingBanner" );
|
||||
this->AddChild( &m_Banner[i] );
|
||||
}
|
||||
}
|
||||
|
||||
void FadingBanner::ScaleToClipped( float fWidth, float fHeight )
|
||||
{
|
||||
for( int i=0; i<NUM_BANNERS; i++ )
|
||||
m_Banner[i].ScaleToClipped( fWidth, fHeight );
|
||||
}
|
||||
|
||||
void FadingBanner::UpdateInternal( float fDeltaTime )
|
||||
{
|
||||
// update children manually
|
||||
// ActorFrame::UpdateInternal( fDeltaTime );
|
||||
Actor::UpdateInternal( fDeltaTime );
|
||||
|
||||
if( !m_bSkipNextBannerUpdate )
|
||||
{
|
||||
for( int i = 0; i < NUM_BANNERS; ++i )
|
||||
m_Banner[i].Update( fDeltaTime );
|
||||
}
|
||||
|
||||
m_bSkipNextBannerUpdate = false;
|
||||
}
|
||||
|
||||
void FadingBanner::DrawPrimitives()
|
||||
{
|
||||
// draw manually
|
||||
// ActorFrame::DrawPrimitives();
|
||||
|
||||
// Render the latest banner first.
|
||||
for( int i = 0; i < NUM_BANNERS; ++i )
|
||||
{
|
||||
int index = m_iIndexLatest - i;
|
||||
wrap( index, NUM_BANNERS );
|
||||
m_Banner[index].Draw();
|
||||
}
|
||||
}
|
||||
|
||||
void FadingBanner::Load( RageTextureID ID, bool bLowResToHighRes )
|
||||
{
|
||||
BeforeChange( bLowResToHighRes );
|
||||
m_Banner[m_iIndexLatest].Load(ID);
|
||||
|
||||
/* XXX: Hack to keep movies from updating multiple times.
|
||||
* We need to either completely disallow movies in banners or support
|
||||
* them. There are a number of files that use them currently in the
|
||||
* wild. If we wanted to support them, then perhaps we should use an
|
||||
* all-black texture for the low quality texture. */
|
||||
RageTexture *pTexture = m_Banner[m_iIndexLatest].GetTexture();
|
||||
if( !pTexture || !pTexture->IsAMovie() )
|
||||
return;
|
||||
m_Banner[m_iIndexLatest].SetSecondsIntoAnimation( 0.f );
|
||||
for( int i = 1; i < NUM_BANNERS; ++i )
|
||||
{
|
||||
int index = m_iIndexLatest - i;
|
||||
wrap( index, NUM_BANNERS );
|
||||
if( m_Banner[index].GetTexturePath() == ID.filename )
|
||||
m_Banner[index].UnloadTexture();
|
||||
}
|
||||
}
|
||||
|
||||
/* If bLowResToHighRes is true, we're fading from a low-res banner to the
|
||||
* corresponding high-res banner. */
|
||||
void FadingBanner::BeforeChange( bool bLowResToHighRes )
|
||||
{
|
||||
RString sCommand;
|
||||
if( bLowResToHighRes )
|
||||
sCommand = "FadeFromCached";
|
||||
else
|
||||
sCommand = "FadeOff";
|
||||
|
||||
m_Banner[m_iIndexLatest].PlayCommand( sCommand );
|
||||
++m_iIndexLatest;
|
||||
wrap( m_iIndexLatest, NUM_BANNERS );
|
||||
|
||||
m_Banner[m_iIndexLatest].PlayCommand( "ResetFade" );
|
||||
|
||||
/* We're about to load a banner. It'll probably cause a frame skip or two.
|
||||
* Skip an update, so the fade-in doesn't skip. */
|
||||
m_bSkipNextBannerUpdate = true;
|
||||
}
|
||||
|
||||
/* If this returns true, a low-resolution banner was loaded, and the full-res
|
||||
* banner should be loaded later. */
|
||||
bool FadingBanner::LoadFromCachedBanner( const RString &path )
|
||||
{
|
||||
// If we're already on the given banner, don't fade again.
|
||||
if( path != "" && m_Banner[m_iIndexLatest].GetTexturePath() == path )
|
||||
return false;
|
||||
|
||||
if( path == "" )
|
||||
{
|
||||
LoadFallback();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If we're currently fading to the given banner, go through this again,
|
||||
* which will cause the fade-in to be further delayed. */
|
||||
|
||||
RageTextureID ID;
|
||||
bool bLowRes = (PREFSMAN->m_BannerCache != BNCACHE_FULL);
|
||||
if( !bLowRes )
|
||||
{
|
||||
ID = Sprite::SongBannerTexture( path );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to load the low quality version.
|
||||
ID = BANNERCACHE->LoadCachedBanner( path );
|
||||
}
|
||||
|
||||
if( !TEXTUREMAN->IsTextureRegistered(ID) )
|
||||
{
|
||||
/* Oops. We couldn't load a banner quickly. We can load the actual
|
||||
* banner, but that's slow, so we don't want to do that when we're moving
|
||||
* fast on the music wheel. In that case, we should just keep the banner
|
||||
* that's there (or load a "moving fast" banner). Once we settle down,
|
||||
* we'll get called again and load the real banner. */
|
||||
|
||||
if( m_bMovingFast )
|
||||
return false;
|
||||
|
||||
if( IsAFile(path) )
|
||||
Load( path );
|
||||
else
|
||||
LoadFallback();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Load( ID );
|
||||
|
||||
return bLowRes;
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFromSong( const Song* pSong )
|
||||
{
|
||||
if( pSong == NULL )
|
||||
{
|
||||
LoadFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't call HasBanner. That'll do disk access and cause the music wheel
|
||||
* to skip. */
|
||||
RString sPath = pSong->GetBannerPath();
|
||||
if( sPath.empty() )
|
||||
LoadFallback();
|
||||
else
|
||||
LoadFromCachedBanner( sPath );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadMode()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadMode();
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFromSongGroup( RString sSongGroup )
|
||||
{
|
||||
const RString sGroupBannerPath = SONGMAN->GetSongGroupBannerPath( sSongGroup );
|
||||
LoadFromCachedBanner( sGroupBannerPath );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFromCourse( const Course* pCourse )
|
||||
{
|
||||
if( pCourse == NULL )
|
||||
{
|
||||
LoadFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't call HasBanner. That'll do disk access and cause the music wheel
|
||||
* to skip. */
|
||||
RString sPath = pCourse->GetBannerPath();
|
||||
if( sPath.empty() )
|
||||
LoadCourseFallback();
|
||||
else
|
||||
LoadFromCachedBanner( sPath );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadIconFromCharacter( Character* pCharacter )
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadIconFromCharacter( pCharacter );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadBannerFromUnlockEntry( const UnlockEntry* pUE )
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadBannerFromUnlockEntry( pUE );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadRoulette()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadRoulette();
|
||||
m_Banner[m_iIndexLatest].PlayCommand( "Roulette" );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadRandom()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadRandom();
|
||||
m_Banner[m_iIndexLatest].PlayCommand( "Random" );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFromSortOrder( SortOrder so )
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadFromSortOrder(so);
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFallback()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadFallback();
|
||||
}
|
||||
|
||||
void FadingBanner::LoadCourseFallback()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadCourseFallback();
|
||||
}
|
||||
|
||||
void FadingBanner::LoadCustom( RString sBanner )
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].Load( THEME->GetPathG( "Banner", sBanner ) );
|
||||
m_Banner[m_iIndexLatest].PlayCommand( sBanner );
|
||||
}
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
/** @brief Allow Lua to have access to the FadingBanner. */
|
||||
class LunaFadingBanner: public Luna<FadingBanner>
|
||||
{
|
||||
public:
|
||||
static int scaletoclipped( T* p, lua_State *L ) { p->ScaleToClipped(FArg(1),FArg(2)); return 0; }
|
||||
static int ScaleToClipped( T* p, lua_State *L ) { p->ScaleToClipped(FArg(1),FArg(2)); return 0; }
|
||||
static int LoadFromSong( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromSong( NULL ); }
|
||||
else { Song *pS = Luna<Song>::check(L,1); p->LoadFromSong( pS ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromCourse( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromCourse( NULL ); }
|
||||
else { Course *pC = Luna<Course>::check(L,1); p->LoadFromCourse( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadIconFromCharacter( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadIconFromCharacter( NULL ); }
|
||||
else { Character *pC = Luna<Character>::check(L,1); p->LoadIconFromCharacter( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadCardFromCharacter( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadIconFromCharacter( NULL ); }
|
||||
else { Character *pC = Luna<Character>::check(L,1); p->LoadIconFromCharacter( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromSongGroup( T* p, lua_State *L ) { p->LoadFromSongGroup( SArg(1) ); return 0; }
|
||||
static int LoadRandom( T* p, lua_State *L ) { p->LoadRandom(); return 0; }
|
||||
static int LoadRoulette( T* p, lua_State *L ) { p->LoadRoulette(); return 0; }
|
||||
static int LoadCourseFallback( T* p, lua_State *L ) { p->LoadCourseFallback(); return 0; }
|
||||
static int LoadFallback( T* p, lua_State *L ) { p->LoadFallback(); return 0; }
|
||||
static int LoadFromSortOrder( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromSortOrder( SortOrder_Invalid ); }
|
||||
else
|
||||
{
|
||||
SortOrder so = Enum::Check<SortOrder>(L, 1);
|
||||
p->LoadFromSortOrder( so );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int GetLatestIndex( T* p, lua_State *L ){ lua_pushnumber( L, p->GetLatestIndex() ); return 1; }
|
||||
|
||||
LunaFadingBanner()
|
||||
{
|
||||
ADD_METHOD( scaletoclipped );
|
||||
ADD_METHOD( ScaleToClipped );
|
||||
ADD_METHOD( LoadFromSong );
|
||||
ADD_METHOD( LoadFromSongGroup );
|
||||
ADD_METHOD( LoadFromCourse );
|
||||
ADD_METHOD( LoadIconFromCharacter );
|
||||
ADD_METHOD( LoadCardFromCharacter );
|
||||
ADD_METHOD( LoadRandom );
|
||||
ADD_METHOD( LoadRoulette );
|
||||
ADD_METHOD( LoadCourseFallback );
|
||||
ADD_METHOD( LoadFallback );
|
||||
ADD_METHOD( LoadFromSortOrder );
|
||||
ADD_METHOD( GetLatestIndex );
|
||||
//ADD_METHOD( GetBanner );
|
||||
}
|
||||
};
|
||||
|
||||
LUA_REGISTER_DERIVED_CLASS( FadingBanner, ActorFrame )
|
||||
// lua end
|
||||
|
||||
/*
|
||||
* (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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "FadingBanner.h"
|
||||
#include "RageTextureManager.h"
|
||||
#include "BannerCache.h"
|
||||
#include "Song.h"
|
||||
#include "RageLog.h"
|
||||
#include "Course.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "SongManager.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "ActorUtil.h"
|
||||
|
||||
REGISTER_ACTOR_CLASS( FadingBanner );
|
||||
|
||||
/* Allow fading from one banner to another. We can handle two fades at once;
|
||||
* this is used to fade from an old banner to a low-quality banner to a high-
|
||||
* quality banner smoothly.
|
||||
*
|
||||
* m_iIndexLatest is the latest banner loaded, and the one that we'll end up
|
||||
* displaying when the fades stop. */
|
||||
FadingBanner::FadingBanner()
|
||||
{
|
||||
m_bMovingFast = false;
|
||||
m_bSkipNextBannerUpdate = false;
|
||||
m_iIndexLatest = 0;
|
||||
for( int i=0; i<NUM_BANNERS; i++ )
|
||||
{
|
||||
m_Banner[i].SetName( "Banner" );
|
||||
ActorUtil::LoadAllCommandsAndOnCommand( m_Banner[i], "FadingBanner" );
|
||||
this->AddChild( &m_Banner[i] );
|
||||
}
|
||||
}
|
||||
|
||||
void FadingBanner::ScaleToClipped( float fWidth, float fHeight )
|
||||
{
|
||||
for( int i=0; i<NUM_BANNERS; i++ )
|
||||
m_Banner[i].ScaleToClipped( fWidth, fHeight );
|
||||
}
|
||||
|
||||
void FadingBanner::UpdateInternal( float fDeltaTime )
|
||||
{
|
||||
// update children manually
|
||||
// ActorFrame::UpdateInternal( fDeltaTime );
|
||||
Actor::UpdateInternal( fDeltaTime );
|
||||
|
||||
if( !m_bSkipNextBannerUpdate )
|
||||
{
|
||||
for( int i = 0; i < NUM_BANNERS; ++i )
|
||||
m_Banner[i].Update( fDeltaTime );
|
||||
}
|
||||
|
||||
m_bSkipNextBannerUpdate = false;
|
||||
}
|
||||
|
||||
void FadingBanner::DrawPrimitives()
|
||||
{
|
||||
// draw manually
|
||||
// ActorFrame::DrawPrimitives();
|
||||
|
||||
// Render the latest banner first.
|
||||
for( int i = 0; i < NUM_BANNERS; ++i )
|
||||
{
|
||||
int index = m_iIndexLatest - i;
|
||||
wrap( index, NUM_BANNERS );
|
||||
m_Banner[index].Draw();
|
||||
}
|
||||
}
|
||||
|
||||
void FadingBanner::Load( RageTextureID ID, bool bLowResToHighRes )
|
||||
{
|
||||
BeforeChange( bLowResToHighRes );
|
||||
m_Banner[m_iIndexLatest].Load(ID);
|
||||
|
||||
/* XXX: Hack to keep movies from updating multiple times.
|
||||
* We need to either completely disallow movies in banners or support
|
||||
* them. There are a number of files that use them currently in the
|
||||
* wild. If we wanted to support them, then perhaps we should use an
|
||||
* all-black texture for the low quality texture. */
|
||||
RageTexture *pTexture = m_Banner[m_iIndexLatest].GetTexture();
|
||||
if( !pTexture || !pTexture->IsAMovie() )
|
||||
return;
|
||||
m_Banner[m_iIndexLatest].SetSecondsIntoAnimation( 0.f );
|
||||
for( int i = 1; i < NUM_BANNERS; ++i )
|
||||
{
|
||||
int index = m_iIndexLatest - i;
|
||||
wrap( index, NUM_BANNERS );
|
||||
if( m_Banner[index].GetTexturePath() == ID.filename )
|
||||
m_Banner[index].UnloadTexture();
|
||||
}
|
||||
}
|
||||
|
||||
/* If bLowResToHighRes is true, we're fading from a low-res banner to the
|
||||
* corresponding high-res banner. */
|
||||
void FadingBanner::BeforeChange( bool bLowResToHighRes )
|
||||
{
|
||||
RString sCommand;
|
||||
if( bLowResToHighRes )
|
||||
sCommand = "FadeFromCached";
|
||||
else
|
||||
sCommand = "FadeOff";
|
||||
|
||||
m_Banner[m_iIndexLatest].PlayCommand( sCommand );
|
||||
++m_iIndexLatest;
|
||||
wrap( m_iIndexLatest, NUM_BANNERS );
|
||||
|
||||
m_Banner[m_iIndexLatest].PlayCommand( "ResetFade" );
|
||||
|
||||
/* We're about to load a banner. It'll probably cause a frame skip or two.
|
||||
* Skip an update, so the fade-in doesn't skip. */
|
||||
m_bSkipNextBannerUpdate = true;
|
||||
}
|
||||
|
||||
/* If this returns true, a low-resolution banner was loaded, and the full-res
|
||||
* banner should be loaded later. */
|
||||
bool FadingBanner::LoadFromCachedBanner( const RString &path )
|
||||
{
|
||||
// If we're already on the given banner, don't fade again.
|
||||
if( path != "" && m_Banner[m_iIndexLatest].GetTexturePath() == path )
|
||||
return false;
|
||||
|
||||
if( path == "" )
|
||||
{
|
||||
LoadFallback();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If we're currently fading to the given banner, go through this again,
|
||||
* which will cause the fade-in to be further delayed. */
|
||||
|
||||
RageTextureID ID;
|
||||
bool bLowRes = (PREFSMAN->m_BannerCache != BNCACHE_FULL);
|
||||
if( !bLowRes )
|
||||
{
|
||||
ID = Sprite::SongBannerTexture( path );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to load the low quality version.
|
||||
ID = BANNERCACHE->LoadCachedBanner( path );
|
||||
}
|
||||
|
||||
if( !TEXTUREMAN->IsTextureRegistered(ID) )
|
||||
{
|
||||
/* Oops. We couldn't load a banner quickly. We can load the actual
|
||||
* banner, but that's slow, so we don't want to do that when we're moving
|
||||
* fast on the music wheel. In that case, we should just keep the banner
|
||||
* that's there (or load a "moving fast" banner). Once we settle down,
|
||||
* we'll get called again and load the real banner. */
|
||||
|
||||
if( m_bMovingFast )
|
||||
return false;
|
||||
|
||||
if( IsAFile(path) )
|
||||
Load( path );
|
||||
else
|
||||
LoadFallback();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Load( ID );
|
||||
|
||||
return bLowRes;
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFromSong( const Song* pSong )
|
||||
{
|
||||
if( pSong == nullptr )
|
||||
{
|
||||
LoadFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't call HasBanner. That'll do disk access and cause the music wheel
|
||||
* to skip. */
|
||||
RString sPath = pSong->GetBannerPath();
|
||||
if( sPath.empty() )
|
||||
LoadFallback();
|
||||
else
|
||||
LoadFromCachedBanner( sPath );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadMode()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadMode();
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFromSongGroup( RString sSongGroup )
|
||||
{
|
||||
const RString sGroupBannerPath = SONGMAN->GetSongGroupBannerPath( sSongGroup );
|
||||
LoadFromCachedBanner( sGroupBannerPath );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFromCourse( const Course* pCourse )
|
||||
{
|
||||
if( pCourse == nullptr )
|
||||
{
|
||||
LoadFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't call HasBanner. That'll do disk access and cause the music wheel
|
||||
* to skip. */
|
||||
RString sPath = pCourse->GetBannerPath();
|
||||
if( sPath.empty() )
|
||||
LoadCourseFallback();
|
||||
else
|
||||
LoadFromCachedBanner( sPath );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadIconFromCharacter( Character* pCharacter )
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadIconFromCharacter( pCharacter );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadBannerFromUnlockEntry( const UnlockEntry* pUE )
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadBannerFromUnlockEntry( pUE );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadRoulette()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadRoulette();
|
||||
m_Banner[m_iIndexLatest].PlayCommand( "Roulette" );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadRandom()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadRandom();
|
||||
m_Banner[m_iIndexLatest].PlayCommand( "Random" );
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFromSortOrder( SortOrder so )
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadFromSortOrder(so);
|
||||
}
|
||||
|
||||
void FadingBanner::LoadFallback()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadFallback();
|
||||
}
|
||||
|
||||
void FadingBanner::LoadCourseFallback()
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].LoadCourseFallback();
|
||||
}
|
||||
|
||||
void FadingBanner::LoadCustom( RString sBanner )
|
||||
{
|
||||
BeforeChange();
|
||||
m_Banner[m_iIndexLatest].Load( THEME->GetPathG( "Banner", sBanner ) );
|
||||
m_Banner[m_iIndexLatest].PlayCommand( sBanner );
|
||||
}
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
/** @brief Allow Lua to have access to the FadingBanner. */
|
||||
class LunaFadingBanner: public Luna<FadingBanner>
|
||||
{
|
||||
public:
|
||||
static int scaletoclipped( T* p, lua_State *L ) { p->ScaleToClipped(FArg(1),FArg(2)); return 0; }
|
||||
static int ScaleToClipped( T* p, lua_State *L ) { p->ScaleToClipped(FArg(1),FArg(2)); return 0; }
|
||||
static int LoadFromSong( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromSong( NULL ); }
|
||||
else { Song *pS = Luna<Song>::check(L,1); p->LoadFromSong( pS ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromCourse( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromCourse( NULL ); }
|
||||
else { Course *pC = Luna<Course>::check(L,1); p->LoadFromCourse( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadIconFromCharacter( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadIconFromCharacter( NULL ); }
|
||||
else { Character *pC = Luna<Character>::check(L,1); p->LoadIconFromCharacter( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadCardFromCharacter( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadIconFromCharacter( NULL ); }
|
||||
else { Character *pC = Luna<Character>::check(L,1); p->LoadIconFromCharacter( pC ); }
|
||||
return 0;
|
||||
}
|
||||
static int LoadFromSongGroup( T* p, lua_State *L ) { p->LoadFromSongGroup( SArg(1) ); return 0; }
|
||||
static int LoadRandom( T* p, lua_State *L ) { p->LoadRandom(); return 0; }
|
||||
static int LoadRoulette( T* p, lua_State *L ) { p->LoadRoulette(); return 0; }
|
||||
static int LoadCourseFallback( T* p, lua_State *L ) { p->LoadCourseFallback(); return 0; }
|
||||
static int LoadFallback( T* p, lua_State *L ) { p->LoadFallback(); return 0; }
|
||||
static int LoadFromSortOrder( T* p, lua_State *L )
|
||||
{
|
||||
if( lua_isnil(L,1) ) { p->LoadFromSortOrder( SortOrder_Invalid ); }
|
||||
else
|
||||
{
|
||||
SortOrder so = Enum::Check<SortOrder>(L, 1);
|
||||
p->LoadFromSortOrder( so );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int GetLatestIndex( T* p, lua_State *L ){ lua_pushnumber( L, p->GetLatestIndex() ); return 1; }
|
||||
|
||||
LunaFadingBanner()
|
||||
{
|
||||
ADD_METHOD( scaletoclipped );
|
||||
ADD_METHOD( ScaleToClipped );
|
||||
ADD_METHOD( LoadFromSong );
|
||||
ADD_METHOD( LoadFromSongGroup );
|
||||
ADD_METHOD( LoadFromCourse );
|
||||
ADD_METHOD( LoadIconFromCharacter );
|
||||
ADD_METHOD( LoadCardFromCharacter );
|
||||
ADD_METHOD( LoadRandom );
|
||||
ADD_METHOD( LoadRoulette );
|
||||
ADD_METHOD( LoadCourseFallback );
|
||||
ADD_METHOD( LoadFallback );
|
||||
ADD_METHOD( LoadFromSortOrder );
|
||||
ADD_METHOD( GetLatestIndex );
|
||||
//ADD_METHOD( GetBanner );
|
||||
}
|
||||
};
|
||||
|
||||
LUA_REGISTER_DERIVED_CLASS( FadingBanner, ActorFrame )
|
||||
// lua end
|
||||
|
||||
/*
|
||||
* (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.
|
||||
*/
|
||||
|
||||
+2
-2
@@ -269,7 +269,7 @@ void Font::MergeFont(Font &f)
|
||||
* page. It'll usually be overridden later on by one of our own font
|
||||
* pages; this will be used only if we don't have any font pages at
|
||||
* all. */
|
||||
if( m_pDefault == NULL )
|
||||
if( m_pDefault == nullptr )
|
||||
m_pDefault = f.m_pDefault;
|
||||
|
||||
for(map<wchar_t,glyph*>::iterator it = f.m_iCharToGlyph.begin();
|
||||
@@ -605,7 +605,7 @@ RString FontPageSettings::MapRange( RString sMapping, int iMapOffset, int iGlyph
|
||||
}
|
||||
|
||||
const wchar_t *pMapping = FontCharmaps::get_char_map( sMapping );
|
||||
if( pMapping == NULL )
|
||||
if( pMapping == nullptr )
|
||||
return "Unknown mapping";
|
||||
|
||||
while( *pMapping != 0 && iMapOffset )
|
||||
|
||||
+9
-9
@@ -88,7 +88,7 @@ bool GameCommand::DescribesCurrentMode( PlayerNumber pn ) const
|
||||
// HACK: don't compare m_dc if m_pSteps is set. This causes problems
|
||||
// in ScreenSelectOptionsMaster::ImportOptions if m_PreferredDifficulty
|
||||
// doesn't match the difficulty of m_pCurSteps.
|
||||
if( m_pSteps == NULL && m_dc != Difficulty_Invalid )
|
||||
if( m_pSteps == nullptr && m_dc != Difficulty_Invalid )
|
||||
{
|
||||
// Why is this checking for all players?
|
||||
FOREACH_HumanPlayer( human )
|
||||
@@ -244,7 +244,7 @@ void GameCommand::LoadOne( const Command& cmd )
|
||||
else if( sName == "song" )
|
||||
{
|
||||
m_pSong = SONGMAN->FindSong( sValue );
|
||||
if( m_pSong == NULL )
|
||||
if( m_pSong == nullptr )
|
||||
{
|
||||
m_sInvalidReason = ssprintf( "Song \"%s\" not found", sValue.c_str() );
|
||||
m_bInvalid |= true;
|
||||
@@ -260,7 +260,7 @@ void GameCommand::LoadOne( const Command& cmd )
|
||||
{
|
||||
Song *pSong = (m_pSong != nullptr)? m_pSong:GAMESTATE->m_pCurSong;
|
||||
const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle();
|
||||
if( pSong == NULL || pStyle == NULL )
|
||||
if( pSong == nullptr || pStyle == nullptr )
|
||||
RageException::Throw( "Must set Song and Style to set Steps." );
|
||||
|
||||
Difficulty dc = StringToDifficulty( sSteps );
|
||||
@@ -268,7 +268,7 @@ void GameCommand::LoadOne( const Command& cmd )
|
||||
m_pSteps = SongUtil::GetStepsByDifficulty( pSong, pStyle->m_StepsType, dc );
|
||||
else
|
||||
m_pSteps = SongUtil::GetStepsByDescription( pSong, pStyle->m_StepsType, sSteps );
|
||||
if( m_pSteps == NULL )
|
||||
if( m_pSteps == nullptr )
|
||||
{
|
||||
m_sInvalidReason = "steps not found";
|
||||
m_bInvalid |= true;
|
||||
@@ -279,7 +279,7 @@ void GameCommand::LoadOne( const Command& cmd )
|
||||
else if( sName == "course" )
|
||||
{
|
||||
m_pCourse = SONGMAN->FindCourse( "", sValue );
|
||||
if( m_pCourse == NULL )
|
||||
if( m_pCourse == nullptr )
|
||||
{
|
||||
m_sInvalidReason = ssprintf( "Course \"%s\" not found", sValue.c_str() );
|
||||
m_bInvalid |= true;
|
||||
@@ -295,14 +295,14 @@ void GameCommand::LoadOne( const Command& cmd )
|
||||
{
|
||||
Course *pCourse = (m_pCourse != nullptr)? m_pCourse:GAMESTATE->m_pCurCourse;
|
||||
const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle();
|
||||
if( pCourse == NULL || pStyle == NULL )
|
||||
if( pCourse == nullptr || pStyle == nullptr )
|
||||
RageException::Throw( "Must set Course and Style to set Steps." );
|
||||
|
||||
const CourseDifficulty cd = StringToDifficulty( sTrail );
|
||||
ASSERT_M( cd != Difficulty_Invalid, ssprintf("Invalid difficulty '%s'", sTrail.c_str()) );
|
||||
|
||||
m_pTrail = pCourse->GetTrail( pStyle->m_StepsType, cd );
|
||||
if( m_pTrail == NULL )
|
||||
if( m_pTrail == nullptr )
|
||||
{
|
||||
m_sInvalidReason = "trail not found";
|
||||
m_bInvalid |= true;
|
||||
@@ -389,7 +389,7 @@ void GameCommand::LoadOne( const Command& cmd )
|
||||
if( cmd.m_vsArgs.size() == 3 )
|
||||
{
|
||||
IPreference *pPref = IPreference::GetPreferenceByName( cmd.m_vsArgs[1] );
|
||||
if( pPref == NULL )
|
||||
if( pPref == nullptr )
|
||||
{
|
||||
m_sInvalidReason = ssprintf("unknown preference \"%s\"", cmd.m_vsArgs[1].c_str() );
|
||||
m_bInvalid |= true;
|
||||
@@ -418,7 +418,7 @@ void GameCommand::LoadOne( const Command& cmd )
|
||||
|
||||
static bool AreStyleAndPlayModeCompatible( const Style *style, PlayMode pm )
|
||||
{
|
||||
if( style == NULL || pm == PlayMode_Invalid )
|
||||
if( style == nullptr || pm == PlayMode_Invalid )
|
||||
return true;
|
||||
|
||||
switch( pm )
|
||||
|
||||
+1
-1
@@ -338,7 +338,7 @@ int ConcurrentRenderer::StartRenderThread( void *p )
|
||||
|
||||
void GameLoop::StartConcurrentRendering()
|
||||
{
|
||||
if( g_pConcurrentRenderer == NULL )
|
||||
if( g_pConcurrentRenderer == nullptr )
|
||||
g_pConcurrentRenderer = new ConcurrentRenderer;
|
||||
g_pConcurrentRenderer->Start();
|
||||
}
|
||||
|
||||
+3
-3
@@ -3029,15 +3029,15 @@ void GameManager::GetEnabledGames( vector<const Game*>& aGamesOut )
|
||||
const Game* GameManager::GetDefaultGame()
|
||||
{
|
||||
const Game *pDefault = NULL;
|
||||
if( pDefault == NULL )
|
||||
if( pDefault == nullptr )
|
||||
{
|
||||
for( size_t i=0; pDefault == NULL && i < ARRAYLEN(g_Games); ++i )
|
||||
for( size_t i=0; pDefault == nullptr && i < ARRAYLEN(g_Games); ++i )
|
||||
{
|
||||
if( IsGameEnabled(g_Games[i]) )
|
||||
pDefault = g_Games[i];
|
||||
}
|
||||
|
||||
if( pDefault == NULL )
|
||||
if( pDefault == nullptr )
|
||||
RageException::Throw( "No NoteSkins found" );
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -608,7 +608,7 @@ int GameState::GetNumStagesForCurrentSongAndStepsOrCourse() const
|
||||
{
|
||||
const Style *pStyle = m_pCurStyle;
|
||||
int numSidesJoined = GetNumSidesJoined();
|
||||
if( pStyle == NULL )
|
||||
if( pStyle == nullptr )
|
||||
{
|
||||
const Steps *pSteps = NULL;
|
||||
if( this->GetMasterPlayerNumber() != PlayerNumber_Invalid )
|
||||
@@ -806,9 +806,9 @@ void GameState::LoadCurrentSettingsFromProfile( PlayerNumber pn )
|
||||
// Only set the PreferredStepsType if it wasn't already set by a GameCommand (or by an earlier profile)
|
||||
if( m_PreferredStepsType == StepsType_Invalid && pProfile->m_LastStepsType != StepsType_Invalid )
|
||||
m_PreferredStepsType.Set( pProfile->m_LastStepsType );
|
||||
if( m_pPreferredSong == NULL )
|
||||
if( m_pPreferredSong == nullptr )
|
||||
m_pPreferredSong = pProfile->m_lastSong.ToSong();
|
||||
if( m_pPreferredCourse == NULL )
|
||||
if( m_pPreferredCourse == nullptr )
|
||||
m_pPreferredCourse = pProfile->m_lastCourse.ToCourse();
|
||||
}
|
||||
|
||||
@@ -1094,7 +1094,7 @@ RString GameState::GetPlayerDisplayName( PlayerNumber pn ) const
|
||||
|
||||
bool GameState::PlayersCanJoin() const
|
||||
{
|
||||
bool b = GetNumSidesJoined() == 0 || GetCurrentStyle() == NULL; // selecting a style finalizes the players
|
||||
bool b = GetNumSidesJoined() == 0 || GetCurrentStyle() == nullptr; // selecting a style finalizes the players
|
||||
if( ALLOW_LATE_JOIN.IsLoaded() && ALLOW_LATE_JOIN )
|
||||
{
|
||||
Screen *pScreen = SCREENMAN->GetTopScreen();
|
||||
@@ -1176,7 +1176,7 @@ bool GameState::IsHumanPlayer( PlayerNumber pn ) const
|
||||
if( pn == PLAYER_INVALID )
|
||||
return false;
|
||||
|
||||
if( GetCurrentStyle() == NULL ) // no style chosen
|
||||
if( GetCurrentStyle() == nullptr ) // no style chosen
|
||||
{
|
||||
if( PlayersCanJoin() )
|
||||
return m_bSideIsJoined[pn]; // only allow input from sides that have already joined
|
||||
@@ -1989,7 +1989,7 @@ Difficulty GameState::GetEasiestStepsDifficulty() const
|
||||
Difficulty dc = Difficulty_Invalid;
|
||||
FOREACH_HumanPlayer( p )
|
||||
{
|
||||
if( m_pCurSteps[p] == NULL )
|
||||
if( m_pCurSteps[p] == nullptr )
|
||||
{
|
||||
LOG->Warn( "GetEasiestStepsDifficulty called but p%i hasn't chosen notes", p+1 );
|
||||
continue;
|
||||
@@ -2004,7 +2004,7 @@ Difficulty GameState::GetHardestStepsDifficulty() const
|
||||
Difficulty dc = Difficulty_Beginner;
|
||||
FOREACH_HumanPlayer( p )
|
||||
{
|
||||
if( m_pCurSteps[p] == NULL )
|
||||
if( m_pCurSteps[p] == nullptr )
|
||||
{
|
||||
LOG->Warn( "GetHardestStepsDifficulty called but p%i hasn't chosen notes", p+1 );
|
||||
continue;
|
||||
@@ -2349,7 +2349,7 @@ public:
|
||||
static int GetCurrentStepsCredits( T* t, lua_State *L )
|
||||
{
|
||||
const Song* pSong = t->m_pCurSong;
|
||||
if( pSong == NULL )
|
||||
if( pSong == nullptr )
|
||||
return 0;
|
||||
|
||||
// use a vector and not a set so that ordering is maintained
|
||||
@@ -2357,7 +2357,7 @@ public:
|
||||
FOREACH_HumanPlayer( p )
|
||||
{
|
||||
const Steps* pSteps = GAMESTATE->m_pCurSteps[p];
|
||||
if( pSteps == NULL )
|
||||
if( pSteps == nullptr )
|
||||
return 0;
|
||||
bool bAlreadyAdded = find( vpStepsToShow.begin(), vpStepsToShow.end(), pSteps ) != vpStepsToShow.end();
|
||||
if( !bAlreadyAdded )
|
||||
|
||||
+280
-280
@@ -1,280 +1,280 @@
|
||||
#include "global.h"
|
||||
#include "GrooveRadar.h"
|
||||
#include "RageUtil.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "Steps.h"
|
||||
#include "RageDisplay.h"
|
||||
#include "RageMath.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "CommonMetrics.h"
|
||||
#include "ActorUtil.h"
|
||||
// I feel weird about this coupling, but it has to be done. -aj
|
||||
#include "GameState.h"
|
||||
|
||||
REGISTER_ACTOR_CLASS(GrooveRadar);
|
||||
|
||||
static const ThemeMetric<float> RADAR_EDGE_WIDTH ("GrooveRadar","EdgeWidth");
|
||||
static const ThemeMetric<float> RADAR_CENTER_ALPHA ("GrooveRadar","CenterAlpha");
|
||||
|
||||
static float RADAR_VALUE_ROTATION( int iValueIndex ) { return PI/2 + PI*2 / 5.0f * iValueIndex; }
|
||||
|
||||
static const int NUM_SHOWN_RADAR_CATEGORIES = 5;
|
||||
|
||||
GrooveRadar::GrooveRadar()
|
||||
{
|
||||
m_sprRadarBase.Load( THEME->GetPathG("GrooveRadar","base") );
|
||||
m_Frame.AddChild( m_sprRadarBase );
|
||||
m_Frame.SetName( "RadarFrame" );
|
||||
ActorUtil::LoadAllCommands( m_Frame, "GrooveRadar" );
|
||||
|
||||
FOREACH_PlayerNumber( p )
|
||||
{
|
||||
// todo: remove dependency on radar base being a sprite. -aj
|
||||
m_GrooveRadarValueMap[p].SetRadius( m_sprRadarBase->GetZoomedWidth() );
|
||||
m_Frame.AddChild( &m_GrooveRadarValueMap[p] );
|
||||
m_GrooveRadarValueMap[p].SetName( ssprintf("RadarValueMapP%d",p+1) );
|
||||
ActorUtil::LoadAllCommands( m_GrooveRadarValueMap[p], "GrooveRadar" );
|
||||
}
|
||||
|
||||
this->AddChild( &m_Frame );
|
||||
|
||||
for( int c=0; c<NUM_SHOWN_RADAR_CATEGORIES; c++ )
|
||||
{
|
||||
m_sprRadarLabels[c].SetName( ssprintf("Label%i",c+1) );
|
||||
m_sprRadarLabels[c].Load( THEME->GetPathG("GrooveRadar","labels 1x5") );
|
||||
m_sprRadarLabels[c].StopAnimating();
|
||||
m_sprRadarLabels[c].SetState( c );
|
||||
ActorUtil::LoadAllCommandsAndSetXY( m_sprRadarLabels[c], "GrooveRadar" );
|
||||
this->AddChild( &m_sprRadarLabels[c] );
|
||||
}
|
||||
}
|
||||
|
||||
void GrooveRadar::LoadFromNode( const XNode* pNode )
|
||||
{
|
||||
ActorFrame::LoadFromNode( pNode );
|
||||
}
|
||||
|
||||
void GrooveRadar::SetEmpty( PlayerNumber pn )
|
||||
{
|
||||
SetFromSteps( pn, NULL );
|
||||
}
|
||||
|
||||
void GrooveRadar::SetFromRadarValues( PlayerNumber pn, const RadarValues &rv )
|
||||
{
|
||||
m_GrooveRadarValueMap[pn].SetFromSteps( rv );
|
||||
}
|
||||
|
||||
void GrooveRadar::SetFromSteps( PlayerNumber pn, Steps* pSteps ) // NULL means no Song
|
||||
{
|
||||
if( pSteps == NULL )
|
||||
{
|
||||
m_GrooveRadarValueMap[pn].SetEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
const RadarValues &rv = pSteps->GetRadarValues( pn );
|
||||
m_GrooveRadarValueMap[pn].SetFromSteps( rv );
|
||||
}
|
||||
|
||||
void GrooveRadar::SetFromValues( PlayerNumber pn, vector<float> vals )
|
||||
{
|
||||
m_GrooveRadarValueMap[pn].SetFromValues(vals);
|
||||
}
|
||||
|
||||
GrooveRadar::GrooveRadarValueMap::GrooveRadarValueMap()
|
||||
{
|
||||
m_bValuesVisible = false;
|
||||
m_PercentTowardNew = 0;
|
||||
|
||||
for( int c=0; c<NUM_SHOWN_RADAR_CATEGORIES; c++ )
|
||||
{
|
||||
m_fValuesNew[c] = 0;
|
||||
m_fValuesOld[c] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::SetEmpty()
|
||||
{
|
||||
m_bValuesVisible = false;
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::SetFromSteps( const RadarValues &rv )
|
||||
{
|
||||
m_bValuesVisible = true;
|
||||
for( int c=0; c<NUM_SHOWN_RADAR_CATEGORIES; c++ )
|
||||
{
|
||||
const float fValueCurrent = m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew;
|
||||
m_fValuesOld[c] = fValueCurrent;
|
||||
m_fValuesNew[c] = rv[c];
|
||||
}
|
||||
|
||||
if( !m_bValuesVisible ) // the values WERE invisible
|
||||
m_PercentTowardNew = 1;
|
||||
else
|
||||
m_PercentTowardNew = 0;
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::SetFromValues( vector<float> vals )
|
||||
{
|
||||
m_bValuesVisible = true;
|
||||
for( int c=0; c<NUM_SHOWN_RADAR_CATEGORIES; c++ )
|
||||
{
|
||||
const float fValueCurrent = m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew;
|
||||
m_fValuesOld[c] = fValueCurrent;
|
||||
m_fValuesNew[c] = vals[c];
|
||||
}
|
||||
|
||||
if( !m_bValuesVisible ) // the values WERE invisible
|
||||
m_PercentTowardNew = 1;
|
||||
else
|
||||
m_PercentTowardNew = 0;
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::Update( float fDeltaTime )
|
||||
{
|
||||
ActorFrame::Update( fDeltaTime );
|
||||
|
||||
m_PercentTowardNew = min( m_PercentTowardNew+4.0f*fDeltaTime, 1 );
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::DrawPrimitives()
|
||||
{
|
||||
ActorFrame::DrawPrimitives();
|
||||
|
||||
// draw radar filling
|
||||
const float fRadius = GetUnzoomedWidth()/2.0f*1.1f;
|
||||
|
||||
DISPLAY->ClearAllTextures();
|
||||
DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Modulate );
|
||||
RageSpriteVertex v[12]; // needed to draw 5 fan primitives and 10 strip primitives
|
||||
|
||||
// xxx: We could either make the values invisible or draw a dot
|
||||
// (simulating real DDR). TODO: Make that choice up to the themer. -aj
|
||||
if( !m_bValuesVisible )
|
||||
return;
|
||||
|
||||
// use a fan to draw the volume
|
||||
RageColor color = this->m_pTempState->diffuse[0];
|
||||
color.a = 0.5f;
|
||||
v[0].p = RageVector3( 0, 0, 0 );
|
||||
RageColor midcolor = color;
|
||||
midcolor.a = RADAR_CENTER_ALPHA;
|
||||
v[0].c = midcolor;
|
||||
v[1].c = color;
|
||||
|
||||
for( int i=0; i<NUM_SHOWN_RADAR_CATEGORIES+1; i++ ) // do one extra to close the fan
|
||||
{
|
||||
const int c = i%NUM_SHOWN_RADAR_CATEGORIES;
|
||||
const float fDistFromCenter =
|
||||
( m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew + 0.07f ) * fRadius;
|
||||
const float fRotation = RADAR_VALUE_ROTATION(i);
|
||||
const float fX = RageFastCos(fRotation) * fDistFromCenter;
|
||||
const float fY = -RageFastSin(fRotation) * fDistFromCenter;
|
||||
|
||||
v[1+i].p = RageVector3( fX, fY, 0 );
|
||||
v[1+i].c = v[1].c;
|
||||
}
|
||||
|
||||
DISPLAY->DrawFan( v, NUM_SHOWN_RADAR_CATEGORIES+2 );
|
||||
|
||||
// use a line loop to draw the thick line
|
||||
for( int i=0; i<=NUM_SHOWN_RADAR_CATEGORIES; i++ )
|
||||
{
|
||||
const int c = i%NUM_SHOWN_RADAR_CATEGORIES;
|
||||
const float fDistFromCenter =
|
||||
( m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew + 0.07f ) * fRadius;
|
||||
const float fRotation = RADAR_VALUE_ROTATION(i);
|
||||
const float fX = RageFastCos(fRotation) * fDistFromCenter;
|
||||
const float fY = -RageFastSin(fRotation) * fDistFromCenter;
|
||||
|
||||
v[i].p = RageVector3( fX, fY, 0 );
|
||||
v[i].c = this->m_pTempState->diffuse[0];
|
||||
}
|
||||
|
||||
// TODO: Add this back in -Chris
|
||||
// switch( PREFSMAN->m_iPolygonRadar )
|
||||
// {
|
||||
// case 0: DISPLAY->DrawLoop_LinesAndPoints( v, NUM_SHOWN_RADAR_CATEGORIES, RADAR_EDGE_WIDTH ); break;
|
||||
// case 1: DISPLAY->DrawLoop_Polys( v, NUM_SHOWN_RADAR_CATEGORIES, RADAR_EDGE_WIDTH ); break;
|
||||
// default:
|
||||
// case -1:
|
||||
DISPLAY->DrawLineStrip( v, NUM_SHOWN_RADAR_CATEGORIES+1, RADAR_EDGE_WIDTH );
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
/** @brief Allow Lua to have access to the GrooveRadar. */
|
||||
class LunaGrooveRadar: public Luna<GrooveRadar>
|
||||
{
|
||||
public:
|
||||
static int SetFromRadarValues( T* p, lua_State *L )
|
||||
{
|
||||
PlayerNumber pn = Enum::Check<PlayerNumber>(L, 1);
|
||||
if( lua_isnil(L,2) )
|
||||
{
|
||||
p->SetEmpty( pn );
|
||||
}
|
||||
else
|
||||
{
|
||||
RadarValues *pRV = Luna<RadarValues>::check(L,2);
|
||||
p->SetFromRadarValues( pn, *pRV );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int SetFromValues( T* p, lua_State *L )
|
||||
{
|
||||
PlayerNumber pn = Enum::Check<PlayerNumber>(L, 1);
|
||||
if( !lua_istable(L, 2) || lua_isnil(L,2) )
|
||||
{
|
||||
p->SetEmpty( pn );
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<float> vals;
|
||||
LuaHelpers::ReadArrayFromTable( vals, L );
|
||||
p->SetFromValues(pn, vals);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int SetEmpty( T* p, lua_State *L ) { p->SetEmpty( Enum::Check<PlayerNumber>(L, 1) ); return 0; }
|
||||
|
||||
LunaGrooveRadar()
|
||||
{
|
||||
ADD_METHOD( SetFromRadarValues );
|
||||
ADD_METHOD( SetFromValues );
|
||||
ADD_METHOD( SetEmpty );
|
||||
}
|
||||
};
|
||||
|
||||
LUA_REGISTER_DERIVED_CLASS( GrooveRadar, ActorFrame )
|
||||
// lua end
|
||||
|
||||
/*
|
||||
* (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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "GrooveRadar.h"
|
||||
#include "RageUtil.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "Steps.h"
|
||||
#include "RageDisplay.h"
|
||||
#include "RageMath.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "CommonMetrics.h"
|
||||
#include "ActorUtil.h"
|
||||
// I feel weird about this coupling, but it has to be done. -aj
|
||||
#include "GameState.h"
|
||||
|
||||
REGISTER_ACTOR_CLASS(GrooveRadar);
|
||||
|
||||
static const ThemeMetric<float> RADAR_EDGE_WIDTH ("GrooveRadar","EdgeWidth");
|
||||
static const ThemeMetric<float> RADAR_CENTER_ALPHA ("GrooveRadar","CenterAlpha");
|
||||
|
||||
static float RADAR_VALUE_ROTATION( int iValueIndex ) { return PI/2 + PI*2 / 5.0f * iValueIndex; }
|
||||
|
||||
static const int NUM_SHOWN_RADAR_CATEGORIES = 5;
|
||||
|
||||
GrooveRadar::GrooveRadar()
|
||||
{
|
||||
m_sprRadarBase.Load( THEME->GetPathG("GrooveRadar","base") );
|
||||
m_Frame.AddChild( m_sprRadarBase );
|
||||
m_Frame.SetName( "RadarFrame" );
|
||||
ActorUtil::LoadAllCommands( m_Frame, "GrooveRadar" );
|
||||
|
||||
FOREACH_PlayerNumber( p )
|
||||
{
|
||||
// todo: remove dependency on radar base being a sprite. -aj
|
||||
m_GrooveRadarValueMap[p].SetRadius( m_sprRadarBase->GetZoomedWidth() );
|
||||
m_Frame.AddChild( &m_GrooveRadarValueMap[p] );
|
||||
m_GrooveRadarValueMap[p].SetName( ssprintf("RadarValueMapP%d",p+1) );
|
||||
ActorUtil::LoadAllCommands( m_GrooveRadarValueMap[p], "GrooveRadar" );
|
||||
}
|
||||
|
||||
this->AddChild( &m_Frame );
|
||||
|
||||
for( int c=0; c<NUM_SHOWN_RADAR_CATEGORIES; c++ )
|
||||
{
|
||||
m_sprRadarLabels[c].SetName( ssprintf("Label%i",c+1) );
|
||||
m_sprRadarLabels[c].Load( THEME->GetPathG("GrooveRadar","labels 1x5") );
|
||||
m_sprRadarLabels[c].StopAnimating();
|
||||
m_sprRadarLabels[c].SetState( c );
|
||||
ActorUtil::LoadAllCommandsAndSetXY( m_sprRadarLabels[c], "GrooveRadar" );
|
||||
this->AddChild( &m_sprRadarLabels[c] );
|
||||
}
|
||||
}
|
||||
|
||||
void GrooveRadar::LoadFromNode( const XNode* pNode )
|
||||
{
|
||||
ActorFrame::LoadFromNode( pNode );
|
||||
}
|
||||
|
||||
void GrooveRadar::SetEmpty( PlayerNumber pn )
|
||||
{
|
||||
SetFromSteps( pn, NULL );
|
||||
}
|
||||
|
||||
void GrooveRadar::SetFromRadarValues( PlayerNumber pn, const RadarValues &rv )
|
||||
{
|
||||
m_GrooveRadarValueMap[pn].SetFromSteps( rv );
|
||||
}
|
||||
|
||||
void GrooveRadar::SetFromSteps( PlayerNumber pn, Steps* pSteps ) // NULL means no Song
|
||||
{
|
||||
if( pSteps == nullptr )
|
||||
{
|
||||
m_GrooveRadarValueMap[pn].SetEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
const RadarValues &rv = pSteps->GetRadarValues( pn );
|
||||
m_GrooveRadarValueMap[pn].SetFromSteps( rv );
|
||||
}
|
||||
|
||||
void GrooveRadar::SetFromValues( PlayerNumber pn, vector<float> vals )
|
||||
{
|
||||
m_GrooveRadarValueMap[pn].SetFromValues(vals);
|
||||
}
|
||||
|
||||
GrooveRadar::GrooveRadarValueMap::GrooveRadarValueMap()
|
||||
{
|
||||
m_bValuesVisible = false;
|
||||
m_PercentTowardNew = 0;
|
||||
|
||||
for( int c=0; c<NUM_SHOWN_RADAR_CATEGORIES; c++ )
|
||||
{
|
||||
m_fValuesNew[c] = 0;
|
||||
m_fValuesOld[c] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::SetEmpty()
|
||||
{
|
||||
m_bValuesVisible = false;
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::SetFromSteps( const RadarValues &rv )
|
||||
{
|
||||
m_bValuesVisible = true;
|
||||
for( int c=0; c<NUM_SHOWN_RADAR_CATEGORIES; c++ )
|
||||
{
|
||||
const float fValueCurrent = m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew;
|
||||
m_fValuesOld[c] = fValueCurrent;
|
||||
m_fValuesNew[c] = rv[c];
|
||||
}
|
||||
|
||||
if( !m_bValuesVisible ) // the values WERE invisible
|
||||
m_PercentTowardNew = 1;
|
||||
else
|
||||
m_PercentTowardNew = 0;
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::SetFromValues( vector<float> vals )
|
||||
{
|
||||
m_bValuesVisible = true;
|
||||
for( int c=0; c<NUM_SHOWN_RADAR_CATEGORIES; c++ )
|
||||
{
|
||||
const float fValueCurrent = m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew;
|
||||
m_fValuesOld[c] = fValueCurrent;
|
||||
m_fValuesNew[c] = vals[c];
|
||||
}
|
||||
|
||||
if( !m_bValuesVisible ) // the values WERE invisible
|
||||
m_PercentTowardNew = 1;
|
||||
else
|
||||
m_PercentTowardNew = 0;
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::Update( float fDeltaTime )
|
||||
{
|
||||
ActorFrame::Update( fDeltaTime );
|
||||
|
||||
m_PercentTowardNew = min( m_PercentTowardNew+4.0f*fDeltaTime, 1 );
|
||||
}
|
||||
|
||||
void GrooveRadar::GrooveRadarValueMap::DrawPrimitives()
|
||||
{
|
||||
ActorFrame::DrawPrimitives();
|
||||
|
||||
// draw radar filling
|
||||
const float fRadius = GetUnzoomedWidth()/2.0f*1.1f;
|
||||
|
||||
DISPLAY->ClearAllTextures();
|
||||
DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Modulate );
|
||||
RageSpriteVertex v[12]; // needed to draw 5 fan primitives and 10 strip primitives
|
||||
|
||||
// xxx: We could either make the values invisible or draw a dot
|
||||
// (simulating real DDR). TODO: Make that choice up to the themer. -aj
|
||||
if( !m_bValuesVisible )
|
||||
return;
|
||||
|
||||
// use a fan to draw the volume
|
||||
RageColor color = this->m_pTempState->diffuse[0];
|
||||
color.a = 0.5f;
|
||||
v[0].p = RageVector3( 0, 0, 0 );
|
||||
RageColor midcolor = color;
|
||||
midcolor.a = RADAR_CENTER_ALPHA;
|
||||
v[0].c = midcolor;
|
||||
v[1].c = color;
|
||||
|
||||
for( int i=0; i<NUM_SHOWN_RADAR_CATEGORIES+1; i++ ) // do one extra to close the fan
|
||||
{
|
||||
const int c = i%NUM_SHOWN_RADAR_CATEGORIES;
|
||||
const float fDistFromCenter =
|
||||
( m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew + 0.07f ) * fRadius;
|
||||
const float fRotation = RADAR_VALUE_ROTATION(i);
|
||||
const float fX = RageFastCos(fRotation) * fDistFromCenter;
|
||||
const float fY = -RageFastSin(fRotation) * fDistFromCenter;
|
||||
|
||||
v[1+i].p = RageVector3( fX, fY, 0 );
|
||||
v[1+i].c = v[1].c;
|
||||
}
|
||||
|
||||
DISPLAY->DrawFan( v, NUM_SHOWN_RADAR_CATEGORIES+2 );
|
||||
|
||||
// use a line loop to draw the thick line
|
||||
for( int i=0; i<=NUM_SHOWN_RADAR_CATEGORIES; i++ )
|
||||
{
|
||||
const int c = i%NUM_SHOWN_RADAR_CATEGORIES;
|
||||
const float fDistFromCenter =
|
||||
( m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew + 0.07f ) * fRadius;
|
||||
const float fRotation = RADAR_VALUE_ROTATION(i);
|
||||
const float fX = RageFastCos(fRotation) * fDistFromCenter;
|
||||
const float fY = -RageFastSin(fRotation) * fDistFromCenter;
|
||||
|
||||
v[i].p = RageVector3( fX, fY, 0 );
|
||||
v[i].c = this->m_pTempState->diffuse[0];
|
||||
}
|
||||
|
||||
// TODO: Add this back in -Chris
|
||||
// switch( PREFSMAN->m_iPolygonRadar )
|
||||
// {
|
||||
// case 0: DISPLAY->DrawLoop_LinesAndPoints( v, NUM_SHOWN_RADAR_CATEGORIES, RADAR_EDGE_WIDTH ); break;
|
||||
// case 1: DISPLAY->DrawLoop_Polys( v, NUM_SHOWN_RADAR_CATEGORIES, RADAR_EDGE_WIDTH ); break;
|
||||
// default:
|
||||
// case -1:
|
||||
DISPLAY->DrawLineStrip( v, NUM_SHOWN_RADAR_CATEGORIES+1, RADAR_EDGE_WIDTH );
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
/** @brief Allow Lua to have access to the GrooveRadar. */
|
||||
class LunaGrooveRadar: public Luna<GrooveRadar>
|
||||
{
|
||||
public:
|
||||
static int SetFromRadarValues( T* p, lua_State *L )
|
||||
{
|
||||
PlayerNumber pn = Enum::Check<PlayerNumber>(L, 1);
|
||||
if( lua_isnil(L,2) )
|
||||
{
|
||||
p->SetEmpty( pn );
|
||||
}
|
||||
else
|
||||
{
|
||||
RadarValues *pRV = Luna<RadarValues>::check(L,2);
|
||||
p->SetFromRadarValues( pn, *pRV );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int SetFromValues( T* p, lua_State *L )
|
||||
{
|
||||
PlayerNumber pn = Enum::Check<PlayerNumber>(L, 1);
|
||||
if( !lua_istable(L, 2) || lua_isnil(L,2) )
|
||||
{
|
||||
p->SetEmpty( pn );
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<float> vals;
|
||||
LuaHelpers::ReadArrayFromTable( vals, L );
|
||||
p->SetFromValues(pn, vals);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int SetEmpty( T* p, lua_State *L ) { p->SetEmpty( Enum::Check<PlayerNumber>(L, 1) ); return 0; }
|
||||
|
||||
LunaGrooveRadar()
|
||||
{
|
||||
ADD_METHOD( SetFromRadarValues );
|
||||
ADD_METHOD( SetFromValues );
|
||||
ADD_METHOD( SetEmpty );
|
||||
}
|
||||
};
|
||||
|
||||
LUA_REGISTER_DERIVED_CLASS( GrooveRadar, ActorFrame )
|
||||
// lua end
|
||||
|
||||
/*
|
||||
* (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.
|
||||
*/
|
||||
|
||||
+3
-3
@@ -148,7 +148,7 @@ bool IniFile::WriteFile( RageFileBasic &f ) const
|
||||
bool IniFile::DeleteValue(const RString &keyname, const RString &valuename)
|
||||
{
|
||||
XNode* pNode = GetChild( keyname );
|
||||
if( pNode == NULL )
|
||||
if( pNode == nullptr )
|
||||
return false;
|
||||
return pNode->RemoveAttr( valuename );
|
||||
}
|
||||
@@ -157,7 +157,7 @@ bool IniFile::DeleteValue(const RString &keyname, const RString &valuename)
|
||||
bool IniFile::DeleteKey(const RString &keyname)
|
||||
{
|
||||
XNode* pNode = GetChild( keyname );
|
||||
if( pNode == NULL )
|
||||
if( pNode == nullptr )
|
||||
return false;
|
||||
return RemoveChild( pNode );
|
||||
}
|
||||
@@ -169,7 +169,7 @@ bool IniFile::RenameKey(const RString &from, const RString &to)
|
||||
return false;
|
||||
|
||||
XNode* pNode = GetChild( from );
|
||||
if( pNode == NULL )
|
||||
if( pNode == nullptr )
|
||||
return false;
|
||||
|
||||
pNode->SetName( to );
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@ public:
|
||||
bool GetValue( const RString &sKey, const RString &sValueName, T& value ) const
|
||||
{
|
||||
const XNode* pNode = GetChild( sKey );
|
||||
if( pNode == NULL )
|
||||
if( pNode == nullptr )
|
||||
return false;
|
||||
return pNode->GetAttrValue<T>( sValueName, value );
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
void SetValue( const RString &sKey, const RString &sValueName, const T &value )
|
||||
{
|
||||
XNode* pNode = GetChild( sKey );
|
||||
if( pNode == NULL )
|
||||
if( pNode == nullptr )
|
||||
pNode = AppendChild( sKey );
|
||||
pNode->AppendAttr<T>( sValueName, value );
|
||||
}
|
||||
|
||||
+5
-5
@@ -344,7 +344,7 @@ const T *FindItemBinarySearch( IT begin, IT end, const T &i )
|
||||
bool InputFilter::IsBeingPressed( const DeviceInput &di, const DeviceInputList *pButtonState ) const
|
||||
{
|
||||
LockMut(*queuemutex);
|
||||
if( pButtonState == NULL )
|
||||
if( pButtonState == nullptr )
|
||||
pButtonState = &g_CurrentState;
|
||||
const DeviceInput *pDI = FindItemBinarySearch( pButtonState->begin(), pButtonState->end(), di );
|
||||
return pDI != nullptr && pDI->bDown;
|
||||
@@ -353,10 +353,10 @@ bool InputFilter::IsBeingPressed( const DeviceInput &di, const DeviceInputList *
|
||||
float InputFilter::GetSecsHeld( const DeviceInput &di, const DeviceInputList *pButtonState ) const
|
||||
{
|
||||
LockMut(*queuemutex);
|
||||
if( pButtonState == NULL )
|
||||
if( pButtonState == nullptr )
|
||||
pButtonState = &g_CurrentState;
|
||||
const DeviceInput *pDI = FindItemBinarySearch( pButtonState->begin(), pButtonState->end(), di );
|
||||
if( pDI == NULL )
|
||||
if( pDI == nullptr )
|
||||
return 0;
|
||||
return pDI->ts.Ago();
|
||||
}
|
||||
@@ -364,10 +364,10 @@ float InputFilter::GetSecsHeld( const DeviceInput &di, const DeviceInputList *pB
|
||||
float InputFilter::GetLevel( const DeviceInput &di, const DeviceInputList *pButtonState ) const
|
||||
{
|
||||
LockMut(*queuemutex);
|
||||
if( pButtonState == NULL )
|
||||
if( pButtonState == nullptr )
|
||||
pButtonState = &g_CurrentState;
|
||||
const DeviceInput *pDI = FindItemBinarySearch( pButtonState->begin(), pButtonState->end(), di );
|
||||
if( pDI == NULL )
|
||||
if( pDI == nullptr )
|
||||
return 0.0f;
|
||||
return pDI->level;
|
||||
}
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ bool InputQueueCode::EnteredCode( GameController controller ) const
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( pIEP == NULL )
|
||||
if( pIEP == nullptr )
|
||||
break; // didn't find the button
|
||||
|
||||
// Check that m_aButtonsToHold were being held when the buttons were pressed.
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ namespace
|
||||
{
|
||||
void RegisterTypes( lua_State *L )
|
||||
{
|
||||
if( m_Subscribers.m_pSubscribers == NULL )
|
||||
if( m_Subscribers.m_pSubscribers == nullptr )
|
||||
return;
|
||||
|
||||
/* Register base classes first. */
|
||||
@@ -358,7 +358,7 @@ LuaClass &LuaClass::operator=( const LuaClass &cpy )
|
||||
|
||||
LuaClass::~LuaClass()
|
||||
{
|
||||
if( LUA == NULL )
|
||||
if( LUA == nullptr )
|
||||
return;
|
||||
|
||||
Lua *L = LUA->Get();
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ public:
|
||||
void T::PushSelf( lua_State *L ) { Luna<B>::PushObject( L, Luna<T>::m_sClassName, this ); } \
|
||||
static Luna##T registera##T; \
|
||||
/* Call PushSelf, so we always call the derived Luna<T>::Push. */ \
|
||||
namespace LuaHelpers { template<> void Push<T*>( lua_State *L, T *const &pObject ) { if( pObject == NULL ) lua_pushnil(L); else pObject->PushSelf( L ); } }
|
||||
namespace LuaHelpers { template<> void Push<T*>( lua_State *L, T *const &pObject ) { if( pObject == nullptr ) lua_pushnil(L); else pObject->PushSelf( L ); } }
|
||||
|
||||
#define DEFINE_METHOD( method_name, expr ) \
|
||||
static int method_name( T* p, lua_State *L ) { LuaHelpers::Push( L, p->expr ); return 1; }
|
||||
|
||||
+1
-1
@@ -230,7 +230,7 @@ static vector<RegisterWithLuaFn> *g_vRegisterActorTypes = NULL;
|
||||
|
||||
void LuaManager::Register( RegisterWithLuaFn pfn )
|
||||
{
|
||||
if( g_vRegisterActorTypes == NULL )
|
||||
if( g_vRegisterActorTypes == nullptr )
|
||||
g_vRegisterActorTypes = new vector<RegisterWithLuaFn>;
|
||||
|
||||
g_vRegisterActorTypes->push_back( pfn );
|
||||
|
||||
@@ -112,7 +112,7 @@ int LuaReference::GetLuaType() const
|
||||
|
||||
void LuaReference::Unregister()
|
||||
{
|
||||
if( LUA == NULL || m_iReference == LUA_NOREF )
|
||||
if( LUA == nullptr || m_iReference == LUA_NOREF )
|
||||
return; // nothing to do
|
||||
|
||||
Lua *L = LUA->Get();
|
||||
|
||||
+117
-117
@@ -1,117 +1,117 @@
|
||||
#include "global.h"
|
||||
#include "LyricDisplay.h"
|
||||
#include "ScreenDimensions.h"
|
||||
#include "GameState.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "Song.h"
|
||||
#include "ActorUtil.h"
|
||||
|
||||
static ThemeMetric<float> IN_LENGTH ("LyricDisplay","InLength");
|
||||
static ThemeMetric<float> OUT_LENGTH ("LyricDisplay","OutLength");
|
||||
|
||||
LyricDisplay::LyricDisplay()
|
||||
{
|
||||
m_textLyrics[0].SetName( "LyricBack" );
|
||||
ActorUtil::LoadAllCommands( m_textLyrics[0], "LyricDisplay" );
|
||||
m_textLyrics[0].LoadFromFont( THEME->GetPathF("LyricDisplay","text") );
|
||||
this->AddChild( &m_textLyrics[0] );
|
||||
|
||||
m_textLyrics[1].SetName( "LyricFront" );
|
||||
ActorUtil::LoadAllCommands( m_textLyrics[1], "LyricDisplay" );
|
||||
m_textLyrics[1].LoadFromFont( THEME->GetPathF("LyricDisplay","text") );
|
||||
this->AddChild( &m_textLyrics[1] );
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
void LyricDisplay::Init()
|
||||
{
|
||||
for( int i=0; i<2; i++ )
|
||||
m_textLyrics[i].SetText("");
|
||||
m_iCurLyricNumber = 0;
|
||||
|
||||
m_fLastSecond = -500;
|
||||
m_bStopped = false;
|
||||
}
|
||||
|
||||
void LyricDisplay::Stop() {
|
||||
m_bStopped = true;
|
||||
}
|
||||
|
||||
void LyricDisplay::Update( float fDeltaTime )
|
||||
{
|
||||
if( m_bStopped )
|
||||
return;
|
||||
|
||||
ActorFrame::Update( fDeltaTime );
|
||||
|
||||
if( GAMESTATE->m_pCurSong == NULL )
|
||||
return;
|
||||
|
||||
// If the song has changed (in a course), reset.
|
||||
if( GAMESTATE->m_Position.m_fMusicSeconds < m_fLastSecond )
|
||||
Init();
|
||||
m_fLastSecond = GAMESTATE->m_Position.m_fMusicSeconds;
|
||||
|
||||
if( m_iCurLyricNumber >= GAMESTATE->m_pCurSong->m_LyricSegments.size() )
|
||||
return;
|
||||
|
||||
const Song *pSong = GAMESTATE->m_pCurSong;
|
||||
const float fStartTime = (pSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime) - IN_LENGTH.GetValue();
|
||||
|
||||
if( GAMESTATE->m_Position.m_fMusicSeconds < fStartTime )
|
||||
return;
|
||||
|
||||
// Clamp this lyric to the beginning of the next or the end of the music.
|
||||
float fEndTime;
|
||||
if( m_iCurLyricNumber+1 < GAMESTATE->m_pCurSong->m_LyricSegments.size() )
|
||||
fEndTime = pSong->m_LyricSegments[m_iCurLyricNumber+1].m_fStartTime;
|
||||
else
|
||||
fEndTime = pSong->GetLastSecond();
|
||||
|
||||
const float fDistance = fEndTime - pSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime;
|
||||
const float fTweenBufferTime = IN_LENGTH.GetValue() + OUT_LENGTH.GetValue();
|
||||
|
||||
/* If it's negative, two lyrics are so close together that there's no time
|
||||
* to tween properly. Lyrics should never be this brief, anyway, so just
|
||||
* skip it. */
|
||||
float fShowLength = max( fDistance - fTweenBufferTime, 0.0f );
|
||||
|
||||
// Make lyrics show faster for faster song rates.
|
||||
fShowLength /= GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate;
|
||||
|
||||
const LyricSegment &seg = GAMESTATE->m_pCurSong->m_LyricSegments[m_iCurLyricNumber];
|
||||
|
||||
LuaThreadVariable var1( "LyricText", seg.m_sLyric );
|
||||
LuaThreadVariable var2( "LyricDuration", LuaReference::Create(fShowLength) );
|
||||
LuaThreadVariable var3( "LyricColor", LuaReference::Create(seg.m_Color) );
|
||||
|
||||
PlayCommand( "Changed" );
|
||||
|
||||
m_iCurLyricNumber++;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2004 Kevin Slaughter, Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "LyricDisplay.h"
|
||||
#include "ScreenDimensions.h"
|
||||
#include "GameState.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "Song.h"
|
||||
#include "ActorUtil.h"
|
||||
|
||||
static ThemeMetric<float> IN_LENGTH ("LyricDisplay","InLength");
|
||||
static ThemeMetric<float> OUT_LENGTH ("LyricDisplay","OutLength");
|
||||
|
||||
LyricDisplay::LyricDisplay()
|
||||
{
|
||||
m_textLyrics[0].SetName( "LyricBack" );
|
||||
ActorUtil::LoadAllCommands( m_textLyrics[0], "LyricDisplay" );
|
||||
m_textLyrics[0].LoadFromFont( THEME->GetPathF("LyricDisplay","text") );
|
||||
this->AddChild( &m_textLyrics[0] );
|
||||
|
||||
m_textLyrics[1].SetName( "LyricFront" );
|
||||
ActorUtil::LoadAllCommands( m_textLyrics[1], "LyricDisplay" );
|
||||
m_textLyrics[1].LoadFromFont( THEME->GetPathF("LyricDisplay","text") );
|
||||
this->AddChild( &m_textLyrics[1] );
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
void LyricDisplay::Init()
|
||||
{
|
||||
for( int i=0; i<2; i++ )
|
||||
m_textLyrics[i].SetText("");
|
||||
m_iCurLyricNumber = 0;
|
||||
|
||||
m_fLastSecond = -500;
|
||||
m_bStopped = false;
|
||||
}
|
||||
|
||||
void LyricDisplay::Stop() {
|
||||
m_bStopped = true;
|
||||
}
|
||||
|
||||
void LyricDisplay::Update( float fDeltaTime )
|
||||
{
|
||||
if( m_bStopped )
|
||||
return;
|
||||
|
||||
ActorFrame::Update( fDeltaTime );
|
||||
|
||||
if( GAMESTATE->m_pCurSong == nullptr )
|
||||
return;
|
||||
|
||||
// If the song has changed (in a course), reset.
|
||||
if( GAMESTATE->m_Position.m_fMusicSeconds < m_fLastSecond )
|
||||
Init();
|
||||
m_fLastSecond = GAMESTATE->m_Position.m_fMusicSeconds;
|
||||
|
||||
if( m_iCurLyricNumber >= GAMESTATE->m_pCurSong->m_LyricSegments.size() )
|
||||
return;
|
||||
|
||||
const Song *pSong = GAMESTATE->m_pCurSong;
|
||||
const float fStartTime = (pSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime) - IN_LENGTH.GetValue();
|
||||
|
||||
if( GAMESTATE->m_Position.m_fMusicSeconds < fStartTime )
|
||||
return;
|
||||
|
||||
// Clamp this lyric to the beginning of the next or the end of the music.
|
||||
float fEndTime;
|
||||
if( m_iCurLyricNumber+1 < GAMESTATE->m_pCurSong->m_LyricSegments.size() )
|
||||
fEndTime = pSong->m_LyricSegments[m_iCurLyricNumber+1].m_fStartTime;
|
||||
else
|
||||
fEndTime = pSong->GetLastSecond();
|
||||
|
||||
const float fDistance = fEndTime - pSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime;
|
||||
const float fTweenBufferTime = IN_LENGTH.GetValue() + OUT_LENGTH.GetValue();
|
||||
|
||||
/* If it's negative, two lyrics are so close together that there's no time
|
||||
* to tween properly. Lyrics should never be this brief, anyway, so just
|
||||
* skip it. */
|
||||
float fShowLength = max( fDistance - fTweenBufferTime, 0.0f );
|
||||
|
||||
// Make lyrics show faster for faster song rates.
|
||||
fShowLength /= GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate;
|
||||
|
||||
const LyricSegment &seg = GAMESTATE->m_pCurSong->m_LyricSegments[m_iCurLyricNumber];
|
||||
|
||||
LuaThreadVariable var1( "LyricText", seg.m_sLyric );
|
||||
LuaThreadVariable var2( "LyricDuration", LuaReference::Create(fShowLength) );
|
||||
LuaThreadVariable var3( "LyricColor", LuaReference::Create(seg.m_Color) );
|
||||
|
||||
PlayCommand( "Changed" );
|
||||
|
||||
m_iCurLyricNumber++;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2004 Kevin Slaughter, Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -257,7 +257,7 @@ static ThreadedMemoryCardWorker *g_pWorker = NULL;
|
||||
|
||||
MemoryCardManager::MemoryCardManager()
|
||||
{
|
||||
ASSERT( g_pWorker == NULL );
|
||||
ASSERT( g_pWorker == nullptr );
|
||||
|
||||
// Register with Lua.
|
||||
{
|
||||
@@ -608,7 +608,7 @@ bool MemoryCardManager::MountCard( PlayerNumber pn, int iTimeout )
|
||||
m_bMounted[pn] = true;
|
||||
|
||||
RageFileDriver *pDriver = FILEMAN->GetFileDriver( MEM_CARD_MOUNT_POINT_INTERNAL[pn] );
|
||||
if( pDriver == NULL )
|
||||
if( pDriver == nullptr )
|
||||
{
|
||||
LOG->Warn( "FILEMAN->GetFileDriver(%s) failed", MEM_CARD_MOUNT_POINT_INTERNAL[pn].c_str() );
|
||||
return true;
|
||||
|
||||
@@ -32,7 +32,7 @@ void MeterDisplay::LoadFromNode( const XNode* pNode )
|
||||
LOG->Trace( "MeterDisplay::LoadFromNode(%s)", ActorUtil::GetWhere(pNode).c_str() );
|
||||
|
||||
const XNode *pStream = pNode->GetChild( "Stream" );
|
||||
if( pStream == NULL )
|
||||
if( pStream == nullptr )
|
||||
RageException::Throw( "%s: MeterDisplay: missing the \"Stream\" attribute", ActorUtil::GetWhere(pNode).c_str() );
|
||||
m_sprStream.LoadActorFromNode( pStream, this );
|
||||
this->AddChild( m_sprStream );
|
||||
|
||||
+8
-8
@@ -79,7 +79,7 @@ void Model::LoadPieces( const RString &sMeshesPath, const RString &sMaterialsPat
|
||||
// TRICKY: Load materials before geometry so we can figure out whether the materials require normals.
|
||||
LoadMaterialsFromMilkshapeAscii( sMaterialsPath );
|
||||
|
||||
ASSERT( m_pGeometry == NULL );
|
||||
ASSERT( m_pGeometry == nullptr );
|
||||
m_pGeometry = MODELMAN->LoadMilkshapeAscii( sMeshesPath, this->MaterialsNeedNormals() );
|
||||
|
||||
// Validate material indices.
|
||||
@@ -284,7 +284,7 @@ bool Model::LoadMilkshapeAsciiBones( const RString &sAniName, const RString &sPa
|
||||
|
||||
bool Model::EarlyAbortDraw() const
|
||||
{
|
||||
return m_pGeometry == NULL || m_pGeometry->m_Meshes.empty();
|
||||
return m_pGeometry == nullptr || m_pGeometry->m_Meshes.empty();
|
||||
}
|
||||
|
||||
void Model::DrawCelShaded()
|
||||
@@ -567,7 +567,7 @@ void Model::SetPosition( float fSeconds )
|
||||
|
||||
void Model::AdvanceFrame( float fDeltaTime )
|
||||
{
|
||||
if( m_pGeometry == NULL ||
|
||||
if( m_pGeometry == nullptr ||
|
||||
m_pGeometry->m_Meshes.empty() ||
|
||||
!m_pCurAnimation )
|
||||
{
|
||||
@@ -625,9 +625,9 @@ void Model::SetBones( const msAnimation* pAnimation, float fFrame, vector<myBone
|
||||
const float s = SCALE( fFrame, pLastPositionKey->fTime, pThisPositionKey->fTime, 0, 1 );
|
||||
vPos = pLastPositionKey->Position + (pThisPositionKey->Position - pLastPositionKey->Position) * s;
|
||||
}
|
||||
else if( pLastPositionKey == NULL )
|
||||
else if( pLastPositionKey == nullptr )
|
||||
vPos = pThisPositionKey->Position;
|
||||
else if( pThisPositionKey == NULL )
|
||||
else if( pThisPositionKey == nullptr )
|
||||
vPos = pLastPositionKey->Position;
|
||||
|
||||
// search for the adjacent rotation keys
|
||||
@@ -649,11 +649,11 @@ void Model::SetBones( const msAnimation* pAnimation, float fFrame, vector<myBone
|
||||
const float s = SCALE( fFrame, pLastRotationKey->fTime, pThisRotationKey->fTime, 0, 1 );
|
||||
RageQuatSlerp( &vRot, pLastRotationKey->Rotation, pThisRotationKey->Rotation, s );
|
||||
}
|
||||
else if( pLastRotationKey == NULL )
|
||||
else if( pLastRotationKey == nullptr )
|
||||
{
|
||||
vRot = pThisRotationKey->Rotation;
|
||||
}
|
||||
else if( pThisRotationKey == NULL )
|
||||
else if( pThisRotationKey == nullptr )
|
||||
{
|
||||
vRot = pLastRotationKey->Rotation;
|
||||
}
|
||||
@@ -678,7 +678,7 @@ void Model::SetBones( const msAnimation* pAnimation, float fFrame, vector<myBone
|
||||
|
||||
void Model::UpdateTempGeometry()
|
||||
{
|
||||
if( m_pGeometry == NULL || m_pTempGeometry == NULL )
|
||||
if( m_pGeometry == nullptr || m_pTempGeometry == nullptr )
|
||||
return;
|
||||
|
||||
for( unsigned i = 0; i < m_pGeometry->m_Meshes.size(); ++i )
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ void AnimatedTexture::Load( const RString &sTexOrIniPath )
|
||||
RageException::Throw( "Error reading \"%s\": %s", sTexOrIniPath.c_str(), ini.GetError().c_str() );
|
||||
|
||||
const XNode* pAnimatedTexture = ini.GetChild("AnimatedTexture");
|
||||
if( pAnimatedTexture == NULL )
|
||||
if( pAnimatedTexture == nullptr )
|
||||
RageException::Throw( "The animated texture file \"%s\" doesn't contain a section called \"AnimatedTexture\".", sTexOrIniPath.c_str() );
|
||||
|
||||
pAnimatedTexture->GetAttrValue( "TexVelocityX", m_vTexVelocity.x );
|
||||
|
||||
+2
-2
@@ -298,7 +298,7 @@ bool MusicWheel::SelectSection( const RString & SectionName )
|
||||
|
||||
bool MusicWheel::SelectSong( const Song *p )
|
||||
{
|
||||
if( p == NULL )
|
||||
if( p == nullptr )
|
||||
return false;
|
||||
|
||||
unsigned i;
|
||||
@@ -326,7 +326,7 @@ bool MusicWheel::SelectSong( const Song *p )
|
||||
|
||||
bool MusicWheel::SelectCourse( const Course *p )
|
||||
{
|
||||
if( p == NULL )
|
||||
if( p == nullptr )
|
||||
return false;
|
||||
|
||||
unsigned i;
|
||||
|
||||
@@ -145,7 +145,7 @@ MusicWheelItem::MusicWheelItem( const MusicWheelItem &cpy ):
|
||||
|
||||
FOREACH_ENUM( MusicWheelItemType, i )
|
||||
{
|
||||
if( cpy.m_pText[i] == NULL )
|
||||
if( cpy.m_pText[i] == nullptr )
|
||||
{
|
||||
m_pText[i] = NULL;
|
||||
}
|
||||
@@ -307,13 +307,13 @@ void MusicWheelItem::RefreshGrades()
|
||||
{
|
||||
const MusicWheelItemData *pWID = dynamic_cast<const MusicWheelItemData*>( m_pData );
|
||||
|
||||
if( pWID == NULL )
|
||||
if( pWID == nullptr )
|
||||
return; // LoadFromWheelItemData() hasn't been called yet.
|
||||
FOREACH_HumanPlayer( p )
|
||||
{
|
||||
m_pGradeDisplay[p]->SetVisible( false );
|
||||
|
||||
if( pWID->m_pSong == NULL && pWID->m_pCourse == NULL )
|
||||
if( pWID->m_pSong == nullptr && pWID->m_pCourse == nullptr )
|
||||
continue;
|
||||
|
||||
Difficulty dc;
|
||||
|
||||
+1
-1
@@ -366,7 +366,7 @@ bool NoteData::IsHoldHeadOrBodyAtRow( int iTrack, int iRow, int *pHeadRow ) cons
|
||||
bool NoteData::IsHoldNoteAtRow( int iTrack, int iRow, int *pHeadRow ) const
|
||||
{
|
||||
int iDummy;
|
||||
if( pHeadRow == NULL )
|
||||
if( pHeadRow == nullptr )
|
||||
pHeadRow = &iDummy;
|
||||
|
||||
/* Starting at iRow, search upwards. If we find a TapNote::hold_head, we're within
|
||||
|
||||
@@ -453,7 +453,7 @@ void NoteDataUtil::SplitCompositeNoteData( const NoteData &in, vector<NoteData>
|
||||
Hopefully this hack can be removed soon. -- Jason "Wolfman2000" Felds
|
||||
*/
|
||||
const Style *curStyle = GAMESTATE->GetCurrentStyle();
|
||||
if( (curStyle == NULL || curStyle->m_StyleType == StyleType_TwoPlayersSharedSides )
|
||||
if( (curStyle == nullptr || curStyle->m_StyleType == StyleType_TwoPlayersSharedSides )
|
||||
&& int( tn.pn ) > NUM_PlayerNumber )
|
||||
{
|
||||
tn.pn = PLAYER_1;
|
||||
|
||||
+1
-1
@@ -368,7 +368,7 @@ void NoteField::DrawBoard( int iDrawDistanceAfterTargetsPixels, int iDrawDistanc
|
||||
|
||||
// todo: make this an AutoActor instead? -aj
|
||||
Sprite *pSprite = dynamic_cast<Sprite *>( (Actor*)m_sprBoard );
|
||||
if( pSprite == NULL )
|
||||
if( pSprite == nullptr )
|
||||
RageException::Throw( "Board must be a Sprite" );
|
||||
|
||||
RectF rect = *pSprite->GetCurrentTextureCoordRect();
|
||||
|
||||
@@ -407,7 +407,7 @@ Actor *NoteSkinManager::LoadActor( const RString &sButton, const RString &sEleme
|
||||
}
|
||||
|
||||
auto_ptr<XNode> pNode( XmlFileUtil::XNodeFromTable(L) );
|
||||
if( pNode.get() == NULL )
|
||||
if( pNode.get() == nullptr )
|
||||
{
|
||||
// XNode will warn about the error
|
||||
return new Actor;
|
||||
@@ -421,7 +421,7 @@ Actor *NoteSkinManager::LoadActor( const RString &sButton, const RString &sEleme
|
||||
{
|
||||
// Make sure pActor is a Sprite (or something derived from Sprite).
|
||||
Sprite *pSprite = dynamic_cast<Sprite *>( pRet );
|
||||
if( pSprite == NULL )
|
||||
if( pSprite == nullptr )
|
||||
LOG->Warn( "%s: %s %s must be a Sprite", m_sCurrentNoteSkin.c_str(), sButton.c_str(), sElement.c_str() );
|
||||
}
|
||||
|
||||
|
||||
@@ -992,7 +992,7 @@ bool SMLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath
|
||||
sSongFullTitle.Replace( '\\', '/' );
|
||||
|
||||
pSong = SONGMAN->FindSong( sSongFullTitle );
|
||||
if( pSong == NULL )
|
||||
if( pSong == nullptr )
|
||||
{
|
||||
LOG->UserLog( "Edit file", sEditFilePath, "requires a song \"%s\" that isn't present.", sSongFullTitle.c_str() );
|
||||
return false;
|
||||
@@ -1007,7 +1007,7 @@ bool SMLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath
|
||||
|
||||
else if( sValueName=="NOTES" )
|
||||
{
|
||||
if( pSong == NULL )
|
||||
if( pSong == nullptr )
|
||||
{
|
||||
LOG->UserLog( "Edit file", sEditFilePath, "doesn't have a #SONG tag preceeding the first #NOTES tag." );
|
||||
return false;
|
||||
|
||||
@@ -868,7 +868,7 @@ bool SSCLoader::LoadEditFromMsd(const MsdFile &msd,
|
||||
sSongFullTitle.Replace( '\\', '/' );
|
||||
|
||||
pSong = SONGMAN->FindSong( sSongFullTitle );
|
||||
if( pSong == NULL )
|
||||
if( pSong == nullptr )
|
||||
{
|
||||
LOG->UserLog("Edit file",
|
||||
sEditFilePath,
|
||||
@@ -1005,7 +1005,7 @@ bool SSCLoader::LoadEditFromMsd(const MsdFile &msd,
|
||||
}
|
||||
else if( sValueName=="NOTES" )
|
||||
{
|
||||
if( pSong == NULL )
|
||||
if( pSong == nullptr )
|
||||
{
|
||||
LOG->UserLog("Edit file",
|
||||
sEditFilePath,
|
||||
|
||||
+1
-1
@@ -496,7 +496,7 @@ void OptionRow::PositionUnderlines( PlayerNumber pn )
|
||||
void OptionRow::PositionIcons( PlayerNumber pn )
|
||||
{
|
||||
ModIcon *pIcon = m_ModIcons[pn];
|
||||
if( pIcon == NULL )
|
||||
if( pIcon == nullptr )
|
||||
return;
|
||||
|
||||
pIcon->SetX( m_pParentType->MOD_ICON_X.GetValue(pn) );
|
||||
|
||||
@@ -782,7 +782,7 @@ class OptionRowHandlerListSongsInCurrentSongGroup: public OptionRowHandlerList
|
||||
{
|
||||
const vector<Song*> &vpSongs = SONGMAN->GetSongs( GAMESTATE->m_sPreferredSongGroup );
|
||||
|
||||
if( GAMESTATE->m_pCurSong == NULL )
|
||||
if( GAMESTATE->m_pCurSong == nullptr )
|
||||
GAMESTATE->m_pCurSong.Set( vpSongs[0] );
|
||||
|
||||
m_Def.m_sName = "SongsInCurrentSongGroup";
|
||||
@@ -873,7 +873,7 @@ public:
|
||||
lua_pushstring( L, "Name" );
|
||||
lua_gettable( L, -2 );
|
||||
const char *pStr = lua_tostring( L, -1 );
|
||||
if( pStr == NULL )
|
||||
if( pStr == nullptr )
|
||||
RageException::Throw( "\"%s\" \"Name\" entry is not a string.", sLuaFunction.c_str() );
|
||||
m_Def.m_sName = pStr;
|
||||
lua_pop( L, 1 );
|
||||
@@ -891,7 +891,7 @@ public:
|
||||
lua_pushstring( L, "LayoutType" );
|
||||
lua_gettable( L, -2 );
|
||||
pStr = lua_tostring( L, -1 );
|
||||
if( pStr == NULL )
|
||||
if( pStr == nullptr )
|
||||
RageException::Throw( "\"%s\" \"LayoutType\" entry is not a string.", sLuaFunction.c_str() );
|
||||
m_Def.m_layoutType = StringToLayoutType( pStr );
|
||||
ASSERT( m_Def.m_layoutType != LayoutType_Invalid );
|
||||
@@ -900,7 +900,7 @@ public:
|
||||
lua_pushstring( L, "SelectType" );
|
||||
lua_gettable( L, -2 );
|
||||
pStr = lua_tostring( L, -1 );
|
||||
if( pStr == NULL )
|
||||
if( pStr == nullptr )
|
||||
RageException::Throw( "\"%s\" \"SelectType\" entry is not a string.", sLuaFunction.c_str() );
|
||||
m_Def.m_selectType = StringToSelectType( pStr );
|
||||
ASSERT( m_Def.m_selectType != SelectType_Invalid );
|
||||
@@ -917,7 +917,7 @@ public:
|
||||
{
|
||||
// `key' is at index -2 and `value' at index -1
|
||||
const char *pValue = lua_tostring( L, -1 );
|
||||
if( pValue == NULL )
|
||||
if( pValue == nullptr )
|
||||
RageException::Throw( "\"%s\" Column entry is not a string.", sLuaFunction.c_str() );
|
||||
// LOG->Trace( "'%s'", pValue);
|
||||
|
||||
@@ -949,7 +949,7 @@ public:
|
||||
{
|
||||
// `key' is at index -2 and `value' at index -1
|
||||
const char *pValue = lua_tostring( L, -1 );
|
||||
if( pValue == NULL )
|
||||
if( pValue == nullptr )
|
||||
RageException::Throw( "\"%s\" Column entry is not a string.", sLuaFunction.c_str() );
|
||||
LOG->Trace( "Found ReloadRowMessage '%s'", pValue);
|
||||
|
||||
@@ -1116,7 +1116,7 @@ public:
|
||||
m_Def.m_bOneChoiceForAllPlayers = true;
|
||||
|
||||
ConfOption *pConfOption = ConfOption::Find( sParam );
|
||||
if( pConfOption == NULL )
|
||||
if( pConfOption == nullptr )
|
||||
{
|
||||
LOG->Warn( "Invalid Conf type \"%s\"", sParam.c_str() );
|
||||
pConfOption = ConfOption::Find( "Invalid" );
|
||||
|
||||
+2
-2
@@ -47,7 +47,7 @@ void OptionListRow::SetFromHandler( const OptionRowHandler *pHandler )
|
||||
this->FinishTweening();
|
||||
this->RemoveAllChildren();
|
||||
|
||||
if( pHandler == NULL )
|
||||
if( pHandler == nullptr )
|
||||
return;
|
||||
|
||||
int iNum = max( pHandler->m_Def.m_vsChoices.size(), m_Text.size() )+1;
|
||||
@@ -217,7 +217,7 @@ void OptionsList::Load( RString sType, PlayerNumber pn )
|
||||
ParseCommands( sRowCommands, cmds );
|
||||
|
||||
OptionRowHandler *pHand = OptionRowHandlerUtil::Make( cmds );
|
||||
if( pHand == NULL )
|
||||
if( pHand == nullptr )
|
||||
RageException::Throw( "Invalid OptionRowHandler '%s' in %s::Line%s", cmds.GetOriginalCommandString().c_str(), m_sName.c_str(), sLineName.c_str() );
|
||||
|
||||
m_Rows[sLineName] = pHand;
|
||||
|
||||
@@ -41,7 +41,7 @@ void PercentageDisplay::LoadFromNode( const XNode* pNode )
|
||||
}
|
||||
|
||||
const XNode *pChild = pNode->GetChild( "Percent" );
|
||||
if( pChild == NULL )
|
||||
if( pChild == nullptr )
|
||||
RageException::Throw( "%s: PercentageDisplay: missing the node \"Percent\"", ActorUtil::GetWhere(pNode).c_str() );
|
||||
m_textPercent.LoadFromNode( pChild );
|
||||
this->AddChild( &m_textPercent );
|
||||
|
||||
+1
-1
@@ -633,7 +633,7 @@ void Player::Load()
|
||||
PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
|
||||
|
||||
bool bOniDead = GAMESTATE->m_SongOptions.GetStage().m_LifeType == SongOptions::LIFE_BATTERY &&
|
||||
(m_pPlayerStageStats == NULL || m_pPlayerStageStats->m_bFailed);
|
||||
(m_pPlayerStageStats == nullptr || m_pPlayerStageStats->m_bFailed);
|
||||
|
||||
/* The editor reuses Players ... so we really need to make sure everything
|
||||
* is reset and not tweening. Perhaps ActorFrame should recurse to subactors;
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ void PlayerAI::InitFromDisk()
|
||||
{
|
||||
RString sKey = ssprintf("Skill%d", i);
|
||||
XNode* pNode = ini.GetChild(sKey);
|
||||
if( pNode == NULL )
|
||||
if( pNode == nullptr )
|
||||
RageException::Throw( "AI.ini: \"%s\" doesn't exist.", sKey.c_str() );
|
||||
|
||||
TapScoreDistribution& dist = g_Distributions[i];
|
||||
|
||||
+1
-1
@@ -200,7 +200,7 @@ const SongPosition &PlayerState::GetDisplayedPosition() const
|
||||
const TimingData &PlayerState::GetDisplayedTiming() const
|
||||
{
|
||||
Steps *steps = GAMESTATE->m_pCurSteps[m_PlayerNumber];
|
||||
if( steps == NULL )
|
||||
if( steps == nullptr )
|
||||
return GAMESTATE->m_pCurSong->m_SongTiming;
|
||||
return *steps->GetTimingData();
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ void IPreference::SavePrefsToNode( XNode* pNode )
|
||||
|
||||
void IPreference::ReadAllDefaultsFromNode( const XNode* pNode )
|
||||
{
|
||||
if( pNode == NULL )
|
||||
if( pNode == nullptr )
|
||||
return;
|
||||
for (IPreference *p : *m_Subscribers.m_pSubscribers)
|
||||
p->ReadDefaultFrom( pNode );
|
||||
|
||||
@@ -428,7 +428,7 @@ void PrefsManager::ReadPrefsFromIni( const IniFile &ini, const RString &sSection
|
||||
|
||||
/*
|
||||
IPreference *pPref = PREFSMAN->GetPreferenceByName( *sName );
|
||||
if( pPref == NULL )
|
||||
if( pPref == nullptr )
|
||||
{
|
||||
LOG->Warn( "Unknown preference in [%s]: %s", sClassName.c_str(), sName->c_str() );
|
||||
continue;
|
||||
@@ -495,7 +495,7 @@ void PrefsManager::SavePrefsToIni( IniFile &ini )
|
||||
StoreGamePrefs();
|
||||
|
||||
XNode* pNode = ini.GetChild( "Options" );
|
||||
if( pNode == NULL )
|
||||
if( pNode == nullptr )
|
||||
pNode = ini.AppendChild( "Options" );
|
||||
IPreference::SavePrefsToNode( pNode );
|
||||
|
||||
@@ -536,7 +536,7 @@ public:
|
||||
{
|
||||
RString sName = SArg(1);
|
||||
IPreference *pPref = IPreference::GetPreferenceByName( sName );
|
||||
if( pPref == NULL )
|
||||
if( pPref == nullptr )
|
||||
{
|
||||
LOG->Warn( "GetPreference: unknown preference \"%s\"", sName.c_str() );
|
||||
lua_pushnil( L );
|
||||
@@ -551,7 +551,7 @@ public:
|
||||
RString sName = SArg(1);
|
||||
|
||||
IPreference *pPref = IPreference::GetPreferenceByName( sName );
|
||||
if( pPref == NULL )
|
||||
if( pPref == nullptr )
|
||||
{
|
||||
LOG->Warn( "SetPreference: unknown preference \"%s\"", sName.c_str() );
|
||||
return 0;
|
||||
@@ -566,7 +566,7 @@ public:
|
||||
RString sName = SArg(1);
|
||||
|
||||
IPreference *pPref = IPreference::GetPreferenceByName( sName );
|
||||
if( pPref == NULL )
|
||||
if( pPref == nullptr )
|
||||
{
|
||||
LOG->Warn( "SetPreferenceToDefault: unknown preference \"%s\"", sName.c_str() );
|
||||
return 0;
|
||||
@@ -581,7 +581,7 @@ public:
|
||||
RString sName = SArg(1);
|
||||
|
||||
IPreference *pPref = IPreference::GetPreferenceByName( sName );
|
||||
if( pPref == NULL )
|
||||
if( pPref == nullptr )
|
||||
{
|
||||
lua_pushboolean( L, false );
|
||||
return 1;
|
||||
|
||||
+13
-13
@@ -287,7 +287,7 @@ int Profile::GetTotalTrailsWithTopGrade( StepsType st, CourseDifficulty d, Grade
|
||||
|
||||
vector<Trail*> vTrails;
|
||||
Trail* pTrail = pCourse->GetTrail( st, d );
|
||||
if( pTrail == NULL )
|
||||
if( pTrail == nullptr )
|
||||
continue;
|
||||
|
||||
const HighScoreList &hsl = GetCourseHighScoreList( pCourse, pTrail );
|
||||
@@ -347,7 +347,7 @@ float Profile::GetSongsActual( StepsType st, Difficulty dc ) const
|
||||
|
||||
// If the Song isn't loaded on the current machine, then we can't
|
||||
// get radar values to compute dance points.
|
||||
if( pSong == NULL )
|
||||
if( pSong == nullptr )
|
||||
continue;
|
||||
|
||||
if( !pSong->NormallyDisplayed() )
|
||||
@@ -364,7 +364,7 @@ float Profile::GetSongsActual( StepsType st, Difficulty dc ) const
|
||||
|
||||
// If the Steps isn't loaded on the current machine, then we can't
|
||||
// get radar values to compute dance points.
|
||||
if( pSteps == NULL )
|
||||
if( pSteps == nullptr )
|
||||
continue;
|
||||
|
||||
if( pSteps->m_StepsType != st )
|
||||
@@ -426,7 +426,7 @@ float Profile::GetCoursesActual( StepsType st, CourseDifficulty cd ) const
|
||||
for (Course const *c : vpCourses)
|
||||
{
|
||||
Trail *pTrail = c->GetTrail( st, cd );
|
||||
if( pTrail == NULL )
|
||||
if( pTrail == nullptr )
|
||||
continue;
|
||||
|
||||
const HighScoreList& hsl = GetCourseHighScoreList( c, pTrail );
|
||||
@@ -468,7 +468,7 @@ int Profile::GetSongNumTimesPlayed( const Song* pSong ) const
|
||||
int Profile::GetSongNumTimesPlayed( const SongID& songID ) const
|
||||
{
|
||||
const HighScoresForASong *hsSong = GetHighScoresForASong( songID );
|
||||
if( hsSong == NULL )
|
||||
if( hsSong == nullptr )
|
||||
return 0;
|
||||
|
||||
int iTotalNumTimesPlayed = 0;
|
||||
@@ -635,7 +635,7 @@ void Profile::GetGrades( const Song* pSong, StepsType st, int iCounts[NUM_Grade]
|
||||
|
||||
memset( iCounts, 0, sizeof(int)*NUM_Grade );
|
||||
const HighScoresForASong *hsSong = GetHighScoresForASong( songID );
|
||||
if( hsSong == NULL )
|
||||
if( hsSong == nullptr )
|
||||
return;
|
||||
|
||||
FOREACH_ENUM( Grade,g)
|
||||
@@ -689,7 +689,7 @@ int Profile::GetCourseNumTimesPlayed( const Course* pCourse ) const
|
||||
int Profile::GetCourseNumTimesPlayed( const CourseID &courseID ) const
|
||||
{
|
||||
const HighScoresForACourse *hsCourse = GetHighScoresForACourse( courseID );
|
||||
if( hsCourse == NULL )
|
||||
if( hsCourse == nullptr )
|
||||
return 0;
|
||||
|
||||
int iTotalNumTimesPlayed = 0;
|
||||
@@ -802,7 +802,7 @@ ProfileLoadResult Profile::LoadAllFromDir( RString sDir, bool bRequireSignature
|
||||
|
||||
int iError;
|
||||
auto_ptr<RageFileBasic> pFile( FILEMAN->Open(fn, RageFile::READ, iError) );
|
||||
if( pFile.get() == NULL )
|
||||
if( pFile.get() == nullptr )
|
||||
{
|
||||
LOG->Trace( "Error opening %s: %s", fn.c_str(), strerror(iError) );
|
||||
return ProfileLoadResult_FailedTampered;
|
||||
@@ -813,7 +813,7 @@ ProfileLoadResult Profile::LoadAllFromDir( RString sDir, bool bRequireSignature
|
||||
RString sError;
|
||||
uint32_t iCRC32;
|
||||
RageFileObjInflate *pInflate = GunzipFile( pFile.release(), sError, &iCRC32 );
|
||||
if( pInflate == NULL )
|
||||
if( pInflate == nullptr )
|
||||
{
|
||||
LOG->Trace( "Error opening %s: %s", fn.c_str(), sError.c_str() );
|
||||
return ProfileLoadResult_FailedTampered;
|
||||
@@ -1433,7 +1433,7 @@ void Profile::LoadSongScoresFromNode( const XNode* pSongScores )
|
||||
WARN_AND_CONTINUE;
|
||||
|
||||
const XNode *pHighScoreListNode = pSteps->GetChild("HighScoreList");
|
||||
if( pHighScoreListNode == NULL )
|
||||
if( pHighScoreListNode == nullptr )
|
||||
WARN_AND_CONTINUE;
|
||||
|
||||
HighScoreList &hsl = m_SongHighScores[songID].m_StepsHighScores[stepsID].hsl;
|
||||
@@ -1510,7 +1510,7 @@ void Profile::LoadCourseScoresFromNode( const XNode* pCourseScores )
|
||||
// and search for matches of just the file name.
|
||||
{
|
||||
Course *pC = courseID.ToCourse();
|
||||
if( pC == NULL )
|
||||
if( pC == nullptr )
|
||||
{
|
||||
RString sDir, sFName, sExt;
|
||||
splitpath( courseID.GetPath(), sDir, sFName, sExt );
|
||||
@@ -1542,7 +1542,7 @@ void Profile::LoadCourseScoresFromNode( const XNode* pCourseScores )
|
||||
WARN_AND_CONTINUE;
|
||||
|
||||
const XNode *pHighScoreListNode = pTrail->GetChild("HighScoreList");
|
||||
if( pHighScoreListNode == NULL )
|
||||
if( pHighScoreListNode == nullptr )
|
||||
WARN_AND_CONTINUE;
|
||||
|
||||
HighScoreList &hsl = m_CourseHighScores[courseID].m_TrailHighScores[trailID].hsl;
|
||||
@@ -1617,7 +1617,7 @@ void Profile::LoadCategoryScoresFromNode( const XNode* pCategoryScores )
|
||||
WARN_AND_CONTINUE_M( str );
|
||||
|
||||
const XNode *pHighScoreListNode = pRadarCategory->GetChild("HighScoreList");
|
||||
if( pHighScoreListNode == NULL )
|
||||
if( pHighScoreListNode == nullptr )
|
||||
WARN_AND_CONTINUE;
|
||||
|
||||
HighScoreList &hsl = this->GetCategoryHighScoreList( st, rc );
|
||||
|
||||
@@ -195,7 +195,7 @@ bool ProfileManager::LoadLocalProfileFromMachine( PlayerNumber pn )
|
||||
m_bWasLoadedFromMemoryCard[pn] = false;
|
||||
m_bLastLoadWasFromLastGood[pn] = false;
|
||||
|
||||
if( GetLocalProfile(sProfileID) == NULL )
|
||||
if( GetLocalProfile(sProfileID) == nullptr )
|
||||
{
|
||||
m_sProfileDir[pn] = "";
|
||||
return false;
|
||||
@@ -457,7 +457,7 @@ bool ProfileManager::CreateLocalProfile( RString sName, RString &sProfileIDOut )
|
||||
void ProfileManager::AddLocalProfileByID( Profile *pProfile, RString sProfileID )
|
||||
{
|
||||
// make sure this id doesn't already exist
|
||||
ASSERT_M( GetLocalProfile(sProfileID) == NULL,
|
||||
ASSERT_M( GetLocalProfile(sProfileID) == nullptr,
|
||||
ssprintf("creating \"%s\" \"%s\" that already exists",
|
||||
pProfile->m_sDisplayName.c_str(), sProfileID.c_str()) );
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ void RageBitmapTexture::Create()
|
||||
RageSurface *pImg = RageSurfaceUtils::LoadFile( actualID.filename, error );
|
||||
|
||||
/* Tolerate corrupt/unknown images. */
|
||||
if( pImg == NULL )
|
||||
if( pImg == nullptr )
|
||||
{
|
||||
RString sWarning = ssprintf( "RageBitmapTexture: Couldn't load %s: %s", actualID.filename.c_str(), error.c_str() );
|
||||
Dialog::OK( sWarning );
|
||||
|
||||
@@ -344,7 +344,7 @@ D3DFORMAT FindBackBufferType(bool bWindowed, int iBPP)
|
||||
|
||||
RString SetD3DParams( bool &bNewDeviceOut )
|
||||
{
|
||||
if( g_pd3dDevice == NULL ) // device is not yet created. We need to create it
|
||||
if( g_pd3dDevice == nullptr ) // device is not yet created. We need to create it
|
||||
{
|
||||
bNewDeviceOut = true;
|
||||
HRESULT hr = g_pd3d->CreateDevice(
|
||||
@@ -704,7 +704,7 @@ void RageDisplay_D3D::SendCurrentMatrices()
|
||||
// If no texture is set for this texture unit, don't bother setting it up.
|
||||
IDirect3DBaseTexture9* pTexture = NULL;
|
||||
g_pd3dDevice->GetTexture( tu, &pTexture );
|
||||
if( pTexture == NULL )
|
||||
if( pTexture == nullptr )
|
||||
continue;
|
||||
pTexture->Release();
|
||||
|
||||
|
||||
@@ -2228,7 +2228,7 @@ public:
|
||||
void Lock( unsigned iTexHandle, RageSurface *pSurface )
|
||||
{
|
||||
ASSERT( m_iTexHandle == 0 );
|
||||
ASSERT( pSurface->pixels == NULL );
|
||||
ASSERT( pSurface->pixels == nullptr );
|
||||
|
||||
CreateObject();
|
||||
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ bool RageFile::Open( const RString& path, int mode )
|
||||
int error;
|
||||
m_File = FILEMAN->Open( path, mode, error );
|
||||
|
||||
if( m_File == NULL )
|
||||
if( m_File == nullptr )
|
||||
{
|
||||
SetError( strerror(error) );
|
||||
return false;
|
||||
@@ -78,7 +78,7 @@ bool RageFile::Open( const RString& path, int mode )
|
||||
|
||||
void RageFile::Close()
|
||||
{
|
||||
if( m_File == NULL )
|
||||
if( m_File == nullptr )
|
||||
return;
|
||||
delete m_File;
|
||||
if( m_Mode & WRITE )
|
||||
|
||||
@@ -129,7 +129,7 @@ int RageFileObj::Read( void *pBuffer, size_t iBytes )
|
||||
|
||||
/* If buffering is disabled, or the block is bigger than the buffer,
|
||||
* read the remainder of the data directly into the desteination buffer. */
|
||||
if( m_pReadBuffer == NULL || iBytes >= BSIZE )
|
||||
if( m_pReadBuffer == nullptr || iBytes >= BSIZE )
|
||||
{
|
||||
/* We have a lot more to read, so don't waste time copying it into the
|
||||
* buffer. */
|
||||
@@ -204,7 +204,7 @@ int RageFileObj::Read( void *pBuffer, size_t iBytes, int iNmemb )
|
||||
/* Empty the write buffer to disk. Return -1 on error, 0 on success. */
|
||||
int RageFileObj::EmptyWriteBuf()
|
||||
{
|
||||
if( m_pWriteBuffer == NULL )
|
||||
if( m_pWriteBuffer == nullptr )
|
||||
return 0;
|
||||
|
||||
if( m_iWriteBufferUsed )
|
||||
@@ -285,13 +285,13 @@ int RageFileObj::Flush()
|
||||
|
||||
void RageFileObj::EnableReadBuffering()
|
||||
{
|
||||
if( m_pReadBuffer == NULL )
|
||||
if( m_pReadBuffer == nullptr )
|
||||
m_pReadBuffer = new char[BSIZE];
|
||||
}
|
||||
|
||||
void RageFileObj::EnableWriteBuffering( int iBytes )
|
||||
{
|
||||
if( m_pWriteBuffer == NULL )
|
||||
if( m_pWriteBuffer == nullptr )
|
||||
{
|
||||
m_pWriteBuffer = new char[iBytes];
|
||||
m_iWriteBufferPos = m_iFilePos;
|
||||
@@ -339,7 +339,7 @@ int RageFileObj::GetLine( RString &sOut )
|
||||
/* Find the end of the block we'll move to out. */
|
||||
char *p = (char *) memchr( m_pReadBuf, '\n', m_iReadBufAvail );
|
||||
bool bReAddCR = false;
|
||||
if( p == NULL )
|
||||
if( p == nullptr )
|
||||
{
|
||||
/* Hack: If the last character of the buffer is \r, then it's likely that an
|
||||
* \r\n has been split across buffers. Move everything else, then move the
|
||||
|
||||
@@ -522,7 +522,7 @@ bool GunzipString( const RString &sIn, RString &sOut, RString &sError )
|
||||
|
||||
uint32_t iCRC32;
|
||||
RageFileBasic *pFile = GunzipFile( mem, sError, &iCRC32 );
|
||||
if( pFile == NULL )
|
||||
if( pFile == nullptr )
|
||||
return false;
|
||||
|
||||
pFile->Read( sOut );
|
||||
|
||||
+469
-469
@@ -1,469 +1,469 @@
|
||||
#include "global.h"
|
||||
#include "RageFileDriverDirect.h"
|
||||
#include "RageFileDriverDirectHelpers.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageUtil_FileDB.h"
|
||||
#include "RageLog.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !defined(WIN32)
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#endif // !defined(WIN32)
|
||||
|
||||
/* Direct filesystem access: */
|
||||
static struct FileDriverEntry_DIR: public FileDriverEntry
|
||||
{
|
||||
FileDriverEntry_DIR(): FileDriverEntry( "DIR" ) { }
|
||||
RageFileDriver *Create( const RString &sRoot ) const { return new RageFileDriverDirect( sRoot ); }
|
||||
} const g_RegisterDriver;
|
||||
|
||||
/* Direct read-only filesystem access: */
|
||||
static struct FileDriverEntry_DIRRO: public FileDriverEntry
|
||||
{
|
||||
FileDriverEntry_DIRRO(): FileDriverEntry( "DIRRO" ) { }
|
||||
RageFileDriver *Create( const RString &sRoot ) const { return new RageFileDriverDirectReadOnly( sRoot ); }
|
||||
} const g_RegisterDriver2;
|
||||
|
||||
RageFileDriverDirect::RageFileDriverDirect( const RString &sRoot ):
|
||||
RageFileDriver( new DirectFilenameDB(sRoot) )
|
||||
{
|
||||
Remount( sRoot );
|
||||
}
|
||||
|
||||
|
||||
static RString MakeTempFilename( const RString &sPath )
|
||||
{
|
||||
/* "Foo/bar/baz" -> "Foo/bar/new.baz.new". Both prepend and append: we don't
|
||||
* want a wildcard search for the filename to match (foo.txt.new matches foo.txt*),
|
||||
* and we don't want to have the same extension (so "new.foo.sm" doesn't show up
|
||||
* in *.sm). */
|
||||
return Dirname(sPath) + "new." + Basename(sPath) + ".new";
|
||||
}
|
||||
|
||||
static RageFileObjDirect *MakeFileObjDirect( RString sPath, int iMode, int &iError )
|
||||
{
|
||||
int iFD;
|
||||
if( iMode & RageFile::READ )
|
||||
{
|
||||
iFD = DoOpen( sPath, O_BINARY|O_RDONLY, 0666 );
|
||||
|
||||
/* XXX: Windows returns EACCES if we try to open a file on a CDROM that isn't
|
||||
* ready, instead of something like ENODEV. We want to return that case as
|
||||
* ENOENT, but we can't distinguish it from file permission errors. */
|
||||
}
|
||||
else
|
||||
{
|
||||
RString sOut;
|
||||
if( iMode & RageFile::STREAMED )
|
||||
sOut = sPath;
|
||||
else
|
||||
sOut = MakeTempFilename(sPath);
|
||||
|
||||
/* Open a temporary file for writing. */
|
||||
iFD = DoOpen( sOut, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666 );
|
||||
}
|
||||
|
||||
if( iFD == -1 )
|
||||
{
|
||||
iError = errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(UNIX)
|
||||
struct stat st;
|
||||
if( fstat(iFD, &st) != -1 && (st.st_mode & S_IFDIR) )
|
||||
{
|
||||
iError = EISDIR;
|
||||
close( iFD );
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return new RageFileObjDirect( sPath, iFD, iMode );
|
||||
}
|
||||
|
||||
RageFileBasic *RageFileDriverDirect::Open( const RString &sPath_, int iMode, int &iError )
|
||||
{
|
||||
RString sPath = sPath_;
|
||||
ASSERT( sPath.size() && sPath[0] == '/' );
|
||||
|
||||
/* This partially resolves. For example, if "abc/def" exists, and we're opening
|
||||
* "ABC/DEF/GHI/jkl/mno", this will resolve it to "abc/def/GHI/jkl/mno"; we'll
|
||||
* create the missing parts below. */
|
||||
FDB->ResolvePath( sPath );
|
||||
|
||||
if( iMode & RageFile::WRITE )
|
||||
{
|
||||
const RString dir = Dirname(sPath);
|
||||
if( this->GetFileType(dir) != RageFileManager::TYPE_DIR )
|
||||
CreateDirectories( m_sRoot + dir );
|
||||
}
|
||||
|
||||
return MakeFileObjDirect( m_sRoot + sPath, iMode, iError );
|
||||
}
|
||||
|
||||
bool RageFileDriverDirect::Move( const RString &sOldPath_, const RString &sNewPath_ )
|
||||
{
|
||||
RString sOldPath = sOldPath_;
|
||||
RString sNewPath = sNewPath_;
|
||||
FDB->ResolvePath( sOldPath );
|
||||
FDB->ResolvePath( sNewPath );
|
||||
|
||||
if( this->GetFileType(sOldPath) == RageFileManager::TYPE_NONE )
|
||||
return false;
|
||||
|
||||
{
|
||||
const RString sDir = Dirname(sNewPath);
|
||||
CreateDirectories( m_sRoot + sDir );
|
||||
}
|
||||
int size = FDB->GetFileSize( sOldPath );
|
||||
int hash = FDB->GetFileHash( sOldPath );
|
||||
TRACE( ssprintf("rename \"%s\" -> \"%s\"", (m_sRoot + sOldPath).c_str(), (m_sRoot + sNewPath).c_str()) );
|
||||
if( DoRename(m_sRoot + sOldPath, m_sRoot + sNewPath) == -1 )
|
||||
{
|
||||
WARN( ssprintf("rename(%s,%s) failed: %s", (m_sRoot + sOldPath).c_str(), (m_sRoot + sNewPath).c_str(), strerror(errno)) );
|
||||
return false;
|
||||
}
|
||||
|
||||
FDB->DelFile( sOldPath );
|
||||
FDB->AddFile( sNewPath, size, hash, NULL );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RageFileDriverDirect::Remove( const RString &sPath_ )
|
||||
{
|
||||
RString sPath = sPath_;
|
||||
FDB->ResolvePath( sPath );
|
||||
RageFileManager::FileType type = this->GetFileType(sPath);
|
||||
switch( type )
|
||||
{
|
||||
case RageFileManager::TYPE_FILE:
|
||||
TRACE( ssprintf("remove '%s'", (m_sRoot + sPath).c_str()) );
|
||||
if( DoRemove(m_sRoot + sPath) == -1 )
|
||||
{
|
||||
WARN( ssprintf("remove(%s) failed: %s", (m_sRoot + sPath).c_str(), strerror(errno)) );
|
||||
return false;
|
||||
}
|
||||
FDB->DelFile( sPath );
|
||||
return true;
|
||||
|
||||
case RageFileManager::TYPE_DIR:
|
||||
TRACE( ssprintf("rmdir '%s'", (m_sRoot + sPath).c_str()) );
|
||||
if( DoRmdir(m_sRoot + sPath) == -1 )
|
||||
{
|
||||
WARN( ssprintf("rmdir(%s) failed: %s", (m_sRoot + sPath).c_str(), strerror(errno)) );
|
||||
return false;
|
||||
}
|
||||
FDB->DelFile( sPath );
|
||||
return true;
|
||||
|
||||
case RageFileManager::TYPE_NONE:
|
||||
return false;
|
||||
|
||||
default:
|
||||
FAIL_M(ssprintf("Invalid FileType: %i", type));
|
||||
}
|
||||
}
|
||||
|
||||
RageFileObjDirect *RageFileObjDirect::Copy() const
|
||||
{
|
||||
int iErr;
|
||||
RageFileObjDirect *ret = MakeFileObjDirect( m_sPath, m_iMode, iErr );
|
||||
|
||||
if( ret == NULL )
|
||||
RageException::Throw( "Couldn't reopen \"%s\": %s", m_sPath.c_str(), strerror(iErr) );
|
||||
|
||||
ret->Seek( (int)lseek( m_iFD, 0, SEEK_CUR ) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool RageFileDriverDirect::Remount( const RString &sPath )
|
||||
{
|
||||
m_sRoot = sPath;
|
||||
((DirectFilenameDB *) FDB)->SetRoot( sPath );
|
||||
|
||||
/* If the root path doesn't exist, create it. */
|
||||
CreateDirectories( m_sRoot );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The DIRRO driver is just like DIR, except writes are disallowed. */
|
||||
RageFileDriverDirectReadOnly::RageFileDriverDirectReadOnly( const RString &sRoot ):
|
||||
RageFileDriverDirect( sRoot ) { }
|
||||
RageFileBasic *RageFileDriverDirectReadOnly::Open( const RString &sPath, int iMode, int &iError )
|
||||
{
|
||||
if( iMode & RageFile::WRITE )
|
||||
{
|
||||
iError = EROFS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return RageFileDriverDirect::Open( sPath, iMode, iError );
|
||||
}
|
||||
bool RageFileDriverDirectReadOnly::Move( const RString & /* sOldPath */, const RString & /* sNewPath */ ) { return false; }
|
||||
bool RageFileDriverDirectReadOnly::Remove( const RString & /* sPath */ ) { return false; }
|
||||
|
||||
static const unsigned int BUFSIZE = 1024*64;
|
||||
RageFileObjDirect::RageFileObjDirect( const RString &sPath, int iFD, int iMode )
|
||||
{
|
||||
m_sPath = sPath;
|
||||
m_iFD = iFD;
|
||||
m_bWriteFailed = false;
|
||||
m_iMode = iMode;
|
||||
ASSERT( m_iFD != -1 );
|
||||
|
||||
if( m_iMode & RageFile::WRITE )
|
||||
this->EnableWriteBuffering( BUFSIZE );
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
#if !defined(WIN32)
|
||||
bool FlushDir( RString sPath, RString &sError )
|
||||
{
|
||||
/* Wait for the directory to be flushed. */
|
||||
int dirfd = open( sPath, O_RDONLY );
|
||||
if( dirfd == -1 )
|
||||
{
|
||||
sError = strerror(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( fsync( dirfd ) == -1 )
|
||||
{
|
||||
sError = strerror(errno);
|
||||
close( dirfd );
|
||||
return false;
|
||||
}
|
||||
|
||||
close( dirfd );
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool FlushDir( RString /* sPath */, RString & /* sError */ )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool RageFileObjDirect::FinalFlush()
|
||||
{
|
||||
if( !(m_iMode & RageFile::WRITE) )
|
||||
return true;
|
||||
|
||||
/* Flush the output buffer. */
|
||||
if( Flush() == -1 )
|
||||
return false;
|
||||
|
||||
/* Only do the rest of the flushes if SLOW_FLUSH is enabled. */
|
||||
if( !(m_iMode & RageFile::SLOW_FLUSH) )
|
||||
return true;
|
||||
|
||||
/* Force a kernel buffer flush. */
|
||||
if( fsync( m_iFD ) == -1 )
|
||||
{
|
||||
WARN( ssprintf("Error synchronizing %s: %s", this->m_sPath.c_str(), strerror(errno)) );
|
||||
SetError( strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
RString sError;
|
||||
if( !FlushDir(Dirname(m_sPath), sError) )
|
||||
{
|
||||
WARN( ssprintf("Error synchronizing fsync(%s dir): %s", this->m_sPath.c_str(), sError.c_str()) );
|
||||
SetError( sError );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RageFileObjDirect::~RageFileObjDirect()
|
||||
{
|
||||
bool bFailed = !FinalFlush();
|
||||
|
||||
if( m_iFD != -1 )
|
||||
{
|
||||
if( close( m_iFD ) == -1 )
|
||||
{
|
||||
WARN( ssprintf("Error closing %s: %s", this->m_sPath.c_str(), strerror(errno)) );
|
||||
SetError( strerror(errno) );
|
||||
bFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( !(m_iMode & RageFile::WRITE) || (m_iMode & RageFile::STREAMED) )
|
||||
return;
|
||||
|
||||
/* We now have path written to MakeTempFilename(m_sPath).
|
||||
* Rename the temporary file over the real path. */
|
||||
|
||||
do
|
||||
{
|
||||
if( bFailed || WriteFailed() )
|
||||
break;
|
||||
|
||||
/* We now have path written to MakeTempFilename(m_sPath). Rename the
|
||||
* temporary file over the real path. This should be an atomic operation
|
||||
* with a journalling filesystem. That is, there should be no
|
||||
* intermediate state a JFS might restore the file we're writing (in the
|
||||
* case of a crash/powerdown) to an empty or partial file. */
|
||||
|
||||
RString sOldPath = MakeTempFilename(m_sPath);
|
||||
RString sNewPath = m_sPath;
|
||||
|
||||
#if defined(WIN32)
|
||||
if( WinMoveFile(DoPathReplace(sOldPath), DoPathReplace(sNewPath)) )
|
||||
return;
|
||||
|
||||
/* We failed. */
|
||||
int err = GetLastError();
|
||||
const RString error = werr_ssprintf( err, "Error renaming \"%s\" to \"%s\"", sOldPath.c_str(), sNewPath.c_str() );
|
||||
WARN( ssprintf("%s", error.c_str()) );
|
||||
SetError( error );
|
||||
break;
|
||||
#else
|
||||
if( rename( sOldPath, sNewPath ) == -1 )
|
||||
{
|
||||
WARN( ssprintf("Error renaming \"%s\" to \"%s\": %s",
|
||||
sOldPath.c_str(), sNewPath.c_str(), strerror(errno)) );
|
||||
SetError( strerror(errno) );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( m_iMode & RageFile::SLOW_FLUSH )
|
||||
{
|
||||
RString sError;
|
||||
if( !FlushDir(Dirname(m_sPath), sError) )
|
||||
{
|
||||
WARN( ssprintf("Error synchronizing fsync(%s dir): %s", this->m_sPath.c_str(), sError.c_str()) );
|
||||
SetError( sError );
|
||||
}
|
||||
}
|
||||
|
||||
// Success.
|
||||
return;
|
||||
#endif
|
||||
} while(0);
|
||||
|
||||
// The write or the rename failed. Delete the incomplete temporary file.
|
||||
DoRemove( MakeTempFilename(m_sPath) );
|
||||
}
|
||||
|
||||
int RageFileObjDirect::ReadInternal( void *pBuf, size_t iBytes )
|
||||
{
|
||||
int iRet = read( m_iFD, pBuf, iBytes );
|
||||
if( iRet == -1 )
|
||||
{
|
||||
SetError( strerror(errno) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return iRet;
|
||||
}
|
||||
|
||||
// write(), but retry a couple times on EINTR.
|
||||
static int RetriedWrite( int iFD, const void *pBuf, size_t iCount )
|
||||
{
|
||||
int iTries = 3, iRet;
|
||||
do
|
||||
{
|
||||
iRet = write( iFD, pBuf, iCount );
|
||||
}
|
||||
while( iRet == -1 && errno == EINTR && iTries-- );
|
||||
|
||||
return iRet;
|
||||
}
|
||||
|
||||
|
||||
int RageFileObjDirect::FlushInternal()
|
||||
{
|
||||
if( WriteFailed() )
|
||||
{
|
||||
SetError( "previous write failed" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RageFileObjDirect::WriteInternal( const void *pBuf, size_t iBytes )
|
||||
{
|
||||
if( WriteFailed() )
|
||||
{
|
||||
SetError( "previous write failed" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The buffer is cleared. If we still don't have space, it's bigger than
|
||||
* the buffer size, so just write it directly. */
|
||||
int iRet = RetriedWrite( m_iFD, pBuf, iBytes );
|
||||
if( iRet == -1 )
|
||||
{
|
||||
SetError( strerror(errno) );
|
||||
m_bWriteFailed = true;
|
||||
return -1;
|
||||
}
|
||||
return iBytes;
|
||||
}
|
||||
|
||||
int RageFileObjDirect::SeekInternal( int iOffset )
|
||||
{
|
||||
return (int)lseek( m_iFD, iOffset, SEEK_SET );
|
||||
}
|
||||
|
||||
int RageFileObjDirect::GetFileSize() const
|
||||
{
|
||||
const int iOldPos = (int)lseek( m_iFD, 0, SEEK_CUR );
|
||||
ASSERT_M( iOldPos != -1, ssprintf("\"%s\": %s", m_sPath.c_str(), strerror(errno)) );
|
||||
const int iRet = (int)lseek( m_iFD, 0, SEEK_END );
|
||||
ASSERT_M( iRet != -1, ssprintf("\"%s\": %s", m_sPath.c_str(), strerror(errno)) );
|
||||
lseek( m_iFD, iOldPos, SEEK_SET );
|
||||
return iRet;
|
||||
}
|
||||
|
||||
int RageFileObjDirect::GetFD()
|
||||
{
|
||||
return m_iFD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003-2004 Glenn Maynard, 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.
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "RageFileDriverDirect.h"
|
||||
#include "RageFileDriverDirectHelpers.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageUtil_FileDB.h"
|
||||
#include "RageLog.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !defined(WIN32)
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#endif // !defined(WIN32)
|
||||
|
||||
/* Direct filesystem access: */
|
||||
static struct FileDriverEntry_DIR: public FileDriverEntry
|
||||
{
|
||||
FileDriverEntry_DIR(): FileDriverEntry( "DIR" ) { }
|
||||
RageFileDriver *Create( const RString &sRoot ) const { return new RageFileDriverDirect( sRoot ); }
|
||||
} const g_RegisterDriver;
|
||||
|
||||
/* Direct read-only filesystem access: */
|
||||
static struct FileDriverEntry_DIRRO: public FileDriverEntry
|
||||
{
|
||||
FileDriverEntry_DIRRO(): FileDriverEntry( "DIRRO" ) { }
|
||||
RageFileDriver *Create( const RString &sRoot ) const { return new RageFileDriverDirectReadOnly( sRoot ); }
|
||||
} const g_RegisterDriver2;
|
||||
|
||||
RageFileDriverDirect::RageFileDriverDirect( const RString &sRoot ):
|
||||
RageFileDriver( new DirectFilenameDB(sRoot) )
|
||||
{
|
||||
Remount( sRoot );
|
||||
}
|
||||
|
||||
|
||||
static RString MakeTempFilename( const RString &sPath )
|
||||
{
|
||||
/* "Foo/bar/baz" -> "Foo/bar/new.baz.new". Both prepend and append: we don't
|
||||
* want a wildcard search for the filename to match (foo.txt.new matches foo.txt*),
|
||||
* and we don't want to have the same extension (so "new.foo.sm" doesn't show up
|
||||
* in *.sm). */
|
||||
return Dirname(sPath) + "new." + Basename(sPath) + ".new";
|
||||
}
|
||||
|
||||
static RageFileObjDirect *MakeFileObjDirect( RString sPath, int iMode, int &iError )
|
||||
{
|
||||
int iFD;
|
||||
if( iMode & RageFile::READ )
|
||||
{
|
||||
iFD = DoOpen( sPath, O_BINARY|O_RDONLY, 0666 );
|
||||
|
||||
/* XXX: Windows returns EACCES if we try to open a file on a CDROM that isn't
|
||||
* ready, instead of something like ENODEV. We want to return that case as
|
||||
* ENOENT, but we can't distinguish it from file permission errors. */
|
||||
}
|
||||
else
|
||||
{
|
||||
RString sOut;
|
||||
if( iMode & RageFile::STREAMED )
|
||||
sOut = sPath;
|
||||
else
|
||||
sOut = MakeTempFilename(sPath);
|
||||
|
||||
/* Open a temporary file for writing. */
|
||||
iFD = DoOpen( sOut, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666 );
|
||||
}
|
||||
|
||||
if( iFD == -1 )
|
||||
{
|
||||
iError = errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(UNIX)
|
||||
struct stat st;
|
||||
if( fstat(iFD, &st) != -1 && (st.st_mode & S_IFDIR) )
|
||||
{
|
||||
iError = EISDIR;
|
||||
close( iFD );
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return new RageFileObjDirect( sPath, iFD, iMode );
|
||||
}
|
||||
|
||||
RageFileBasic *RageFileDriverDirect::Open( const RString &sPath_, int iMode, int &iError )
|
||||
{
|
||||
RString sPath = sPath_;
|
||||
ASSERT( sPath.size() && sPath[0] == '/' );
|
||||
|
||||
/* This partially resolves. For example, if "abc/def" exists, and we're opening
|
||||
* "ABC/DEF/GHI/jkl/mno", this will resolve it to "abc/def/GHI/jkl/mno"; we'll
|
||||
* create the missing parts below. */
|
||||
FDB->ResolvePath( sPath );
|
||||
|
||||
if( iMode & RageFile::WRITE )
|
||||
{
|
||||
const RString dir = Dirname(sPath);
|
||||
if( this->GetFileType(dir) != RageFileManager::TYPE_DIR )
|
||||
CreateDirectories( m_sRoot + dir );
|
||||
}
|
||||
|
||||
return MakeFileObjDirect( m_sRoot + sPath, iMode, iError );
|
||||
}
|
||||
|
||||
bool RageFileDriverDirect::Move( const RString &sOldPath_, const RString &sNewPath_ )
|
||||
{
|
||||
RString sOldPath = sOldPath_;
|
||||
RString sNewPath = sNewPath_;
|
||||
FDB->ResolvePath( sOldPath );
|
||||
FDB->ResolvePath( sNewPath );
|
||||
|
||||
if( this->GetFileType(sOldPath) == RageFileManager::TYPE_NONE )
|
||||
return false;
|
||||
|
||||
{
|
||||
const RString sDir = Dirname(sNewPath);
|
||||
CreateDirectories( m_sRoot + sDir );
|
||||
}
|
||||
int size = FDB->GetFileSize( sOldPath );
|
||||
int hash = FDB->GetFileHash( sOldPath );
|
||||
TRACE( ssprintf("rename \"%s\" -> \"%s\"", (m_sRoot + sOldPath).c_str(), (m_sRoot + sNewPath).c_str()) );
|
||||
if( DoRename(m_sRoot + sOldPath, m_sRoot + sNewPath) == -1 )
|
||||
{
|
||||
WARN( ssprintf("rename(%s,%s) failed: %s", (m_sRoot + sOldPath).c_str(), (m_sRoot + sNewPath).c_str(), strerror(errno)) );
|
||||
return false;
|
||||
}
|
||||
|
||||
FDB->DelFile( sOldPath );
|
||||
FDB->AddFile( sNewPath, size, hash, NULL );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RageFileDriverDirect::Remove( const RString &sPath_ )
|
||||
{
|
||||
RString sPath = sPath_;
|
||||
FDB->ResolvePath( sPath );
|
||||
RageFileManager::FileType type = this->GetFileType(sPath);
|
||||
switch( type )
|
||||
{
|
||||
case RageFileManager::TYPE_FILE:
|
||||
TRACE( ssprintf("remove '%s'", (m_sRoot + sPath).c_str()) );
|
||||
if( DoRemove(m_sRoot + sPath) == -1 )
|
||||
{
|
||||
WARN( ssprintf("remove(%s) failed: %s", (m_sRoot + sPath).c_str(), strerror(errno)) );
|
||||
return false;
|
||||
}
|
||||
FDB->DelFile( sPath );
|
||||
return true;
|
||||
|
||||
case RageFileManager::TYPE_DIR:
|
||||
TRACE( ssprintf("rmdir '%s'", (m_sRoot + sPath).c_str()) );
|
||||
if( DoRmdir(m_sRoot + sPath) == -1 )
|
||||
{
|
||||
WARN( ssprintf("rmdir(%s) failed: %s", (m_sRoot + sPath).c_str(), strerror(errno)) );
|
||||
return false;
|
||||
}
|
||||
FDB->DelFile( sPath );
|
||||
return true;
|
||||
|
||||
case RageFileManager::TYPE_NONE:
|
||||
return false;
|
||||
|
||||
default:
|
||||
FAIL_M(ssprintf("Invalid FileType: %i", type));
|
||||
}
|
||||
}
|
||||
|
||||
RageFileObjDirect *RageFileObjDirect::Copy() const
|
||||
{
|
||||
int iErr;
|
||||
RageFileObjDirect *ret = MakeFileObjDirect( m_sPath, m_iMode, iErr );
|
||||
|
||||
if( ret == nullptr )
|
||||
RageException::Throw( "Couldn't reopen \"%s\": %s", m_sPath.c_str(), strerror(iErr) );
|
||||
|
||||
ret->Seek( (int)lseek( m_iFD, 0, SEEK_CUR ) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool RageFileDriverDirect::Remount( const RString &sPath )
|
||||
{
|
||||
m_sRoot = sPath;
|
||||
((DirectFilenameDB *) FDB)->SetRoot( sPath );
|
||||
|
||||
/* If the root path doesn't exist, create it. */
|
||||
CreateDirectories( m_sRoot );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The DIRRO driver is just like DIR, except writes are disallowed. */
|
||||
RageFileDriverDirectReadOnly::RageFileDriverDirectReadOnly( const RString &sRoot ):
|
||||
RageFileDriverDirect( sRoot ) { }
|
||||
RageFileBasic *RageFileDriverDirectReadOnly::Open( const RString &sPath, int iMode, int &iError )
|
||||
{
|
||||
if( iMode & RageFile::WRITE )
|
||||
{
|
||||
iError = EROFS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return RageFileDriverDirect::Open( sPath, iMode, iError );
|
||||
}
|
||||
bool RageFileDriverDirectReadOnly::Move( const RString & /* sOldPath */, const RString & /* sNewPath */ ) { return false; }
|
||||
bool RageFileDriverDirectReadOnly::Remove( const RString & /* sPath */ ) { return false; }
|
||||
|
||||
static const unsigned int BUFSIZE = 1024*64;
|
||||
RageFileObjDirect::RageFileObjDirect( const RString &sPath, int iFD, int iMode )
|
||||
{
|
||||
m_sPath = sPath;
|
||||
m_iFD = iFD;
|
||||
m_bWriteFailed = false;
|
||||
m_iMode = iMode;
|
||||
ASSERT( m_iFD != -1 );
|
||||
|
||||
if( m_iMode & RageFile::WRITE )
|
||||
this->EnableWriteBuffering( BUFSIZE );
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
#if !defined(WIN32)
|
||||
bool FlushDir( RString sPath, RString &sError )
|
||||
{
|
||||
/* Wait for the directory to be flushed. */
|
||||
int dirfd = open( sPath, O_RDONLY );
|
||||
if( dirfd == -1 )
|
||||
{
|
||||
sError = strerror(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( fsync( dirfd ) == -1 )
|
||||
{
|
||||
sError = strerror(errno);
|
||||
close( dirfd );
|
||||
return false;
|
||||
}
|
||||
|
||||
close( dirfd );
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool FlushDir( RString /* sPath */, RString & /* sError */ )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool RageFileObjDirect::FinalFlush()
|
||||
{
|
||||
if( !(m_iMode & RageFile::WRITE) )
|
||||
return true;
|
||||
|
||||
/* Flush the output buffer. */
|
||||
if( Flush() == -1 )
|
||||
return false;
|
||||
|
||||
/* Only do the rest of the flushes if SLOW_FLUSH is enabled. */
|
||||
if( !(m_iMode & RageFile::SLOW_FLUSH) )
|
||||
return true;
|
||||
|
||||
/* Force a kernel buffer flush. */
|
||||
if( fsync( m_iFD ) == -1 )
|
||||
{
|
||||
WARN( ssprintf("Error synchronizing %s: %s", this->m_sPath.c_str(), strerror(errno)) );
|
||||
SetError( strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
RString sError;
|
||||
if( !FlushDir(Dirname(m_sPath), sError) )
|
||||
{
|
||||
WARN( ssprintf("Error synchronizing fsync(%s dir): %s", this->m_sPath.c_str(), sError.c_str()) );
|
||||
SetError( sError );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RageFileObjDirect::~RageFileObjDirect()
|
||||
{
|
||||
bool bFailed = !FinalFlush();
|
||||
|
||||
if( m_iFD != -1 )
|
||||
{
|
||||
if( close( m_iFD ) == -1 )
|
||||
{
|
||||
WARN( ssprintf("Error closing %s: %s", this->m_sPath.c_str(), strerror(errno)) );
|
||||
SetError( strerror(errno) );
|
||||
bFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( !(m_iMode & RageFile::WRITE) || (m_iMode & RageFile::STREAMED) )
|
||||
return;
|
||||
|
||||
/* We now have path written to MakeTempFilename(m_sPath).
|
||||
* Rename the temporary file over the real path. */
|
||||
|
||||
do
|
||||
{
|
||||
if( bFailed || WriteFailed() )
|
||||
break;
|
||||
|
||||
/* We now have path written to MakeTempFilename(m_sPath). Rename the
|
||||
* temporary file over the real path. This should be an atomic operation
|
||||
* with a journalling filesystem. That is, there should be no
|
||||
* intermediate state a JFS might restore the file we're writing (in the
|
||||
* case of a crash/powerdown) to an empty or partial file. */
|
||||
|
||||
RString sOldPath = MakeTempFilename(m_sPath);
|
||||
RString sNewPath = m_sPath;
|
||||
|
||||
#if defined(WIN32)
|
||||
if( WinMoveFile(DoPathReplace(sOldPath), DoPathReplace(sNewPath)) )
|
||||
return;
|
||||
|
||||
/* We failed. */
|
||||
int err = GetLastError();
|
||||
const RString error = werr_ssprintf( err, "Error renaming \"%s\" to \"%s\"", sOldPath.c_str(), sNewPath.c_str() );
|
||||
WARN( ssprintf("%s", error.c_str()) );
|
||||
SetError( error );
|
||||
break;
|
||||
#else
|
||||
if( rename( sOldPath, sNewPath ) == -1 )
|
||||
{
|
||||
WARN( ssprintf("Error renaming \"%s\" to \"%s\": %s",
|
||||
sOldPath.c_str(), sNewPath.c_str(), strerror(errno)) );
|
||||
SetError( strerror(errno) );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( m_iMode & RageFile::SLOW_FLUSH )
|
||||
{
|
||||
RString sError;
|
||||
if( !FlushDir(Dirname(m_sPath), sError) )
|
||||
{
|
||||
WARN( ssprintf("Error synchronizing fsync(%s dir): %s", this->m_sPath.c_str(), sError.c_str()) );
|
||||
SetError( sError );
|
||||
}
|
||||
}
|
||||
|
||||
// Success.
|
||||
return;
|
||||
#endif
|
||||
} while(0);
|
||||
|
||||
// The write or the rename failed. Delete the incomplete temporary file.
|
||||
DoRemove( MakeTempFilename(m_sPath) );
|
||||
}
|
||||
|
||||
int RageFileObjDirect::ReadInternal( void *pBuf, size_t iBytes )
|
||||
{
|
||||
int iRet = read( m_iFD, pBuf, iBytes );
|
||||
if( iRet == -1 )
|
||||
{
|
||||
SetError( strerror(errno) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return iRet;
|
||||
}
|
||||
|
||||
// write(), but retry a couple times on EINTR.
|
||||
static int RetriedWrite( int iFD, const void *pBuf, size_t iCount )
|
||||
{
|
||||
int iTries = 3, iRet;
|
||||
do
|
||||
{
|
||||
iRet = write( iFD, pBuf, iCount );
|
||||
}
|
||||
while( iRet == -1 && errno == EINTR && iTries-- );
|
||||
|
||||
return iRet;
|
||||
}
|
||||
|
||||
|
||||
int RageFileObjDirect::FlushInternal()
|
||||
{
|
||||
if( WriteFailed() )
|
||||
{
|
||||
SetError( "previous write failed" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RageFileObjDirect::WriteInternal( const void *pBuf, size_t iBytes )
|
||||
{
|
||||
if( WriteFailed() )
|
||||
{
|
||||
SetError( "previous write failed" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The buffer is cleared. If we still don't have space, it's bigger than
|
||||
* the buffer size, so just write it directly. */
|
||||
int iRet = RetriedWrite( m_iFD, pBuf, iBytes );
|
||||
if( iRet == -1 )
|
||||
{
|
||||
SetError( strerror(errno) );
|
||||
m_bWriteFailed = true;
|
||||
return -1;
|
||||
}
|
||||
return iBytes;
|
||||
}
|
||||
|
||||
int RageFileObjDirect::SeekInternal( int iOffset )
|
||||
{
|
||||
return (int)lseek( m_iFD, iOffset, SEEK_SET );
|
||||
}
|
||||
|
||||
int RageFileObjDirect::GetFileSize() const
|
||||
{
|
||||
const int iOldPos = (int)lseek( m_iFD, 0, SEEK_CUR );
|
||||
ASSERT_M( iOldPos != -1, ssprintf("\"%s\": %s", m_sPath.c_str(), strerror(errno)) );
|
||||
const int iRet = (int)lseek( m_iFD, 0, SEEK_END );
|
||||
ASSERT_M( iRet != -1, ssprintf("\"%s\": %s", m_sPath.c_str(), strerror(errno)) );
|
||||
lseek( m_iFD, iOldPos, SEEK_SET );
|
||||
return iRet;
|
||||
}
|
||||
|
||||
int RageFileObjDirect::GetFD()
|
||||
{
|
||||
return m_iFD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003-2004 Glenn Maynard, 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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ void DirectFilenameDB::CacheFile( const RString &sPath )
|
||||
CHECKPOINT_M( root+sPath );
|
||||
RString sDir = Dirname( sPath );
|
||||
FileSet *pFileSet = GetFileSet( sDir, false );
|
||||
if( pFileSet == NULL )
|
||||
if( pFileSet == nullptr )
|
||||
{
|
||||
// This directory isn't cached so do nothing.
|
||||
m_Mutex.Unlock(); // Locked by GetFileSet()
|
||||
@@ -251,7 +251,7 @@ void DirectFilenameDB::PopulateFileSet( FileSet &fs, const RString &path )
|
||||
* scans are I/O-bound. */
|
||||
|
||||
DIR *pDir = opendir(root+sPath);
|
||||
if( pDir == NULL )
|
||||
if( pDir == nullptr )
|
||||
return;
|
||||
|
||||
while( struct dirent *pEnt = readdir(pDir) )
|
||||
|
||||
+207
-207
@@ -1,207 +1,207 @@
|
||||
#include "global.h"
|
||||
#include "RageFileDriverMemory.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageUtil_FileDB.h"
|
||||
#include <errno.h>
|
||||
|
||||
struct RageFileObjMemFile
|
||||
{
|
||||
RageFileObjMemFile():
|
||||
m_iRefs(0),
|
||||
m_Mutex("RageFileObjMemFile") { }
|
||||
RString m_sBuf;
|
||||
int m_iRefs;
|
||||
RageMutex m_Mutex;
|
||||
|
||||
static void AddReference( RageFileObjMemFile *pFile )
|
||||
{
|
||||
pFile->m_Mutex.Lock();
|
||||
++pFile->m_iRefs;
|
||||
pFile->m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
static void ReleaseReference( RageFileObjMemFile *pFile )
|
||||
{
|
||||
pFile->m_Mutex.Lock();
|
||||
const int iRefs = --pFile->m_iRefs;
|
||||
const bool bShouldDelete = (pFile->m_iRefs == 0);
|
||||
pFile->m_Mutex.Unlock();
|
||||
ASSERT( iRefs >= 0 );
|
||||
|
||||
if( bShouldDelete )
|
||||
delete pFile;
|
||||
}
|
||||
};
|
||||
|
||||
RageFileObjMem::RageFileObjMem( RageFileObjMemFile *pFile )
|
||||
{
|
||||
if( pFile == NULL )
|
||||
pFile = new RageFileObjMemFile;
|
||||
|
||||
m_pFile = pFile;
|
||||
m_iFilePos = 0;
|
||||
RageFileObjMemFile::AddReference( m_pFile );
|
||||
}
|
||||
|
||||
RageFileObjMem::~RageFileObjMem()
|
||||
{
|
||||
RageFileObjMemFile::ReleaseReference( m_pFile );
|
||||
}
|
||||
|
||||
int RageFileObjMem::ReadInternal( void *buffer, size_t bytes )
|
||||
{
|
||||
LockMut(m_pFile->m_Mutex);
|
||||
|
||||
m_iFilePos = min( m_iFilePos, GetFileSize() );
|
||||
bytes = min( bytes, (size_t) GetFileSize() - m_iFilePos );
|
||||
if( bytes == 0 )
|
||||
return 0;
|
||||
memcpy( buffer, &m_pFile->m_sBuf[m_iFilePos], bytes );
|
||||
m_iFilePos += bytes;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int RageFileObjMem::WriteInternal( const void *buffer, size_t bytes )
|
||||
{
|
||||
m_pFile->m_Mutex.Lock();
|
||||
m_pFile->m_sBuf.replace( m_iFilePos, bytes, (const char *) buffer, bytes );
|
||||
m_pFile->m_Mutex.Unlock();
|
||||
|
||||
m_iFilePos += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int RageFileObjMem::SeekInternal( int offset )
|
||||
{
|
||||
m_iFilePos = clamp( offset, 0, GetFileSize() );
|
||||
return m_iFilePos;
|
||||
}
|
||||
|
||||
int RageFileObjMem::GetFileSize() const
|
||||
{
|
||||
LockMut(m_pFile->m_Mutex);
|
||||
return m_pFile->m_sBuf.size();
|
||||
}
|
||||
|
||||
RageFileObjMem::RageFileObjMem( const RageFileObjMem &cpy ):
|
||||
RageFileObj( cpy )
|
||||
{
|
||||
m_pFile = cpy.m_pFile;
|
||||
m_iFilePos = cpy.m_iFilePos;
|
||||
RageFileObjMemFile::AddReference( m_pFile );
|
||||
}
|
||||
|
||||
RageFileObjMem *RageFileObjMem::Copy() const
|
||||
{
|
||||
RageFileObjMem *pRet = new RageFileObjMem( *this );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
const RString &RageFileObjMem::GetString() const
|
||||
{
|
||||
return m_pFile->m_sBuf;
|
||||
}
|
||||
|
||||
void RageFileObjMem::PutString( const RString &sBuf )
|
||||
{
|
||||
m_pFile->m_Mutex.Lock();
|
||||
m_pFile->m_sBuf = sBuf;
|
||||
m_pFile->m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
RageFileDriverMem::RageFileDriverMem():
|
||||
RageFileDriver( new NullFilenameDB ),
|
||||
m_Mutex("RageFileDriverMem")
|
||||
{
|
||||
}
|
||||
|
||||
RageFileDriverMem::~RageFileDriverMem()
|
||||
{
|
||||
for( unsigned i = 0; i < m_Files.size(); ++i )
|
||||
{
|
||||
RageFileObjMemFile *pFile = m_Files[i];
|
||||
RageFileObjMemFile::ReleaseReference( pFile );
|
||||
}
|
||||
}
|
||||
|
||||
RageFileBasic *RageFileDriverMem::Open( const RString &sPath, int mode, int &err )
|
||||
{
|
||||
LockMut(m_Mutex);
|
||||
|
||||
if( mode == RageFile::WRITE )
|
||||
{
|
||||
/* If the file exists, delete it. */
|
||||
Remove( sPath );
|
||||
|
||||
RageFileObjMemFile *pFile = new RageFileObjMemFile;
|
||||
|
||||
/* Add one reference, representing the file in the filesystem. */
|
||||
RageFileObjMemFile::AddReference( pFile );
|
||||
|
||||
m_Files.push_back( pFile );
|
||||
FDB->AddFile( sPath, 0, 0, pFile );
|
||||
|
||||
return new RageFileObjMem( pFile );
|
||||
}
|
||||
|
||||
RageFileObjMemFile *pFile = (RageFileObjMemFile *) FDB->GetFilePriv( sPath );
|
||||
if( pFile == NULL )
|
||||
{
|
||||
err = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new RageFileObjMem( pFile );
|
||||
}
|
||||
|
||||
bool RageFileDriverMem::Remove( const RString &sPath )
|
||||
{
|
||||
LockMut(m_Mutex);
|
||||
|
||||
RageFileObjMemFile *pFile = (RageFileObjMemFile *) FDB->GetFilePriv( sPath );
|
||||
if( pFile == NULL )
|
||||
return false;
|
||||
|
||||
/* Unregister the file. */
|
||||
FDB->DelFile( sPath );
|
||||
vector<RageFileObjMemFile *>::iterator it = find( m_Files.begin(), m_Files.end(), pFile );
|
||||
ASSERT( it != m_Files.end() );
|
||||
m_Files.erase( it );
|
||||
|
||||
RageFileObjMemFile::ReleaseReference( pFile );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct FileDriverEntry_MEM: public FileDriverEntry
|
||||
{
|
||||
FileDriverEntry_MEM(): FileDriverEntry( "MEM" ) { }
|
||||
RageFileDriver *Create( const RString &sRoot ) const { return new RageFileDriverMem(); }
|
||||
} const g_RegisterDriver;
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "RageFileDriverMemory.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageUtil_FileDB.h"
|
||||
#include <errno.h>
|
||||
|
||||
struct RageFileObjMemFile
|
||||
{
|
||||
RageFileObjMemFile():
|
||||
m_iRefs(0),
|
||||
m_Mutex("RageFileObjMemFile") { }
|
||||
RString m_sBuf;
|
||||
int m_iRefs;
|
||||
RageMutex m_Mutex;
|
||||
|
||||
static void AddReference( RageFileObjMemFile *pFile )
|
||||
{
|
||||
pFile->m_Mutex.Lock();
|
||||
++pFile->m_iRefs;
|
||||
pFile->m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
static void ReleaseReference( RageFileObjMemFile *pFile )
|
||||
{
|
||||
pFile->m_Mutex.Lock();
|
||||
const int iRefs = --pFile->m_iRefs;
|
||||
const bool bShouldDelete = (pFile->m_iRefs == 0);
|
||||
pFile->m_Mutex.Unlock();
|
||||
ASSERT( iRefs >= 0 );
|
||||
|
||||
if( bShouldDelete )
|
||||
delete pFile;
|
||||
}
|
||||
};
|
||||
|
||||
RageFileObjMem::RageFileObjMem( RageFileObjMemFile *pFile )
|
||||
{
|
||||
if( pFile == nullptr )
|
||||
pFile = new RageFileObjMemFile;
|
||||
|
||||
m_pFile = pFile;
|
||||
m_iFilePos = 0;
|
||||
RageFileObjMemFile::AddReference( m_pFile );
|
||||
}
|
||||
|
||||
RageFileObjMem::~RageFileObjMem()
|
||||
{
|
||||
RageFileObjMemFile::ReleaseReference( m_pFile );
|
||||
}
|
||||
|
||||
int RageFileObjMem::ReadInternal( void *buffer, size_t bytes )
|
||||
{
|
||||
LockMut(m_pFile->m_Mutex);
|
||||
|
||||
m_iFilePos = min( m_iFilePos, GetFileSize() );
|
||||
bytes = min( bytes, (size_t) GetFileSize() - m_iFilePos );
|
||||
if( bytes == 0 )
|
||||
return 0;
|
||||
memcpy( buffer, &m_pFile->m_sBuf[m_iFilePos], bytes );
|
||||
m_iFilePos += bytes;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int RageFileObjMem::WriteInternal( const void *buffer, size_t bytes )
|
||||
{
|
||||
m_pFile->m_Mutex.Lock();
|
||||
m_pFile->m_sBuf.replace( m_iFilePos, bytes, (const char *) buffer, bytes );
|
||||
m_pFile->m_Mutex.Unlock();
|
||||
|
||||
m_iFilePos += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int RageFileObjMem::SeekInternal( int offset )
|
||||
{
|
||||
m_iFilePos = clamp( offset, 0, GetFileSize() );
|
||||
return m_iFilePos;
|
||||
}
|
||||
|
||||
int RageFileObjMem::GetFileSize() const
|
||||
{
|
||||
LockMut(m_pFile->m_Mutex);
|
||||
return m_pFile->m_sBuf.size();
|
||||
}
|
||||
|
||||
RageFileObjMem::RageFileObjMem( const RageFileObjMem &cpy ):
|
||||
RageFileObj( cpy )
|
||||
{
|
||||
m_pFile = cpy.m_pFile;
|
||||
m_iFilePos = cpy.m_iFilePos;
|
||||
RageFileObjMemFile::AddReference( m_pFile );
|
||||
}
|
||||
|
||||
RageFileObjMem *RageFileObjMem::Copy() const
|
||||
{
|
||||
RageFileObjMem *pRet = new RageFileObjMem( *this );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
const RString &RageFileObjMem::GetString() const
|
||||
{
|
||||
return m_pFile->m_sBuf;
|
||||
}
|
||||
|
||||
void RageFileObjMem::PutString( const RString &sBuf )
|
||||
{
|
||||
m_pFile->m_Mutex.Lock();
|
||||
m_pFile->m_sBuf = sBuf;
|
||||
m_pFile->m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
RageFileDriverMem::RageFileDriverMem():
|
||||
RageFileDriver( new NullFilenameDB ),
|
||||
m_Mutex("RageFileDriverMem")
|
||||
{
|
||||
}
|
||||
|
||||
RageFileDriverMem::~RageFileDriverMem()
|
||||
{
|
||||
for( unsigned i = 0; i < m_Files.size(); ++i )
|
||||
{
|
||||
RageFileObjMemFile *pFile = m_Files[i];
|
||||
RageFileObjMemFile::ReleaseReference( pFile );
|
||||
}
|
||||
}
|
||||
|
||||
RageFileBasic *RageFileDriverMem::Open( const RString &sPath, int mode, int &err )
|
||||
{
|
||||
LockMut(m_Mutex);
|
||||
|
||||
if( mode == RageFile::WRITE )
|
||||
{
|
||||
/* If the file exists, delete it. */
|
||||
Remove( sPath );
|
||||
|
||||
RageFileObjMemFile *pFile = new RageFileObjMemFile;
|
||||
|
||||
/* Add one reference, representing the file in the filesystem. */
|
||||
RageFileObjMemFile::AddReference( pFile );
|
||||
|
||||
m_Files.push_back( pFile );
|
||||
FDB->AddFile( sPath, 0, 0, pFile );
|
||||
|
||||
return new RageFileObjMem( pFile );
|
||||
}
|
||||
|
||||
RageFileObjMemFile *pFile = (RageFileObjMemFile *) FDB->GetFilePriv( sPath );
|
||||
if( pFile == nullptr )
|
||||
{
|
||||
err = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new RageFileObjMem( pFile );
|
||||
}
|
||||
|
||||
bool RageFileDriverMem::Remove( const RString &sPath )
|
||||
{
|
||||
LockMut(m_Mutex);
|
||||
|
||||
RageFileObjMemFile *pFile = (RageFileObjMemFile *) FDB->GetFilePriv( sPath );
|
||||
if( pFile == nullptr )
|
||||
return false;
|
||||
|
||||
/* Unregister the file. */
|
||||
FDB->DelFile( sPath );
|
||||
vector<RageFileObjMemFile *>::iterator it = find( m_Files.begin(), m_Files.end(), pFile );
|
||||
ASSERT( it != m_Files.end() );
|
||||
m_Files.erase( it );
|
||||
|
||||
RageFileObjMemFile::ReleaseReference( pFile );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct FileDriverEntry_MEM: public FileDriverEntry
|
||||
{
|
||||
FileDriverEntry_MEM(): FileDriverEntry( "MEM" ) { }
|
||||
RageFileDriver *Create( const RString &sRoot ) const { return new RageFileDriverMem(); }
|
||||
} const g_RegisterDriver;
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -158,7 +158,7 @@ ThreadedFileWorker::ThreadedFileWorker( RString sPath ):
|
||||
{
|
||||
/* Grab a reference to the child driver. We'll operate on it directly. */
|
||||
m_pChildDriver = FILEMAN->GetFileDriver( sPath );
|
||||
if( m_pChildDriver == NULL )
|
||||
if( m_pChildDriver == nullptr )
|
||||
WARN( ssprintf("ThreadedFileWorker: Mountpoint \"%s\" not found", sPath.c_str()) );
|
||||
|
||||
m_pResultFile = NULL;
|
||||
@@ -209,7 +209,7 @@ void ThreadedFileWorker::HandleRequest( int iRequest )
|
||||
switch( iRequest )
|
||||
{
|
||||
case REQ_OPEN:
|
||||
ASSERT( m_pResultFile == NULL );
|
||||
ASSERT( m_pResultFile == nullptr );
|
||||
ASSERT( !m_sRequestPath.empty() );
|
||||
m_iResultRequest = 0;
|
||||
m_pResultFile = m_pChildDriver->Open( m_sRequestPath, m_iRequestMode, m_iResultRequest );
|
||||
@@ -296,7 +296,7 @@ void ThreadedFileWorker::RequestTimedOut()
|
||||
|
||||
RageFileBasic *ThreadedFileWorker::Open( const RString &sPath, int iMode, int &iErr )
|
||||
{
|
||||
if( m_pChildDriver == NULL )
|
||||
if( m_pChildDriver == nullptr )
|
||||
{
|
||||
iErr = ENODEV;
|
||||
return NULL;
|
||||
@@ -330,7 +330,7 @@ void ThreadedFileWorker::Close( RageFileBasic *pFile )
|
||||
{
|
||||
ASSERT( m_pChildDriver != nullptr ); /* how did you get a file to begin with? */
|
||||
|
||||
if( pFile == NULL )
|
||||
if( pFile == nullptr )
|
||||
return;
|
||||
|
||||
if( !IsTimedOut() )
|
||||
@@ -362,7 +362,7 @@ int ThreadedFileWorker::GetFileSize( RageFileBasic *&pFile )
|
||||
pFile = NULL;
|
||||
}
|
||||
|
||||
if( pFile == NULL )
|
||||
if( pFile == nullptr )
|
||||
return -1;
|
||||
|
||||
m_pRequestFile = pFile;
|
||||
@@ -390,7 +390,7 @@ int ThreadedFileWorker::GetFD( RageFileBasic *&pFile )
|
||||
pFile = NULL;
|
||||
}
|
||||
|
||||
if( pFile == NULL )
|
||||
if( pFile == nullptr )
|
||||
return -1;
|
||||
|
||||
m_pRequestFile = pFile;
|
||||
@@ -418,7 +418,7 @@ int ThreadedFileWorker::Seek( RageFileBasic *&pFile, int iPos, RString &sError )
|
||||
pFile = NULL;
|
||||
}
|
||||
|
||||
if( pFile == NULL )
|
||||
if( pFile == nullptr )
|
||||
{
|
||||
sError = "Operation timed out";
|
||||
return -1;
|
||||
@@ -453,7 +453,7 @@ int ThreadedFileWorker::Read( RageFileBasic *&pFile, void *pBuf, int iSize, RStr
|
||||
pFile = NULL;
|
||||
}
|
||||
|
||||
if( pFile == NULL )
|
||||
if( pFile == nullptr )
|
||||
{
|
||||
sError = "Operation timed out";
|
||||
return -1;
|
||||
@@ -495,7 +495,7 @@ int ThreadedFileWorker::Write( RageFileBasic *&pFile, const void *pBuf, int iSiz
|
||||
pFile = NULL;
|
||||
}
|
||||
|
||||
if( pFile == NULL )
|
||||
if( pFile == nullptr )
|
||||
{
|
||||
sError = "Operation timed out";
|
||||
return -1;
|
||||
@@ -536,7 +536,7 @@ int ThreadedFileWorker::Flush( RageFileBasic *&pFile, RString &sError )
|
||||
pFile = NULL;
|
||||
}
|
||||
|
||||
if( pFile == NULL )
|
||||
if( pFile == nullptr )
|
||||
{
|
||||
sError = "Operation timed out";
|
||||
return -1;
|
||||
@@ -571,7 +571,7 @@ RageFileBasic *ThreadedFileWorker::Copy( RageFileBasic *&pFile, RString &sError
|
||||
pFile = NULL;
|
||||
}
|
||||
|
||||
if( pFile == NULL )
|
||||
if( pFile == nullptr )
|
||||
{
|
||||
sError = "Operation timed out";
|
||||
return NULL;
|
||||
@@ -596,7 +596,7 @@ RageFileBasic *ThreadedFileWorker::Copy( RageFileBasic *&pFile, RString &sError
|
||||
|
||||
bool ThreadedFileWorker::PopulateFileSet( FileSet &fs, const RString &sPath )
|
||||
{
|
||||
if( m_pChildDriver == NULL )
|
||||
if( m_pChildDriver == nullptr )
|
||||
return false;
|
||||
|
||||
/* If we're currently in a timed-out state, fail. */
|
||||
@@ -664,7 +664,7 @@ bool ThreadedFileWorker::FlushDirCache( const RString &sPath )
|
||||
if( !bTimeoutEnabled )
|
||||
SetTimeout(1);
|
||||
|
||||
if( m_pChildDriver == NULL )
|
||||
if( m_pChildDriver == nullptr )
|
||||
return false;
|
||||
|
||||
/* If we're currently in a timed-out state, fail. */
|
||||
@@ -727,7 +727,7 @@ public:
|
||||
RString sError;
|
||||
int iRet = m_pWorker->GetFD( m_pFile );
|
||||
|
||||
if( m_pFile == NULL )
|
||||
if( m_pFile == nullptr )
|
||||
{
|
||||
SetError( "Operation timed out" );
|
||||
return -1;
|
||||
@@ -744,13 +744,13 @@ public:
|
||||
RString sError;
|
||||
RageFileBasic *pCopy = m_pWorker->Copy( m_pFile, sError );
|
||||
|
||||
if( m_pFile == NULL )
|
||||
if( m_pFile == nullptr )
|
||||
{
|
||||
// SetError( "Operation timed out" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( pCopy == NULL )
|
||||
if( pCopy == nullptr )
|
||||
{
|
||||
// SetError( sError );
|
||||
return NULL;
|
||||
@@ -765,7 +765,7 @@ protected:
|
||||
RString sError;
|
||||
int iRet = m_pWorker->Seek( m_pFile, iPos, sError );
|
||||
|
||||
if( m_pFile == NULL )
|
||||
if( m_pFile == nullptr )
|
||||
{
|
||||
SetError( "Operation timed out" );
|
||||
return -1;
|
||||
@@ -783,7 +783,7 @@ protected:
|
||||
RString sError;
|
||||
int iRet = m_pWorker->Read( m_pFile, pBuffer, iBytes, sError );
|
||||
|
||||
if( m_pFile == NULL )
|
||||
if( m_pFile == nullptr )
|
||||
{
|
||||
SetError( "Operation timed out" );
|
||||
return -1;
|
||||
@@ -800,7 +800,7 @@ protected:
|
||||
RString sError;
|
||||
int iRet = m_pWorker->Write( m_pFile, pBuffer, iBytes, sError );
|
||||
|
||||
if( m_pFile == NULL )
|
||||
if( m_pFile == nullptr )
|
||||
{
|
||||
SetError( "Operation timed out" );
|
||||
return -1;
|
||||
@@ -817,7 +817,7 @@ protected:
|
||||
RString sError;
|
||||
int iRet = m_pWorker->Flush( m_pFile, sError );
|
||||
|
||||
if( m_pFile == NULL )
|
||||
if( m_pFile == nullptr )
|
||||
{
|
||||
SetError( "Operation timed out" );
|
||||
return -1;
|
||||
@@ -878,7 +878,7 @@ RageFileDriverTimeout::RageFileDriverTimeout( const RString &sPath ):
|
||||
RageFileBasic *RageFileDriverTimeout::Open( const RString &sPath, int iMode, int &iErr )
|
||||
{
|
||||
RageFileBasic *pChildFile = m_pWorker->Open( sPath, iMode, iErr );
|
||||
if( pChildFile == NULL )
|
||||
if( pChildFile == nullptr )
|
||||
return NULL;
|
||||
|
||||
/* RageBasicFile::GetFileSize isn't allowed to fail, but we are; grab the file
|
||||
@@ -890,7 +890,7 @@ RageFileBasic *RageFileDriverTimeout::Open( const RString &sPath, int iMode, int
|
||||
if( iSize == -1 )
|
||||
{
|
||||
/* When m_pWorker->GetFileSize fails, it takes ownership of pChildFile. */
|
||||
ASSERT( pChildFile == NULL );
|
||||
ASSERT( pChildFile == nullptr );
|
||||
iErr = EFAULT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+374
-374
@@ -1,374 +1,374 @@
|
||||
/*
|
||||
* Ref: http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "RageFileDriverZip.h"
|
||||
#include "RageFileDriverSlice.h"
|
||||
#include "RageFileDriverDeflate.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageUtil_FileDB.h"
|
||||
#include <cerrno>
|
||||
|
||||
static struct FileDriverEntry_ZIP: public FileDriverEntry
|
||||
{
|
||||
FileDriverEntry_ZIP(): FileDriverEntry( "ZIP" ) { }
|
||||
RageFileDriver *Create( const RString &sRoot ) const { return new RageFileDriverZip( sRoot ); }
|
||||
} const g_RegisterDriver;
|
||||
|
||||
|
||||
RageFileDriverZip::RageFileDriverZip():
|
||||
RageFileDriver( new NullFilenameDB ),
|
||||
m_Mutex( "RageFileDriverZip" )
|
||||
{
|
||||
m_bFileOwned = false;
|
||||
m_pZip = NULL;
|
||||
}
|
||||
|
||||
RageFileDriverZip::RageFileDriverZip( const RString &sPath ):
|
||||
RageFileDriver( new NullFilenameDB ),
|
||||
m_Mutex( "RageFileDriverZip" )
|
||||
{
|
||||
m_bFileOwned = false;
|
||||
m_pZip = NULL;
|
||||
Load( sPath );
|
||||
}
|
||||
|
||||
bool RageFileDriverZip::Load( const RString &sPath )
|
||||
{
|
||||
ASSERT( m_pZip == NULL ); /* don't load twice */
|
||||
|
||||
m_bFileOwned = true;
|
||||
m_sPath = sPath;
|
||||
m_Mutex.SetName( ssprintf("RageFileDriverZip(%s)", sPath.c_str()) );
|
||||
|
||||
RageFile *pFile = new RageFile;
|
||||
|
||||
if( !pFile->Open(sPath) )
|
||||
{
|
||||
WARN( ssprintf("Couldn't open %s: %s", sPath.c_str(), pFile->GetError().c_str()) );
|
||||
delete pFile;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pZip = pFile;
|
||||
|
||||
return ParseZipfile();
|
||||
}
|
||||
|
||||
bool RageFileDriverZip::Load( RageFileBasic *pFile )
|
||||
{
|
||||
ASSERT( m_pZip == NULL ); /* don't load twice */
|
||||
m_sPath = ssprintf("%p", pFile);
|
||||
m_Mutex.SetName( ssprintf("RageFileDriverZip(%p)", pFile) );
|
||||
|
||||
m_pZip = pFile;
|
||||
|
||||
return ParseZipfile();
|
||||
}
|
||||
|
||||
|
||||
bool RageFileDriverZip::ReadEndCentralRecord( int &iTotalEntries, int &iCentralDirectoryOffset )
|
||||
{
|
||||
RString sError;
|
||||
RString sSig = FileReading::ReadString( *m_pZip, 4, sError );
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip number of this disk */
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip disk with central directory */
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip number of entries on this disk */
|
||||
iTotalEntries = FileReading::read_16_le( *m_pZip, sError );
|
||||
FileReading::read_32_le( *m_pZip, sError ); /* skip size of the central directory */
|
||||
iCentralDirectoryOffset = FileReading::read_32_le( *m_pZip, sError );
|
||||
int iCommentLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
m_sComment = FileReading::ReadString( *m_pZip, iCommentLength, sError );
|
||||
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), sError.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Find the end of central directory record, and seek to it. */
|
||||
bool RageFileDriverZip::SeekToEndCentralRecord()
|
||||
{
|
||||
const int iSearchTo = max( m_pZip->GetFileSize() - 1024*32, 0 );
|
||||
int iRealPos = m_pZip->GetFileSize();
|
||||
|
||||
while( iRealPos > 0 && iRealPos >= iSearchTo )
|
||||
{
|
||||
/* Move back in the file; leave some overlap between checks, to handle
|
||||
* the case where the signature crosses the block boundary. */
|
||||
char buf[1024*4];
|
||||
iRealPos -= sizeof(buf) - 4;
|
||||
iRealPos = max( 0, iRealPos );
|
||||
m_pZip->Seek( iRealPos );
|
||||
|
||||
int iGot = m_pZip->Read( buf, sizeof(buf) );
|
||||
if( iGot == -1 )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), m_pZip->GetError().c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
for( int iPos = iGot - 4; iPos >= 0; --iPos )
|
||||
{
|
||||
if( memcmp(buf + iPos, "\x50\x4B\x05\x06", 4) )
|
||||
continue;
|
||||
|
||||
m_pZip->Seek( iRealPos + iPos );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RageFileDriverZip::ParseZipfile()
|
||||
{
|
||||
if( !SeekToEndCentralRecord() )
|
||||
{
|
||||
WARN( ssprintf("Couldn't open %s: couldn't find end of central directory record", m_sPath.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Read the end of central directory record. */
|
||||
int iTotalEntries, iCentralDirectoryOffset;
|
||||
if( !ReadEndCentralRecord(iTotalEntries, iCentralDirectoryOffset) )
|
||||
return false; /* warned already */
|
||||
|
||||
/* Seek to the start of the central file directory. */
|
||||
m_pZip->Seek( iCentralDirectoryOffset );
|
||||
|
||||
/* Loop through files in central directory. */
|
||||
for( int i = 0; i < iTotalEntries; ++i )
|
||||
{
|
||||
FileInfo info;
|
||||
info.m_iDataOffset = -1;
|
||||
int got = ProcessCdirFileHdr( info );
|
||||
if( got == -1 ) /* error */
|
||||
break;
|
||||
if( got == 0 ) /* skip */
|
||||
continue;
|
||||
|
||||
FileInfo *pInfo = new FileInfo( info );
|
||||
m_pFiles.push_back( pInfo );
|
||||
FDB->AddFile( "/" + pInfo->m_sName, pInfo->m_iUncompressedSize, pInfo->m_iCRC32, pInfo );
|
||||
}
|
||||
|
||||
if( m_pFiles.size() == 0 )
|
||||
WARN( ssprintf("%s: no files found in central file header", m_sPath.c_str()) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int RageFileDriverZip::ProcessCdirFileHdr( FileInfo &info )
|
||||
{
|
||||
RString sError;
|
||||
RString sSig = FileReading::ReadString( *m_pZip, 4, sError );
|
||||
if( sSig != "\x50\x4B\x01\x02" )
|
||||
{
|
||||
WARN( ssprintf("%s: central directory record signature not found", m_sPath.c_str()) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
FileReading::read_8( *m_pZip, sError ); /* skip version made by */
|
||||
int iOSMadeBy = FileReading::read_8( *m_pZip, sError );
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip version needed to extract */
|
||||
int iGeneralPurpose = FileReading::read_16_le( *m_pZip, sError );
|
||||
info.m_iCompressionMethod = (ZipCompressionMethod) FileReading::read_16_le( *m_pZip, sError );
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip last mod file time */
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip last mod file date */
|
||||
info.m_iCRC32 = FileReading::read_32_le( *m_pZip, sError );
|
||||
info.m_iCompressedSize = FileReading::read_32_le( *m_pZip, sError );
|
||||
info.m_iUncompressedSize = FileReading::read_32_le( *m_pZip, sError );
|
||||
int iFilenameLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
int iExtraFieldLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
int iFileCommentLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* relative offset of local header */
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip internal file attributes */
|
||||
unsigned iExternalFileAttributes = FileReading::read_32_le( *m_pZip, sError );
|
||||
info.m_iOffset = FileReading::read_32_le( *m_pZip, sError );
|
||||
|
||||
/* Check for errors before reading variable-length fields. */
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), sError.c_str()) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
info.m_sName = FileReading::ReadString( *m_pZip, iFilenameLength, sError );
|
||||
FileReading::SkipBytes( *m_pZip, iExtraFieldLength, sError ); /* skip extra field */
|
||||
FileReading::SkipBytes( *m_pZip, iFileCommentLength, sError ); /* skip file comment */
|
||||
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), sError.c_str()) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check usability last, so we always read past the whole entry and don't leave the
|
||||
* file pointer in the middle of a record. */
|
||||
if( iGeneralPurpose & 1 )
|
||||
{
|
||||
WARN( ssprintf("Skipped encrypted \"%s\" in \"%s\"", info.m_sName.c_str(), m_sPath.c_str()) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip directories. */
|
||||
if( iExternalFileAttributes & (1<<4) )
|
||||
return 0;
|
||||
|
||||
info.m_iFilePermissions = 0;
|
||||
enum { MADE_BY_UNIX = 3 };
|
||||
switch( iOSMadeBy )
|
||||
{
|
||||
case MADE_BY_UNIX:
|
||||
info.m_iFilePermissions = (iExternalFileAttributes >> 16) & 0x1FF;
|
||||
break;
|
||||
}
|
||||
|
||||
if( info.m_iCompressionMethod != STORED && info.m_iCompressionMethod != DEFLATED )
|
||||
{
|
||||
WARN( ssprintf("File \"%s\" in \"%s\" uses unsupported compression method %i",
|
||||
info.m_sName.c_str(), m_sPath.c_str(), info.m_iCompressionMethod) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool RageFileDriverZip::ReadLocalFileHeader( FileInfo &info )
|
||||
{
|
||||
/* Seek to and read the local file header. */
|
||||
m_pZip->Seek( info.m_iOffset );
|
||||
|
||||
RString sError;
|
||||
RString sSig = FileReading::ReadString( *m_pZip, 4, sError );
|
||||
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: error opening \"%s\": %s", m_sPath.c_str(), info.m_sName.c_str(), sError.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( sSig != "\x50\x4B\x03\x04" )
|
||||
{
|
||||
WARN( ssprintf("%s: local file header not found for \"%s\"", m_sPath.c_str(), info.m_sName.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
FileReading::SkipBytes( *m_pZip, 22, sError ); /* skip most of the local file header */
|
||||
|
||||
const int iFilenameLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
const int iExtraFieldLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
info.m_iDataOffset = m_pZip->Tell() + iFilenameLength + iExtraFieldLength;
|
||||
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), sError.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RageFileDriverZip::~RageFileDriverZip()
|
||||
{
|
||||
for( unsigned i = 0; i < m_pFiles.size(); ++i )
|
||||
delete m_pFiles[i];
|
||||
|
||||
if( m_bFileOwned )
|
||||
delete m_pZip;
|
||||
}
|
||||
|
||||
const RageFileDriverZip::FileInfo *RageFileDriverZip::GetFileInfo( const RString &sPath ) const
|
||||
{
|
||||
return (const FileInfo *) FDB->GetFilePriv( sPath );
|
||||
}
|
||||
|
||||
RageFileBasic *RageFileDriverZip::Open( const RString &sPath, int iMode, int &iErr )
|
||||
{
|
||||
if( iMode & RageFile::WRITE )
|
||||
{
|
||||
iErr = ERROR_WRITING_NOT_SUPPORTED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FileInfo *info = (FileInfo *) FDB->GetFilePriv( sPath );
|
||||
if( info == NULL )
|
||||
{
|
||||
iErr = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_Mutex.Lock();
|
||||
|
||||
/* If we haven't figured out the offset to the real data yet, do so now. */
|
||||
if( info->m_iDataOffset == -1 )
|
||||
{
|
||||
if( !ReadLocalFileHeader(*info) )
|
||||
{
|
||||
m_Mutex.Unlock();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* We won't do any further access to zip, except to copy it (which is
|
||||
* threadsafe), so we can unlock now. */
|
||||
m_Mutex.Unlock();
|
||||
|
||||
RageFileDriverSlice *pSlice = new RageFileDriverSlice( m_pZip->Copy(), info->m_iDataOffset, info->m_iCompressedSize );
|
||||
pSlice->DeleteFileWhenFinished();
|
||||
|
||||
switch( info->m_iCompressionMethod )
|
||||
{
|
||||
case STORED:
|
||||
return pSlice;
|
||||
case DEFLATED:
|
||||
{
|
||||
RageFileObjInflate *pInflate = new RageFileObjInflate( pSlice, info->m_iUncompressedSize );
|
||||
pInflate->DeleteFileWhenFinished();
|
||||
return pInflate;
|
||||
}
|
||||
default:
|
||||
/* unknown compression method */
|
||||
iErr = ENOSYS;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOP for now. This could check to see if the ZIP's mtime has changed, and reload. */
|
||||
void RageFileDriverZip::FlushDirCache( const RString &sPath )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003-2005 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Ref: http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "RageFileDriverZip.h"
|
||||
#include "RageFileDriverSlice.h"
|
||||
#include "RageFileDriverDeflate.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageUtil_FileDB.h"
|
||||
#include <cerrno>
|
||||
|
||||
static struct FileDriverEntry_ZIP: public FileDriverEntry
|
||||
{
|
||||
FileDriverEntry_ZIP(): FileDriverEntry( "ZIP" ) { }
|
||||
RageFileDriver *Create( const RString &sRoot ) const { return new RageFileDriverZip( sRoot ); }
|
||||
} const g_RegisterDriver;
|
||||
|
||||
|
||||
RageFileDriverZip::RageFileDriverZip():
|
||||
RageFileDriver( new NullFilenameDB ),
|
||||
m_Mutex( "RageFileDriverZip" )
|
||||
{
|
||||
m_bFileOwned = false;
|
||||
m_pZip = NULL;
|
||||
}
|
||||
|
||||
RageFileDriverZip::RageFileDriverZip( const RString &sPath ):
|
||||
RageFileDriver( new NullFilenameDB ),
|
||||
m_Mutex( "RageFileDriverZip" )
|
||||
{
|
||||
m_bFileOwned = false;
|
||||
m_pZip = NULL;
|
||||
Load( sPath );
|
||||
}
|
||||
|
||||
bool RageFileDriverZip::Load( const RString &sPath )
|
||||
{
|
||||
ASSERT( m_pZip == nullptr ); /* don't load twice */
|
||||
|
||||
m_bFileOwned = true;
|
||||
m_sPath = sPath;
|
||||
m_Mutex.SetName( ssprintf("RageFileDriverZip(%s)", sPath.c_str()) );
|
||||
|
||||
RageFile *pFile = new RageFile;
|
||||
|
||||
if( !pFile->Open(sPath) )
|
||||
{
|
||||
WARN( ssprintf("Couldn't open %s: %s", sPath.c_str(), pFile->GetError().c_str()) );
|
||||
delete pFile;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pZip = pFile;
|
||||
|
||||
return ParseZipfile();
|
||||
}
|
||||
|
||||
bool RageFileDriverZip::Load( RageFileBasic *pFile )
|
||||
{
|
||||
ASSERT( m_pZip == nullptr ); /* don't load twice */
|
||||
m_sPath = ssprintf("%p", pFile);
|
||||
m_Mutex.SetName( ssprintf("RageFileDriverZip(%p)", pFile) );
|
||||
|
||||
m_pZip = pFile;
|
||||
|
||||
return ParseZipfile();
|
||||
}
|
||||
|
||||
|
||||
bool RageFileDriverZip::ReadEndCentralRecord( int &iTotalEntries, int &iCentralDirectoryOffset )
|
||||
{
|
||||
RString sError;
|
||||
RString sSig = FileReading::ReadString( *m_pZip, 4, sError );
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip number of this disk */
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip disk with central directory */
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip number of entries on this disk */
|
||||
iTotalEntries = FileReading::read_16_le( *m_pZip, sError );
|
||||
FileReading::read_32_le( *m_pZip, sError ); /* skip size of the central directory */
|
||||
iCentralDirectoryOffset = FileReading::read_32_le( *m_pZip, sError );
|
||||
int iCommentLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
m_sComment = FileReading::ReadString( *m_pZip, iCommentLength, sError );
|
||||
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), sError.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Find the end of central directory record, and seek to it. */
|
||||
bool RageFileDriverZip::SeekToEndCentralRecord()
|
||||
{
|
||||
const int iSearchTo = max( m_pZip->GetFileSize() - 1024*32, 0 );
|
||||
int iRealPos = m_pZip->GetFileSize();
|
||||
|
||||
while( iRealPos > 0 && iRealPos >= iSearchTo )
|
||||
{
|
||||
/* Move back in the file; leave some overlap between checks, to handle
|
||||
* the case where the signature crosses the block boundary. */
|
||||
char buf[1024*4];
|
||||
iRealPos -= sizeof(buf) - 4;
|
||||
iRealPos = max( 0, iRealPos );
|
||||
m_pZip->Seek( iRealPos );
|
||||
|
||||
int iGot = m_pZip->Read( buf, sizeof(buf) );
|
||||
if( iGot == -1 )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), m_pZip->GetError().c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
for( int iPos = iGot - 4; iPos >= 0; --iPos )
|
||||
{
|
||||
if( memcmp(buf + iPos, "\x50\x4B\x05\x06", 4) )
|
||||
continue;
|
||||
|
||||
m_pZip->Seek( iRealPos + iPos );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RageFileDriverZip::ParseZipfile()
|
||||
{
|
||||
if( !SeekToEndCentralRecord() )
|
||||
{
|
||||
WARN( ssprintf("Couldn't open %s: couldn't find end of central directory record", m_sPath.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Read the end of central directory record. */
|
||||
int iTotalEntries, iCentralDirectoryOffset;
|
||||
if( !ReadEndCentralRecord(iTotalEntries, iCentralDirectoryOffset) )
|
||||
return false; /* warned already */
|
||||
|
||||
/* Seek to the start of the central file directory. */
|
||||
m_pZip->Seek( iCentralDirectoryOffset );
|
||||
|
||||
/* Loop through files in central directory. */
|
||||
for( int i = 0; i < iTotalEntries; ++i )
|
||||
{
|
||||
FileInfo info;
|
||||
info.m_iDataOffset = -1;
|
||||
int got = ProcessCdirFileHdr( info );
|
||||
if( got == -1 ) /* error */
|
||||
break;
|
||||
if( got == 0 ) /* skip */
|
||||
continue;
|
||||
|
||||
FileInfo *pInfo = new FileInfo( info );
|
||||
m_pFiles.push_back( pInfo );
|
||||
FDB->AddFile( "/" + pInfo->m_sName, pInfo->m_iUncompressedSize, pInfo->m_iCRC32, pInfo );
|
||||
}
|
||||
|
||||
if( m_pFiles.size() == 0 )
|
||||
WARN( ssprintf("%s: no files found in central file header", m_sPath.c_str()) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int RageFileDriverZip::ProcessCdirFileHdr( FileInfo &info )
|
||||
{
|
||||
RString sError;
|
||||
RString sSig = FileReading::ReadString( *m_pZip, 4, sError );
|
||||
if( sSig != "\x50\x4B\x01\x02" )
|
||||
{
|
||||
WARN( ssprintf("%s: central directory record signature not found", m_sPath.c_str()) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
FileReading::read_8( *m_pZip, sError ); /* skip version made by */
|
||||
int iOSMadeBy = FileReading::read_8( *m_pZip, sError );
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip version needed to extract */
|
||||
int iGeneralPurpose = FileReading::read_16_le( *m_pZip, sError );
|
||||
info.m_iCompressionMethod = (ZipCompressionMethod) FileReading::read_16_le( *m_pZip, sError );
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip last mod file time */
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip last mod file date */
|
||||
info.m_iCRC32 = FileReading::read_32_le( *m_pZip, sError );
|
||||
info.m_iCompressedSize = FileReading::read_32_le( *m_pZip, sError );
|
||||
info.m_iUncompressedSize = FileReading::read_32_le( *m_pZip, sError );
|
||||
int iFilenameLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
int iExtraFieldLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
int iFileCommentLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* relative offset of local header */
|
||||
FileReading::read_16_le( *m_pZip, sError ); /* skip internal file attributes */
|
||||
unsigned iExternalFileAttributes = FileReading::read_32_le( *m_pZip, sError );
|
||||
info.m_iOffset = FileReading::read_32_le( *m_pZip, sError );
|
||||
|
||||
/* Check for errors before reading variable-length fields. */
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), sError.c_str()) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
info.m_sName = FileReading::ReadString( *m_pZip, iFilenameLength, sError );
|
||||
FileReading::SkipBytes( *m_pZip, iExtraFieldLength, sError ); /* skip extra field */
|
||||
FileReading::SkipBytes( *m_pZip, iFileCommentLength, sError ); /* skip file comment */
|
||||
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), sError.c_str()) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check usability last, so we always read past the whole entry and don't leave the
|
||||
* file pointer in the middle of a record. */
|
||||
if( iGeneralPurpose & 1 )
|
||||
{
|
||||
WARN( ssprintf("Skipped encrypted \"%s\" in \"%s\"", info.m_sName.c_str(), m_sPath.c_str()) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip directories. */
|
||||
if( iExternalFileAttributes & (1<<4) )
|
||||
return 0;
|
||||
|
||||
info.m_iFilePermissions = 0;
|
||||
enum { MADE_BY_UNIX = 3 };
|
||||
switch( iOSMadeBy )
|
||||
{
|
||||
case MADE_BY_UNIX:
|
||||
info.m_iFilePermissions = (iExternalFileAttributes >> 16) & 0x1FF;
|
||||
break;
|
||||
}
|
||||
|
||||
if( info.m_iCompressionMethod != STORED && info.m_iCompressionMethod != DEFLATED )
|
||||
{
|
||||
WARN( ssprintf("File \"%s\" in \"%s\" uses unsupported compression method %i",
|
||||
info.m_sName.c_str(), m_sPath.c_str(), info.m_iCompressionMethod) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool RageFileDriverZip::ReadLocalFileHeader( FileInfo &info )
|
||||
{
|
||||
/* Seek to and read the local file header. */
|
||||
m_pZip->Seek( info.m_iOffset );
|
||||
|
||||
RString sError;
|
||||
RString sSig = FileReading::ReadString( *m_pZip, 4, sError );
|
||||
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: error opening \"%s\": %s", m_sPath.c_str(), info.m_sName.c_str(), sError.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( sSig != "\x50\x4B\x03\x04" )
|
||||
{
|
||||
WARN( ssprintf("%s: local file header not found for \"%s\"", m_sPath.c_str(), info.m_sName.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
FileReading::SkipBytes( *m_pZip, 22, sError ); /* skip most of the local file header */
|
||||
|
||||
const int iFilenameLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
const int iExtraFieldLength = FileReading::read_16_le( *m_pZip, sError );
|
||||
info.m_iDataOffset = m_pZip->Tell() + iFilenameLength + iExtraFieldLength;
|
||||
|
||||
if( sError != "" )
|
||||
{
|
||||
WARN( ssprintf("%s: %s", m_sPath.c_str(), sError.c_str()) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RageFileDriverZip::~RageFileDriverZip()
|
||||
{
|
||||
for( unsigned i = 0; i < m_pFiles.size(); ++i )
|
||||
delete m_pFiles[i];
|
||||
|
||||
if( m_bFileOwned )
|
||||
delete m_pZip;
|
||||
}
|
||||
|
||||
const RageFileDriverZip::FileInfo *RageFileDriverZip::GetFileInfo( const RString &sPath ) const
|
||||
{
|
||||
return (const FileInfo *) FDB->GetFilePriv( sPath );
|
||||
}
|
||||
|
||||
RageFileBasic *RageFileDriverZip::Open( const RString &sPath, int iMode, int &iErr )
|
||||
{
|
||||
if( iMode & RageFile::WRITE )
|
||||
{
|
||||
iErr = ERROR_WRITING_NOT_SUPPORTED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FileInfo *info = (FileInfo *) FDB->GetFilePriv( sPath );
|
||||
if( info == nullptr )
|
||||
{
|
||||
iErr = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_Mutex.Lock();
|
||||
|
||||
/* If we haven't figured out the offset to the real data yet, do so now. */
|
||||
if( info->m_iDataOffset == -1 )
|
||||
{
|
||||
if( !ReadLocalFileHeader(*info) )
|
||||
{
|
||||
m_Mutex.Unlock();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* We won't do any further access to zip, except to copy it (which is
|
||||
* threadsafe), so we can unlock now. */
|
||||
m_Mutex.Unlock();
|
||||
|
||||
RageFileDriverSlice *pSlice = new RageFileDriverSlice( m_pZip->Copy(), info->m_iDataOffset, info->m_iCompressedSize );
|
||||
pSlice->DeleteFileWhenFinished();
|
||||
|
||||
switch( info->m_iCompressionMethod )
|
||||
{
|
||||
case STORED:
|
||||
return pSlice;
|
||||
case DEFLATED:
|
||||
{
|
||||
RageFileObjInflate *pInflate = new RageFileObjInflate( pSlice, info->m_iUncompressedSize );
|
||||
pInflate->DeleteFileWhenFinished();
|
||||
return pInflate;
|
||||
}
|
||||
default:
|
||||
/* unknown compression method */
|
||||
iErr = ENOSYS;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOP for now. This could check to see if the ZIP's mtime has changed, and reload. */
|
||||
void RageFileDriverZip::FlushDirCache( const RString &sPath )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003-2005 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -502,7 +502,7 @@ bool RageFileManager::Mount( const RString &sType, const RString &sRoot_, const
|
||||
|
||||
CHECKPOINT;
|
||||
RageFileDriver *pDriver = MakeFileDriver( sType, sRoot );
|
||||
if( pDriver == NULL )
|
||||
if( pDriver == nullptr )
|
||||
{
|
||||
CHECKPOINT;
|
||||
|
||||
@@ -595,7 +595,7 @@ void RageFileManager::Unmount( const RString &sType, const RString &sRoot_, cons
|
||||
void RageFileManager::Remount( RString sMountpoint, RString sPath )
|
||||
{
|
||||
RageFileDriver *pDriver = GetFileDriver( sMountpoint );
|
||||
if( pDriver == NULL )
|
||||
if( pDriver == nullptr )
|
||||
{
|
||||
if( LOG )
|
||||
LOG->Warn( "Remount(%s,%s): mountpoint not found", sMountpoint.c_str(), sPath.c_str() );
|
||||
|
||||
+8
-8
@@ -160,7 +160,7 @@ bool RageSound::Load( RString sSoundFilePath, bool bPrecache, const RageSoundLoa
|
||||
{
|
||||
LOG->Trace( "RageSound: Load \"%s\" (precache: %i)", sSoundFilePath.c_str(), bPrecache );
|
||||
|
||||
if( pParams == NULL )
|
||||
if( pParams == nullptr )
|
||||
{
|
||||
static const RageSoundLoadParams Defaults;
|
||||
pParams = &Defaults;
|
||||
@@ -170,12 +170,12 @@ bool RageSound::Load( RString sSoundFilePath, bool bPrecache, const RageSoundLoa
|
||||
* of that. Since RageSoundReader_Preload is refcounted, this is cheap. */
|
||||
RageSoundReader *pSound = SOUNDMAN->GetLoadedSound( sSoundFilePath );
|
||||
bool bNeedBuffer = true;
|
||||
if( pSound == NULL )
|
||||
if( pSound == nullptr )
|
||||
{
|
||||
RString error;
|
||||
bool bPrebuffer;
|
||||
pSound = RageSoundReader_FileReader::OpenFile( sSoundFilePath, error, &bPrebuffer );
|
||||
if( pSound == NULL )
|
||||
if( pSound == nullptr )
|
||||
{
|
||||
LOG->Warn( "RageSound::Load: error opening sound \"%s\": %s",
|
||||
sSoundFilePath.c_str(), error.c_str() );
|
||||
@@ -394,7 +394,7 @@ void RageSound::SoundIsFinishedPlaying()
|
||||
|
||||
void RageSound::Play( const RageSoundParams *pParams )
|
||||
{
|
||||
if( m_pSource == NULL )
|
||||
if( m_pSource == nullptr )
|
||||
{
|
||||
LOG->Warn( "RageSound::Play: sound not loaded" );
|
||||
return;
|
||||
@@ -430,7 +430,7 @@ void RageSound::Stop()
|
||||
|
||||
bool RageSound::Pause( bool bPause )
|
||||
{
|
||||
if( m_pSource == NULL )
|
||||
if( m_pSource == nullptr )
|
||||
{
|
||||
LOG->Warn( "RageSound::Pause: sound not loaded" );
|
||||
return false;
|
||||
@@ -441,7 +441,7 @@ bool RageSound::Pause( bool bPause )
|
||||
|
||||
float RageSound::GetLengthSeconds()
|
||||
{
|
||||
if( m_pSource == NULL )
|
||||
if( m_pSource == nullptr )
|
||||
{
|
||||
LOG->Warn( "RageSound::GetLengthSeconds: sound not loaded" );
|
||||
return -1;
|
||||
@@ -515,7 +515,7 @@ bool RageSound::SetPositionFrames( int iFrames )
|
||||
{
|
||||
LockMut( m_Mutex );
|
||||
|
||||
if( m_pSource == NULL )
|
||||
if( m_pSource == nullptr )
|
||||
{
|
||||
LOG->Warn( "RageSound::SetPositionFrames(%d): sound not loaded", iFrames );
|
||||
return false;
|
||||
@@ -559,7 +559,7 @@ void RageSound::SetParams( const RageSoundParams &p )
|
||||
|
||||
void RageSound::ApplyParams()
|
||||
{
|
||||
if( m_pSource == NULL )
|
||||
if( m_pSource == nullptr )
|
||||
return;
|
||||
|
||||
m_pSource->SetProperty( "Pitch", m_Param.m_fPitch );
|
||||
|
||||
@@ -42,7 +42,7 @@ static LocalizedString COULDNT_FIND_SOUND_DRIVER( "RageSoundManager", "Couldn't
|
||||
void RageSoundManager::Init()
|
||||
{
|
||||
m_pDriver = RageSoundDriver::Create( g_sSoundDrivers );
|
||||
if( m_pDriver == NULL )
|
||||
if( m_pDriver == nullptr )
|
||||
RageException::Throw( "%s", COULDNT_FIND_SOUND_DRIVER.GetValue().c_str() );
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ void RageSoundManager::StopMixing( RageSoundBase *pSound )
|
||||
|
||||
bool RageSoundManager::Pause( RageSoundBase *pSound, bool bPause )
|
||||
{
|
||||
if( m_pDriver == NULL )
|
||||
if( m_pDriver == nullptr )
|
||||
return false;
|
||||
else
|
||||
return m_pDriver->PauseMixing( pSound, bPause );
|
||||
@@ -89,7 +89,7 @@ bool RageSoundManager::Pause( RageSoundBase *pSound, bool bPause )
|
||||
|
||||
int64_t RageSoundManager::GetPosition( RageTimer *pTimer ) const
|
||||
{
|
||||
if( m_pDriver == NULL )
|
||||
if( m_pDriver == nullptr )
|
||||
return 0;
|
||||
return m_pDriver->GetHardwareFrame( pTimer );
|
||||
}
|
||||
@@ -124,7 +124,7 @@ void RageSoundManager::Update()
|
||||
|
||||
float RageSoundManager::GetPlayLatency() const
|
||||
{
|
||||
if( m_pDriver == NULL )
|
||||
if( m_pDriver == nullptr )
|
||||
return 0;
|
||||
|
||||
return m_pDriver->GetPlayLatency();
|
||||
@@ -132,7 +132,7 @@ float RageSoundManager::GetPlayLatency() const
|
||||
|
||||
int RageSoundManager::GetDriverSampleRate() const
|
||||
{
|
||||
if( m_pDriver == NULL )
|
||||
if( m_pDriver == nullptr )
|
||||
return 44100;
|
||||
|
||||
return m_pDriver->GetSampleRate();
|
||||
|
||||
@@ -77,7 +77,7 @@ int RageSoundReader_Chain::LoadSound( RString sPath )
|
||||
RString sError;
|
||||
bool bPrebuffer;
|
||||
RageSoundReader *pReader = RageSoundReader_FileReader::OpenFile( sPath, sError, &bPrebuffer );
|
||||
if( pReader == NULL )
|
||||
if( pReader == nullptr )
|
||||
{
|
||||
LOG->Warn( "RageSoundReader_Chain: error opening sound \"%s\": %s",
|
||||
sPath.c_str(), sError.c_str() );
|
||||
@@ -140,7 +140,7 @@ void RageSoundReader_Chain::Finish()
|
||||
{
|
||||
Sound &sound = m_aSounds[i];
|
||||
|
||||
if( m_apLoadedSounds[sound.iIndex] == NULL )
|
||||
if( m_apLoadedSounds[sound.iIndex] == nullptr )
|
||||
{
|
||||
m_aSounds.erase( m_aSounds.begin()+i );
|
||||
continue;
|
||||
|
||||
@@ -223,7 +223,7 @@ void RageSurfaceUtils::Palettize( RageSurface *&pImg, int iColors, bool bDither
|
||||
{
|
||||
// No; search acolormap for closest match.
|
||||
static int square_table[512], *pSquareTable = NULL;
|
||||
if( pSquareTable == NULL )
|
||||
if( pSquareTable == nullptr )
|
||||
{
|
||||
pSquareTable = square_table+256;
|
||||
for( int c = -256; c < 256; ++c )
|
||||
|
||||
@@ -135,7 +135,7 @@ void RageSurfaceUtils::Zoom( RageSurface *&src, int dstwidth, int dstheight )
|
||||
{
|
||||
ASSERT_M( dstwidth > 0, ssprintf("%i",dstwidth) );
|
||||
ASSERT_M( dstheight > 0, ssprintf("%i",dstheight) );
|
||||
if( src == NULL )
|
||||
if( src == nullptr )
|
||||
return;
|
||||
|
||||
if( src->w == dstwidth && src->h == dstheight )
|
||||
|
||||
+249
-249
@@ -1,249 +1,249 @@
|
||||
#include "global.h"
|
||||
#include "RageSurface_Load_JPEG.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageSurface.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
// work around namespace bugs in win32/libjpeg:
|
||||
#define XMD_H
|
||||
#undef FAR
|
||||
#include "jpeglib.h"
|
||||
#include "jerror.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma comment(lib, "jpeg.lib")
|
||||
#endif
|
||||
|
||||
#pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
|
||||
#else
|
||||
extern "C" {
|
||||
#if defined(MACOSX)
|
||||
#include <../extern/libjpeg/jpeglib.h>
|
||||
#include <../extern/libjpeg/jerror.h>
|
||||
#else
|
||||
#include "jpeglib.h"
|
||||
#include "jerror.h"
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
struct my_jpeg_error_mgr
|
||||
{
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
char errorbuf[JMSG_LENGTH_MAX];
|
||||
};
|
||||
|
||||
|
||||
void my_output_message( j_common_ptr cinfo )
|
||||
{
|
||||
my_jpeg_error_mgr *myerr = (my_jpeg_error_mgr *) cinfo->err;
|
||||
(*cinfo->err->format_message)( cinfo, myerr->errorbuf );
|
||||
}
|
||||
|
||||
|
||||
void my_error_exit( j_common_ptr cinfo )
|
||||
{
|
||||
my_jpeg_error_mgr *myerr = (my_jpeg_error_mgr *) cinfo->err;
|
||||
(*cinfo->err->output_message)(cinfo);
|
||||
|
||||
longjmp( myerr->setjmp_buffer, 1 );
|
||||
}
|
||||
|
||||
struct RageFile_source_mgr
|
||||
{
|
||||
struct jpeg_source_mgr pub; /* public fields */
|
||||
|
||||
RageFile *file; /* source stream */
|
||||
JOCTET buffer[1024*4];
|
||||
bool start_of_file; /* have we gotten any data yet? */
|
||||
};
|
||||
|
||||
void RageFile_JPEG_init_source( j_decompress_ptr cinfo )
|
||||
{
|
||||
RageFile_source_mgr *src = (RageFile_source_mgr *) cinfo->src;
|
||||
src->start_of_file = true;
|
||||
src->pub.next_input_byte = NULL;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
}
|
||||
|
||||
boolean RageFile_JPEG_fill_input_buffer( j_decompress_ptr cinfo )
|
||||
{
|
||||
RageFile_source_mgr *src = (RageFile_source_mgr *) cinfo->src;
|
||||
size_t nbytes = src->file->Read( src->buffer, sizeof(src->buffer) );
|
||||
|
||||
if( nbytes <= 0 )
|
||||
{
|
||||
if( src->start_of_file ) /* Treat empty input file as fatal error */
|
||||
ERREXIT( cinfo, JERR_INPUT_EMPTY );
|
||||
|
||||
WARNMS( cinfo, JWRN_JPEG_EOF );
|
||||
|
||||
/* Insert a fake EOI marker */
|
||||
src->buffer[0] = (JOCTET) 0xFF;
|
||||
src->buffer[1] = (JOCTET) JPEG_EOI;
|
||||
nbytes = 2;
|
||||
}
|
||||
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
src->start_of_file = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void RageFile_JPEG_skip_input_data( j_decompress_ptr cinfo, long num_bytes )
|
||||
{
|
||||
RageFile_source_mgr *src = (RageFile_source_mgr *) cinfo->src;
|
||||
|
||||
int in_buffer = min( (long) src->pub.bytes_in_buffer, num_bytes );
|
||||
src->pub.next_input_byte += in_buffer;
|
||||
src->pub.bytes_in_buffer -= in_buffer;
|
||||
num_bytes -= in_buffer;
|
||||
|
||||
if( num_bytes )
|
||||
src->file->Seek( src->file->Tell() + num_bytes );
|
||||
}
|
||||
|
||||
void RageFile_JPEG_term_source( j_decompress_ptr cinfo )
|
||||
{
|
||||
}
|
||||
|
||||
static RageSurface *RageSurface_Load_JPEG( RageFile *f, const char *fn, char errorbuf[JMSG_LENGTH_MAX] )
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
|
||||
struct my_jpeg_error_mgr jerr;
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
jerr.pub.output_message = my_output_message;
|
||||
|
||||
RageSurface *volatile img = NULL; /* volatile to prevent possible problems with setjmp */
|
||||
|
||||
if( setjmp(jerr.setjmp_buffer) )
|
||||
{
|
||||
my_jpeg_error_mgr *myerr = (my_jpeg_error_mgr *) cinfo.err;
|
||||
memcpy( errorbuf, myerr->errorbuf, JMSG_LENGTH_MAX );
|
||||
|
||||
jpeg_destroy_decompress( &cinfo );
|
||||
delete img;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress( &cinfo );
|
||||
|
||||
/* Step 2: specify data source (eg, a file) */
|
||||
RageFile_source_mgr RageFileJpegSource;
|
||||
RageFileJpegSource.pub.init_source = RageFile_JPEG_init_source;
|
||||
RageFileJpegSource.pub.fill_input_buffer = RageFile_JPEG_fill_input_buffer;
|
||||
RageFileJpegSource.pub.skip_input_data = RageFile_JPEG_skip_input_data;
|
||||
RageFileJpegSource.pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
|
||||
RageFileJpegSource.pub.term_source = RageFile_JPEG_term_source;
|
||||
RageFileJpegSource.file = f;
|
||||
|
||||
cinfo.src = (jpeg_source_mgr *) &RageFileJpegSource;
|
||||
|
||||
jpeg_read_header( &cinfo, TRUE );
|
||||
|
||||
switch( cinfo.jpeg_color_space )
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
cinfo.out_color_space = JCS_GRAYSCALE;
|
||||
break;
|
||||
|
||||
case JCS_YCCK:
|
||||
case JCS_CMYK:
|
||||
sprintf( errorbuf, "Color format \"%s\" not supported", cinfo.jpeg_color_space == JCS_YCCK? "YCCK":"CMYK" );
|
||||
jpeg_destroy_decompress( &cinfo );
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
break;
|
||||
}
|
||||
|
||||
jpeg_start_decompress( &cinfo );
|
||||
|
||||
if( cinfo.out_color_space == JCS_GRAYSCALE )
|
||||
{
|
||||
img = CreateSurface( cinfo.output_width, cinfo.output_height, 8, 0, 0, 0, 0 );
|
||||
|
||||
for( int i = 0; i < 256; ++i )
|
||||
{
|
||||
RageSurfaceColor color;
|
||||
color.r = color.g = color.b = (int8_t) i;
|
||||
color.a = 0xFF;
|
||||
img->fmt.palette->colors[i] = color;
|
||||
}
|
||||
} else {
|
||||
img = CreateSurface( cinfo.output_width, cinfo.output_height, 24,
|
||||
Swap24BE( 0xFF0000 ),
|
||||
Swap24BE( 0x00FF00 ),
|
||||
Swap24BE( 0x0000FF ),
|
||||
Swap24BE( 0x000000 ) );
|
||||
}
|
||||
|
||||
while( cinfo.output_scanline < cinfo.output_height )
|
||||
{
|
||||
JSAMPROW p = (JSAMPROW) img->pixels;
|
||||
p += cinfo.output_scanline * img->pitch;
|
||||
jpeg_read_scanlines(&cinfo, &p, 1);
|
||||
}
|
||||
|
||||
jpeg_finish_decompress( &cinfo );
|
||||
jpeg_destroy_decompress( &cinfo );
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
RageSurfaceUtils::OpenResult RageSurface_Load_JPEG( const RString &sPath, RageSurface *&ret, bool bHeaderOnly, RString &error )
|
||||
{
|
||||
RageFile f;
|
||||
if( !f.Open( sPath ) )
|
||||
{
|
||||
error = f.GetError();
|
||||
return RageSurfaceUtils::OPEN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
char errorbuf[1024];
|
||||
ret = RageSurface_Load_JPEG( &f, sPath, errorbuf );
|
||||
if( ret == NULL )
|
||||
{
|
||||
error = errorbuf;
|
||||
return RageSurfaceUtils::OPEN_UNKNOWN_FILE_FORMAT; // XXX
|
||||
}
|
||||
|
||||
return RageSurfaceUtils::OPEN_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "RageSurface_Load_JPEG.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageSurface.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
// work around namespace bugs in win32/libjpeg:
|
||||
#define XMD_H
|
||||
#undef FAR
|
||||
#include "jpeglib.h"
|
||||
#include "jerror.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma comment(lib, "jpeg.lib")
|
||||
#endif
|
||||
|
||||
#pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
|
||||
#else
|
||||
extern "C" {
|
||||
#if defined(MACOSX)
|
||||
#include <../extern/libjpeg/jpeglib.h>
|
||||
#include <../extern/libjpeg/jerror.h>
|
||||
#else
|
||||
#include "jpeglib.h"
|
||||
#include "jerror.h"
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
struct my_jpeg_error_mgr
|
||||
{
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
char errorbuf[JMSG_LENGTH_MAX];
|
||||
};
|
||||
|
||||
|
||||
void my_output_message( j_common_ptr cinfo )
|
||||
{
|
||||
my_jpeg_error_mgr *myerr = (my_jpeg_error_mgr *) cinfo->err;
|
||||
(*cinfo->err->format_message)( cinfo, myerr->errorbuf );
|
||||
}
|
||||
|
||||
|
||||
void my_error_exit( j_common_ptr cinfo )
|
||||
{
|
||||
my_jpeg_error_mgr *myerr = (my_jpeg_error_mgr *) cinfo->err;
|
||||
(*cinfo->err->output_message)(cinfo);
|
||||
|
||||
longjmp( myerr->setjmp_buffer, 1 );
|
||||
}
|
||||
|
||||
struct RageFile_source_mgr
|
||||
{
|
||||
struct jpeg_source_mgr pub; /* public fields */
|
||||
|
||||
RageFile *file; /* source stream */
|
||||
JOCTET buffer[1024*4];
|
||||
bool start_of_file; /* have we gotten any data yet? */
|
||||
};
|
||||
|
||||
void RageFile_JPEG_init_source( j_decompress_ptr cinfo )
|
||||
{
|
||||
RageFile_source_mgr *src = (RageFile_source_mgr *) cinfo->src;
|
||||
src->start_of_file = true;
|
||||
src->pub.next_input_byte = NULL;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
}
|
||||
|
||||
boolean RageFile_JPEG_fill_input_buffer( j_decompress_ptr cinfo )
|
||||
{
|
||||
RageFile_source_mgr *src = (RageFile_source_mgr *) cinfo->src;
|
||||
size_t nbytes = src->file->Read( src->buffer, sizeof(src->buffer) );
|
||||
|
||||
if( nbytes <= 0 )
|
||||
{
|
||||
if( src->start_of_file ) /* Treat empty input file as fatal error */
|
||||
ERREXIT( cinfo, JERR_INPUT_EMPTY );
|
||||
|
||||
WARNMS( cinfo, JWRN_JPEG_EOF );
|
||||
|
||||
/* Insert a fake EOI marker */
|
||||
src->buffer[0] = (JOCTET) 0xFF;
|
||||
src->buffer[1] = (JOCTET) JPEG_EOI;
|
||||
nbytes = 2;
|
||||
}
|
||||
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
src->start_of_file = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void RageFile_JPEG_skip_input_data( j_decompress_ptr cinfo, long num_bytes )
|
||||
{
|
||||
RageFile_source_mgr *src = (RageFile_source_mgr *) cinfo->src;
|
||||
|
||||
int in_buffer = min( (long) src->pub.bytes_in_buffer, num_bytes );
|
||||
src->pub.next_input_byte += in_buffer;
|
||||
src->pub.bytes_in_buffer -= in_buffer;
|
||||
num_bytes -= in_buffer;
|
||||
|
||||
if( num_bytes )
|
||||
src->file->Seek( src->file->Tell() + num_bytes );
|
||||
}
|
||||
|
||||
void RageFile_JPEG_term_source( j_decompress_ptr cinfo )
|
||||
{
|
||||
}
|
||||
|
||||
static RageSurface *RageSurface_Load_JPEG( RageFile *f, const char *fn, char errorbuf[JMSG_LENGTH_MAX] )
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
|
||||
struct my_jpeg_error_mgr jerr;
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
jerr.pub.output_message = my_output_message;
|
||||
|
||||
RageSurface *volatile img = NULL; /* volatile to prevent possible problems with setjmp */
|
||||
|
||||
if( setjmp(jerr.setjmp_buffer) )
|
||||
{
|
||||
my_jpeg_error_mgr *myerr = (my_jpeg_error_mgr *) cinfo.err;
|
||||
memcpy( errorbuf, myerr->errorbuf, JMSG_LENGTH_MAX );
|
||||
|
||||
jpeg_destroy_decompress( &cinfo );
|
||||
delete img;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress( &cinfo );
|
||||
|
||||
/* Step 2: specify data source (eg, a file) */
|
||||
RageFile_source_mgr RageFileJpegSource;
|
||||
RageFileJpegSource.pub.init_source = RageFile_JPEG_init_source;
|
||||
RageFileJpegSource.pub.fill_input_buffer = RageFile_JPEG_fill_input_buffer;
|
||||
RageFileJpegSource.pub.skip_input_data = RageFile_JPEG_skip_input_data;
|
||||
RageFileJpegSource.pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
|
||||
RageFileJpegSource.pub.term_source = RageFile_JPEG_term_source;
|
||||
RageFileJpegSource.file = f;
|
||||
|
||||
cinfo.src = (jpeg_source_mgr *) &RageFileJpegSource;
|
||||
|
||||
jpeg_read_header( &cinfo, TRUE );
|
||||
|
||||
switch( cinfo.jpeg_color_space )
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
cinfo.out_color_space = JCS_GRAYSCALE;
|
||||
break;
|
||||
|
||||
case JCS_YCCK:
|
||||
case JCS_CMYK:
|
||||
sprintf( errorbuf, "Color format \"%s\" not supported", cinfo.jpeg_color_space == JCS_YCCK? "YCCK":"CMYK" );
|
||||
jpeg_destroy_decompress( &cinfo );
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
break;
|
||||
}
|
||||
|
||||
jpeg_start_decompress( &cinfo );
|
||||
|
||||
if( cinfo.out_color_space == JCS_GRAYSCALE )
|
||||
{
|
||||
img = CreateSurface( cinfo.output_width, cinfo.output_height, 8, 0, 0, 0, 0 );
|
||||
|
||||
for( int i = 0; i < 256; ++i )
|
||||
{
|
||||
RageSurfaceColor color;
|
||||
color.r = color.g = color.b = (int8_t) i;
|
||||
color.a = 0xFF;
|
||||
img->fmt.palette->colors[i] = color;
|
||||
}
|
||||
} else {
|
||||
img = CreateSurface( cinfo.output_width, cinfo.output_height, 24,
|
||||
Swap24BE( 0xFF0000 ),
|
||||
Swap24BE( 0x00FF00 ),
|
||||
Swap24BE( 0x0000FF ),
|
||||
Swap24BE( 0x000000 ) );
|
||||
}
|
||||
|
||||
while( cinfo.output_scanline < cinfo.output_height )
|
||||
{
|
||||
JSAMPROW p = (JSAMPROW) img->pixels;
|
||||
p += cinfo.output_scanline * img->pitch;
|
||||
jpeg_read_scanlines(&cinfo, &p, 1);
|
||||
}
|
||||
|
||||
jpeg_finish_decompress( &cinfo );
|
||||
jpeg_destroy_decompress( &cinfo );
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
RageSurfaceUtils::OpenResult RageSurface_Load_JPEG( const RString &sPath, RageSurface *&ret, bool bHeaderOnly, RString &error )
|
||||
{
|
||||
RageFile f;
|
||||
if( !f.Open( sPath ) )
|
||||
{
|
||||
error = f.GetError();
|
||||
return RageSurfaceUtils::OPEN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
char errorbuf[1024];
|
||||
ret = RageSurface_Load_JPEG( &f, sPath, errorbuf );
|
||||
if( ret == nullptr )
|
||||
{
|
||||
error = errorbuf;
|
||||
return RageSurfaceUtils::OPEN_UNKNOWN_FILE_FORMAT; // XXX
|
||||
}
|
||||
|
||||
return RageSurfaceUtils::OPEN_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -71,14 +71,14 @@ static RageSurface *RageSurface_Load_PNG( RageFile *f, const char *fn, char erro
|
||||
|
||||
png_struct *png = png_create_read_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning );
|
||||
|
||||
if( png == NULL )
|
||||
if( png == nullptr )
|
||||
{
|
||||
sprintf( errorbuf, "creating png_create_read_struct failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_info *info_ptr = png_create_info_struct(png);
|
||||
if( info_ptr == NULL )
|
||||
if( info_ptr == nullptr )
|
||||
{
|
||||
png_destroy_read_struct( &png, NULL, NULL );
|
||||
sprintf( errorbuf, "creating png_create_info_struct failed");
|
||||
@@ -264,7 +264,7 @@ RageSurfaceUtils::OpenResult RageSurface_Load_PNG( const RString &sPath, RageSur
|
||||
|
||||
char errorbuf[1024];
|
||||
ret = RageSurface_Load_PNG( &f, sPath, errorbuf, bHeaderOnly );
|
||||
if( ret == NULL )
|
||||
if( ret == nullptr )
|
||||
{
|
||||
error = errorbuf;
|
||||
return RageSurfaceUtils::OPEN_UNKNOWN_FILE_FORMAT; // XXX
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <map>
|
||||
|
||||
#define CheckLine() \
|
||||
if( xpm[line] == NULL ) { \
|
||||
if( xpm[line] == nullptr ) { \
|
||||
error = "short file"; \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
+181
-181
@@ -1,181 +1,181 @@
|
||||
#include "global.h"
|
||||
#include "RageSurface.h"
|
||||
#include "RageSurfaceUtils.h"
|
||||
#include "RageSurface_Save_JPEG.h"
|
||||
|
||||
#include "RageUtil.h"
|
||||
#include "RageFile.h"
|
||||
|
||||
#undef FAR // fix for VC
|
||||
/** @brief A helper to get the jpeg lib. */
|
||||
namespace jpeg
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#if defined(MACOSX)
|
||||
#include <../extern/libjpeg/jpeglib.h>
|
||||
#else
|
||||
#include "jpeglib.h"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Pull in JPEG library here.
|
||||
#if defined _MSC_VER
|
||||
#pragma comment(lib, "jpeg.lib")
|
||||
#endif
|
||||
|
||||
#define OUTPUT_BUFFER_SIZE 4096
|
||||
typedef struct
|
||||
{
|
||||
struct jpeg::jpeg_destination_mgr pub;
|
||||
|
||||
RageFile *f;
|
||||
uint8_t buffer[OUTPUT_BUFFER_SIZE];
|
||||
} my_destination_mgr;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize source --- called by jpeg_read_header
|
||||
* before any data is actually read.
|
||||
*/
|
||||
static void init_destination( jpeg::j_compress_ptr cinfo )
|
||||
{
|
||||
/* nop */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Empty the output buffer; called whenever buffer is full. */
|
||||
static jpeg::boolean empty_output_buffer( jpeg::j_compress_ptr cinfo )
|
||||
{
|
||||
my_destination_mgr * dest = (my_destination_mgr *) cinfo->dest;
|
||||
dest->f->Write( dest->buffer, OUTPUT_BUFFER_SIZE );
|
||||
// XXX err
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUFFER_SIZE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Terminate source --- called by jpeg_finish_decompress
|
||||
* after all data has been read.
|
||||
*/
|
||||
static void term_destination (jpeg::j_compress_ptr cinfo)
|
||||
{
|
||||
/* Write data remaining in the buffer */
|
||||
my_destination_mgr *dest = (my_destination_mgr *) cinfo->dest;
|
||||
dest->f->Write( dest->buffer, OUTPUT_BUFFER_SIZE - dest->pub.free_in_buffer );
|
||||
// XXX err
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare for output to a stdio stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing decompression.
|
||||
*/
|
||||
static void jpeg_RageFile_dest( jpeg::j_compress_ptr cinfo, RageFile &f )
|
||||
{
|
||||
ASSERT( cinfo->dest == NULL );
|
||||
|
||||
cinfo->dest = (struct jpeg::jpeg_destination_mgr *)
|
||||
(*cinfo->mem->alloc_small) ( (jpeg::j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof(my_destination_mgr) );
|
||||
|
||||
my_destination_mgr *dest = (my_destination_mgr *) cinfo->dest;
|
||||
dest->pub.init_destination = init_destination;
|
||||
dest->pub.empty_output_buffer = empty_output_buffer;
|
||||
dest->pub.term_destination = term_destination;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUFFER_SIZE; /* forces fill_input_buffer on first read */
|
||||
dest->pub.next_output_byte = dest->buffer; /* until buffer loaded */
|
||||
|
||||
dest->f = &f;
|
||||
}
|
||||
|
||||
/* Save a JPEG to a file. cjpeg.c and example.c from jpeglib were helpful in writing this. */
|
||||
bool RageSurfaceUtils::SaveJPEG( RageSurface *surface, RageFile &f, bool bHighQual )
|
||||
{
|
||||
RageSurface *dst_surface;
|
||||
if( RageSurfaceUtils::ConvertSurface( surface, dst_surface,
|
||||
surface->w, surface->h, 24, Swap24BE(0xFF0000), Swap24BE(0x00FF00), Swap24BE(0x0000FF), 0 ) )
|
||||
surface = dst_surface;
|
||||
|
||||
struct jpeg::jpeg_compress_struct cinfo;
|
||||
|
||||
/* Set up the error handler. */
|
||||
struct jpeg::jpeg_error_mgr jerr;
|
||||
cinfo.err = jpeg::jpeg_std_error( &jerr );
|
||||
|
||||
/* Now we can initialize the JPEG compression object. */
|
||||
jpeg::jpeg_CreateCompress(&cinfo, JPEG_LIB_VERSION, \
|
||||
(size_t) sizeof(struct jpeg::jpeg_compress_struct));
|
||||
|
||||
cinfo.image_width = surface->w; /* image width and height, in pixels */
|
||||
cinfo.image_height = surface->h;
|
||||
cinfo.input_components = 3; /* # of color components per pixel */
|
||||
cinfo.in_color_space = jpeg::JCS_RGB; /* colorspace of input image */
|
||||
|
||||
/* Set compression parameters. You must set at least cinfo.in_color_space before
|
||||
* calling this.*/
|
||||
jpeg::jpeg_set_defaults(&cinfo);
|
||||
|
||||
if( bHighQual )
|
||||
jpeg::jpeg_set_quality( &cinfo, 150, TRUE );
|
||||
else
|
||||
jpeg::jpeg_set_quality( &cinfo, 70, TRUE );
|
||||
|
||||
jpeg_RageFile_dest( &cinfo, f );
|
||||
|
||||
/* Start the compressor. */
|
||||
jpeg::jpeg_start_compress( &cinfo, TRUE );
|
||||
|
||||
/* Here we use the library's state variable cinfo.next_scanline as the
|
||||
* loop counter, so that we don't have to keep track ourselves.
|
||||
* To keep things simple, we pass one scanline per call; you can pass
|
||||
* more if you wish, though. */
|
||||
const int row_stride = surface->pitch; /* JSAMPLEs per row in image_buffer */
|
||||
|
||||
while( cinfo.next_scanline < cinfo.image_height )
|
||||
{
|
||||
/* jpeg_write_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could pass
|
||||
* more than one scanline at a time if that's more convenient. */
|
||||
jpeg::JSAMPROW row_pointer = & ((jpeg::JSAMPLE*)surface->pixels)[cinfo.next_scanline * row_stride];
|
||||
jpeg::jpeg_write_scanlines( &cinfo, &row_pointer, 1 );
|
||||
}
|
||||
|
||||
/* Finish compression. */
|
||||
jpeg::jpeg_finish_compress( &cinfo );
|
||||
jpeg::jpeg_destroy_compress( &cinfo );
|
||||
|
||||
delete dst_surface;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 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.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "RageSurface.h"
|
||||
#include "RageSurfaceUtils.h"
|
||||
#include "RageSurface_Save_JPEG.h"
|
||||
|
||||
#include "RageUtil.h"
|
||||
#include "RageFile.h"
|
||||
|
||||
#undef FAR // fix for VC
|
||||
/** @brief A helper to get the jpeg lib. */
|
||||
namespace jpeg
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#if defined(MACOSX)
|
||||
#include <../extern/libjpeg/jpeglib.h>
|
||||
#else
|
||||
#include "jpeglib.h"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Pull in JPEG library here.
|
||||
#if defined _MSC_VER
|
||||
#pragma comment(lib, "jpeg.lib")
|
||||
#endif
|
||||
|
||||
#define OUTPUT_BUFFER_SIZE 4096
|
||||
typedef struct
|
||||
{
|
||||
struct jpeg::jpeg_destination_mgr pub;
|
||||
|
||||
RageFile *f;
|
||||
uint8_t buffer[OUTPUT_BUFFER_SIZE];
|
||||
} my_destination_mgr;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize source --- called by jpeg_read_header
|
||||
* before any data is actually read.
|
||||
*/
|
||||
static void init_destination( jpeg::j_compress_ptr cinfo )
|
||||
{
|
||||
/* nop */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Empty the output buffer; called whenever buffer is full. */
|
||||
static jpeg::boolean empty_output_buffer( jpeg::j_compress_ptr cinfo )
|
||||
{
|
||||
my_destination_mgr * dest = (my_destination_mgr *) cinfo->dest;
|
||||
dest->f->Write( dest->buffer, OUTPUT_BUFFER_SIZE );
|
||||
// XXX err
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUFFER_SIZE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Terminate source --- called by jpeg_finish_decompress
|
||||
* after all data has been read.
|
||||
*/
|
||||
static void term_destination (jpeg::j_compress_ptr cinfo)
|
||||
{
|
||||
/* Write data remaining in the buffer */
|
||||
my_destination_mgr *dest = (my_destination_mgr *) cinfo->dest;
|
||||
dest->f->Write( dest->buffer, OUTPUT_BUFFER_SIZE - dest->pub.free_in_buffer );
|
||||
// XXX err
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare for output to a stdio stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing decompression.
|
||||
*/
|
||||
static void jpeg_RageFile_dest( jpeg::j_compress_ptr cinfo, RageFile &f )
|
||||
{
|
||||
ASSERT( cinfo->dest == nullptr );
|
||||
|
||||
cinfo->dest = (struct jpeg::jpeg_destination_mgr *)
|
||||
(*cinfo->mem->alloc_small) ( (jpeg::j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof(my_destination_mgr) );
|
||||
|
||||
my_destination_mgr *dest = (my_destination_mgr *) cinfo->dest;
|
||||
dest->pub.init_destination = init_destination;
|
||||
dest->pub.empty_output_buffer = empty_output_buffer;
|
||||
dest->pub.term_destination = term_destination;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUFFER_SIZE; /* forces fill_input_buffer on first read */
|
||||
dest->pub.next_output_byte = dest->buffer; /* until buffer loaded */
|
||||
|
||||
dest->f = &f;
|
||||
}
|
||||
|
||||
/* Save a JPEG to a file. cjpeg.c and example.c from jpeglib were helpful in writing this. */
|
||||
bool RageSurfaceUtils::SaveJPEG( RageSurface *surface, RageFile &f, bool bHighQual )
|
||||
{
|
||||
RageSurface *dst_surface;
|
||||
if( RageSurfaceUtils::ConvertSurface( surface, dst_surface,
|
||||
surface->w, surface->h, 24, Swap24BE(0xFF0000), Swap24BE(0x00FF00), Swap24BE(0x0000FF), 0 ) )
|
||||
surface = dst_surface;
|
||||
|
||||
struct jpeg::jpeg_compress_struct cinfo;
|
||||
|
||||
/* Set up the error handler. */
|
||||
struct jpeg::jpeg_error_mgr jerr;
|
||||
cinfo.err = jpeg::jpeg_std_error( &jerr );
|
||||
|
||||
/* Now we can initialize the JPEG compression object. */
|
||||
jpeg::jpeg_CreateCompress(&cinfo, JPEG_LIB_VERSION, \
|
||||
(size_t) sizeof(struct jpeg::jpeg_compress_struct));
|
||||
|
||||
cinfo.image_width = surface->w; /* image width and height, in pixels */
|
||||
cinfo.image_height = surface->h;
|
||||
cinfo.input_components = 3; /* # of color components per pixel */
|
||||
cinfo.in_color_space = jpeg::JCS_RGB; /* colorspace of input image */
|
||||
|
||||
/* Set compression parameters. You must set at least cinfo.in_color_space before
|
||||
* calling this.*/
|
||||
jpeg::jpeg_set_defaults(&cinfo);
|
||||
|
||||
if( bHighQual )
|
||||
jpeg::jpeg_set_quality( &cinfo, 150, TRUE );
|
||||
else
|
||||
jpeg::jpeg_set_quality( &cinfo, 70, TRUE );
|
||||
|
||||
jpeg_RageFile_dest( &cinfo, f );
|
||||
|
||||
/* Start the compressor. */
|
||||
jpeg::jpeg_start_compress( &cinfo, TRUE );
|
||||
|
||||
/* Here we use the library's state variable cinfo.next_scanline as the
|
||||
* loop counter, so that we don't have to keep track ourselves.
|
||||
* To keep things simple, we pass one scanline per call; you can pass
|
||||
* more if you wish, though. */
|
||||
const int row_stride = surface->pitch; /* JSAMPLEs per row in image_buffer */
|
||||
|
||||
while( cinfo.next_scanline < cinfo.image_height )
|
||||
{
|
||||
/* jpeg_write_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could pass
|
||||
* more than one scanline at a time if that's more convenient. */
|
||||
jpeg::JSAMPROW row_pointer = & ((jpeg::JSAMPLE*)surface->pixels)[cinfo.next_scanline * row_stride];
|
||||
jpeg::jpeg_write_scanlines( &cinfo, &row_pointer, 1 );
|
||||
}
|
||||
|
||||
/* Finish compression. */
|
||||
jpeg::jpeg_finish_compress( &cinfo );
|
||||
jpeg::jpeg_destroy_compress( &cinfo );
|
||||
|
||||
delete dst_surface;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 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.
|
||||
*/
|
||||
|
||||
@@ -81,14 +81,14 @@ static bool RageSurface_Save_PNG( RageFile &f, char szErrorbuf[1024], RageSurfac
|
||||
error.szErr = szErrorbuf;
|
||||
|
||||
png_struct *pPng = png_create_write_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning );
|
||||
if( pPng == NULL )
|
||||
if( pPng == nullptr )
|
||||
{
|
||||
sprintf( szErrorbuf, "creating png_create_write_struct failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
png_info *pInfo = png_create_info_struct(pPng);
|
||||
if( pInfo == NULL )
|
||||
if( pInfo == nullptr )
|
||||
{
|
||||
png_destroy_read_struct( &pPng, NULL, NULL );
|
||||
if( bDeleteImg )
|
||||
|
||||
@@ -176,7 +176,7 @@ void RageTextureManager::VolatileTexture( RageTextureID ID )
|
||||
|
||||
void RageTextureManager::UnloadTexture( RageTexture *t )
|
||||
{
|
||||
if( t == NULL )
|
||||
if( t == nullptr )
|
||||
return;
|
||||
|
||||
t->m_iRefCount--;
|
||||
|
||||
@@ -35,7 +35,7 @@ void RageTexturePreloader::Load( const RageTextureID &ID )
|
||||
|
||||
void RageTexturePreloader::UnloadAll()
|
||||
{
|
||||
if( TEXTUREMAN == NULL )
|
||||
if( TEXTUREMAN == nullptr )
|
||||
return;
|
||||
|
||||
for( unsigned i = 0; i < m_apTextures.size(); ++i )
|
||||
|
||||
+12
-12
@@ -97,7 +97,7 @@ void ThreadSlot::ThreadCheckpoint::Set( const char *szFile, int iLine, const cha
|
||||
if( m_szFile != nullptr )
|
||||
{
|
||||
const char *p = strrchr( m_szFile, '/' );
|
||||
if( p == NULL )
|
||||
if( p == nullptr )
|
||||
p = strrchr( m_szFile, '\\' );
|
||||
if( p != nullptr && p[1] != '\0' )
|
||||
m_szFile = p+1;
|
||||
@@ -108,7 +108,7 @@ void ThreadSlot::ThreadCheckpoint::Set( const char *szFile, int iLine, const cha
|
||||
|
||||
const char *ThreadSlot::ThreadCheckpoint::GetFormattedCheckpoint()
|
||||
{
|
||||
if( m_szFile == NULL )
|
||||
if( m_szFile == nullptr )
|
||||
return NULL;
|
||||
|
||||
/* Make sure it's terminated: */
|
||||
@@ -231,7 +231,7 @@ const char *ThreadSlot::GetThreadName() const
|
||||
void RageThread::Create( int (*fn)(void *), void *data )
|
||||
{
|
||||
/* Don't create a thread that's already running: */
|
||||
ASSERT( m_pSlot == NULL );
|
||||
ASSERT( m_pSlot == nullptr );
|
||||
|
||||
InitThreads();
|
||||
|
||||
@@ -286,7 +286,7 @@ const char *RageThread::GetCurrentThreadName()
|
||||
const char *RageThread::GetThreadNameByID( uint64_t iID )
|
||||
{
|
||||
ThreadSlot *slot = GetThreadSlotFromID( iID );
|
||||
if( slot == NULL )
|
||||
if( slot == nullptr )
|
||||
return "???";
|
||||
|
||||
return slot->GetThreadName();
|
||||
@@ -341,7 +341,7 @@ void RageThread::HaltAllThreads( bool Kill )
|
||||
{
|
||||
if( !g_ThreadSlots[entry].m_bUsed )
|
||||
continue;
|
||||
if( ThisThreadID == g_ThreadSlots[entry].m_iID || g_ThreadSlots[entry].m_pImpl == NULL )
|
||||
if( ThisThreadID == g_ThreadSlots[entry].m_iID || g_ThreadSlots[entry].m_pImpl == nullptr )
|
||||
continue;
|
||||
g_ThreadSlots[entry].m_pImpl->Halt( Kill );
|
||||
}
|
||||
@@ -354,7 +354,7 @@ void RageThread::ResumeAllThreads()
|
||||
{
|
||||
if( !g_ThreadSlots[entry].m_bUsed )
|
||||
continue;
|
||||
if( ThisThreadID == g_ThreadSlots[entry].m_iID || g_ThreadSlots[entry].m_pImpl == NULL )
|
||||
if( ThisThreadID == g_ThreadSlots[entry].m_iID || g_ThreadSlots[entry].m_pImpl == nullptr )
|
||||
continue;
|
||||
|
||||
g_ThreadSlots[entry].m_pImpl->Resume();
|
||||
@@ -381,10 +381,10 @@ void Checkpoints::LogCheckpoints( bool on )
|
||||
void Checkpoints::SetCheckpoint( const char *file, int line, const char *message )
|
||||
{
|
||||
ThreadSlot *slot = GetCurThreadSlot();
|
||||
if( slot == NULL )
|
||||
if( slot == nullptr )
|
||||
slot = GetUnknownThreadSlot();
|
||||
/* We can't ASSERT here, since that uses checkpoints. */
|
||||
if( slot == NULL )
|
||||
if( slot == nullptr )
|
||||
sm_crash( "GetUnknownThreadSlot() returned NULL" );
|
||||
|
||||
/* Ignore everything up to and including the first "src/". */
|
||||
@@ -409,7 +409,7 @@ static const char *GetCheckpointLog( int slotno, int lineno )
|
||||
return NULL;
|
||||
|
||||
/* Only show the "Unknown thread" entry if it has at least one checkpoint. */
|
||||
if( &slot == g_pUnknownThreadSlot && slot.GetFormattedCheckpoint(0) == NULL )
|
||||
if( &slot == g_pUnknownThreadSlot && slot.GetFormattedCheckpoint(0) == nullptr )
|
||||
return NULL;
|
||||
|
||||
if( lineno != 0 )
|
||||
@@ -427,7 +427,7 @@ void Checkpoints::GetLogs( char *pBuf, int iSize, const char *delim )
|
||||
for( int slotno = 0; slotno < MAX_THREADS; ++slotno )
|
||||
{
|
||||
const char *buf = GetCheckpointLog( slotno, 0 );
|
||||
if( buf == NULL )
|
||||
if( buf == nullptr )
|
||||
continue;
|
||||
strcat( pBuf, buf );
|
||||
strcat( pBuf, delim );
|
||||
@@ -529,7 +529,7 @@ RageMutex::RageMutex( const RString &name ):
|
||||
m_LockedBy(GetInvalidThreadId()), m_LockCnt(0)
|
||||
{
|
||||
|
||||
/* if( g_FreeMutexIDs == NULL )
|
||||
/* if( g_FreeMutexIDs == nullptr )
|
||||
{
|
||||
g_FreeMutexIDs = new set<int>;
|
||||
for( int i = 0; i < MAX_MUTEXES; ++i )
|
||||
@@ -554,7 +554,7 @@ RageMutex::RageMutex( const RString &name ):
|
||||
|
||||
g_FreeMutexIDs->erase( g_FreeMutexIDs->begin() );
|
||||
|
||||
if( g_MutexList == NULL )
|
||||
if( g_MutexList == nullptr )
|
||||
g_MutexList = new vector<RageMutex*>;
|
||||
|
||||
g_MutexList->push_back( this );
|
||||
|
||||
+1
-1
@@ -1349,7 +1349,7 @@ void Regex::Compile()
|
||||
int offset;
|
||||
m_pReg = pcre_compile( m_sPattern.c_str(), PCRE_CASELESS, &error, &offset, NULL );
|
||||
|
||||
if( m_pReg == NULL )
|
||||
if( m_pReg == nullptr )
|
||||
RageException::Throw( "Invalid regex: \"%s\" (%s).", m_sPattern.c_str(), error );
|
||||
|
||||
int iRet = pcre_fullinfo( (pcre *) m_pReg, NULL, PCRE_INFO_CAPTURECOUNT, &m_iBackrefs );
|
||||
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
template<class U>
|
||||
HiddenPtr( const HiddenPtr<U> &cpy )
|
||||
{
|
||||
if( cpy.m_pPtr == NULL )
|
||||
if( cpy.m_pPtr == nullptr )
|
||||
m_pPtr = NULL;
|
||||
else
|
||||
m_pPtr = HiddenPtrTraits<U>::Copy( cpy.m_pPtr );
|
||||
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
CachedObjectHelpers::Lock();
|
||||
for( typename set<ObjectPointer *>::iterator p = m_spObjectPointers.begin(); p != m_spObjectPointers.end(); ++p )
|
||||
{
|
||||
if( (*p)->m_pCache == NULL )
|
||||
if( (*p)->m_pCache == nullptr )
|
||||
(*p)->m_bCacheIsSet = false;
|
||||
}
|
||||
CachedObjectHelpers::Unlock();
|
||||
|
||||
+171
-171
@@ -1,171 +1,171 @@
|
||||
#include "global.h"
|
||||
#include "RageUtil_CharConversions.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
#include <windows.h>
|
||||
|
||||
/* Convert from the given codepage to UTF-8. Return true if successful. */
|
||||
static bool CodePageConvert( RString &sText, int iCodePage )
|
||||
{
|
||||
int iSize = MultiByteToWideChar( iCodePage, MB_ERR_INVALID_CHARS, sText.data(), sText.size(), NULL, 0 );
|
||||
if( iSize == 0 )
|
||||
{
|
||||
LOG->Trace( "%s\n", werr_ssprintf(GetLastError(), "err: ").c_str() );
|
||||
return false; /* error */
|
||||
}
|
||||
|
||||
wstring sOut;
|
||||
sOut.append( iSize, ' ' );
|
||||
/* Nonportable: */
|
||||
iSize = MultiByteToWideChar( iCodePage, MB_ERR_INVALID_CHARS, sText.data(), sText.size(), (wchar_t *) sOut.data(), iSize );
|
||||
ASSERT( iSize != 0 );
|
||||
|
||||
sText = WStringToRString( sOut );
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool AttemptEnglishConversion( RString &sText ) { return CodePageConvert( sText, 1252 ); }
|
||||
static bool AttemptKoreanConversion( RString &sText ) { return CodePageConvert( sText, 949 ); }
|
||||
static bool AttemptJapaneseConversion( RString &sText ) { return CodePageConvert( sText, 932 ); }
|
||||
|
||||
#elif defined(HAVE_ICONV)
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
|
||||
static bool ConvertFromCharset( RString &sText, const char *szCharset )
|
||||
{
|
||||
iconv_t converter = iconv_open( "UTF-8", szCharset );
|
||||
if( converter == (iconv_t) -1 )
|
||||
{
|
||||
LOG->MapLog( ssprintf("conv %s", szCharset), "iconv_open(%s): %s", szCharset, strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Copy the string into a char* for iconv */
|
||||
ICONV_CONST char *szTextIn = const_cast<ICONV_CONST char*>( sText.data() );
|
||||
size_t iInLeft = sText.size();
|
||||
|
||||
/* Create a new string with enough room for the new conversion */
|
||||
RString sBuf;
|
||||
sBuf.resize( sText.size() * 5 );
|
||||
|
||||
char *sTextOut = const_cast<char*>( sBuf.data() );
|
||||
size_t iOutLeft = sBuf.size();
|
||||
size_t size = iconv( converter, &szTextIn, &iInLeft, &sTextOut, &iOutLeft );
|
||||
|
||||
iconv_close( converter );
|
||||
|
||||
if( size == (size_t)(-1) )
|
||||
{
|
||||
LOG->Trace( "%s\n", strerror( errno ) );
|
||||
return false; /* Returned an error */
|
||||
}
|
||||
|
||||
if( iInLeft != 0 )
|
||||
{
|
||||
LOG->Warn( "iconv(UTF-8,%s) for \"%s\": whole buffer not converted (%i left)", szCharset, sText.c_str(), int(iInLeft) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( sBuf.size() == iOutLeft )
|
||||
return false; /* Conversion failed */
|
||||
|
||||
sBuf.resize( sBuf.size()-iOutLeft );
|
||||
|
||||
sText = sBuf;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool AttemptEnglishConversion( RString &sText ) { return ConvertFromCharset( sText, "CP1252" ); }
|
||||
static bool AttemptKoreanConversion( RString &sText ) { return ConvertFromCharset( sText, "CP949" ); }
|
||||
static bool AttemptJapaneseConversion( RString &sText ) { return ConvertFromCharset( sText, "CP932" ); }
|
||||
|
||||
#elif defined(MACOSX)
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
static bool ConvertFromCP( RString &sText, int iCodePage )
|
||||
{
|
||||
CFStringEncoding encoding = CFStringConvertWindowsCodepageToEncoding( iCodePage );
|
||||
|
||||
if( encoding == kCFStringEncodingInvalidId )
|
||||
return false;
|
||||
|
||||
CFStringRef old = CFStringCreateWithCString( kCFAllocatorDefault, sText, encoding );
|
||||
|
||||
if( old == NULL )
|
||||
return false;
|
||||
const size_t size = CFStringGetMaximumSizeForEncoding( CFStringGetLength(old), kCFStringEncodingUTF8 );
|
||||
|
||||
char *buf = new char[size+1];
|
||||
buf[0] = '\0';
|
||||
bool result = CFStringGetCString( old, buf, size, kCFStringEncodingUTF8 );
|
||||
sText = buf;
|
||||
delete[] buf;
|
||||
CFRelease( old );
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool AttemptEnglishConversion( RString &sText ) { return ConvertFromCP( sText, 1252 ); }
|
||||
static bool AttemptKoreanConversion( RString &sText ) { return ConvertFromCP( sText, 949 ); }
|
||||
static bool AttemptJapaneseConversion( RString &sText ) { return ConvertFromCP( sText, 932 ); }
|
||||
|
||||
#else
|
||||
|
||||
/* No converters are available, so all fail--we only accept UTF-8. */
|
||||
static bool AttemptEnglishConversion( RString &sText ) { return false; }
|
||||
static bool AttemptKoreanConversion( RString &sText ) { return false; }
|
||||
static bool AttemptJapaneseConversion( RString &sText ) { return false; }
|
||||
|
||||
#endif
|
||||
|
||||
bool ConvertString( RString &str, const RString &encodings )
|
||||
{
|
||||
if( str.empty() )
|
||||
return true;
|
||||
|
||||
vector<RString> lst;
|
||||
split( encodings, ",", lst );
|
||||
|
||||
for(unsigned i = 0; i < lst.size(); ++i)
|
||||
{
|
||||
if( lst[i] == "utf-8" )
|
||||
{
|
||||
/* Is the string already valid utf-8? */
|
||||
if( utf8_is_valid(str) )
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
if( lst[i] == "english" )
|
||||
{
|
||||
if( AttemptEnglishConversion(str) )
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( lst[i] == "japanese" )
|
||||
{
|
||||
if( AttemptJapaneseConversion(str) )
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( lst[i] == "korean" )
|
||||
{
|
||||
if( AttemptKoreanConversion(str) )
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
RageException::Throw( "Unexpected conversion string \"%s\" (string \"%s\").",
|
||||
lst[i].c_str(), str.c_str() );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Written by Glenn Maynard. In the public domain; there are so many
|
||||
* simple conversion interfaces that restricting them is silly. */
|
||||
#include "global.h"
|
||||
#include "RageUtil_CharConversions.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
#include <windows.h>
|
||||
|
||||
/* Convert from the given codepage to UTF-8. Return true if successful. */
|
||||
static bool CodePageConvert( RString &sText, int iCodePage )
|
||||
{
|
||||
int iSize = MultiByteToWideChar( iCodePage, MB_ERR_INVALID_CHARS, sText.data(), sText.size(), NULL, 0 );
|
||||
if( iSize == 0 )
|
||||
{
|
||||
LOG->Trace( "%s\n", werr_ssprintf(GetLastError(), "err: ").c_str() );
|
||||
return false; /* error */
|
||||
}
|
||||
|
||||
wstring sOut;
|
||||
sOut.append( iSize, ' ' );
|
||||
/* Nonportable: */
|
||||
iSize = MultiByteToWideChar( iCodePage, MB_ERR_INVALID_CHARS, sText.data(), sText.size(), (wchar_t *) sOut.data(), iSize );
|
||||
ASSERT( iSize != 0 );
|
||||
|
||||
sText = WStringToRString( sOut );
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool AttemptEnglishConversion( RString &sText ) { return CodePageConvert( sText, 1252 ); }
|
||||
static bool AttemptKoreanConversion( RString &sText ) { return CodePageConvert( sText, 949 ); }
|
||||
static bool AttemptJapaneseConversion( RString &sText ) { return CodePageConvert( sText, 932 ); }
|
||||
|
||||
#elif defined(HAVE_ICONV)
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
|
||||
static bool ConvertFromCharset( RString &sText, const char *szCharset )
|
||||
{
|
||||
iconv_t converter = iconv_open( "UTF-8", szCharset );
|
||||
if( converter == (iconv_t) -1 )
|
||||
{
|
||||
LOG->MapLog( ssprintf("conv %s", szCharset), "iconv_open(%s): %s", szCharset, strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Copy the string into a char* for iconv */
|
||||
ICONV_CONST char *szTextIn = const_cast<ICONV_CONST char*>( sText.data() );
|
||||
size_t iInLeft = sText.size();
|
||||
|
||||
/* Create a new string with enough room for the new conversion */
|
||||
RString sBuf;
|
||||
sBuf.resize( sText.size() * 5 );
|
||||
|
||||
char *sTextOut = const_cast<char*>( sBuf.data() );
|
||||
size_t iOutLeft = sBuf.size();
|
||||
size_t size = iconv( converter, &szTextIn, &iInLeft, &sTextOut, &iOutLeft );
|
||||
|
||||
iconv_close( converter );
|
||||
|
||||
if( size == (size_t)(-1) )
|
||||
{
|
||||
LOG->Trace( "%s\n", strerror( errno ) );
|
||||
return false; /* Returned an error */
|
||||
}
|
||||
|
||||
if( iInLeft != 0 )
|
||||
{
|
||||
LOG->Warn( "iconv(UTF-8,%s) for \"%s\": whole buffer not converted (%i left)", szCharset, sText.c_str(), int(iInLeft) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( sBuf.size() == iOutLeft )
|
||||
return false; /* Conversion failed */
|
||||
|
||||
sBuf.resize( sBuf.size()-iOutLeft );
|
||||
|
||||
sText = sBuf;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool AttemptEnglishConversion( RString &sText ) { return ConvertFromCharset( sText, "CP1252" ); }
|
||||
static bool AttemptKoreanConversion( RString &sText ) { return ConvertFromCharset( sText, "CP949" ); }
|
||||
static bool AttemptJapaneseConversion( RString &sText ) { return ConvertFromCharset( sText, "CP932" ); }
|
||||
|
||||
#elif defined(MACOSX)
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
static bool ConvertFromCP( RString &sText, int iCodePage )
|
||||
{
|
||||
CFStringEncoding encoding = CFStringConvertWindowsCodepageToEncoding( iCodePage );
|
||||
|
||||
if( encoding == kCFStringEncodingInvalidId )
|
||||
return false;
|
||||
|
||||
CFStringRef old = CFStringCreateWithCString( kCFAllocatorDefault, sText, encoding );
|
||||
|
||||
if( old == nullptr )
|
||||
return false;
|
||||
const size_t size = CFStringGetMaximumSizeForEncoding( CFStringGetLength(old), kCFStringEncodingUTF8 );
|
||||
|
||||
char *buf = new char[size+1];
|
||||
buf[0] = '\0';
|
||||
bool result = CFStringGetCString( old, buf, size, kCFStringEncodingUTF8 );
|
||||
sText = buf;
|
||||
delete[] buf;
|
||||
CFRelease( old );
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool AttemptEnglishConversion( RString &sText ) { return ConvertFromCP( sText, 1252 ); }
|
||||
static bool AttemptKoreanConversion( RString &sText ) { return ConvertFromCP( sText, 949 ); }
|
||||
static bool AttemptJapaneseConversion( RString &sText ) { return ConvertFromCP( sText, 932 ); }
|
||||
|
||||
#else
|
||||
|
||||
/* No converters are available, so all fail--we only accept UTF-8. */
|
||||
static bool AttemptEnglishConversion( RString &sText ) { return false; }
|
||||
static bool AttemptKoreanConversion( RString &sText ) { return false; }
|
||||
static bool AttemptJapaneseConversion( RString &sText ) { return false; }
|
||||
|
||||
#endif
|
||||
|
||||
bool ConvertString( RString &str, const RString &encodings )
|
||||
{
|
||||
if( str.empty() )
|
||||
return true;
|
||||
|
||||
vector<RString> lst;
|
||||
split( encodings, ",", lst );
|
||||
|
||||
for(unsigned i = 0; i < lst.size(); ++i)
|
||||
{
|
||||
if( lst[i] == "utf-8" )
|
||||
{
|
||||
/* Is the string already valid utf-8? */
|
||||
if( utf8_is_valid(str) )
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
if( lst[i] == "english" )
|
||||
{
|
||||
if( AttemptEnglishConversion(str) )
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( lst[i] == "japanese" )
|
||||
{
|
||||
if( AttemptJapaneseConversion(str) )
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( lst[i] == "korean" )
|
||||
{
|
||||
if( AttemptKoreanConversion(str) )
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
RageException::Throw( "Unexpected conversion string \"%s\" (string \"%s\").",
|
||||
lst[i].c_str(), str.c_str() );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Written by Glenn Maynard. In the public domain; there are so many
|
||||
* simple conversion interfaces that restricting them is silly. */
|
||||
|
||||
@@ -181,7 +181,7 @@ bool FilenameDB::ResolvePath( RString &sPath )
|
||||
if( iBegin == (int) sPath.size() )
|
||||
break;
|
||||
|
||||
if( fs == NULL )
|
||||
if( fs == nullptr )
|
||||
fs = GetFileSet( ret );
|
||||
else
|
||||
m_Mutex.Lock(); /* for access to fs */
|
||||
|
||||
@@ -58,7 +58,7 @@ class IDebugLine
|
||||
public:
|
||||
IDebugLine()
|
||||
{
|
||||
if( g_pvpSubscribers == NULL )
|
||||
if( g_pvpSubscribers == nullptr )
|
||||
g_pvpSubscribers = new vector<IDebugLine*>;
|
||||
g_pvpSubscribers->push_back( this );
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ void ScreenDemonstration::Init()
|
||||
|
||||
ScreenJukebox::Init();
|
||||
|
||||
if( GAMESTATE->m_pCurSong == NULL ) // we didn't find a song.
|
||||
if( GAMESTATE->m_pCurSong == nullptr ) // we didn't find a song.
|
||||
{
|
||||
PostScreenMessage( SM_GoToNextScreen, 0 ); // Abort demonstration.
|
||||
return;
|
||||
|
||||
+4
-4
@@ -1540,7 +1540,7 @@ static ThemeMetric<RString> PREVIEW_START_FORMAT("ScreenEdit", "PreviewStartForm
|
||||
static ThemeMetric<RString> PREVIEW_LENGTH_FORMAT("ScreenEdit", "PreviewLengthFormat");
|
||||
void ScreenEdit::UpdateTextInfo()
|
||||
{
|
||||
if( m_pSteps == NULL )
|
||||
if( m_pSteps == nullptr )
|
||||
return;
|
||||
|
||||
// Don't update the text during playback or record. It causes skips.
|
||||
@@ -2509,7 +2509,7 @@ bool ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
{
|
||||
// TODO: Give Song/Step Timing switches/functions here?
|
||||
Course *pCourse = GAMESTATE->m_pCurCourse;
|
||||
if( pCourse == NULL )
|
||||
if( pCourse == nullptr )
|
||||
return false;
|
||||
CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex];
|
||||
float fStartTime = m_pSteps->GetTimingData()->GetElapsedTimeFromBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat );
|
||||
@@ -2581,7 +2581,7 @@ bool ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
float fStart, fEnd;
|
||||
PlayerOptions po;
|
||||
const Course *pCourse = GAMESTATE->m_pCurCourse;
|
||||
if( pCourse == NULL )
|
||||
if( pCourse == nullptr )
|
||||
return false;
|
||||
const CourseEntry &ce = pCourse->m_vEntries[GAMESTATE->m_iEditCourseEntryIndex];
|
||||
|
||||
@@ -3232,7 +3232,7 @@ void ScreenEdit::HandleMessage( const Message &msg )
|
||||
if( GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetCurrent().m_bMuteOnError )
|
||||
{
|
||||
RageSoundReader *pSoundReader = m_AutoKeysounds.GetPlayerSound( pn );
|
||||
if( pSoundReader == NULL )
|
||||
if( pSoundReader == nullptr )
|
||||
pSoundReader = m_AutoKeysounds.GetSharedSound();
|
||||
|
||||
HoldNoteScore hns;
|
||||
|
||||
+19
-19
@@ -381,7 +381,7 @@ void ScreenGameplay::Init()
|
||||
|
||||
m_pCombinedLifeMeter = NULL;
|
||||
|
||||
if( GAMESTATE->m_pCurSong == NULL && GAMESTATE->m_pCurCourse == NULL )
|
||||
if( GAMESTATE->m_pCurSong == nullptr && GAMESTATE->m_pCurCourse == nullptr )
|
||||
return; // ScreenDemonstration will move us to the next screen. We just need to survive for one update without crashing.
|
||||
|
||||
/* Save settings to the profile now. Don't do this on extra stages, since the
|
||||
@@ -627,7 +627,7 @@ void ScreenGameplay::Init()
|
||||
{
|
||||
if( GAMESTATE->IsCourseMode() )
|
||||
{
|
||||
ASSERT( pi->m_ptextCourseSongNumber == NULL );
|
||||
ASSERT( pi->m_ptextCourseSongNumber == nullptr );
|
||||
SONG_NUMBER_FORMAT.Load( m_sName, "SongNumberFormat" );
|
||||
pi->m_ptextCourseSongNumber = new BitmapText;
|
||||
pi->m_ptextCourseSongNumber->LoadFromFont( THEME->GetPathF(m_sName,"SongNum") );
|
||||
@@ -638,7 +638,7 @@ void ScreenGameplay::Init()
|
||||
this->AddChild( pi->m_ptextCourseSongNumber );
|
||||
}
|
||||
|
||||
ASSERT( pi->m_ptextStepsDescription == NULL );
|
||||
ASSERT( pi->m_ptextStepsDescription == nullptr );
|
||||
pi->m_ptextStepsDescription = new BitmapText;
|
||||
pi->m_ptextStepsDescription->LoadFromFont( THEME->GetPathF(m_sName,"StepsDescription") );
|
||||
pi->m_ptextStepsDescription->SetName( ssprintf("StepsDescription%s",pi->GetName().c_str()) );
|
||||
@@ -646,7 +646,7 @@ void ScreenGameplay::Init()
|
||||
this->AddChild( pi->m_ptextStepsDescription );
|
||||
|
||||
// Player/Song options
|
||||
ASSERT( pi->m_ptextPlayerOptions == NULL );
|
||||
ASSERT( pi->m_ptextPlayerOptions == nullptr );
|
||||
pi->m_ptextPlayerOptions = new BitmapText;
|
||||
pi->m_ptextPlayerOptions->LoadFromFont( THEME->GetPathF(m_sName,"player options") );
|
||||
pi->m_ptextPlayerOptions->SetName( ssprintf("PlayerOptions%s",pi->GetName().c_str()) );
|
||||
@@ -654,7 +654,7 @@ void ScreenGameplay::Init()
|
||||
this->AddChild( pi->m_ptextPlayerOptions );
|
||||
|
||||
// Difficulty icon and meter
|
||||
ASSERT( pi->m_pStepsDisplay == NULL );
|
||||
ASSERT( pi->m_pStepsDisplay == nullptr );
|
||||
pi->m_pStepsDisplay = new StepsDisplay;
|
||||
pi->m_pStepsDisplay->Load("StepsDisplayGameplay", pi->GetPlayerState() );
|
||||
pi->m_pStepsDisplay->SetName( ssprintf("StepsDisplay%s",pi->GetName().c_str()) );
|
||||
@@ -685,7 +685,7 @@ void ScreenGameplay::Init()
|
||||
|
||||
FOREACH_VisiblePlayerInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
ASSERT( pi->m_pActiveAttackList == NULL );
|
||||
ASSERT( pi->m_pActiveAttackList == nullptr );
|
||||
pi->m_pActiveAttackList = new ActiveAttackList;
|
||||
pi->m_pActiveAttackList->LoadFromFont( THEME->GetPathF(m_sName,"ActiveAttackList") );
|
||||
pi->m_pActiveAttackList->Init( pi->GetPlayerState() );
|
||||
@@ -1270,7 +1270,7 @@ void ScreenGameplay::LoadNextSong()
|
||||
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
RageSoundReader *pPlayerSound = m_AutoKeysounds.GetPlayerSound(pi->m_pn);
|
||||
if( pPlayerSound == NULL && pi->m_pn == GAMESTATE->GetMasterPlayerNumber() )
|
||||
if( pPlayerSound == nullptr && pi->m_pn == GAMESTATE->GetMasterPlayerNumber() )
|
||||
pPlayerSound = m_AutoKeysounds.GetSharedSound();
|
||||
pi->m_SoundEffectControl.SetSoundReader( pPlayerSound );
|
||||
}
|
||||
@@ -1327,7 +1327,7 @@ void ScreenGameplay::LoadLights()
|
||||
pSteps = SongUtil::GetClosestNotes( GAMESTATE->m_pCurSong, st, d1 );
|
||||
|
||||
// If we can't find anything at all, stop.
|
||||
if( pSteps == NULL )
|
||||
if( pSteps == nullptr )
|
||||
return;
|
||||
|
||||
NoteData TapNoteData1;
|
||||
@@ -1430,7 +1430,7 @@ void ScreenGameplay::PlayAnnouncer( const RString &type, float fSeconds, float *
|
||||
/* Don't play before the first beat, or after we're finished. */
|
||||
if( m_DancingState != STATE_DANCING )
|
||||
return;
|
||||
if(GAMESTATE->m_pCurSong == NULL || // this will be true on ScreenDemonstration sometimes
|
||||
if(GAMESTATE->m_pCurSong == nullptr || // this will be true on ScreenDemonstration sometimes
|
||||
GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->GetFirstBeat())
|
||||
return;
|
||||
|
||||
@@ -1454,7 +1454,7 @@ void ScreenGameplay::UpdateSongPosition( float fDeltaTime )
|
||||
|
||||
void ScreenGameplay::BeginScreen()
|
||||
{
|
||||
if( GAMESTATE->m_pCurSong == NULL )
|
||||
if( GAMESTATE->m_pCurSong == nullptr )
|
||||
return;
|
||||
|
||||
ScreenWithMenuElements::BeginScreen();
|
||||
@@ -1535,7 +1535,7 @@ void ScreenGameplay::GetMusicEndTiming( float &fSecondsToStartFadingOutMusic, fl
|
||||
|
||||
void ScreenGameplay::Update( float fDeltaTime )
|
||||
{
|
||||
if( GAMESTATE->m_pCurSong == NULL )
|
||||
if( GAMESTATE->m_pCurSong == nullptr )
|
||||
{
|
||||
/* ScreenDemonstration will move us to the next screen. We just need to
|
||||
* survive for one update without crashing. We need to call Screen::Update
|
||||
@@ -1558,7 +1558,7 @@ void ScreenGameplay::Update( float fDeltaTime )
|
||||
|
||||
/* This happens if ScreenDemonstration::HandleScreenMessage sets a new screen when
|
||||
* PREFSMAN->m_bDelayedScreenLoad. */
|
||||
if( GAMESTATE->m_pCurSong == NULL )
|
||||
if( GAMESTATE->m_pCurSong == nullptr )
|
||||
return;
|
||||
/* This can happen if ScreenDemonstration::HandleScreenMessage sets a new screen when
|
||||
* !PREFSMAN->m_bDelayedScreenLoad. (The new screen was loaded when we called Screen::Update,
|
||||
@@ -1640,7 +1640,7 @@ void ScreenGameplay::Update( float fDeltaTime )
|
||||
continue;
|
||||
|
||||
// check for individual fail
|
||||
if( pi->m_pLifeMeter == NULL || !pi->m_pLifeMeter->IsFailing() )
|
||||
if( pi->m_pLifeMeter == nullptr || !pi->m_pLifeMeter->IsFailing() )
|
||||
continue; /* isn't failing */
|
||||
if( pi->GetPlayerStageStats()->m_bFailed )
|
||||
continue; /* failed and is already dead */
|
||||
@@ -1685,7 +1685,7 @@ void ScreenGameplay::Update( float fDeltaTime )
|
||||
switch( ft )
|
||||
{
|
||||
case PlayerOptions::FAIL_IMMEDIATE:
|
||||
if( pi->m_pLifeMeter == NULL || (pi->m_pLifeMeter && !pi->m_pLifeMeter->IsFailing()) )
|
||||
if( pi->m_pLifeMeter == nullptr || (pi->m_pLifeMeter && !pi->m_pLifeMeter->IsFailing()) )
|
||||
bAllFailed = false;
|
||||
break;
|
||||
case PlayerOptions::FAIL_IMMEDIATE_CONTINUE:
|
||||
@@ -2681,7 +2681,7 @@ void ScreenGameplay::HandleMessage( const Message &msg )
|
||||
continue;
|
||||
|
||||
RageSoundReader *pSoundReader = m_AutoKeysounds.GetPlayerSound( pn );
|
||||
if( pSoundReader == NULL )
|
||||
if( pSoundReader == nullptr )
|
||||
pSoundReader = m_AutoKeysounds.GetSharedSound();
|
||||
|
||||
HoldNoteScore hns;
|
||||
@@ -2835,10 +2835,10 @@ public:
|
||||
PlayerNumber pn = Enum::Check<PlayerNumber>( L, 1 );
|
||||
|
||||
PlayerInfo *pi = p->GetPlayerInfo(pn);
|
||||
if( pi == NULL )
|
||||
if( pi == nullptr )
|
||||
return 0;
|
||||
LifeMeter *pLM = pi->m_pLifeMeter;
|
||||
if( pLM == NULL )
|
||||
if( pLM == nullptr )
|
||||
return 0;
|
||||
|
||||
pLM->PushSelf( L );
|
||||
@@ -2849,7 +2849,7 @@ public:
|
||||
PlayerNumber pn = Enum::Check<PlayerNumber>( L, 1 );
|
||||
|
||||
PlayerInfo *pi = p->GetPlayerInfo(pn);
|
||||
if( pi == NULL )
|
||||
if( pi == nullptr )
|
||||
return 0;
|
||||
|
||||
pi->PushSelf( L );
|
||||
@@ -2859,7 +2859,7 @@ public:
|
||||
{
|
||||
int iDummyIndex = IArg(1);
|
||||
PlayerInfo *pi = p->GetDummyPlayerInfo(iDummyIndex);
|
||||
if( pi == NULL )
|
||||
if( pi == nullptr )
|
||||
return 0;
|
||||
pi->PushSelf( L );
|
||||
return 1;
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
}
|
||||
RString GetStatus() const
|
||||
{
|
||||
if( m_pTransfer == NULL )
|
||||
if( m_pTransfer == nullptr )
|
||||
return "";
|
||||
else
|
||||
return m_pTransfer->GetStatus();
|
||||
@@ -224,7 +224,7 @@ public:
|
||||
RString sUrl = m_vsQueuedPackageUrls.back();
|
||||
m_vsQueuedPackageUrls.pop_back();
|
||||
m_sCurrentPackageTempFile = MakeTempFileName(sUrl);
|
||||
ASSERT(m_pTransfer == NULL);
|
||||
ASSERT(m_pTransfer == nullptr);
|
||||
m_pTransfer = new FileTransfer();
|
||||
m_pTransfer->StartDownload( sUrl, m_sCurrentPackageTempFile );
|
||||
}
|
||||
@@ -243,7 +243,7 @@ public:
|
||||
RString sUrl = m_vsQueuedPackageUrls.back();
|
||||
m_vsQueuedPackageUrls.pop_back();
|
||||
m_sCurrentPackageTempFile = MakeTempFileName(sUrl);
|
||||
ASSERT(m_pTransfer == NULL);
|
||||
ASSERT(m_pTransfer == nullptr);
|
||||
m_pTransfer = new FileTransfer();
|
||||
m_pTransfer->StartDownload( sUrl, m_sCurrentPackageTempFile );
|
||||
}
|
||||
@@ -252,7 +252,7 @@ public:
|
||||
}
|
||||
bool bFinished = m_DownloadState == packages &&
|
||||
m_vsQueuedPackageUrls.empty() &&
|
||||
m_pTransfer == NULL;
|
||||
m_pTransfer == nullptr;
|
||||
if( bFinished )
|
||||
{
|
||||
Message msg( "DownloadFinished" );
|
||||
|
||||
@@ -84,7 +84,7 @@ void ScreenJukebox::SetSong()
|
||||
Difficulty dc = vDifficultiesToShow[ RandomInt(vDifficultiesToShow.size()) ];
|
||||
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, dc );
|
||||
|
||||
if( pSteps == NULL )
|
||||
if( pSteps == nullptr )
|
||||
continue; // skip
|
||||
|
||||
if( !PREFSMAN->m_bAutogenSteps && pSteps->IsAutogen())
|
||||
@@ -110,7 +110,7 @@ void ScreenJukebox::SetSong()
|
||||
{
|
||||
Course *lCourse = apCourses[j];
|
||||
const CourseEntry *pEntry = lCourse->FindFixedSong( pSong );
|
||||
if( pEntry == NULL || pEntry->attacks.size() == 0 )
|
||||
if( pEntry == nullptr || pEntry->attacks.size() == 0 )
|
||||
continue;
|
||||
|
||||
if( !ALLOW_ADVANCED_MODIFIERS )
|
||||
@@ -226,7 +226,7 @@ void ScreenJukebox::Init()
|
||||
// Now that we've set up, init the base class.
|
||||
ScreenGameplay::Init();
|
||||
|
||||
if( GAMESTATE->m_pCurSong == NULL ) // we didn't find a song.
|
||||
if( GAMESTATE->m_pCurSong == nullptr ) // we didn't find a song.
|
||||
{
|
||||
this->PostScreenMessage( SM_GoToNextScreen, 0 ); // Abort demonstration.
|
||||
return;
|
||||
|
||||
@@ -218,7 +218,7 @@ using namespace ScreenManagerUtil;
|
||||
|
||||
RegisterScreenClass::RegisterScreenClass( const RString& sClassName, CreateScreenFn pfn )
|
||||
{
|
||||
if( g_pmapRegistrees == NULL )
|
||||
if( g_pmapRegistrees == nullptr )
|
||||
g_pmapRegistrees = new map<RString,CreateScreenFn>;
|
||||
|
||||
map<RString,CreateScreenFn>::iterator iter = g_pmapRegistrees->find( sClassName );
|
||||
@@ -573,7 +573,7 @@ void ScreenManager::PrepareScreen( const RString &sScreenName )
|
||||
|
||||
// Create the new background before deleting the previous so that we keep
|
||||
// any common textures loaded.
|
||||
if( pNewBGA == NULL )
|
||||
if( pNewBGA == nullptr )
|
||||
{
|
||||
LOG->Trace( "Loading screen background \"%s\"", sNewBGA.c_str() );
|
||||
Actor *pActor = ActorUtil::MakeActor( sNewBGA );
|
||||
@@ -615,7 +615,7 @@ bool ScreenManager::ActivatePreparedScreenAndBackground( const RString &sScreenN
|
||||
bool bLoadedBoth = true;
|
||||
|
||||
// Find the prepped screen.
|
||||
if( GetTopScreen() == NULL || GetTopScreen()->GetName() != sScreenName )
|
||||
if( GetTopScreen() == nullptr || GetTopScreen()->GetName() != sScreenName )
|
||||
{
|
||||
LoadedScreen ls;
|
||||
if( !GetPreppedScreen(sScreenName, ls) )
|
||||
@@ -652,7 +652,7 @@ bool ScreenManager::ActivatePreparedScreenAndBackground( const RString &sScreenN
|
||||
|
||||
/* If the BGA isn't loaded yet, load a dummy actor. If we're not going to use the same
|
||||
* BGA for the new screen, always move the old BGA back to g_vPreparedBackgrounds now. */
|
||||
if( pNewBGA == NULL )
|
||||
if( pNewBGA == nullptr )
|
||||
{
|
||||
bLoadedBoth = false;
|
||||
pNewBGA = new Actor;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user