Merge branch 'illwieckz/files'
authorTimePath <andrew.hardaker1995@gmail.com>
Sun, 30 Jul 2017 04:11:48 +0000 (14:11 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Sun, 30 Jul 2017 04:13:32 +0000 (14:13 +1000)
14 files changed:
CMakeLists.txt
Makefile
include/CMakeLists.txt
include/dpkdeps.h [new file with mode: 0644]
include/version.h
plugins/vfspk3/vfs.cpp
radiant/environment.cpp
radiant/main.cpp
radiant/mainframe.cpp
radiant/map.cpp
radiant/map.h
radiant/plugin.cpp
radiant/texwindow.cpp
radiant/texwindow.h

index 0a242ef..5871521 100644 (file)
@@ -16,6 +16,7 @@ set(NetRadiant_VERSION "${NetRadiant_VERSION_MAJOR}.${NetRadiant_VERSION_MINOR}.
 
 file(WRITE "${PROJECT_BINARY_DIR}/RADIANT_MAJOR" ${NetRadiant_VERSION_MAJOR})
 file(WRITE "${PROJECT_BINARY_DIR}/RADIANT_MINOR" ${NetRadiant_VERSION_MINOR})
+file(WRITE "${PROJECT_BINARY_DIR}/RADIANT_PATCH" ${NetRadiant_VERSION_PATCH})
 
 set(RADIANT_ABOUTMSG "Custom build" CACHE STRING "About message")
 
@@ -68,6 +69,7 @@ set(GTK_NS "GTK2" CACHE STRING "GTK variable prefix")
 add_definitions(-DRADIANT_VERSION="${NetRadiant_VERSION}")
 add_definitions(-DRADIANT_MAJOR_VERSION="${NetRadiant_VERSION_MAJOR}")
 add_definitions(-DRADIANT_MINOR_VERSION="${NetRadiant_VERSION_MINOR}")
+add_definitions(-DRADIANT_PATCH_VERSION="${NetRadiant_VERSION_PATCH}")
 
 add_definitions(-DRADIANT_ABOUTMSG="${NetRadiant_ABOUT}")
 
index 1ead725..fddd004 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -241,10 +241,11 @@ endif
 endif
 
 # VERSION!
-RADIANT_VERSION_NUMBER = 1.5.0
+RADIANT_MAJOR_VERSION = 1
+RADIANT_MINOR_VERSION = 5
+RADIANT_PATCH_VERSION = 0
+RADIANT_VERSION_NUMBER = $(RADIANT_MAJOR_VERSION).$(RADIANT_MINOR_VERSION).$(RADIANT_PATCH_VERSION)
 RADIANT_VERSION = $(RADIANT_VERSION_NUMBER)n
-RADIANT_MAJOR_VERSION = 5
-RADIANT_MINOR_VERSION = 0
 Q3MAP_VERSION = 2.5.17n
 
 # Executable extension
@@ -256,7 +257,7 @@ ifneq ($(GIT_VERSION),)
        Q3MAP_VERSION := $(Q3MAP_VERSION)-git-$(GIT_VERSION)
 endif
 
-CPPFLAGS += -DRADIANT_VERSION="\"$(RADIANT_VERSION)\"" -DRADIANT_MAJOR_VERSION="\"$(RADIANT_MAJOR_VERSION)\"" -DRADIANT_MINOR_VERSION="\"$(RADIANT_MINOR_VERSION)\"" -DRADIANT_ABOUTMSG="\"$(RADIANT_ABOUTMSG)\"" -DQ3MAP_VERSION="\"$(Q3MAP_VERSION)\"" -DRADIANT_EXECUTABLE="\"$(RADIANT_EXECUTABLE)\""
+CPPFLAGS += -DRADIANT_VERSION="\"$(RADIANT_VERSION)\"" -DRADIANT_MAJOR_VERSION="\"$(RADIANT_MAJOR_VERSION)\"" -DRADIANT_MINOR_VERSION="\"$(RADIANT_MINOR_VERSION)\"" -DRADIANT_PATCH_VERSION="\"$(RADIANT_PATCH_VERSION)\"" -DRADIANT_ABOUTMSG="\"$(RADIANT_ABOUTMSG)\"" -DQ3MAP_VERSION="\"$(Q3MAP_VERSION)\"" -DRADIANT_EXECUTABLE="\"$(RADIANT_EXECUTABLE)\""
 
 .PHONY: all
 all: \
@@ -1058,8 +1059,9 @@ install-data: binaries
        $(MKDIR) $(INSTALLDIR)/games
        $(FIND) $(INSTALLDIR_BASE)/ -name .svn -exec $(RM_R) {} \; -prune
        DOWNLOAD_GAMEPACKS="$(DOWNLOAD_GAMEPACKS)" GIT="$(GIT)" SVN="$(SVN)" WGET="$(WGET)" RM_R="$(RM_R)" MV="$(MV)" UNZIPPER="$(UNZIPPER)" ECHO="$(ECHO)" SH="$(SH)" CP="$(CP)" CP_R="$(CP_R)" $(SH) install-gamepacks.sh "$(INSTALLDIR)"
-       $(ECHO) $(RADIANT_MINOR_VERSION) > $(INSTALLDIR)/RADIANT_MINOR
        $(ECHO) $(RADIANT_MAJOR_VERSION) > $(INSTALLDIR)/RADIANT_MAJOR
+       $(ECHO) $(RADIANT_MINOR_VERSION) > $(INSTALLDIR)/RADIANT_MINOR
+       $(ECHO) $(RADIANT_PATCH_VERSION) > $(INSTALLDIR)/RADIANT_PATCH
        $(CP_R) setup/data/tools/* $(INSTALLDIR)/
        $(MKDIR) $(INSTALLDIR)/docs
        $(CP_R) docs/* $(INSTALLDIR)/docs/
index 02d7923..5c2a286 100644 (file)
@@ -1,6 +1,7 @@
 add_library(includes
         aboutmsg.h
         cullable.cpp cullable.h
+        dpkdeps.h
         editable.cpp editable.h
         iarchive.cpp iarchive.h
         ibrush.cpp ibrush.h
diff --git a/include/dpkdeps.h b/include/dpkdeps.h
new file mode 100644 (file)
index 0000000..424fbdc
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __DPKDEPS_H__
+#define __DPKDEPS_H__
+
+#include <locale>
+#include "string/string.h"
+
+// Comparaison function for version numbers
+// Implementation is based on dpkg's version comparison code (verrevcmp() and order())
+// http://anonscm.debian.org/gitweb/?p=dpkg/dpkg.git;a=blob;f=lib/dpkg/version.c;hb=74946af470550a3295e00cf57eca1747215b9311
+inline int char_weight(char c){
+       if (std::isdigit(c))
+               return 0;
+       else if (std::isalpha(c))
+               return c;
+       else if (c == '~')
+               return -1;
+       else if (c)
+               return c + 256;
+       else
+               return 0;
+}
+
+inline int DpkPakVersionCmp(const char* a, const char* b){
+       while (*a || *b) {
+               int firstDiff = 0;
+
+               while ((*a && !std::isdigit(*a)) || (*b && !std::isdigit(*b))) {
+                       int ac = char_weight(*a);
+                       int bc = char_weight(*b);
+
+                       if (ac != bc)
+                               return ac - bc;
+
+                       a++;
+                       b++;
+               }
+
+               while (*a == '0')
+                       a++;
+               while (*b == '0')
+                       b++;
+
+               while (std::isdigit(*a) && std::isdigit(*b)) {
+                       if (firstDiff == 0)
+                               firstDiff = *a - *b;
+                       a++;
+                       b++;
+               }
+
+               if (std::isdigit(*a))
+                       return 1;
+               if (std::isdigit(*b))
+                       return -1;
+               if (firstDiff)
+                       return firstDiff;
+       }
+
+       return false;
+}
+
+// release strings after using
+inline bool DpkReadDepsLine( const char *line, char **pakname, char **pakversion ){
+       const char* c = line;
+       const char* p_name;
+       const char* p_name_end;
+       const char* p_version;
+       const char* p_version_end;
+
+       *pakname = 0;
+       *pakversion = 0;
+
+       while ( std::isspace( *c ) && *c != '\0' ) ++c;
+       p_name = c;
+       while ( !std::isspace( *c ) && *c != '\0' ) ++c;
+       p_name_end = c;
+       while ( std::isspace( *c ) && *c != '\0' ) ++c;
+       p_version = c;
+       while ( !std::isspace( *c ) && *c != '\0' ) ++c;
+       p_version_end = c;
+
+       if ( p_name_end - p_name > 0 ){
+               *pakname = string_clone_range( StringRange( p_name, p_name_end ) );
+       } else return false;
+
+       if ( p_version_end - p_version > 0 ) {
+               *pakversion = string_clone_range( StringRange( p_version, p_version_end ) );
+       }
+       return true;
+}
+
+#endif
index 4713451..3df8773 100644 (file)
@@ -8,3 +8,6 @@
 #ifndef RADIANT_MINOR_VERSION
 #error no RADIANT_MINOR_VERSION defined
 #endif
+#ifndef RADIANT_PATCH_VERSION
+#error no RADIANT_PATCH_VERSION defined
+#endif
index bee7403..bb3b5db 100644 (file)
@@ -59,6 +59,7 @@ ArchiveModules& FileSystemQ3API_getArchiveModules();
 #include "os/path.h"
 #include "moduleobservers.h"
 #include "filematch.h"
+#include "dpkdeps.h"
 
 
 #define VFS_MAXDIRS 64
@@ -322,60 +323,6 @@ void AddDpkPak( const char* name, const char* fullpath, bool is_pakfile ){
        g_pakfile_paths.insert( PakfilePathsKV( name, pakfile_path ) );
 }
 
-// Comparaison function for version numbers
-// Implementation is based on dpkg's version comparison code (verrevcmp() and order())
-// http://anonscm.debian.org/gitweb/?p=dpkg/dpkg.git;a=blob;f=lib/dpkg/version.c;hb=74946af470550a3295e00cf57eca1747215b9311
-static int char_weight(char c){
-       if (std::isdigit(c))
-               return 0;
-       else if (std::isalpha(c))
-               return c;
-       else if (c == '~')
-               return -1;
-       else if (c)
-               return c + 256;
-       else
-               return 0;
-}
-
-static int VersionCmp(const char* a, const char* b){
-       while (*a || *b) {
-               int firstDiff = 0;
-
-               while ((*a && !std::isdigit(*a)) || (*b && !std::isdigit(*b))) {
-                       int ac = char_weight(*a);
-                       int bc = char_weight(*b);
-
-                       if (ac != bc)
-                               return ac - bc;
-
-                       a++;
-                       b++;
-               }
-
-               while (*a == '0')
-                       a++;
-               while (*b == '0')
-                       b++;
-
-               while (std::isdigit(*a) && std::isdigit(*b)) {
-                       if (firstDiff == 0)
-                               firstDiff = *a - *b;
-                       a++;
-                       b++;
-               }
-
-               if (std::isdigit(*a))
-                       return 1;
-               if (std::isdigit(*b))
-                       return -1;
-               if (firstDiff)
-                       return firstDiff;
-       }
-
-       return false;
-}
-
 // takes name without ext, returns without ext
 static const char* GetLatestDpkPakVersion( const char* name ){
        const char* maxversion = 0;
@@ -389,7 +336,7 @@ static const char* GetLatestDpkPakVersion( const char* name ){
                pakname = i->first.c_str();
                if ( strncmp( pakname, name, namelen ) != 0 || pakname[namelen] != '_' ) continue;
                pakversion = pakname + (namelen + 1);
-               if ( maxversion == 0 || VersionCmp( pakversion, maxversion ) > 0 ){
+               if ( maxversion == 0 || DpkPakVersionCmp( pakversion, maxversion ) > 0 ){
                        maxversion = pakversion;
                        result = pakname;
                }
@@ -452,40 +399,22 @@ static void LoadDpkPakWithDeps( const char* pakname ){
                TextLinesInputStream<TextInputStream> istream = depsFile->getInputStream();
 
                CopiedString line;
-               const char* c;
-               const char* p_name;
-               const char* p_name_end;
-               const char* p_version;
-               const char* p_version_end;
+               char *p_name;
+               char *p_version;
                while ( line = istream.readLine(), string_length( line.c_str() ) ) {
-                       c = line.c_str();
-                       while ( std::isspace( *c ) && *c != '\0' ) ++c;
-                       p_name = c;
-                       while ( !std::isspace( *c ) && *c != '\0' ) ++c;
-                       p_name_end = c;
-                       while ( std::isspace( *c ) && *c != '\0' ) ++c;
-                       p_version = c;
-                       while ( !std::isspace( *c ) && *c != '\0' ) ++c;
-                       p_version_end = c;
-
-                       if ( p_name_end - p_name == 0 ) continue;
-                       if ( p_version_end - p_version == 0 ) {
-                               const char* p_pakname;
-                               CopiedString name_final = CopiedString( StringRange( p_name, p_name_end ) );
-                               p_pakname = GetLatestDpkPakVersion( name_final.c_str() );
-                               if ( p_pakname != NULL ) {
-                                       LoadDpkPakWithDeps( p_pakname );
-                               }
+                       if ( !DpkReadDepsLine( line.c_str(), &p_name, &p_version ) ) continue;
+                       if ( !p_version ) {
+                               const char* p_latest = GetLatestDpkPakVersion( p_name );
+                               if ( p_latest ) LoadDpkPakWithDeps( p_latest );
                        } else {
-                               int len = ( p_name_end - p_name ) + ( p_version_end - p_version ) + 1;
+                               int len = string_length( p_name ) + string_length( p_version ) + 1;
                                char* p_pakname = string_new( len );
-                               strncpy( p_pakname, p_name, p_name_end - p_name );
-                               p_pakname[ p_name_end - p_name ] = '\0';
-                               strcat( p_pakname, "_" );
-                               strncat( p_pakname, p_version, p_version_end - p_version );
+                               sprintf( p_pakname, "%s_%s", p_name, p_version );
                                LoadDpkPakWithDeps( p_pakname );
                                string_release( p_pakname, len );
                        }
+                       string_release( p_name, string_length( p_name ) );
+                       if ( p_version ) string_release( p_version, string_length( p_version ) );
                }
        }
 
index 954847e..4e15c81 100644 (file)
@@ -245,7 +245,7 @@ void environment_init( int argc, char* argv[] ){
 
        if ( !portable_app_setup() ) {
                StringOutputStream home( 256 );
-               home << DirectoryCleaned( g_get_home_dir() ) << ".netradiant/";
+               home << DirectoryCleaned( g_get_user_config_dir() ) << "netradiant/";
                Q_mkdir( home.c_str() );
                home_path = home.c_str();
        }
index 196297e..e46d903 100644 (file)
@@ -329,7 +329,7 @@ void paths_init(){
 
        {
                StringOutputStream path( 256 );
-               path << home << "1." << RADIANT_MAJOR_VERSION "." << RADIANT_MINOR_VERSION << '/';
+               path << home << "/";
                g_strSettingsPath = path.c_str();
        }
 
@@ -558,8 +558,38 @@ int main( int argc, char* argv[] ){
        }
 #endif
 
+       static GOptionEntry entries[] = {
+               { NULL }
+       };
+       GError *error = NULL;
+       const char* mapname = NULL;
+
        gtk_disable_setlocale();
-       gtk_init( &argc, &argv );
+       if ( !gtk_init_with_args( &argc, &argv, "<filename.map>", entries, NULL, &error) ) {
+               g_print( "%s\n", error->message );
+               return -1;
+       }
+
+       // Gtk already removed parsed `--options`
+       if (argc == 2) {
+               if ( strlen( argv[1] ) > 1 ) {
+                       if ( g_str_has_suffix( argv[1], ".map" ) ) {
+                               if ( g_path_is_absolute( argv[1] ) ) {
+                                       mapname = argv[1];
+                               }
+                               else {
+                                       mapname = g_build_filename( g_get_current_dir(), argv[1], NULL );
+                               }
+                       }
+                       else {
+                               g_print( "bad file name, will not load: %s\n", argv[1] );
+                       }
+               }
+       }
+       else if (argc > 2) {
+               g_print ( "%s\n", "too many arguments" );
+               return -1;
+       }
 
        // redirect Gtk warnings to the console
        g_log_set_handler( "Gdk", (GLogLevelFlags)( G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING |
@@ -620,7 +650,10 @@ int main( int argc, char* argv[] ){
 
        hide_splash();
 
-       if ( g_bLoadLastMap && !g_strLastMap.empty() ) {
+       if ( mapname != NULL ) {
+               Map_LoadFile( mapname );
+       }
+       else if ( g_bLoadLastMap && !g_strLastMap.empty() ) {
                Map_LoadFile( g_strLastMap.c_str() );
        }
        else
index 672b37c..53ef24a 100644 (file)
 #include "renderstate.h"
 #include "feedback.h"
 #include "referencecache.h"
-
+#include "texwindow.h"
 
 
 struct layout_globals_t
@@ -166,6 +166,8 @@ void VFS_Refresh(){
        QE_InitVFS();
        GlobalFileSystem().refresh();
        g_vfsInitialized = true;
+       // also refresh texture browser
+       TextureBrowser_RefreshShaders();
 }
 void VFS_Restart(){
        VFS_Shutdown();
index bdc7841..147cfa9 100644 (file)
@@ -39,7 +39,6 @@ MapModules& ReferenceAPI_getMapModules();
 #include "ifilesystem.h"
 #include "namespace.h"
 #include "moduleobserver.h"
-#include "moduleobservers.h"
 
 #include <set>
 
@@ -82,6 +81,7 @@ MapModules& ReferenceAPI_getMapModules();
 #include "xywindow.h"
 #include "mainframe.h"
 #include "preferences.h"
+#include "preferencesystem.h"
 #include "referencecache.h"
 #include "mru.h"
 #include "commands.h"
@@ -406,29 +406,6 @@ float g_MinWorldCoord = -64 * 1024;
 void AddRegionBrushes( void );
 void RemoveRegionBrushes( void );
 
-/* Map open/close observers */
-
-ModuleObservers g_mapPathObservers;
-
-class MapFileObserver : public ModuleObserver
-{
-void realise() {
-               // Refresh VFS to apply new pak filtering based on mapname
-               // needed for daemon dpk vfs
-               VFS_Refresh();
-}
-void unrealise() { }
-};
-
-MapFileObserver g_mapFileObserver;
-
-void BindMapFileObservers(){
-       g_mapPathObservers.attach( g_mapFileObserver );
-}
-
-void UnBindMapFileObservers(){
-       g_mapPathObservers.detach( g_mapFileObserver );
-}
 
 
 /*
@@ -448,7 +425,6 @@ void Map_Free(){
 
        g_currentMap = 0;
        Brush_unlatchPreferences();
-       g_mapPathObservers.unrealise();
 }
 
 class EntityFindByClassname : public scene::Graph::Walker
@@ -947,6 +923,8 @@ ScopeTimer( const char* message )
 }
 };
 
+CopiedString g_strLastFolder = "";
+
 /*
    ================
    Map_LoadFile
@@ -957,6 +935,9 @@ void Map_LoadFile( const char *filename ){
        globalOutputStream() << "Loading map from " << filename << "\n";
        ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Map" );
 
+       MRU_AddFile( filename );
+       g_strLastFolder = g_path_get_dirname( filename );
+
        {
                ScopeTimer timer( "map load" );
 
@@ -973,7 +954,6 @@ void Map_LoadFile( const char *filename ){
                        }
                        Brush_toggleFormat( i );
                        g_map.m_name = filename;
-                       g_mapPathObservers.realise();
                        Map_UpdateTitle( g_map );
                        g_map.m_resource = GlobalReferenceCache().capture( g_map.m_name.c_str() );
                        if ( format ) {
@@ -1004,6 +984,10 @@ void Map_LoadFile( const char *filename ){
        Map_StartPosition();
 
        g_currentMap = &g_map;
+
+       // restart VFS to apply new pak filtering based on mapname
+       // needed for daemon DPK VFS
+       VFS_Restart();
 }
 
 class Excluder
@@ -1205,15 +1189,16 @@ void Map_RenameAbsolute( const char* absolute ){
 
        g_map.m_resource->detach( g_map );
        GlobalReferenceCache().release( g_map.m_name.c_str() );
-       g_mapPathObservers.unrealise();
 
        g_map.m_resource = resource;
 
        g_map.m_name = absolute;
-       g_mapPathObservers.realise();
        Map_UpdateTitle( g_map );
 
        g_map.m_resource->attach( g_map );
+       // refresh VFS to apply new pak filtering based on mapname
+       // needed for daemon DPK VFS
+       VFS_Refresh();
 }
 
 void Map_Rename( const char* filename ){
@@ -1248,7 +1233,6 @@ void Map_New(){
        //globalOutputStream() << "Map_New\n";
 
        g_map.m_name = "unnamed.map";
-       g_mapPathObservers.realise();
        Map_UpdateTitle( g_map );
 
        {
@@ -1262,6 +1246,10 @@ void Map_New(){
        FocusViews( g_vector3_identity, 0 );
 
        g_currentMap = &g_map;
+
+       // restart VFS to apply new pak filtering based on mapname
+       // needed for daemon DPK VFS
+       VFS_Restart();
 }
 
 extern void ConstructRegionBrushes( scene::Node * brushes[6], const Vector3 &region_mins, const Vector3 &region_maxs );
@@ -1509,6 +1497,8 @@ void Map_RegionBrush( void ){
 bool Map_ImportFile( const char* filename ){
        ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Map" );
 
+       g_strLastFolder = g_path_get_dirname( filename );
+
        bool success = false;
 
        if ( extension_equal( path_get_extension( filename ), "bsp" ) ) {
@@ -1612,7 +1602,13 @@ tryDecompile:
  */
 bool Map_SaveFile( const char* filename ){
        ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Saving Map" );
-       return MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse, filename );
+       bool success = MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse, filename );
+       if ( success ) {
+               // refresh VFS to apply new pak filtering based on mapname
+               // needed for daemon DPK VFS
+               VFS_Refresh();
+       }
+       return success;
 }
 
 //
