The big NULL replacement party part 2.

This may take a bit. Trying to do this by operator/command.
This commit is contained in:
Jason Felds
2013-05-03 23:11:42 -04:00
parent 9f24627bf9
commit ba59dd1656
174 changed files with 6644 additions and 6644 deletions
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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 );
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+5 -5
View File
@@ -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;
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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)
{
+2 -2
View File
@@ -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 );
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 );
+1 -1
View File
@@ -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
View File
@@ -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.
*/
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+3 -3
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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();
+2 -2
View File
@@ -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() );
}
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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
View File
@@ -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) );
+7 -7
View File
@@ -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
View File
@@ -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;
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 );
+6 -6
View File
@@ -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
View File
@@ -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 );
+2 -2
View File
@@ -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()) );
+1 -1
View File
@@ -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 );
+2 -2
View File
@@ -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();
+1 -1
View File
@@ -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
View File
@@ -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 )
+5 -5
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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.
*/
+2 -2
View File
@@ -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
View File
@@ -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.
*/
+22 -22
View File
@@ -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
View File
@@ -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.
*/
+2 -2
View File
@@ -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
View File
@@ -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 );
+5 -5
View File
@@ -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();
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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 )
+1 -1
View File
@@ -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
View File
@@ -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.
*/
+3 -3
View File
@@ -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
+1 -1
View File
@@ -9,7 +9,7 @@
#include <map>
#define CheckLine() \
if( xpm[line] == NULL ) { \
if( xpm[line] == nullptr ) { \
error = "short file"; \
return NULL; \
}
+181 -181
View File
@@ -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.
*/
+2 -2
View File
@@ -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 )
+1 -1
View File
@@ -176,7 +176,7 @@ void RageTextureManager::VolatileTexture( RageTextureID ID )
void RageTextureManager::UnloadTexture( RageTexture *t )
{
if( t == NULL )
if( t == nullptr )
return;
t->m_iRefCount--;
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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 );
+1 -1
View File
@@ -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 );
+1 -1
View File
@@ -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
View File
@@ -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. */
+1 -1
View File
@@ -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 */
+1 -1
View File
@@ -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 );
}
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+4 -4
View File
@@ -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" );
+3 -3
View File
@@ -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;
+4 -4
View File
@@ -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