mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-10 06:31:48 +00:00
added /shaderinfo
This commit is contained in:
parent
049793f8f9
commit
e56a11b638
8 changed files with 190 additions and 17 deletions
|
@ -4,6 +4,8 @@ See the end of this file for known issues.
|
|||
|
||||
DD Mmm 20 - 1.53
|
||||
|
||||
add: /shaderinfo <shadername> [code] prints where the shader was loaded from and optionally the code
|
||||
|
||||
add: console mark mode (selection mode) can be toggled with Ctrl-M
|
||||
use arrow keys, home/end or page up/down to move the cursor or extend the area when pressing shift
|
||||
Ctrl-C/enter copies the selected text to the clipboard without color codes and exits mark mode
|
||||
|
|
|
@ -1797,10 +1797,12 @@ static void CL_InitRef()
|
|||
ri.Hunk_FreeTempMemory = Hunk_FreeTempMemory;
|
||||
ri.CM_DrawDebugSurface = CM_DrawDebugSurface;
|
||||
ri.FS_ReadFile = FS_ReadFile;
|
||||
ri.FS_ReadFilePak = FS_ReadFilePak;
|
||||
ri.FS_FreeFile = FS_FreeFile;
|
||||
ri.FS_WriteFile = FS_WriteFile;
|
||||
ri.FS_FreeFileList = FS_FreeFileList;
|
||||
ri.FS_ListFiles = FS_ListFiles;
|
||||
ri.FS_GetPakPath = FS_GetPakPath;
|
||||
ri.Cvar_Get = Cvar_Get;
|
||||
ri.Cvar_SetHelp = Cvar_SetHelp;
|
||||
ri.Cvar_Set = Cvar_Set;
|
||||
|
|
|
@ -868,7 +868,7 @@ separate file or a ZIP file.
|
|||
*/
|
||||
extern qbool com_fullyInitialized;
|
||||
|
||||
int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qbool uniqueFILE ) {
|
||||
int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qbool uniqueFILE, int *pakChecksum ) {
|
||||
searchpath_t *search;
|
||||
char *netpath;
|
||||
pack_t *pak;
|
||||
|
@ -881,6 +881,9 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qbool uniqueFILE
|
|||
char demoExt[16];
|
||||
|
||||
hash = 0;
|
||||
if ( pakChecksum ) {
|
||||
*pakChecksum = 0;
|
||||
}
|
||||
|
||||
if ( !fs_searchpaths ) {
|
||||
Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" );
|
||||
|
@ -902,6 +905,9 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qbool uniqueFILE
|
|||
// case and separator insensitive comparisons
|
||||
if ( !FS_FilenameCompare( pakFile->name, filename ) ) {
|
||||
// found it!
|
||||
if ( pakChecksum ) {
|
||||
*pakChecksum = pak->checksum;
|
||||
}
|
||||
return qtrue;
|
||||
}
|
||||
pakFile = pakFile->next;
|
||||
|
@ -1024,6 +1030,10 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qbool uniqueFILE
|
|||
unzOpenCurrentFile( fsh[*file].handleFiles.file.z );
|
||||
fsh[*file].zipFilePos = pakFile->pos;
|
||||
|
||||
if ( pakChecksum ) {
|
||||
*pakChecksum = pak->checksum;
|
||||
}
|
||||
|
||||
if ( fs_debug->integer ) {
|
||||
Com_Printf( "FS_FOpenFileRead: %s (found in '%s')\n",
|
||||
filename, pak->pakFilename );
|
||||
|
@ -1359,7 +1369,7 @@ Filename are relative to the quake search path
|
|||
a null buffer will just return the file length without loading
|
||||
============
|
||||
*/
|
||||
int FS_ReadFile( const char *qpath, void **buffer ) {
|
||||
int FS_ReadFilePak( const char *qpath, void **buffer, int *pakChecksum ) {
|
||||
fileHandle_t h;
|
||||
byte* buf;
|
||||
qbool isConfig;
|
||||
|
@ -1374,6 +1384,9 @@ int FS_ReadFile( const char *qpath, void **buffer ) {
|
|||
}
|
||||
|
||||
buf = NULL; // quiet compiler warning
|
||||
if ( pakChecksum ) {
|
||||
*pakChecksum = 0;
|
||||
}
|
||||
|
||||
// if this is a .cfg file and we are playing back a journal, read
|
||||
// it from the journal file
|
||||
|
@ -1421,7 +1434,7 @@ int FS_ReadFile( const char *qpath, void **buffer ) {
|
|||
}
|
||||
|
||||
// look for it in the filesystem or pack files
|
||||
len = FS_FOpenFileRead( qpath, &h, qfalse );
|
||||
len = FS_FOpenFileRead( qpath, &h, qfalse, pakChecksum );
|
||||
if ( h == 0 ) {
|
||||
if ( buffer ) {
|
||||
*buffer = NULL;
|
||||
|
@ -1468,6 +1481,10 @@ int FS_ReadFile( const char *qpath, void **buffer ) {
|
|||
return len;
|
||||
}
|
||||
|
||||
int FS_ReadFile( const char *qpath, void **buffer ) {
|
||||
return FS_ReadFilePak( qpath, buffer, NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
FS_FreeFile
|
||||
|
@ -3229,3 +3246,14 @@ void FS_FilenameCompletion( const char *dir, const char *ext, qbool stripExt,
|
|||
}
|
||||
FS_FreeFileList( filenames );
|
||||
}
|
||||
|
||||
qbool FS_GetPakPath( char *name, int nameSize, int pakChecksum ) {
|
||||
for ( searchpath_t *search = fs_searchpaths; search; search = search->next ) {
|
||||
if ( search->pack && search->pack->checksum == pakChecksum ) {
|
||||
Com_sprintf( name, nameSize, "%s/%s.pk3", search->pack->pakGamename, search->pack->pakBasename );
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
|
|
@ -657,7 +657,7 @@ fileHandle_t FS_FOpenFileWrite( const char *qpath );
|
|||
fileHandle_t FS_SV_FOpenFileWrite( const char *filename );
|
||||
int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
|
||||
void FS_SV_Rename( const char *from, const char *to );
|
||||
int FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qbool uniqueFILE );
|
||||
int FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qbool uniqueFILE, int *pakChecksum = NULL );
|
||||
// if uniqueFILE is qtrue, then a new FILE will be fopened even if the file
|
||||
// is found in an already open pak file. If uniqueFILE is qfalse, you must call
|
||||
// FS_FCloseFile instead of fclose, otherwise the pak FILE would be improperly closed
|
||||
|
@ -676,6 +676,7 @@ void FS_FCloseFile( fileHandle_t f );
|
|||
// note: you can't just fclose from another DLL, due to MS libc issues
|
||||
|
||||
int FS_ReadFile( const char *qpath, void **buffer );
|
||||
int FS_ReadFilePak( const char *qpath, void **buffer, int *pakChecksum );
|
||||
// returns the length of the file
|
||||
// a null buffer will just return the file length without loading
|
||||
// as a quick check for existance. -1 length == not present
|
||||
|
@ -750,6 +751,8 @@ void FS_HomeRemove( const char *homePath );
|
|||
void FS_FilenameCompletion( const char *dir, const char *ext, qbool stripExt,
|
||||
void (*callback)(const char *s), int filters );
|
||||
|
||||
qbool FS_GetPakPath( char *name, int nameSize, int pakChecksum );
|
||||
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
|
|
@ -339,6 +339,7 @@ static const cmdTableItem_t r_cmds[] =
|
|||
{ "gfxinfo", GfxInfo_f, NULL, "prints display mode info" },
|
||||
{ "imagelist", R_ImageList_f, NULL, "prints loaded images" },
|
||||
{ "shaderlist", R_ShaderList_f, NULL, "prints loaded shaders" },
|
||||
{ "shaderinfo", R_ShaderInfo_f, R_CompleteShaderName_f, "prints info for a specific shader" },
|
||||
{ "skinlist", R_SkinList_f, NULL, "prints loaded skins" },
|
||||
{ "modellist", R_Modellist_f, NULL, "prints loaded models" },
|
||||
{ "screenshot", R_ScreenShotTGA_f, NULL, "takes a TARGA (.tga) screenshot" },
|
||||
|
|
|
@ -426,6 +426,10 @@ struct shader_t {
|
|||
|
||||
qbool greyscaleCTF;
|
||||
|
||||
// extra info for /shaderinfo
|
||||
int fileIndex;
|
||||
const char* text;
|
||||
|
||||
shader_t* next;
|
||||
};
|
||||
|
||||
|
@ -1200,6 +1204,8 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qbool mipRawImage )
|
|||
const shader_t* R_GetShaderByHandle( qhandle_t hShader );
|
||||
void R_InitShaders();
|
||||
void R_ShaderList_f( void );
|
||||
void R_ShaderInfo_f();
|
||||
void R_CompleteShaderName_f( int startArg, int compArg );
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
|
|
@ -222,10 +222,12 @@ typedef struct {
|
|||
// a -1 return means the file does not exist
|
||||
// NULL can be passed for buf to just determine existance
|
||||
int (*FS_ReadFile)( const char *name, void **buf );
|
||||
int (*FS_ReadFilePak)( const char *name, void **buf, int* pakChecksum );
|
||||
void (*FS_FreeFile)( void *buf );
|
||||
char** (*FS_ListFiles)( const char *name, const char *extension, int *numfilesfound );
|
||||
void (*FS_FreeFileList)( char **filelist );
|
||||
void (*FS_WriteFile)( const char *qpath, const void *buffer, int size );
|
||||
qbool (*FS_GetPakPath)( char *name, int nameSize, int pakChecksum );
|
||||
|
||||
// cinematic stuff
|
||||
qbool (*CIN_GrabCinematic)( int handle, int* w, int* h, const byte** data, int* client, qbool* dirty );
|
||||
|
|
|
@ -44,6 +44,11 @@ const float r_depthFadeBias[DFT_COUNT][4] =
|
|||
};
|
||||
|
||||
static char* s_shaderText = 0;
|
||||
static int s_numShaderFiles = 0;
|
||||
static char* s_shaderFileNames = 0;
|
||||
static int* s_shaderFileOffsets = 0;
|
||||
static int* s_shaderFileNameOffsets = 0;
|
||||
static int* s_shaderPakChecksums = 0;
|
||||
|
||||
// the shader is parsed into these global variables, then copied into
|
||||
// dynamically allocated memory if it is valid.
|
||||
|
@ -2638,11 +2643,23 @@ shader_t* R_FindShader( const char *name, int lightmapIndex, qbool mipRawImage )
|
|||
#if 0 // enable this when building a pak file to get a global list of all explicit shaders
|
||||
ri.Printf( PRINT_ALL, "*SHADER* %s\n", name );
|
||||
#endif
|
||||
|
||||
const int textOffset = (int)( shaderText - s_shaderText );
|
||||
if ( !ParseShader( &shaderText ) ) {
|
||||
// had errors, so use default shader
|
||||
shader.defaultShader = qtrue;
|
||||
}
|
||||
sh = FinishShader();
|
||||
|
||||
int fileIndex = -1;
|
||||
for ( int i = 0; i < s_numShaderFiles; ++i ) {
|
||||
if ( textOffset >= s_shaderFileOffsets[i] ) {
|
||||
fileIndex = i;
|
||||
}
|
||||
}
|
||||
sh->fileIndex = fileIndex;
|
||||
sh->text = s_shaderText + textOffset;
|
||||
|
||||
return sh;
|
||||
}
|
||||
|
||||
|
@ -2852,6 +2869,100 @@ void R_ShaderList_f( void )
|
|||
}
|
||||
|
||||
|
||||
static void AutoCompleteShaderName( fieldCallback_t callback )
|
||||
{
|
||||
for ( int i = 0; i < tr.numShaders; i++ ) {
|
||||
callback( tr.shaders[i]->name );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void R_CompleteShaderName_f( int startArg, int compArg )
|
||||
{
|
||||
if ( startArg + 1 == compArg )
|
||||
Field_AutoCompleteCustom( startArg, compArg, &AutoCompleteShaderName );
|
||||
}
|
||||
|
||||
|
||||
void R_ShaderInfo_f()
|
||||
{
|
||||
if ( Cmd_Argc() <= 1 ) {
|
||||
ri.Printf( PRINT_ALL, "usage: %s <shadername> [code]\n", Cmd_Argv(0) );
|
||||
return;
|
||||
}
|
||||
|
||||
const char* const name = Cmd_Argv(1);
|
||||
const shader_t* shader = NULL;
|
||||
for ( int i = 0; i < tr.numShaders; i++ ) {
|
||||
if ( !Q_stricmp( tr.shaders[i]->name, name ) ) {
|
||||
shader = tr.shaders[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( shader == NULL ) {
|
||||
ri.Printf( PRINT_ALL, "shader not found\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( shader->text == NULL ) {
|
||||
const char* type;
|
||||
switch ( shader->lightmapIndex ) {
|
||||
case LIGHTMAP_BROKEN: type = "broken lit surface"; break;
|
||||
case LIGHTMAP_2D: type = "UI element"; break;
|
||||
case LIGHTMAP_BY_VERTEX: type = "vertex-lit surface"; break;
|
||||
case LIGHTMAP_NONE: type = "opaque surface"; break;
|
||||
default: type = "lit surface"; break;
|
||||
}
|
||||
ri.Printf( PRINT_ALL, "shader has no code (type: %s)\n", type );
|
||||
return;
|
||||
}
|
||||
|
||||
const int fileIndex = shader->fileIndex;
|
||||
if ( fileIndex >= 0 && fileIndex < s_numShaderFiles ) {
|
||||
const int nameOffset = s_shaderFileNameOffsets[fileIndex];
|
||||
const char* const fileName = s_shaderFileNames + nameOffset;
|
||||
ri.Printf( PRINT_ALL, "File: scripts/%s\n", fileName );
|
||||
|
||||
char pakName[256];
|
||||
const int pakChecksum = s_shaderPakChecksums[fileIndex];
|
||||
if( FS_GetPakPath( pakName, sizeof(pakName), pakChecksum ) ) {
|
||||
ri.Printf( PRINT_ALL, "Pak : %s\n", pakName );
|
||||
}
|
||||
}
|
||||
|
||||
if ( Q_stricmp( Cmd_Argv(2), "code" ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char* s = shader->text;
|
||||
int tabs = 0;
|
||||
for ( ;; ) {
|
||||
const char c0 = s[0];
|
||||
const char c1 = s[1];
|
||||
if ( c0 == '{' ) {
|
||||
tabs++;
|
||||
ri.Printf( PRINT_ALL, "{" );
|
||||
} else if ( c0 == '\n' ) {
|
||||
ri.Printf( PRINT_ALL, "\n" );
|
||||
if ( c1 == '}' ) {
|
||||
tabs--;
|
||||
if ( tabs == 0 ) {
|
||||
ri.Printf( PRINT_ALL, "}\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
for( int i = 0; i < tabs; i++ ) {
|
||||
ri.Printf( PRINT_ALL, " " );
|
||||
}
|
||||
} else {
|
||||
ri.Printf( PRINT_ALL, "%c", c0 );
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// finds and loads all .shader files, combining them into
|
||||
// a single large text block that can be scanned for shader names
|
||||
// note that this does a lot of things very badly, e.g. still loads superceded shaders
|
||||
|
@ -2865,46 +2976,64 @@ static void ScanAndLoadShaderFiles()
|
|||
int i;
|
||||
char* p;
|
||||
|
||||
int numShaders;
|
||||
char** shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaders );
|
||||
int numShaderFiles;
|
||||
char** shaderFileNames = ri.FS_ListFiles( "scripts", ".shader", &numShaderFiles );
|
||||
|
||||
if ( !shaderFiles || !numShaders )
|
||||
if ( !shaderFileNames || !numShaderFiles )
|
||||
{
|
||||
ri.Printf( PRINT_WARNING, "WARNING: no shader files found\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( numShaders > MAX_SHADER_FILES )
|
||||
if ( numShaderFiles > MAX_SHADER_FILES )
|
||||
ri.Error( ERR_DROP, "Shader file limit exceeded" );
|
||||
|
||||
s_shaderFileOffsets = RI_New<int>( numShaderFiles );
|
||||
s_shaderFileNameOffsets = RI_New<int>( numShaderFiles );
|
||||
s_shaderPakChecksums = RI_New<int>( numShaderFiles );
|
||||
s_numShaderFiles = numShaderFiles;
|
||||
|
||||
long sum = 0;
|
||||
long sumNames = 0;
|
||||
// load and parse shader files
|
||||
for ( i = 0; i < numShaders; i++ )
|
||||
for ( i = 0; i < numShaderFiles; i++ )
|
||||
{
|
||||
char filename[MAX_QPATH];
|
||||
Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] );
|
||||
ri.FS_ReadFile( filename, (void **)&buffers[i] );
|
||||
Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFileNames[i] );
|
||||
ri.FS_ReadFilePak( filename, (void **)&buffers[i], &s_shaderPakChecksums[i] );
|
||||
if ( !buffers[i] )
|
||||
ri.Error( ERR_DROP, "Couldn't load %s", filename );
|
||||
len[i] = COM_Compress( buffers[i] );
|
||||
sum += len[i];
|
||||
sumNames += strlen( shaderFileNames[i] );
|
||||
}
|
||||
|
||||
s_shaderText = RI_New<char>( sum + numShaders + 1 );
|
||||
s_shaderText = RI_New<char>( sum + numShaderFiles + 1 );
|
||||
s_shaderFileNames = RI_New<char>( sumNames );
|
||||
|
||||
char* s = s_shaderText;
|
||||
for ( i = 0; i < numShaders; i++ ) {
|
||||
char* s = s_shaderFileNames;
|
||||
for ( i = 0; i < numShaderFiles; i++ ) {
|
||||
s_shaderFileNameOffsets[i] = (int)( s - s_shaderFileNames );
|
||||
const int l = strlen( shaderFileNames[i] );
|
||||
Com_Memcpy( s, shaderFileNames[i], l );
|
||||
s += l;
|
||||
*s++ = '\0';
|
||||
}
|
||||
|
||||
s = s_shaderText;
|
||||
for ( i = 0; i < numShaderFiles; i++ ) {
|
||||
s_shaderFileOffsets[i] = (int)( s - s_shaderText );
|
||||
Com_Memcpy( s, buffers[i], len[i] );
|
||||
s += len[i];
|
||||
*s++ = '\n';
|
||||
}
|
||||
*s = 0;
|
||||
*s = '\0';
|
||||
|
||||
// the files have to be freed backwards because the hunk isn't a real MM
|
||||
for (i = numShaders - 1; i >= 0; --i)
|
||||
for (i = numShaderFiles - 1; i >= 0; --i)
|
||||
ri.FS_FreeFile( buffers[i] );
|
||||
|
||||
ri.FS_FreeFileList( shaderFiles );
|
||||
ri.FS_FreeFileList( shaderFileNames );
|
||||
|
||||
int shaderTextHashTableSizes[MAX_SHADERTEXT_HASH];
|
||||
Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));
|
||||
|
|
Loading…
Reference in a new issue