@@ -1805,16 +1801,26 @@ const char* getMapsPath(){
        return g_mapsPath.c_str();
 }
 
+const char* getLastFolderPath(){
+       if (g_strLastFolder.empty()) {
+               GlobalPreferenceSystem().registerPreference( "LastFolder", CopiedStringImportStringCaller( g_strLastFolder ), CopiedStringExportStringCaller( g_strLastFolder ) );
+               if (g_strLastFolder.empty()) {
+                       g_strLastFolder = g_qeglobals.m_userGamePath;
+               }
+       }
+       return g_strLastFolder.c_str();
+}
+
 const char* map_open( const char* title ){
-       return file_dialog( GTK_WIDGET( MainFrame_getWindow() ), TRUE, title, getMapsPath(), MapFormat::Name(), true, false, false );
+       return file_dialog( GTK_WIDGET( MainFrame_getWindow() ), TRUE, title, getLastFolderPath(), MapFormat::Name(), false, true, false );
 }
 
 const char* map_import( const char* title ){
-       return file_dialog( GTK_WIDGET( MainFrame_getWindow() ), TRUE, title, getMapsPath(), MapFormat::Name(), false, true, false );
+       return file_dialog( GTK_WIDGET( MainFrame_getWindow() ), TRUE, title, getLastFolderPath(), MapFormat::Name(), false, true, false );
 }
 
 const char* map_save( const char* title ){
-       return file_dialog( GTK_WIDGET( MainFrame_getWindow() ), FALSE, title, getMapsPath(), MapFormat::Name(), false, false, true );
+       return file_dialog( GTK_WIDGET( MainFrame_getWindow() ), FALSE, title, getLastFolderPath(), MapFormat::Name(), false, false, true );
 }
 
 void OpenMap(){
@@ -1824,7 +1830,7 @@ void OpenMap(){
 
        const char* filename = map_open( "Open Map" );
 
-       if ( filename != 0 ) {
+       if ( filename != NULL ) {
                MRU_AddFile( filename );
                Map_RegionOff();
                Map_Free();
@@ -1835,7 +1841,7 @@ void OpenMap(){
 void ImportMap(){
        const char* filename = map_import( "Import Map" );
 
-       if ( filename != 0 ) {
+       if ( filename != NULL ) {
                UndoableCommand undo( "mapImport" );
                Map_ImportFile( filename );
        }
@@ -1844,7 +1850,8 @@ void ImportMap(){
 bool Map_SaveAs(){
        const char* filename = map_save( "Save Map" );
 
-       if ( filename != 0 ) {
+       if ( filename != NULL ) {
+               g_strLastFolder = g_path_get_dirname( filename );
                MRU_AddFile( filename );
                Map_Rename( filename );
                return Map_Save();
@@ -1868,7 +1875,8 @@ void SaveMap(){
 void ExportMap(){
        const char* filename = map_save( "Export Selection" );
 
-       if ( filename != 0 ) {
+       if ( filename != NULL ) {
+               g_strLastFolder = g_path_get_dirname( filename );
                Map_SaveSelected( filename );
        }
 }
@@ -1876,7 +1884,8 @@ void ExportMap(){
 void SaveRegion(){
        const char* filename = map_save( "Export Region" );
 
-       if ( filename != 0 ) {
+       if ( filename != NULL ) {
+               g_strLastFolder = g_path_get_dirname( filename );
                Map_SaveRegion( filename );
        }
 }
@@ -2171,8 +2180,6 @@ void unrealise(){
 
 MapModuleObserver g_MapModuleObserver;
 
-#include "preferencesystem.h"
-
 CopiedString g_strLastMap;
 bool g_bLoadLastMap = false;
 
index 8bfd511..a359d46 100644 (file)
@@ -162,7 +162,4 @@ void Map_mergeClonedNames();
 
 const char* getMapsPath();
 
-void BindMapFileObservers();
-void UnBindMapFileObservers();
-
 #endif
index 8adf4d1..9d55cf3 100644 (file)
@@ -250,12 +250,10 @@ Radiant(){
        MapRoot_construct();
 
        EnginePath_verify();
-       BindMapFileObservers();
        EnginePath_Realise();
 }
 ~Radiant(){
        EnginePath_Unrealise();
-       UnBindMapFileObservers();
 
        MapRoot_destroy();
        NullModel_destroy();
index e30f103..1ab8708 100644 (file)
@@ -89,6 +89,9 @@
 #include "shaders.h"
 #include "commands.h"
 
+#define NOTEX_BASENAME "notex"
+#define SHADERNOTEX_BASENAME "shadernotex"
+
 bool TextureBrowser_showWads(){
        return !string_empty( g_pGameDescription->getKeyValue( "show_wads" ) );
 }
@@ -113,8 +116,53 @@ void TextureGroups_addWad( TextureGroups& groups, const char* archive ){
 }
 typedef ReferenceCaller1<TextureGroups, const char*, TextureGroups_addWad> TextureGroupsAddWadCaller;
 
+namespace
+{
+bool g_TextureBrowser_shaderlistOnly = false;
+bool g_TextureBrowser_fixedSize = true;
+bool g_TextureBrowser_filterMissing = false;
+bool g_TextureBrowser_filterFallback = true;
+bool g_TextureBrowser_enableAlpha = true;
+}
+
+CopiedString g_notex;
+CopiedString g_shadernotex;
+bool isMissing(const char* name);
+bool isNotex(const char* name);
+
+bool isMissing(const char* name){
+       if ( string_equal( g_notex.c_str(), name ) ) {
+               return true;
+       }
+       if ( string_equal( g_shadernotex.c_str(), name ) ) {
+               return true;
+       }
+       return false;
+}
+
+bool isNotex(const char* name){
+       if ( string_equal_suffix( name, "/" NOTEX_BASENAME ) ) {
+               return true;
+       }
+       if ( string_equal_suffix( name, "/" SHADERNOTEX_BASENAME ) ) {
+               return true;
+       }
+       return false;
+}
+
 void TextureGroups_addShader( TextureGroups& groups, const char* shaderName ){
        const char* texture = path_make_relative( shaderName, "textures/" );
+
+       // hide notex / shadernotex images
+       if ( g_TextureBrowser_filterFallback ) {
+               if ( isNotex( shaderName ) ) {
+                       return;
+               }
+               if ( isNotex( texture ) ) {
+                       return;
+               }
+       }
+
        if ( texture != shaderName ) {
                const char* last = path_remove_directory( texture );
                if ( !string_empty( last ) ) {
@@ -129,14 +177,6 @@ void TextureGroups_addDirectory( TextureGroups& groups, const char* directory ){
 }
 typedef ReferenceCaller1<TextureGroups, const char*, TextureGroups_addDirectory> TextureGroupsAddDirectoryCaller;
 
-namespace
-{
-bool g_TextureBrowser_shaderlistOnly = false;
-bool g_TextureBrowser_fixedSize = true;
-bool g_TextureBrowser_filterNotex = false;
-bool g_TextureBrowser_enableAlpha = true;
-}
-
 class DeferredAdjustment
 {
 gdouble m_value;
@@ -201,8 +241,11 @@ typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_showShaderlistOnly
 void TextureBrowser_fixedSize( const BoolImportCallback& importer );
 typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_fixedSize> TextureBrowserFixedSizeExport;
 
-void TextureBrowser_filterNotex( const BoolImportCallback& importer );
-typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_filterNotex> TextureBrowserFilterNotexExport;
+void TextureBrowser_filterMissing( const BoolImportCallback& importer );
+typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_filterMissing> TextureBrowserFilterMissingExport;
+
+void TextureBrowser_filterFallback( const BoolImportCallback& importer );
+typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_filterFallback> TextureBrowserFilterFallbackExport;
 
 void TextureBrowser_enableAlpha( const BoolImportCallback& importer );
 typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_enableAlpha> TextureBrowserEnableAlphaExport;
@@ -238,6 +281,7 @@ std::vector<CopiedString> m_copied_tags;
 std::set<CopiedString> m_found_shaders;
 
 ToggleItem m_hideunused_item;
+ToggleItem m_hidenotex_item;
 ToggleItem m_showshaders_item;
 ToggleItem m_showshaderlistonly_item;
 ToggleItem m_fixedsize_item;
@@ -311,7 +355,8 @@ TextureBrowser() :
        m_showshaders_item( TextureBrowserShowShadersExport() ),
        m_showshaderlistonly_item( TextureBrowserShowShaderlistOnlyExport() ),
        m_fixedsize_item( TextureBrowserFixedSizeExport() ),
-       m_filternotex_item( TextureBrowserFilterNotexExport() ),
+       m_filternotex_item( TextureBrowserFilterMissingExport() ),
+       m_hidenotex_item( TextureBrowserFilterFallbackExport() ),
        m_enablealpha_item( TextureBrowserEnableAlphaExport() ),
        m_heightChanged( true ),
        m_originInvalid( true ),
@@ -463,14 +508,23 @@ bool TextureSearch_IsShown( const char* name ){
        }
 }
 
-CopiedString g_notex;
-CopiedString g_shadernotex;
-
 // if texture_showinuse jump over non in-use textures
 bool Texture_IsShown( IShader* shader, bool show_shaders, bool hideUnused ){
-       // filter notex / shadernotex images
-       if ( g_TextureBrowser_filterNotex && ( string_equal( g_notex.c_str(), shader->getTexture()->name ) || string_equal( g_shadernotex.c_str(), shader->getTexture()->name ) ) ) {
-               return false;
+       // filter missing shaders
+       // ugly: filter on built-in fallback name after substitution
+       if ( g_TextureBrowser_filterMissing ) {
+               if ( isMissing( shader->getTexture()->name ) ) {
+                       return false;
+               }
+       }
+       // filter the fallback (notex/shadernotex) for missing shaders or editor image
+       if ( g_TextureBrowser_filterFallback ) {
+               if ( isNotex( shader->getName() ) ) {
+                       return false;
+               }
+               if ( isNotex( shader->getTexture()->name ) ) {
+                       return false;
+               }
        }
 
        if ( g_TextureBrowser_currentDirectory == "Untagged" ) {
@@ -832,10 +886,15 @@ void TextureBrowser_fixedSize( const BoolImportCallback& importer ){
 }
 typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_fixedSize> TextureBrowser_FixedSizeExport;
 
-void TextureBrowser_filterNotex( const BoolImportCallback& importer ){
-       importer( g_TextureBrowser_filterNotex );
+void TextureBrowser_filterMissing( const BoolImportCallback& importer ){
+       importer( g_TextureBrowser_filterMissing );
 }
-typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_filterNotex> TextureBrowser_filterNotexExport;
+typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_filterMissing> TextureBrowser_filterMissingExport;
+
+void TextureBrowser_filterFallback( const BoolImportCallback& importer ){
+       importer( g_TextureBrowser_filterFallback );
+}
+typedef FreeCaller1<const BoolImportCallback&, TextureBrowser_filterFallback> TextureBrowser_filterFallbackExport;
 
 void TextureBrowser_enableAlpha( const BoolImportCallback& importer ){
        importer( g_TextureBrowser_enableAlpha );
@@ -1611,8 +1670,12 @@ GtkMenuItem* TextureBrowser_constructViewMenu( GtkMenu* menu ){
 
        create_check_menu_item_with_mnemonic( menu, "Hide _Unused", "ShowInUse" );
        if ( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) {
-               create_check_menu_item_with_mnemonic( menu, "Hide Image Missing", "FilterNotex" );
+               create_check_menu_item_with_mnemonic( menu, "Hide Image Missing", "FilterMissing" );
        }
+
+       // hide notex and shadernotex on texture browser: no one wants to apply them
+       create_check_menu_item_with_mnemonic( menu, "Hide Fallback", "FilterFallback" );
+
        menu_separator( menu );
 
        create_menu_item_with_mnemonic( menu, "Show All", "ShowAllTextures" );
@@ -1930,11 +1993,11 @@ void TextureBrowser_checkTagFile(){
 
 void TextureBrowser_SetNotex(){
        StringOutputStream name( 256 );
-       name << GlobalRadiant().getAppPath() << "bitmaps/notex.png";
+       name << GlobalRadiant().getAppPath() << "bitmaps/" NOTEX_BASENAME ".png";
        g_notex = name.c_str();
 
        name = NULL;
-       name << GlobalRadiant().getAppPath() << "bitmaps/shadernotex.png";
+       name << GlobalRadiant().getAppPath() << "bitmaps/" SHADERNOTEX_BASENAME " .png";
        g_shadernotex = name.c_str();
 }
 
@@ -2359,9 +2422,8 @@ void TextureBrowser_pasteTag(){
        BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser );
 }
 
-void RefreshShaders(){
+void TextureBrowser_RefreshShaders(){
        ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Shaders" );
-       VFS_Refresh();
        GlobalShaderSystem().refresh();
        UpdateAllWindows();
        GtkTreeSelection* selection = gtk_tree_view_get_selection((GtkTreeView*)GlobalTextureBrowser().m_treeViewTree);
@@ -2436,10 +2498,18 @@ void TextureBrowser_FixedSize(){
        TextureBrowser_activeShadersChanged( GlobalTextureBrowser() );
 }
 
-void TextureBrowser_FilterNotex(){
-       g_TextureBrowser_filterNotex ^= 1;
+void TextureBrowser_FilterMissing(){
+       g_TextureBrowser_filterMissing ^= 1;
        GlobalTextureBrowser().m_filternotex_item.update();
        TextureBrowser_activeShadersChanged( GlobalTextureBrowser() );
+       TextureBrowser_RefreshShaders();
+}
+
+void TextureBrowser_FilterFallback(){
+       g_TextureBrowser_filterFallback ^= 1;
+       GlobalTextureBrowser().m_hidenotex_item.update();
+       TextureBrowser_activeShadersChanged( GlobalTextureBrowser() );
+       TextureBrowser_RefreshShaders();
 }
 
 void TextureBrowser_EnableAlpha(){
@@ -2567,14 +2637,15 @@ void TextureBrowser_Construct(){
        GlobalCommands_insert( "DeleteTag", FreeCaller<TextureBrowser_deleteTag>() );
        GlobalCommands_insert( "CopyTag", FreeCaller<TextureBrowser_copyTag>() );
        GlobalCommands_insert( "PasteTag", FreeCaller<TextureBrowser_pasteTag>() );
-       GlobalCommands_insert( "RefreshShaders", FreeCaller<RefreshShaders>() );
+       GlobalCommands_insert( "RefreshShaders", FreeCaller<VFS_Refresh>() );
        GlobalToggles_insert( "ShowInUse", FreeCaller<TextureBrowser_ToggleHideUnused>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_hideunused_item ), Accelerator( 'U' ) );
        GlobalCommands_insert( "ShowAllTextures", FreeCaller<TextureBrowser_showAll>(), Accelerator( 'A', (GdkModifierType)GDK_CONTROL_MASK ) );
        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( "FixedSize", FreeCaller<TextureBrowser_FixedSize>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_fixedsize_item ) );
-       GlobalToggles_insert( "FilterNotex", FreeCaller<TextureBrowser_FilterNotex>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_filternotex_item ) );
+       GlobalToggles_insert( "FilterMissing", FreeCaller<TextureBrowser_FilterMissing>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_filternotex_item ) );
+       GlobalToggles_insert( "FilterFallback", FreeCaller<TextureBrowser_FilterFallback>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_hidenotex_item ) );
        GlobalToggles_insert( "EnableAlpha", FreeCaller<TextureBrowser_EnableAlpha>(), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_enablealpha_item ) );
 
        GlobalPreferenceSystem().registerPreference( "TextureScale",
@@ -2591,7 +2662,7 @@ void TextureBrowser_Construct(){
        GlobalPreferenceSystem().registerPreference( "ShowShaders", BoolImportStringCaller( GlobalTextureBrowser().m_showShaders ), BoolExportStringCaller( GlobalTextureBrowser().m_showShaders ) );
        GlobalPreferenceSystem().registerPreference( "ShowShaderlistOnly", BoolImportStringCaller( g_TextureBrowser_shaderlistOnly ), BoolExportStringCaller( g_TextureBrowser_shaderlistOnly ) );
        GlobalPreferenceSystem().registerPreference( "FixedSize", BoolImportStringCaller( g_TextureBrowser_fixedSize ), BoolExportStringCaller( g_TextureBrowser_fixedSize ) );
-       GlobalPreferenceSystem().registerPreference( "FilterNotex", BoolImportStringCaller( g_TextureBrowser_filterNotex ), BoolExportStringCaller( g_TextureBrowser_filterNotex ) );
+       GlobalPreferenceSystem().registerPreference( "FilterMissing", BoolImportStringCaller( g_TextureBrowser_filterMissing ), BoolExportStringCaller( g_TextureBrowser_filterMissing ) );
        GlobalPreferenceSystem().registerPreference( "EnableAlpha", BoolImportStringCaller( g_TextureBrowser_enableAlpha ), BoolExportStringCaller( g_TextureBrowser_enableAlpha ) );
        GlobalPreferenceSystem().registerPreference( "LoadShaders", IntImportStringCaller( reinterpret_cast<int&>( GlobalTextureBrowser().m_startupShaders ) ), IntExportStringCaller( reinterpret_cast<int&>( GlobalTextureBrowser().m_startupShaders ) ) );
        GlobalPreferenceSystem().registerPreference( "WheelMouseInc", SizeImportStringCaller( GlobalTextureBrowser().m_mouseWheelScrollIncrement ), SizeExportStringCaller( GlobalTextureBrowser().m_mouseWheelScrollIncrement ) );
index 3a87201..edc67b2 100644 (file)
@@ -59,4 +59,6 @@ void TextureBrowser_setBackgroundColour( TextureBrowser& textureBrowser, const V
 void TextureBrowser_addActiveShadersChangedCallback( const SignalHandler& handler );
 void TextureBrowser_addShadersRealiseCallback( const SignalHandler& handler );
 
+void TextureBrowser_RefreshShaders();
+
 #endif