You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
8.0 KiB
260 lines
8.0 KiB
1 year ago
|
#include "LevelTheme.h"
|
||
|
#include "KeyValues.h"
|
||
|
#include "RoomTemplate.h"
|
||
|
#include "filesystem.h"
|
||
|
#include "asw_system.h"
|
||
|
#include "convar.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include <tier0/memdbgon.h>
|
||
|
|
||
|
CUtlVector<CLevelTheme*> CLevelTheme::s_LevelThemes;
|
||
|
CLevelTheme* CLevelTheme::s_pCurrentTheme = NULL;
|
||
|
CLevelTheme* CLevelTheme::s_pPreviousTheme = NULL;
|
||
|
bool CLevelTheme::s_bLoadedThemes = false;
|
||
|
|
||
|
static FileFindHandle_t g_hthemefind = FILESYSTEM_INVALID_FIND_HANDLE;
|
||
|
|
||
|
ConVar asw_tilegen_theme( "asw_tilegen_theme", "Rydberg", FCVAR_ARCHIVE, "Default theme selected in TileGen" );
|
||
|
|
||
|
// Loads in all level themes found in tilegen/themes/
|
||
|
void CLevelTheme::LoadLevelThemes()
|
||
|
{
|
||
|
if ( s_bLoadedThemes )
|
||
|
return;
|
||
|
|
||
|
s_pCurrentTheme = NULL;
|
||
|
s_LevelThemes.PurgeAndDeleteElements();
|
||
|
s_bLoadedThemes = true;
|
||
|
|
||
|
// Search the directory structure.
|
||
|
char mapwild[MAX_PATH];
|
||
|
Q_strncpy(mapwild,"tilegen/themes/*.theme", sizeof( mapwild ) );
|
||
|
char const *filename;
|
||
|
filename = Sys_FindFirst( g_hthemefind, mapwild, NULL, 0 );
|
||
|
|
||
|
while (filename)
|
||
|
{
|
||
|
// load the level theme
|
||
|
char szFullFileName[256];
|
||
|
Q_snprintf(szFullFileName, sizeof(szFullFileName), "tilegen/themes/%s", filename);
|
||
|
KeyValues *pThemeKeyValues = new KeyValues( filename );
|
||
|
if (pThemeKeyValues->LoadFromFile(g_pFullFileSystem, szFullFileName, "GAME"))
|
||
|
{
|
||
|
CLevelTheme* pTheme = new CLevelTheme(pThemeKeyValues->GetString("ThemeName"),
|
||
|
pThemeKeyValues->GetString("ThemeDescription"),
|
||
|
pThemeKeyValues->GetInt("VMFTweak", 0) > 0 );
|
||
|
pTheme->m_bSkipErrorCheck = ( pThemeKeyValues->GetInt( "SkipErrorCheck", 0 ) > 0 );
|
||
|
sscanf( pThemeKeyValues->GetString( "AmbientLight" ) , "%f %f %f", &pTheme->m_vecAmbientLight.x, &pTheme->m_vecAmbientLight.y, &pTheme->m_vecAmbientLight.z );
|
||
|
// temp to avoid the 0,0,0 losing ambient light bug
|
||
|
if ( pTheme->m_vecAmbientLight == vec3_origin )
|
||
|
{
|
||
|
pTheme->m_vecAmbientLight.x = 1;
|
||
|
pTheme->m_vecAmbientLight.y = 1;
|
||
|
pTheme->m_vecAmbientLight.z = 1;
|
||
|
}
|
||
|
pTheme->LoadRoomTemplates();
|
||
|
s_LevelThemes.AddToTail(pTheme);
|
||
|
if (!Q_stricmp(pTheme->m_szName, asw_tilegen_theme.GetString())) // default to the Rydberg theme
|
||
|
SetCurrentTheme(pTheme);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Msg("Error: failed to load theme %s\n", szFullFileName);
|
||
|
}
|
||
|
pThemeKeyValues->deleteThis();
|
||
|
filename = Sys_FindNext(g_hthemefind, NULL, 0);
|
||
|
}
|
||
|
|
||
|
if ( s_pCurrentTheme == NULL && s_LevelThemes.Count() > 0 )
|
||
|
{
|
||
|
SetCurrentTheme( s_LevelThemes[0] );
|
||
|
}
|
||
|
|
||
|
Sys_FindClose(g_hthemefind);
|
||
|
}
|
||
|
|
||
|
void CLevelTheme::SetCurrentTheme(CLevelTheme* pTheme)
|
||
|
{
|
||
|
if (s_pCurrentTheme)
|
||
|
s_pPreviousTheme = s_pCurrentTheme;
|
||
|
s_pCurrentTheme = pTheme;
|
||
|
asw_tilegen_theme.SetValue( pTheme->m_szName );
|
||
|
}
|
||
|
|
||
|
CLevelTheme::CLevelTheme(const char *szName, const char *szDescription, bool bRequiresVMFTweak)
|
||
|
{
|
||
|
m_szName[0] = '\0';
|
||
|
m_szDescription[0] = '\0';
|
||
|
m_bRequiresVMFTweak = bRequiresVMFTweak;
|
||
|
m_vecAmbientLight = vec3_origin;
|
||
|
|
||
|
if (szName) Q_strcpy(m_szName, szName);
|
||
|
if (szDescription) Q_strcpy(m_szDescription, szDescription);
|
||
|
}
|
||
|
|
||
|
CLevelTheme::~CLevelTheme()
|
||
|
{
|
||
|
m_RoomTemplates.PurgeAndDeleteElements();
|
||
|
}
|
||
|
|
||
|
bool CLevelTheme::SaveTheme(const char *pszThemeName)
|
||
|
{
|
||
|
char szFullFileName[MAX_PATH];
|
||
|
Q_snprintf(szFullFileName, sizeof(szFullFileName), "tilegen/themes/%s.theme", pszThemeName);
|
||
|
KeyValues *pThemeKeyValues = new KeyValues( pszThemeName );
|
||
|
pThemeKeyValues->SetString("ThemeName", m_szName);
|
||
|
pThemeKeyValues->SetString("ThemeDescription", m_szDescription);
|
||
|
pThemeKeyValues->SetBool( "VMFTweak", m_bRequiresVMFTweak );
|
||
|
pThemeKeyValues->SetBool( "SkipErrorCheck", m_bSkipErrorCheck );
|
||
|
char buffer[128];
|
||
|
Q_snprintf( buffer, sizeof( buffer ), "%f %f %f", m_vecAmbientLight.x, m_vecAmbientLight.y, m_vecAmbientLight.z );
|
||
|
pThemeKeyValues->SetString( "AmbientLight", buffer );
|
||
|
if (!pThemeKeyValues->SaveToFile(g_pFullFileSystem, szFullFileName, "GAME"))
|
||
|
{
|
||
|
Msg("Error: Failed to save theme %s\n", szFullFileName);
|
||
|
return false;
|
||
|
}
|
||
|
// TODO: check the room templates folder for this theme exists
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
#define ROOMTEMPLATES_FOLDER "tilegen/roomtemplates/"
|
||
|
|
||
|
// makes this theme load in all its room templates
|
||
|
void CLevelTheme::LoadRoomTemplates()
|
||
|
{
|
||
|
m_RoomTemplates.PurgeAndDeleteElements();
|
||
|
char szPath[MAX_PATH];
|
||
|
Q_snprintf( szPath, sizeof( szPath ), ROOMTEMPLATES_FOLDER "%s", m_szName );
|
||
|
LoadRoomTemplatesInFolder( szPath );
|
||
|
}
|
||
|
|
||
|
void CLevelTheme::LoadRoomTemplatesInFolder( const char *szPath )
|
||
|
{
|
||
|
char mapwild[MAX_PATH];
|
||
|
Q_snprintf( mapwild, sizeof( mapwild ), "%s/*", szPath );
|
||
|
char const *filename;
|
||
|
FileFindHandle_t hRoomfind = FILESYSTEM_INVALID_FIND_HANDLE;
|
||
|
filename = Sys_FindFirst( hRoomfind, mapwild, NULL, 0 );
|
||
|
while ( filename )
|
||
|
{
|
||
|
if ( g_pFullFileSystem->FindIsDirectory( hRoomfind ) )
|
||
|
{
|
||
|
if ( Q_strcmp( filename, "." ) && Q_strcmp( filename, ".." ) )
|
||
|
{
|
||
|
char subfolder[MAX_PATH];
|
||
|
Q_snprintf( subfolder, sizeof( subfolder ), "%s/%s", szPath, filename );
|
||
|
LoadRoomTemplatesInFolder( subfolder );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
const char *pExt = Q_GetFileExtension( filename );
|
||
|
if ( pExt && !Q_stricmp( pExt, "roomtemplate" ) )
|
||
|
{
|
||
|
// load the room template
|
||
|
char szFullFileName[256];
|
||
|
Q_snprintf(szFullFileName, sizeof(szFullFileName), "%s/%s", szPath, filename);
|
||
|
KeyValues *pRoomTemplateKeyValues = new KeyValues( filename );
|
||
|
if (pRoomTemplateKeyValues->LoadFromFile(g_pFullFileSystem, szFullFileName, "GAME"))
|
||
|
{
|
||
|
CRoomTemplate* pRoomTemplate = new CRoomTemplate(this);
|
||
|
pRoomTemplate->LoadFromKeyValues( szFullFileName + Q_strlen( ROOMTEMPLATES_FOLDER ) + 1 + Q_strlen( m_szName ), pRoomTemplateKeyValues ); // sets the room templates properties based on these keyvalues
|
||
|
m_RoomTemplates.Insert(pRoomTemplate);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Msg("Error: failed to load room template %s\n", szFullFileName);
|
||
|
}
|
||
|
pRoomTemplateKeyValues->deleteThis();
|
||
|
}
|
||
|
}
|
||
|
filename = Sys_FindNext(hRoomfind, NULL, 0);
|
||
|
}
|
||
|
|
||
|
Sys_FindClose(hRoomfind);
|
||
|
}
|
||
|
|
||
|
|
||
|
CLevelTheme* CLevelTheme::FindTheme( const char *szThemeName )
|
||
|
{
|
||
|
if ( !s_bLoadedThemes )
|
||
|
{
|
||
|
CLevelTheme::LoadLevelThemes();
|
||
|
}
|
||
|
// find pointer to the room template
|
||
|
// first find the theme with matching name
|
||
|
int iThemes = CLevelTheme::s_LevelThemes.Count();
|
||
|
for (int i=0;i<iThemes;i++)
|
||
|
{
|
||
|
CLevelTheme* pTheme = CLevelTheme::s_LevelThemes[i];
|
||
|
if (!pTheme)
|
||
|
continue;
|
||
|
if (!Q_stricmp(pTheme->m_szName, szThemeName))
|
||
|
{
|
||
|
return pTheme;
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool CRoomTemplateLessFunc::Less( CRoomTemplate* const &pRoomTemplateLHS, CRoomTemplate* const &pRoomTemplateRHS, void *pCtx )
|
||
|
{
|
||
|
return CaselessStringLessThan( pRoomTemplateLHS->GetFullName(), pRoomTemplateRHS->GetFullName() );
|
||
|
}
|
||
|
|
||
|
CRoomTemplate* CLevelTheme::FindRoom( const char *szRoomTemplate )
|
||
|
{
|
||
|
// strip off .vmf if it's there
|
||
|
static char buffer[ 256 ];
|
||
|
Q_snprintf( buffer, sizeof( buffer ), "%s", szRoomTemplate );
|
||
|
int len = Q_strlen( buffer );
|
||
|
if ( len >= 4 && !Q_stricmp( buffer - 4, ".vmf" ) )
|
||
|
{
|
||
|
buffer[ len - 4 ] = 0;
|
||
|
}
|
||
|
Q_FixSlashes( buffer );
|
||
|
|
||
|
for ( int i = 0; i < m_RoomTemplates.Count(); i++ )
|
||
|
{
|
||
|
CRoomTemplate *pTemplate = m_RoomTemplates[i];
|
||
|
if ( !pTemplate )
|
||
|
continue;
|
||
|
|
||
|
if ( !Q_stricmp( pTemplate->GetFullName(), buffer ) )
|
||
|
return pTemplate;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
bool CLevelTheme::SplitThemeAndRoom( const char *pszFullName, char *szThemeOut, int nThemeOutSize, char *szRoomOut, int nRoomOutSize )
|
||
|
{
|
||
|
const char *pszFirstForwardSlash = Q_strnchr( pszFullName, '/', Q_strlen( pszFullName ) );
|
||
|
const char *pszFirstBackSlash = Q_strnchr( pszFullName, '\\', Q_strlen( pszFullName ) );
|
||
|
|
||
|
if ( pszFirstBackSlash && pszFirstForwardSlash )
|
||
|
{
|
||
|
pszFirstForwardSlash = pszFirstForwardSlash < pszFirstBackSlash ? pszFirstForwardSlash : pszFirstBackSlash;
|
||
|
}
|
||
|
else if ( !pszFirstForwardSlash && pszFirstBackSlash )
|
||
|
{
|
||
|
pszFirstForwardSlash = pszFirstBackSlash;
|
||
|
}
|
||
|
else if ( !pszFirstForwardSlash && !pszFirstBackSlash )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
Q_strncpy( szThemeOut, pszFullName, nThemeOutSize );
|
||
|
int iSlashPos = pszFirstForwardSlash - pszFullName;
|
||
|
if ( iSlashPos < nThemeOutSize )
|
||
|
{
|
||
|
szThemeOut[ iSlashPos ] = 0;
|
||
|
}
|
||
|
|
||
|
Q_strncpy( szRoomOut, pszFirstForwardSlash + 1, nRoomOutSize );
|
||
|
return true;
|
||
|
}
|