From 41ed9c2ce57a4fae6ad4e28d6ef704012ba9483c Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Tue, 29 Aug 2017 23:56:21 +0200 Subject: [PATCH 01/12] do not list empty shader dir --- include/ishaders.h | 6 +++++- plugins/shaders/shaders.cpp | 30 ++++++++++++++++++++++++++++++ radiant/texwindow.cpp | 6 +++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/ishaders.h b/include/ishaders.h index 5ade5956..bd35b593 100644 --- a/include/ishaders.h +++ b/include/ishaders.h @@ -111,6 +111,9 @@ typedef void ( WINAPI * PFN_RELOADSHADERS )(); // load all shaders in a given directory // this will scan the list of in-memory shaders, and load the related qtexture_t if needed typedef int ( WINAPI * PFN_LOADSHADERSFROMDIR )( const char* path ); +// count all shaders in a given directory +// this will scan the list of in-memory shaders +typedef bool ( WINAPI * PFN_ISDIRCONTAININGSHADER )( const char* path ); // load a shader file (ie a set of shaders) // after LoadShaderFile shaders will be in memory, next step is to load the qtexture_t Radiant uses to represent them // if a shader with the same name exists, new one will not be loaded - don't use this to refresh the shaders! @@ -178,6 +181,7 @@ struct _QERShadersTable PFN_FREESHADERS m_pfnFreeShaders; PFN_RELOADSHADERS m_pfnReloadShaders; PFN_LOADSHADERSFROMDIR m_pfnLoadShadersFromDir; + PFN_ISDIRCONTAININGSHADER m_pfnIsDirContainingShaders; PFN_LOADSHADERFILE m_pfnLoadShaderFile; PFN_RELOADSHADERFILE m_pfnReloadShaderFile; PFN_HASSHADER m_pfnHasShader; @@ -219,7 +223,7 @@ struct _QERShadersTable #define QERApp_ColorShader_ForName __SHADERSTABLENAME.m_pfnColorShader_ForName #define QERApp_Shader_ForName_NoLoad __SHADERSTABLENAME.m_pfnShader_ForName_NoLoad #define QERApp_LoadShadersFromDir __SHADERSTABLENAME.m_pfnLoadShadersFromDir -#define QERApp_LoadShadersFromDir __SHADERSTABLENAME.m_pfnLoadShadersFromDir +#define QERApp_IsDirContainingShaders __SHADERSTABLENAME.m_pfnIsDirContainingShaders #define QERApp_CreateShader_ForTextureName __SHADERSTABLENAME.m_pfnCreateShader_ForTextureName #define QERApp_GetActiveShaderCount __SHADERSTABLENAME.m_pfnGetActiveShaderCount #define QERApp_ActiveShaders_SetDisplayed __SHADERSTABLENAME.m_pfnActiveShaders_SetDisplayed diff --git a/plugins/shaders/shaders.cpp b/plugins/shaders/shaders.cpp index 792b2ad0..1c75f4d0 100644 --- a/plugins/shaders/shaders.cpp +++ b/plugins/shaders/shaders.cpp @@ -410,6 +410,16 @@ int WINAPI QERApp_LoadShadersFromDir( const char *path ){ for ( int i = 0; i < nSize; i++ ) { CShader *pShader = reinterpret_cast < CShader * >( g_Shaders[i] ); + + // does not uselessly load shader with path not starting with "textures/" + // they will not be displayed by texture browser, because they can't be + // applied to a surface + if ( !g_str_has_prefix( pShader->getName(), "textures/" ) ) { + continue; + } + + // this is basically doing: + // if path in ["scripts/eerie.shader", "textures/eerie/blackness"] if ( strstr( pShader->getShaderFileName(), path ) || strstr( pShader->getName(), path ) ) { count++; // request the shader, this will load the texture if needed and set "inuse" @@ -430,6 +440,25 @@ int WINAPI QERApp_LoadShadersFromDir( const char *path ){ return count; } +bool WINAPI QERApp_IsDirContainingShaders( const char *path ){ + int nSize = g_Shaders.GetSize(); + // exclude shaders that are not starting with "textures/" + // they will not be displayed and are not applicable to surfaces + // exclude shaders from other paths, + // they are not the ones we are looking for + gchar* prefix = g_strconcat("textures/", path, NULL); + for ( int i = 0; i < nSize; i++ ) + { + CShader *pShader = reinterpret_cast < CShader * >( g_Shaders[i] ); + if ( g_str_has_prefix( pShader->getName(), prefix ) ) { + g_free(prefix); + return true; + } + } + g_free(prefix); + return false; +} + bool CShader::Parse(){ char *token = g_ScripLibTable.m_pfnToken(); @@ -924,6 +953,7 @@ bool CSynapseClientShaders::RequestAPI( APIDescriptor_t *pAPI ){ pTable->m_pfnFreeShaders = QERApp_FreeShaders; pTable->m_pfnReloadShaders = QERApp_ReloadShaders; pTable->m_pfnLoadShadersFromDir = QERApp_LoadShadersFromDir; + pTable->m_pfnIsDirContainingShaders = QERApp_IsDirContainingShaders; pTable->m_pfnReloadShaderFile = QERApp_ReloadShaderFile; pTable->m_pfnLoadShaderFile = QERApp_LoadShaderFile; pTable->m_pfnHasShader = QERApp_HasShader; diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index d91842a7..344dc942 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -591,7 +591,10 @@ void FillTextureList( GSList** pArray ) } if ( !found ) { - texdirs = g_slist_prepend( texdirs, g_strdup( shaderfile ) ); + if( QERApp_IsDirContainingShaders( shaderfile ) ) + { + texdirs = g_slist_prepend( texdirs, g_strdup( shaderfile ) ); + } } free( l_shaderfiles->data ); @@ -784,6 +787,7 @@ void Texture_ShowDirectory_by_path( const char* pPath ) ( the GL textures are not flushed though) ============== */ + void Texture_ShowDirectory(){ char name[1024]; char dirstring[1024]; From 39ec17cfd9d553378ed713f892580c3cdbd06599 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 30 Aug 2017 00:09:06 +0200 Subject: [PATCH 02/12] move texture listing outside of texture showing --- radiant/texwindow.cpp | 159 ++++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 76 deletions(-) diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index 344dc942..83abcad0 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -525,6 +525,88 @@ void BuildShaderList(){ } } +void Texture_ListDirectory(){ + char name[1024]; + char dirstring[1024]; + CString strTemp; + int shaders_count = 0; + int textures_count = 0; + GSList *files = NULL, *temp; + + // load texture_directory.shader + // NOTE: because of above call to Texture_ClearInuse, g_ActiveShaders will have the newly loaded shaders only + // we'll use that later to check if textures have a shader associated or not + // NOTE: all shaders loaded through QERApp_LoadShadersFromDir will get their InUse flag to True, we'll need a call to Texture_ShowInUse for later cleanup/adjustment + // NOTE: QERApp_LoadShadersFromDir has two criterions for loading a shader: + // the shaderfile is texture_directory (like "museum" will load everything in museum.shader) + // the shader name contains texture_directory (like "base_floor" will load museum.shader::base_floor/concfloor_rain) + shaders_count = QERApp_LoadShadersFromDir( texture_directory ); + // load remaining texture files + // if a texture is already in use to represent a shader, ignore it + + // need this function "GSList *lst SynapseServer::GetMinorList(char *major_name);" + + sprintf( dirstring, "textures/%s", texture_directory ); + g_ImageManager.BeginExtensionsScan(); + const char* ext; + while ( ( ext = g_ImageManager.GetNextExtension() ) != NULL ) + { + files = g_slist_concat( files, vfsGetFileList( dirstring, ext ) ); + } + + for ( temp = files; temp; temp = temp->next ) + { + sprintf( name, "%s%s", texture_directory, (char*)temp->data ); + + StripExtension( name ); + strTemp = name; + strTemp.MakeLower(); + + // avoid effect textures for Q3 texture sets + if ( strTemp.Find( ".specular" ) >= 0 || + strTemp.Find( ".glow" ) >= 0 || + strTemp.Find( ".bump" ) >= 0 || + strTemp.Find( ".diffuse" ) >= 0 || + strTemp.Find( ".blend" ) >= 0 || + strTemp.Find( ".alpha" ) >= 0 ) { + continue; + } + + // avoid glow, heightmap, normalmap and specular maps for Q4 texture sets + if ( g_str_has_suffix( name, "_g" ) || + g_str_has_suffix( name, "_h" ) || + g_str_has_suffix( name, "_local" ) || + g_str_has_suffix( name, "_nm" ) || + g_str_has_suffix( name, "_s" ) || + g_str_has_suffix( name, "_bump" ) || + g_str_has_suffix( name, "_gloss" ) || + g_str_has_suffix( name, "_luma" ) || + g_str_has_suffix( name, "_norm" ) ) { + continue; + } + + // avoid ever loading a texture name with spaces + if ( strTemp.Find( " " ) >= 0 ) { + Sys_FPrintf( SYS_WRN, "WARNING: Skipping texture name with spaces [%s]\n", strTemp.GetBuffer() ); + continue; + } + + // build a texture name that fits the conventions for qtexture_t::name + char stdName[1024]; + sprintf( stdName, "textures/%s", name ); + // check if this texture doesn't have a shader + if ( !QERApp_ActiveShader_ForTextureName( stdName ) ) { + QERApp_CreateShader_ForTextureName( stdName ); + textures_count++; + } + } + + Sys_Printf( "Loaded %d shaders and created default shader for %d orphan textures.\n", + shaders_count, textures_count ); + + vfsClearFileDirList( &files ); +} + /* ================== FillTextureMenu @@ -790,11 +872,6 @@ void Texture_ShowDirectory_by_path( const char* pPath ) void Texture_ShowDirectory(){ char name[1024]; - char dirstring[1024]; - CString strTemp; - int shaders_count = 0; - int textures_count = 0; - GSList *files = NULL, *temp; g_bScreenUpdates = false; @@ -805,78 +882,8 @@ void Texture_ShowDirectory(){ // NOTE: shaders that are not in use but have been loaded previously are still in memory. But they don't get displayed. g_qeglobals.d_texturewin.originy = 0; - // load texture_directory.shader - // NOTE: because of above call to Texture_ClearInuse, g_ActiveShaders will have the newly loaded shaders only - // we'll use that later to check if textures have a shader associated or not - // NOTE: all shaders loaded through QERApp_LoadShadersFromDir will get their InUse flag to True, we'll need a call to Texture_ShowInUse for later cleanup/adjustment - // NOTE: QERApp_LoadShadersFromDir has two criterions for loading a shader: - // the shaderfile is texture_directory (like "museum" will load everything in museum.shader) - // the shader name contains texture_directory (like "base_floor" will load museum.shader::base_floor/concfloor_rain) - shaders_count = QERApp_LoadShadersFromDir( texture_directory ); - // load remaining texture files - // if a texture is already in use to represent a shader, ignore it - // need this function "GSList *lst SynapseServer::GetMinorList(char *major_name);" - - sprintf( dirstring, "textures/%s", texture_directory ); - g_ImageManager.BeginExtensionsScan(); - const char* ext; - while ( ( ext = g_ImageManager.GetNextExtension() ) != NULL ) - { - files = g_slist_concat( files, vfsGetFileList( dirstring, ext ) ); - } - - for ( temp = files; temp; temp = temp->next ) - { - sprintf( name, "%s%s", texture_directory, (char*)temp->data ); - - StripExtension( name ); - strTemp = name; - strTemp.MakeLower(); - - // avoid effect textures for Q3 texture sets - if ( strTemp.Find( ".specular" ) >= 0 || - strTemp.Find( ".glow" ) >= 0 || - strTemp.Find( ".bump" ) >= 0 || - strTemp.Find( ".diffuse" ) >= 0 || - strTemp.Find( ".blend" ) >= 0 || - strTemp.Find( ".alpha" ) >= 0 ) { - continue; - } - - // avoid glow, heightmap, normalmap and specular maps for Q4 texture sets - if ( g_str_has_suffix( name, "_g" ) || - g_str_has_suffix( name, "_h" ) || - g_str_has_suffix( name, "_local" ) || - g_str_has_suffix( name, "_nm" ) || - g_str_has_suffix( name, "_s" ) || - g_str_has_suffix( name, "_bump" ) || - g_str_has_suffix( name, "_gloss" ) || - g_str_has_suffix( name, "_luma" ) || - g_str_has_suffix( name, "_norm" ) ) { - continue; - } - - // avoid ever loading a texture name with spaces - if ( strTemp.Find( " " ) >= 0 ) { - Sys_FPrintf( SYS_WRN, "WARNING: Skipping texture name with spaces [%s]\n", strTemp.GetBuffer() ); - continue; - } - - // build a texture name that fits the conventions for qtexture_t::name - char stdName[1024]; - sprintf( stdName, "textures/%s", name ); - // check if this texture doesn't have a shader - if ( !QERApp_ActiveShader_ForTextureName( stdName ) ) { - QERApp_CreateShader_ForTextureName( stdName ); - textures_count++; - } - } - - Sys_Printf( "Loaded %d shaders and created default shader for %d orphan textures.\n", - shaders_count, textures_count ); - - vfsClearFileDirList( &files ); + Texture_ListDirectory(); // sort for displaying QERApp_SortActiveShaders(); From a9e54ea54fe204ae9a541ea48aa9386a756518d9 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 30 Aug 2017 02:09:51 +0200 Subject: [PATCH 03/12] move texture name validation outside of texture listing --- radiant/texwindow.cpp | 71 ++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index 83abcad0..48a69075 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -525,10 +525,48 @@ void BuildShaderList(){ } } +bool IsValidTextureName(char* name){ + CString strTemp; + + StripExtension( name ); + strTemp = name; + strTemp.MakeLower(); + + // avoid effect textures for Q3 texture sets + if ( strTemp.Find( ".specular" ) >= 0 || + strTemp.Find( ".glow" ) >= 0 || + strTemp.Find( ".bump" ) >= 0 || + strTemp.Find( ".diffuse" ) >= 0 || + strTemp.Find( ".blend" ) >= 0 || + strTemp.Find( ".alpha" ) >= 0 ) { + return false; + } + + // avoid glow, heightmap, normalmap and specular maps for Q4 texture sets + if ( g_str_has_suffix( name, "_g" ) || + g_str_has_suffix( name, "_h" ) || + g_str_has_suffix( name, "_local" ) || + g_str_has_suffix( name, "_nm" ) || + g_str_has_suffix( name, "_s" ) || + g_str_has_suffix( name, "_bump" ) || + g_str_has_suffix( name, "_gloss" ) || + g_str_has_suffix( name, "_luma" ) || + g_str_has_suffix( name, "_norm" ) ) { + return false; + } + + // avoid ever loading a texture name with spaces + if ( strTemp.Find( " " ) >= 0 ) { + Sys_FPrintf( SYS_WRN, "WARNING: Skipping texture name with spaces [%s]\n", strTemp.GetBuffer() ); + return false; + } + + return true; +} + void Texture_ListDirectory(){ char name[1024]; char dirstring[1024]; - CString strTemp; int shaders_count = 0; int textures_count = 0; GSList *files = NULL, *temp; @@ -558,36 +596,7 @@ void Texture_ListDirectory(){ { sprintf( name, "%s%s", texture_directory, (char*)temp->data ); - StripExtension( name ); - strTemp = name; - strTemp.MakeLower(); - - // avoid effect textures for Q3 texture sets - if ( strTemp.Find( ".specular" ) >= 0 || - strTemp.Find( ".glow" ) >= 0 || - strTemp.Find( ".bump" ) >= 0 || - strTemp.Find( ".diffuse" ) >= 0 || - strTemp.Find( ".blend" ) >= 0 || - strTemp.Find( ".alpha" ) >= 0 ) { - continue; - } - - // avoid glow, heightmap, normalmap and specular maps for Q4 texture sets - if ( g_str_has_suffix( name, "_g" ) || - g_str_has_suffix( name, "_h" ) || - g_str_has_suffix( name, "_local" ) || - g_str_has_suffix( name, "_nm" ) || - g_str_has_suffix( name, "_s" ) || - g_str_has_suffix( name, "_bump" ) || - g_str_has_suffix( name, "_gloss" ) || - g_str_has_suffix( name, "_luma" ) || - g_str_has_suffix( name, "_norm" ) ) { - continue; - } - - // avoid ever loading a texture name with spaces - if ( strTemp.Find( " " ) >= 0 ) { - Sys_FPrintf( SYS_WRN, "WARNING: Skipping texture name with spaces [%s]\n", strTemp.GetBuffer() ); + if ( !IsValidTextureName( name ) ) { continue; } From 67647ac470c69338dc0899d17b16750b7e43063d Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 30 Aug 2017 03:34:05 +0200 Subject: [PATCH 04/12] do not list empty texture dir --- radiant/texwindow.cpp | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index 48a69075..52ce04aa 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -564,6 +564,33 @@ bool IsValidTextureName(char* name){ return true; } +bool IsDirContainingTextures(const char* path){ + char name[1024]; + char dirstring[1024]; + GSList *files = NULL, *temp; + + sprintf( dirstring, "textures/%s", path ); + g_ImageManager.BeginExtensionsScan(); + const char* ext; + while ( ( ext = g_ImageManager.GetNextExtension() ) != NULL ) + { + files = g_slist_concat( files, vfsGetFileList( dirstring, ext ) ); + } + + for ( temp = files; temp; temp = temp->next ) + { + sprintf( name, "%s", (char*)temp->data ); + + if ( IsValidTextureName( name ) ) { + vfsClearFileDirList( &files ); + return true; + } + } + + vfsClearFileDirList( &files ); + return false; +} + void Texture_ListDirectory(){ char name[1024]; char dirstring[1024]; @@ -649,7 +676,10 @@ void FillTextureList( GSList** pArray ) // Hydra: erm, this didn't used to do anything except leak memory... // For Halflife support this is required to work however. // g_slist_append(texdirs, p->data); - texdirs = g_slist_append( texdirs, g_strdup( (char *)p->data ) ); + if ( IsDirContainingTextures( (char*)p->data ) ) + { + texdirs = g_slist_append( texdirs, g_strdup( (char *)p->data ) ); + } } vfsClearFileDirList( &texdirs_tmp ); } From e179e2b4a4428a93d6efe9e5d2885141b6b9f26c Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 30 Aug 2017 02:28:39 +0200 Subject: [PATCH 05/12] more strict shader dir checking --- plugins/shaders/shaders.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/plugins/shaders/shaders.cpp b/plugins/shaders/shaders.cpp index 1c75f4d0..a8ea6496 100644 --- a/plugins/shaders/shaders.cpp +++ b/plugins/shaders/shaders.cpp @@ -404,9 +404,20 @@ void WINAPI QERApp_ReloadShaders(){ int WINAPI QERApp_LoadShadersFromDir( const char *path ){ int count = 0; + + // some code adds a trailing slash + gchar* keyword = g_strdup(path); + if ( g_str_has_suffix( keyword, "/" ) ) { + keyword[ strlen(keyword) -1 ] = '\0'; + } + + gchar* around = g_strconcat("/", keyword, ".", NULL); + gchar* prefix = g_strconcat("textures/", keyword, "/", NULL); + // scan g_Shaders, and call QERApp_Shader_ForName for each in the given path // this will load the texture if needed and will set it in use.. int nSize = g_Shaders.GetSize(); + for ( int i = 0; i < nSize; i++ ) { CShader *pShader = reinterpret_cast < CShader * >( g_Shaders[i] ); @@ -418,9 +429,7 @@ int WINAPI QERApp_LoadShadersFromDir( const char *path ){ continue; } - // this is basically doing: - // if path in ["scripts/eerie.shader", "textures/eerie/blackness"] - if ( strstr( pShader->getShaderFileName(), path ) || strstr( pShader->getName(), path ) ) { + if ( strstr( pShader->getShaderFileName(), around ) != NULL || g_str_has_prefix( pShader->getName(), prefix ) ) { count++; // request the shader, this will load the texture if needed and set "inuse" //++timo FIXME: should we put an Activate member on CShader? @@ -437,6 +446,11 @@ int WINAPI QERApp_LoadShadersFromDir( const char *path ){ #endif } } + + g_free(keyword); + g_free(around); + g_free(prefix); + return count; } @@ -446,7 +460,7 @@ bool WINAPI QERApp_IsDirContainingShaders( const char *path ){ // they will not be displayed and are not applicable to surfaces // exclude shaders from other paths, // they are not the ones we are looking for - gchar* prefix = g_strconcat("textures/", path, NULL); + gchar* prefix = g_strconcat("textures/", path, "/", NULL); for ( int i = 0; i < nSize; i++ ) { CShader *pShader = reinterpret_cast < CShader * >( g_Shaders[i] ); From c832a5591081b77c1bb62e111d77210b1b6d81b9 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 30 Aug 2017 03:12:13 +0200 Subject: [PATCH 06/12] =?UTF-8?q?avoid=20=E2=80=9Cunused=E2=80=9D=20warnin?= =?UTF-8?q?g=20because=20usage=20is=20in=20debug=20code=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/shaders/shaders.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/shaders/shaders.cpp b/plugins/shaders/shaders.cpp index a8ea6496..a389b55f 100644 --- a/plugins/shaders/shaders.cpp +++ b/plugins/shaders/shaders.cpp @@ -431,18 +431,18 @@ int WINAPI QERApp_LoadShadersFromDir( const char *path ){ if ( strstr( pShader->getShaderFileName(), around ) != NULL || g_str_has_prefix( pShader->getName(), prefix ) ) { count++; +#ifdef _DEBUG // request the shader, this will load the texture if needed and set "inuse" //++timo FIXME: should we put an Activate member on CShader? // this QERApp_Shader_ForName call is a kind of hack IShader *pFoo = QERApp_Shader_ForName( pShader->getName() ); -#ifdef _DEBUG // check we activated the right shader // NOTE: if there was something else loaded, the size of g_Shaders may have changed and strange behaviours are to be expected if ( pFoo != pShader ) { Sys_FPrintf( SYS_WRN, "WARNING: unexpected pFoo != pShader in QERApp_LoadShadersFromDir\n" ); } #else - pFoo = NULL; // leo: shut up the compiler + QERApp_Shader_ForName( pShader->getName() ); #endif } } From bdecace9738b9b7d63a3cad7dc4a5bc81ba5c1d4 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 30 Aug 2017 03:25:36 +0200 Subject: [PATCH 07/12] add more well known preview/gloss/normal suffixes --- radiant/texwindow.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index 52ce04aa..b103cf76 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -542,8 +542,8 @@ bool IsValidTextureName(char* name){ return false; } - // avoid glow, heightmap, normalmap and specular maps for Q4 texture sets if ( g_str_has_suffix( name, "_g" ) || + // avoid glow, heightmap, normalmap and specular maps for Q4 texture sets g_str_has_suffix( name, "_h" ) || g_str_has_suffix( name, "_local" ) || g_str_has_suffix( name, "_nm" ) || @@ -551,7 +551,12 @@ bool IsValidTextureName(char* name){ g_str_has_suffix( name, "_bump" ) || g_str_has_suffix( name, "_gloss" ) || g_str_has_suffix( name, "_luma" ) || - g_str_has_suffix( name, "_norm" ) ) { + g_str_has_suffix( name, "_norm" ) || + // more well-known suffixes + g_str_has_suffix( name, "_p" ) || // preview (used by qer_editorimage) + g_str_has_suffix( name, "_g" ) || // gloss + g_str_has_suffix( name, "_n" ) // normal + ) { return false; } From 8051dd88cab1f160f8a48eca29159adee7795b87 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 30 Aug 2017 04:02:21 +0200 Subject: [PATCH 08/12] avoid to misread an unbracketed for loop --- radiant/texwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index b103cf76..08839db2 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -711,10 +711,12 @@ void FillTextureList( GSList** pArray ) } for ( GSList *tmp = texdirs; tmp; tmp = g_slist_next( tmp ) ) + { if ( !strcasecmp( (char*)tmp->data, shaderfile ) ) { found = TRUE; break; } + } if ( !found ) { if( QERApp_IsDirContainingShaders( shaderfile ) ) From a9583eb1e649397437c5e12b4283d8d3e43ab4dc Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 2 Sep 2017 03:55:52 +0200 Subject: [PATCH 09/12] also check against shader script file name when looking for non-empty shader dir Greeting Pan --- plugins/shaders/shaders.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/shaders/shaders.cpp b/plugins/shaders/shaders.cpp index a389b55f..e125584c 100644 --- a/plugins/shaders/shaders.cpp +++ b/plugins/shaders/shaders.cpp @@ -460,15 +460,21 @@ bool WINAPI QERApp_IsDirContainingShaders( const char *path ){ // they will not be displayed and are not applicable to surfaces // exclude shaders from other paths, // they are not the ones we are looking for + + gchar* around = g_strconcat("/", path, ".", NULL); gchar* prefix = g_strconcat("textures/", path, "/", NULL); + for ( int i = 0; i < nSize; i++ ) { CShader *pShader = reinterpret_cast < CShader * >( g_Shaders[i] ); - if ( g_str_has_prefix( pShader->getName(), prefix ) ) { + if ( ( strstr( pShader->getShaderFileName(), around ) != NULL && g_str_has_prefix( pShader->getName(), "textures/" ) ) || g_str_has_prefix( pShader->getName(), prefix ) ) { + g_free(around); g_free(prefix); return true; } } + + g_free(around); g_free(prefix); return false; } From e9e095b4c62f52d78ec29578c26826529ae81518 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 2 Sep 2017 05:09:18 +0200 Subject: [PATCH 10/12] empty shader dir checking: some useful comments --- plugins/shaders/shaders.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/shaders/shaders.cpp b/plugins/shaders/shaders.cpp index e125584c..e6dbde67 100644 --- a/plugins/shaders/shaders.cpp +++ b/plugins/shaders/shaders.cpp @@ -429,6 +429,10 @@ int WINAPI QERApp_LoadShadersFromDir( const char *path ){ continue; } + // - proceed if shader script base name is + // for example: "scripts/eerie.shader" with "eerie" path + // - proceed if shader script base name is and shader path starts with "textures/" + // for example: "scripts/eerie.shader" providing "textures/eerie/blackness" with "eerie" path if ( strstr( pShader->getShaderFileName(), around ) != NULL || g_str_has_prefix( pShader->getName(), prefix ) ) { count++; #ifdef _DEBUG @@ -467,6 +471,11 @@ bool WINAPI QERApp_IsDirContainingShaders( const char *path ){ for ( int i = 0; i < nSize; i++ ) { CShader *pShader = reinterpret_cast < CShader * >( g_Shaders[i] ); + + // - returns true if shader script basename is and shader path starts with "textures/" + // for example: "scripts/rockyvalley.shader" with "rockyvalley" path providing "textures/amethyst7/rockyvalley/rockyvalley_skybox/" + // - returns true if shader startswith "textures/" + // for example: "scripts/eerie.shader" with "eerie" path providing "textures/eerie/blackness" if ( ( strstr( pShader->getShaderFileName(), around ) != NULL && g_str_has_prefix( pShader->getName(), "textures/" ) ) || g_str_has_prefix( pShader->getName(), prefix ) ) { g_free(around); g_free(prefix); From b1c4fb1304346442cf28f22e520b33eed4354360 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 2 Sep 2017 20:04:45 +0200 Subject: [PATCH 11/12] =?UTF-8?q?make=20=E2=80=9Chide=20empty=20directorie?= =?UTF-8?q?s=E2=80=9D=20an=20option?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- radiant/mainframe.cpp | 20 ++++++++++++++++++++ radiant/mainframe.h | 2 ++ radiant/preferences.cpp | 3 +++ radiant/preferences.h | 1 + radiant/texwindow.cpp | 4 ++-- 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index ffa42a86..d8bfeb9d 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -552,6 +552,7 @@ gint HandleCommand( GtkWidget *widget, gpointer data ){ case ID_TEXTURES_LOAD: g_pParentWnd->OnTexturesLoad(); break; case ID_TEXTURES_RELOADSHADERS: g_pParentWnd->OnTexturesReloadshaders(); break; case ID_TEXTURES_SHADERS_SHOW: g_pParentWnd->OnTexturesShadersShow(); break; + case ID_TEXTURES_EMPTYDIRS_HIDE: g_pParentWnd->OnTexturesEmptyDirsHide(); break; case ID_TEXTURES_TEXTUREWINDOWSCALE_200: case ID_TEXTURES_TEXTUREWINDOWSCALE_100: case ID_TEXTURES_TEXTUREWINDOWSCALE_50: @@ -1401,6 +1402,9 @@ void MainFrame::create_main_menu( GtkWidget *window, GtkWidget *vbox ){ item = create_check_menu_item_with_mnemonic( menu, _( "shaderlist.txt only" ), G_CALLBACK( HandleCommand ), ID_TEXTURES_SHADERLISTONLY, FALSE ); g_object_set_data( G_OBJECT( window ), "menu_textures_shaderlistonly", item ); + item = create_check_menu_item_with_mnemonic( menu, _( "Hide empty directories" ), + G_CALLBACK( HandleCommand ), ID_TEXTURES_EMPTYDIRS_HIDE, FALSE ); + g_object_set_data( G_OBJECT( window ), "menu_textures_emptydirs_hide", item ); item = menu_separator( menu ); menu_in_menu = create_menu_in_menu_with_mnemonic( menu, _( "Texture Directories" ) ); @@ -3107,6 +3111,8 @@ void MainFrame::Create(){ g_bIgnoreCommands++; item = GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "menu_textures_shaders_show" ) ); gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), g_PrefsDlg.m_bShowShaders ? TRUE : FALSE ); + item = GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "menu_textures_emptydirs_hide" ) ); + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), g_PrefsDlg.m_bHideEmptyDirs ? TRUE : FALSE ); item = GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "menu_textures_shaderlistonly" ) ); gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), g_PrefsDlg.m_bTexturesShaderlistOnly ? TRUE : FALSE ); g_bIgnoreCommands--; @@ -5950,6 +5956,20 @@ void MainFrame::OnTexturesReloadshaders(){ ClearGSList( texdirs ); } +void MainFrame::OnTexturesEmptyDirsHide(){ + g_PrefsDlg.m_bHideEmptyDirs ^= 1; + GtkWidget *item = GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "menu_textures_emptydirs_hide" ) ); + g_bIgnoreCommands++; + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), g_PrefsDlg.m_bHideEmptyDirs ? TRUE : FALSE ); + g_bIgnoreCommands--; + + GSList *texdirs = NULL; + FillTextureList( &texdirs ); + FillTextureMenu( texdirs ); + FillTextureDirListWidget( texdirs ); + ClearGSList( texdirs ); +} + void MainFrame::OnTexturesShadersShow(){ g_PrefsDlg.m_bShowShaders ^= 1; GtkWidget *item = GTK_WIDGET( g_object_get_data( G_OBJECT( m_pWidget ), "menu_textures_shaders_show" ) ); diff --git a/radiant/mainframe.h b/radiant/mainframe.h index 87e5a35c..cdca6af2 100644 --- a/radiant/mainframe.h +++ b/radiant/mainframe.h @@ -216,6 +216,7 @@ struct SKeyInfo #define ID_VIEW_HIDESHOW_SHOWHIDDEN 33007 #define ID_TEXTURES_SHADERS_SHOW 33008 //#define ID_SELECTION_CSGADD 33009 +#define ID_TEXTURES_EMPTYDIRS_HIDE 33010 #define ID_SELECTION_CSGMERGE 33011 #define ID_TEXTURES_FLUSH_UNUSED 33014 #define ID_DROP_GROUP_REMOVE 33016 @@ -863,6 +864,7 @@ void OnViewCrosshair(); void OnViewHideshowHideselected(); void OnViewHideshowShowhidden(); void OnTexturesShadersShow(); +void OnTexturesEmptyDirsHide(); void OnViewGroups(); void OnDropGroupAddtoWorld(); void OnDropGroupName(); diff --git a/radiant/preferences.cpp b/radiant/preferences.cpp index 4bb3c681..f67129cb 100644 --- a/radiant/preferences.cpp +++ b/radiant/preferences.cpp @@ -119,6 +119,7 @@ #define TEXTURESUBSET_KEY "UseTextureSubsetLoading" #define TEXTUREQUALITY_KEY "TextureQuality" #define SHOWSHADERS_KEY "ShowShaders" +#define HIDEEMPTYDIRS_KEY "HideEmptyDirs" #define SHADERTEST_KEY "ShaderTest" #define GLLIGHTING_KEY "UseGLLighting" #define LOADSHADERS_KEY "LoadShaders" @@ -644,6 +645,7 @@ PrefsDlg::PrefsDlg (){ m_bSelectWholeEntities = TRUE; m_nTextureQuality = 3; m_bShowShaders = TRUE; + m_bHideEmptyDirs = FALSE; m_bGLLighting = FALSE; m_nShader = 0; m_nUndoLevels = 30; @@ -3076,6 +3078,7 @@ void PrefsDlg::LoadPrefs(){ mLocalPrefs.GetPref( SWITCHCLIP_KEY, &m_bSwitchClip, TRUE ); mLocalPrefs.GetPref( SELWHOLEENTS_KEY, &m_bSelectWholeEntities, TRUE ); mLocalPrefs.GetPref( SHOWSHADERS_KEY, &m_bShowShaders, TRUE ); + mLocalPrefs.GetPref( HIDEEMPTYDIRS_KEY, &m_bHideEmptyDirs, FALSE ); mLocalPrefs.GetPref( GLLIGHTING_KEY, &m_bGLLighting, FALSE ); mLocalPrefs.GetPref( NOSTIPPLE_KEY, &m_bNoStipple, FALSE ); mLocalPrefs.GetPref( UNDOLEVELS_KEY, &m_nUndoLevels, 30 ); diff --git a/radiant/preferences.h b/radiant/preferences.h index ac6ca9d0..1cb275b6 100644 --- a/radiant/preferences.h +++ b/radiant/preferences.h @@ -636,6 +636,7 @@ bool m_bTextureScrollbar; bool m_bDisplayLists; bool m_bAntialiasedPointsAndLines; // Fishman - Add antialiazed points and lines support. 09/03/00 bool m_bShowShaders; +bool m_bHideEmptyDirs; int m_nShader; bool m_bNoStipple; int m_nUndoLevels; diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index 08839db2..eef1cdaa 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -681,7 +681,7 @@ void FillTextureList( GSList** pArray ) // Hydra: erm, this didn't used to do anything except leak memory... // For Halflife support this is required to work however. // g_slist_append(texdirs, p->data); - if ( IsDirContainingTextures( (char*)p->data ) ) + if ( !g_PrefsDlg.m_bHideEmptyDirs || IsDirContainingTextures( (char*)p->data ) ) { texdirs = g_slist_append( texdirs, g_strdup( (char *)p->data ) ); } @@ -719,7 +719,7 @@ void FillTextureList( GSList** pArray ) } if ( !found ) { - if( QERApp_IsDirContainingShaders( shaderfile ) ) + if( !g_PrefsDlg.m_bHideEmptyDirs || QERApp_IsDirContainingShaders( shaderfile ) ) { texdirs = g_slist_prepend( texdirs, g_strdup( shaderfile ) ); } From 88805013d4cc8140a2de5c2c4b4431dbee645ba5 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 7 Jan 2018 05:31:42 +0100 Subject: [PATCH 12/12] print hidden empty shader/texture dirs on console <3 @Pan7 --- radiant/texwindow.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index eef1cdaa..eb436b28 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -685,6 +685,10 @@ void FillTextureList( GSList** pArray ) { texdirs = g_slist_append( texdirs, g_strdup( (char *)p->data ) ); } + else + { + Sys_Printf( "Hiding empty texture dir: %s\n", g_strdup( (char *)p->data ) ); + } } vfsClearFileDirList( &texdirs_tmp ); } @@ -723,6 +727,10 @@ void FillTextureList( GSList** pArray ) { texdirs = g_slist_prepend( texdirs, g_strdup( shaderfile ) ); } + else + { + Sys_Printf( "Hiding empty shader dir: %s\n", g_strdup ( shaderfile ) ); + } } free( l_shaderfiles->data );