}
typedef ReferenceCaller1<TextureGroups, const char*, TextureGroups_addWad> TextureGroupsAddWadCaller;
+namespace
+{
+bool softGroups();
+
+CopiedString Texture_getCategoryByName( const char *tex ){
+ char *n = string_clone( tex );
+ int l = string_length( n );
+ char *s = strrchr( n, '/' );
+ char *p = strchr( s ? ( s + 1 ) : n, '-' );
+ if ( softGroups() ) {
+ if ( s ? ( p >= s ) : ( p != NULL ) ) {
+ p[1] = 0;
+ }
+ else if ( s ) {
+ s[1] = 0;
+ }
+ else{
+ n[0] = 0;
+ }
+ }
+ else
+ {
+ if ( s ) {
+ s[0] = 0;
+ }
+ else{
+ n[0] = 0;
+ }
+ }
+ CopiedString cs( n );
+ string_release( n, l );
+ return cs;
+}
+CopiedString Texture_getCategoryDirectory( const char *cat ){
+ if ( !softGroups() ) {
+ StringOutputStream o( 64 );
+ if ( string_length( cat ) ) {
+ o << cat << "/";
+ }
+ return o.c_str();
+ }
+ char *n = string_clone( cat );
+ int l = string_length( n );
+ if ( l == 0 ) {
+ string_release( n, l );
+ return "";
+ }
+ CopiedString cs;
+ char *p = strrchr( n, '/' );
+ if ( p ) {
+ cs = StringRange( n, p + 1 );
+ }
+ else{
+ cs = "";
+ }
+ string_release( n, l );
+ return cs;
+}
+bool Texture_matchCategory( const char *matchcat, const char *texcat ){
+ int l = string_length( matchcat );
+ if ( softGroups() ) {
+ if ( l > 0 && matchcat[l - 1] == '*' ) {
+ return string_equal_n( texcat, matchcat, l - 1 );
+ }
+ }
+ return string_equal( texcat, matchcat );
+}
+};
+
+
void TextureGroups_addShader( TextureGroups& groups, const char* shaderName ){
const char* texture = path_make_relative( shaderName, "textures/" );
+ globalErrorStream() << texture << "\n";
if ( texture != shaderName ) {
- const char* last = path_remove_directory( texture );
- if ( !string_empty( last ) ) {
- groups.insert( CopiedString( StringRange( texture, --last ) ) );
+ CopiedString n = Texture_getCategoryByName( texture );
+ if ( !string_empty( n.c_str() ) ) {
+ groups.insert( n );
}
}
}
typedef ReferenceCaller1<TextureGroups, const char*, TextureGroups_addShader> TextureGroupsAddShaderCaller;
+
+
+class FindTexturesByTypeVisitor : public ImageModules::Visitor
+{
+TextureGroups& m_groups;
+const char* m_dirstring;
+void visitFile( const char *name ) const {
+ StringOutputStream dirstring( 64 );
+ dirstring << m_dirstring << name;
+ TextureGroups_addShader( m_groups, dirstring.c_str() );
+}
+typedef ConstMemberCaller1<FindTexturesByTypeVisitor, const char *, &FindTexturesByTypeVisitor::visitFile> VisitFileMemberCaller;
+public:
+FindTexturesByTypeVisitor( TextureGroups& groups, const char* dirstring )
+ : m_groups( groups ), m_dirstring( dirstring ){
+}
+void visit( const char* minor, const _QERPlugImageTable& table ) const {
+ GlobalFileSystem().forEachFile( m_dirstring, minor, VisitFileMemberCaller( *this ) );
+}
+};
+
void TextureGroups_addDirectory( TextureGroups& groups, const char* directory ){
- groups.insert( directory );
+ if ( softGroups() ) {
+ // enumerate all files, find dashes
+ StringOutputStream dirstring( 64 );
+ dirstring << "textures/" << directory << "/";
+ Radiant_getImageModules().foreachModule( FindTexturesByTypeVisitor( groups, dirstring.c_str() ) );
+ }
+ else
+ {
+ groups.insert( directory );
+ }
}
typedef ReferenceCaller1<TextureGroups, const char*, TextureGroups_addDirectory> TextureGroupsAddDirectoryCaller;
void TextureBrowser_showShadersExport( const BoolImportCallback& importer );
typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_showShadersExport> TextureBrowserShowShadersExport;
+void TextureBrowser_softGroupsExport( const BoolImportCallback& importer );
+typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_softGroupsExport> TextureBrowserSoftGroupsExport;
+
void TextureBrowser_showShaderlistOnly( const BoolImportCallback& importer );
typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport;
ToggleItem m_hideunused_item;
ToggleItem m_showshaders_item;
ToggleItem m_showshaderlistonly_item;
+ToggleItem m_softgroups_item;
ToggleItem m_fixedsize_item;
ToggleItem m_filternotex_item;
std::size_t m_textureScale;
// make the texture increments match the grid changes
bool m_showShaders;
+bool m_softGroups;
bool m_showTextureScrollbar;
StartupShaders m_startupShaders;
// if true, the texture window will only display in-use shaders
m_hideunused_item( TextureBrowserHideUnusedExport() ),
m_showshaders_item( TextureBrowserShowShadersExport() ),
m_showshaderlistonly_item( TextureBrowserShowShaderlistOnlyExport() ),
+ m_softgroups_item( TextureBrowserSoftGroupsExport() ),
m_fixedsize_item( TextureBrowserFixedSizeExport() ),
m_filternotex_item( TextureBrowserFilterNotexExport() ),
m_heightChanged( true ),
m_uniformTextureSize( 128 ){
}
};
+namespace
+{
+bool softGroups(){
+ return GlobalTextureBrowser().m_softGroups;
+}
+};
+
void ( *TextureBrowser_textureSelected )( const char* shader );
}
}
else {
- if ( !shader_equal_prefix( shader_get_textureName( shader->getName() ), g_TextureBrowser_currentDirectory.c_str() ) ) {
+ if ( !Texture_matchCategory( g_TextureBrowser_currentDirectory.c_str(), Texture_getCategoryByName( shader_get_textureName( shader->getName() ) ).c_str() ) ) {
return false;
}
}
m_count = 0;
}
void operator()( const char* name ) const {
- if ( shader_equal_prefix( name, "textures/" )
- && shader_equal_prefix( name + string_length( "textures/" ), m_directory ) ) {
- ++m_count;
- // request the shader, this will load the texture if needed
- // this Shader_ForName call is a kind of hack
- IShader *pFoo = QERApp_Shader_ForName( name );
- pFoo->DecRef();
+ if ( !shader_equal_prefix( name, "textures/" ) ) {
+ return;
+ }
+ if ( !Texture_matchCategory( m_directory, Texture_getCategoryByName( name + string_length( "textures/" ) ).c_str() ) ) {
+ return;
}
+
+ ++m_count;
+ // request the shader, this will load the texture if needed
+ // this Shader_ForName call is a kind of hack
+ IShader *pFoo = QERApp_Shader_ForName( name );
+ pFoo->DecRef();
}
};
-void TextureDirectory_loadTexture( const char* directory, const char* texture ){
+void TextureDirectory_loadTexture( const char* category, const char* texture ){
+ CopiedString directory = Texture_getCategoryDirectory( category );
StringOutputStream name( 256 );
- name << directory << StringRange( texture, path_get_filename_base_end( texture ) );
+ name << "textures/" << directory.c_str() << StringRange( texture, path_get_filename_base_end( texture ) );
if ( texture_name_ignore( name.c_str() ) ) {
return;
return;
}
+ if ( !shader_equal_prefix( name.c_str(), "textures/" ) ) { // can't happen
+ return;
+ }
+ if ( !Texture_matchCategory( category, Texture_getCategoryByName( name.c_str() + string_length( "textures/" ) ).c_str() ) ) {
+ return;
+ }
+
// if a texture is already in use to represent a shader, ignore it
IShader* shader = QERApp_Shader_ForName( name.c_str() );
shader->DecRef();
class LoadTexturesByTypeVisitor : public ImageModules::Visitor
{
-const char* m_dirstring;
+const char* m_catstring;
public:
-LoadTexturesByTypeVisitor( const char* dirstring )
- : m_dirstring( dirstring ){
+LoadTexturesByTypeVisitor( const char* catstring )
+ : m_catstring( catstring ){
}
void visit( const char* minor, const _QERPlugImageTable& table ) const {
- GlobalFileSystem().forEachFile( m_dirstring, minor, TextureDirectoryLoadTextureCaller( m_dirstring ) );
+ StringOutputStream dirstring( 64 );
+ dirstring << "textures/" << Texture_getCategoryDirectory( m_catstring ).c_str();
+ GlobalFileSystem().forEachFile( dirstring.c_str(), minor, TextureDirectoryLoadTextureCaller( m_catstring ) );
}
};
if ( g_pGameDescription->mGameType != "doom3" ) {
// load remaining texture files
-
- StringOutputStream dirstring( 64 );
- dirstring << "textures/" << directory;
-
- Radiant_getImageModules().foreachModule( LoadTexturesByTypeVisitor( dirstring.c_str() ) );
+ Radiant_getImageModules().foreachModule( LoadTexturesByTypeVisitor( directory ) );
}
}
}
typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_showShadersExport> TextureBrowserShowShadersExport;
+void TextureBrowser_softGroupsExport( const BoolImportCallback& importer ){
+ importer( GlobalTextureBrowser().m_softGroups );
+}
+typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_softGroupsExport> TextureBrowserSoftGroupsExport;
+
void TextureBrowser_showShaderlistOnly( const BoolImportCallback& importer ){
importer( g_TextureBrowser_shaderlistOnly );
}
{
const char* dirName = ( *i ).c_str();
const char* firstUnderscore = strchr( dirName, '_' );
+ const char* firstSlash = strchr( dirName, '/' );
+ if ( firstSlash && ( !firstUnderscore || firstSlash < firstUnderscore ) ) {
+ firstUnderscore = firstSlash;
+ }
StringRange dirRoot( dirName, ( firstUnderscore == 0 ) ? dirName : firstUnderscore + 1 );
TextureGroups::const_iterator next = i;
&& next != groups.end()
&& string_equal_start( ( *next ).c_str(), dirRoot ) ) {
gtk_tree_store_append( store, &iter, NULL );
- gtk_tree_store_set( store, &iter, 0, CopiedString( StringRange( dirName, firstUnderscore ) ).c_str(), -1 );
+ StringOutputStream ost( 64 );
+ ost << CopiedString( StringRange( dirName, firstUnderscore ) ).c_str();
+ if ( *firstUnderscore == '/' ) {
+ ost << "/*";
+ }
+ gtk_tree_store_set( store, &iter, 0, ost.c_str(), -1 );
// keep going...
while ( i != groups.end() && string_equal_start( ( *i ).c_str(), dirRoot ) )
g_TextureBrowser.m_searchedTags = false;
- if ( !TextureBrowser_showWads() ) {
- strcat( dirName, "/" );
- }
-
ScopeDisableScreenUpdates disableScreenUpdates( dirName, "Loading Textures" );
TextureBrowser_ShowDirectory( GlobalTextureBrowser(), dirName );
TextureBrowser_queueDraw( GlobalTextureBrowser() );
create_menu_item_with_mnemonic( menu, "Show Untagged", "ShowUntagged" );
}
+ create_check_menu_item_with_mnemonic( menu, "Use soft groups", "ToggleSoftGroups" );
+
create_check_menu_item_with_mnemonic( menu, "Fixed Size", "FixedSize" );
if ( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) {
TextureBrowser_queueDraw( g_TextureBrowser );
}
+void TextureBrowser_constructTreeStore();
+void TextureBrowser_ToggleSoftGroups(){
+ g_TextureBrowser.m_softGroups ^= 1;
+ g_TextureBrowser.m_softgroups_item.update();
+ TextureBrowser_constructTreeStore();
+ GlobalShaderSystem().refresh();
+ UpdateAllWindows();
+}
+
void TextureBrowser_ToggleShowShaderListOnly(){
g_TextureBrowser_shaderlistOnly ^= 1;
g_TextureBrowser.m_showshaderlistonly_item.update();
GlobalCommands_insert( "ToggleTextures", FreeCaller<TextureBrowser_toggleShow>(), Accelerator( 'T' ) );
GlobalToggles_insert( "ToggleShowShaders", FreeCaller<TextureBrowser_ToggleShowShaders>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_showshaders_item ) );
GlobalToggles_insert( "ToggleShowShaderlistOnly", FreeCaller<TextureBrowser_ToggleShowShaderListOnly>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_showshaderlistonly_item ) );
+ GlobalToggles_insert( "ToggleSoftGroups", FreeCaller<TextureBrowser_ToggleSoftGroups>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_softgroups_item ) );
GlobalToggles_insert( "FixedSize", FreeCaller<TextureBrowser_FixedSize>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_fixedsize_item ) );
GlobalToggles_insert( "FilterNotex", FreeCaller<TextureBrowser_FilterNotex>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_filternotex_item ) );
);
GlobalPreferenceSystem().registerPreference( "ShowShaders", BoolImportStringCaller( GlobalTextureBrowser().m_showShaders ), BoolExportStringCaller( GlobalTextureBrowser().m_showShaders ) );
GlobalPreferenceSystem().registerPreference( "ShowShaderlistOnly", BoolImportStringCaller( g_TextureBrowser_shaderlistOnly ), BoolExportStringCaller( g_TextureBrowser_shaderlistOnly ) );
+ GlobalPreferenceSystem().registerPreference( "SoftGroups", BoolImportStringCaller( GlobalTextureBrowser().m_softGroups ), BoolExportStringCaller( GlobalTextureBrowser().m_softGroups ) );
GlobalPreferenceSystem().registerPreference( "FixedSize", BoolImportStringCaller( g_TextureBrowser_fixedSize ), BoolExportStringCaller( g_TextureBrowser_fixedSize ) );
GlobalPreferenceSystem().registerPreference( "FilterNotex", BoolImportStringCaller( g_TextureBrowser_filterNotex ), BoolExportStringCaller( g_TextureBrowser_filterNotex ) );
GlobalPreferenceSystem().registerPreference( "LoadShaders", IntImportStringCaller( reinterpret_cast<int&>( GlobalTextureBrowser().m_startupShaders ) ), IntExportStringCaller( reinterpret_cast<int&>( GlobalTextureBrowser().m_startupShaders ) ) );