From: Thomas Debesse Date: Tue, 21 Jun 2022 02:25:25 +0000 (+0200) Subject: Merge commit '839c9693774fdb0e420391f65b8066e8bd04c591' into master-merge X-Git-Url: https://git.xonotic.org/?a=commitdiff_plain;h=5f72a1053d72cdbfe38d97e5b1fd9688316ceb40;hp=-c;p=xonotic%2Fnetradiant.git Merge commit '839c9693774fdb0e420391f65b8066e8bd04c591' into master-merge --- 5f72a1053d72cdbfe38d97e5b1fd9688316ceb40 diff --combined Makefile index e66cd7f2,8e63b813..2a63b9cc --- a/Makefile +++ b/Makefile @@@ -1,13 -1,3 +1,13 @@@ +# TODO: when deleting this Makefile, don't forget to also delete conftest.cpp +# which is only required by this Makefile + +ifeq ($(I_KNOW_MAKEFILE_IS_DEPRECATED),) + $(shell printf 'ERROR: Makefile build is deprecated, use CMake instead, see README.md\n\n' >&2) + $(error I_KNOW_MAKEFILE_IS_DEPRECATED is not set) +else + $(shell printf 'WARNING: deprecated Makefile build enforced\n\n' >&2) +endif + MAKEFILE_CONF ?= Makefile.conf -include $(MAKEFILE_CONF) @@@ -24,8 -14,6 +24,8 @@@ CXXFLAGS ? CPPFLAGS ?= LIBS ?= RADIANT_ABOUTMSG ?= Custom build +RADIANT_NAME ?= NetRadiant +RADIANT_BASENAME ?= netradiant # warning: this directory may NOT contain any files other than the ones written by this Makefile! # NEVER SET THIS TO A SYSTEM WIDE "bin" DIRECTORY! @@@ -210,7 -198,7 +210,7 @@@ ifeq ($(OS),Linux else ifeq ($(OS),Win32) - CPPFLAGS_COMMON += -DWIN32 -D_WIN32 -D_inline=inline + CPPFLAGS_COMMON += -DWIN32 -D_WIN32 -D_inline=inline -DWORKAROUND_WINDOWS_FLOATING_WINDOW=1 -DWORKAROUND_WINDOWS_GTK2_GLWIDGET=1 CFLAGS_COMMON += -mms-bitfields LDFLAGS_DLL = -Wl,--add-stdcall-alias LIBS_COMMON = -lws2_32 -luser32 -lgdi32 -lole32 @@@ -264,13 -252,16 +264,13 @@@ RADIANT_VERSION_NUMBER = $(RADIANT_MAJO RADIANT_VERSION = $(RADIANT_VERSION_NUMBER)n Q3MAP_VERSION = 2.5.17n -# Executable extension -RADIANT_EXECUTABLE := $(EXE) - GIT_VERSION := $(shell $(GIT) rev-parse --short HEAD $(STDERR_TO_DEVNULL)) ifneq ($(GIT_VERSION),) RADIANT_VERSION := $(RADIANT_VERSION)-git-$(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_PATCH_VERSION="\"$(RADIANT_PATCH_VERSION)\"" -DRADIANT_ABOUTMSG="\"$(RADIANT_ABOUTMSG)\"" -DQ3MAP_VERSION="\"$(Q3MAP_VERSION)\"" -DRADIANT_EXECUTABLE="\"$(RADIANT_EXECUTABLE)\"" +CPPFLAGS += -DRADIANT_VERSION="\"$(RADIANT_VERSION)\"" -DRADIANT_VERSION_STRING="\"$(RADIANT_VERSION_STRING)\"" -DRADIANT_ABOUTMSG="\"$(RADIANT_ABOUTMSG)\"" -DRADIANT_NAME="\"${RADIANT_NAME}\"" -DRADIANT_BASENAME="\"${RADIANT_BASENAME}\"" -DQ3MAP_VERSION="\"$(Q3MAP_VERSION)\"" CPPFLAGS += -DGTK_TARGET=2 .PHONY: all @@@ -441,8 -432,8 +441,8 @@@ binaries-qdata3: .PHONY: binaries-h2data binaries-h2data: \ - $(INSTALLDIR)/heretic2/h2data.$(EXE) \ - $(INSTALLDIR)/heretic2/h2data \ + $(INSTALLDIR)/h2data.$(EXE) \ + $(INSTALLDIR)/h2data \ .PHONY: binaries-tools-quake3 binaries-tools-quake3: \ @@@ -498,7 -489,9 +498,9 @@@ endi %.o: %.c $(if $(findstring $(DEPEND_ON_MAKEFILE),yes),$(wildcard Makefile*),) | dependencies-check $(CC) $< $(CFLAGS) $(CFLAGS_COMMON) $(CPPFLAGS_EXTRA) $(CPPFLAGS_COMMON) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ - $(INSTALLDIR)/q3map2.$(EXE): LDFLAGS_EXTRA := -Wl,--large-address-aware + ifeq ($(OS),Win32) + $(INSTALLDIR)/q3map2.$(EXE): LDFLAGS_EXTRA := -Wl,--large-address-aware,--stack,4194304 + endif $(INSTALLDIR)/q3map2.$(EXE): LIBS_EXTRA := $(LIBS_XML) $(LIBS_GLIB) $(LIBS_PNG) $(LIBS_JPEG) $(LIBS_WEBP) $(LIBS_ZLIB) $(INSTALLDIR)/q3map2.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) $(CPPFLAGS_GLIB) $(CPPFLAGS_PNG) $(CPPFLAGS_JPEG) $(CPPFLAGS_WEBP) -Itools/quake3/common -Ilibs -Iinclude $(INSTALLDIR)/q3map2.$(EXE): \ @@@ -1029,45 -1022,46 +1031,45 @@@ $(INSTALLDIR)/plugins/bkgrnd2d.$(DLL): contrib/bkgrnd2d/dialog.o \ contrib/bkgrnd2d/plugin.o \ -$(INSTALLDIR)/heretic2/h2data.$(EXE): LIBS_EXTRA := $(LIBS_XML) -$(INSTALLDIR)/heretic2/h2data.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) -Itools/quake2/qdata_heretic2/common -Itools/quake2/qdata_heretic2/qcommon -Itools/quake2/qdata_heretic2 -Itools/quake2/common -Ilibs -Iinclude -$(INSTALLDIR)/heretic2/h2data.$(EXE): \ - tools/quake2/qdata_heretic2/common/bspfile.o \ - tools/quake2/qdata_heretic2/common/cmdlib.o \ - tools/quake2/qdata_heretic2/common/inout.o \ - tools/quake2/qdata_heretic2/common/l3dslib.o \ - tools/quake2/qdata_heretic2/common/lbmlib.o \ - tools/quake2/qdata_heretic2/common/mathlib.o \ - tools/quake2/qdata_heretic2/common/md4.o \ - tools/quake2/qdata_heretic2/common/path_init.o \ - tools/quake2/qdata_heretic2/common/qfiles.o \ - tools/quake2/qdata_heretic2/common/scriplib.o \ - tools/quake2/qdata_heretic2/common/threads.o \ - tools/quake2/qdata_heretic2/common/token.o \ - tools/quake2/qdata_heretic2/common/trilib.o \ - tools/quake2/qdata_heretic2/qcommon/reference.o \ - tools/quake2/qdata_heretic2/qcommon/resourcemanager.o \ - tools/quake2/qdata_heretic2/qcommon/skeletons.o \ - tools/quake2/qdata_heretic2/animcomp.o \ - tools/quake2/qdata_heretic2/book.o \ - tools/quake2/qdata_heretic2/fmodels.o \ - tools/quake2/qdata_heretic2/images.o \ - tools/quake2/qdata_heretic2/jointed.o \ - tools/quake2/qdata_heretic2/models.o \ - tools/quake2/qdata_heretic2/pics.o \ - tools/quake2/qdata_heretic2/qdata.o \ - tools/quake2/qdata_heretic2/qd_skeletons.o \ - tools/quake2/qdata_heretic2/sprites.o \ - tools/quake2/qdata_heretic2/svdcmp.o \ - tools/quake2/qdata_heretic2/tables.o \ - tools/quake2/qdata_heretic2/tmix.o \ - tools/quake2/qdata_heretic2/video.o \ +$(INSTALLDIR)/h2data.$(EXE): LIBS_EXTRA := $(LIBS_XML) +$(INSTALLDIR)/h2data.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) -Itools/heretic2/common -Itools/heretic2/qcommon -Itools/heretic2/h2data -Itools/quake2/common -Ilibs -Iinclude +$(INSTALLDIR)/h2data.$(EXE): \ + tools/heretic2/common/bspfile.o \ + tools/heretic2/common/cmdlib.o \ + tools/heretic2/common/inout.o \ + tools/heretic2/common/l3dslib.o \ + tools/heretic2/common/lbmlib.o \ + tools/heretic2/common/mathlib.o \ + tools/heretic2/common/md4.o \ + tools/heretic2/common/path_init.o \ + tools/heretic2/common/qfiles.o \ + tools/heretic2/common/scriplib.o \ + tools/heretic2/common/threads.o \ + tools/heretic2/common/token.o \ + tools/heretic2/common/trilib.o \ + tools/heretic2/qcommon/reference.o \ + tools/heretic2/qcommon/resourcemanager.o \ + tools/heretic2/qcommon/skeletons.o \ + tools/heretic2/h2data/animcomp.o \ + tools/heretic2/h2data/book.o \ + tools/heretic2/h2data/fmodels.o \ + tools/heretic2/h2data/images.o \ + tools/heretic2/h2data/jointed.o \ + tools/heretic2/h2data/models.o \ + tools/heretic2/h2data/pics.o \ + tools/heretic2/h2data/qdata.o \ + tools/heretic2/h2data/qd_skeletons.o \ + tools/heretic2/h2data/sprites.o \ + tools/heretic2/h2data/svdcmp.o \ + tools/heretic2/h2data/tables.o \ + tools/heretic2/h2data/tmix.o \ + tools/heretic2/h2data/video.o \ libl_net.$(A) \ $(if $(findstring $(OS),Win32),icons/h2data.o,) \ .PHONY: install-data install-data: binaries - $(MKDIR) $(INSTALLDIR)/games - DOWNLOAD_GAMEPACKS="$(DOWNLOAD_GAMEPACKS)" DOWNLOADDIR="$(DOWNLOADDIR)" INSTALLDIR="$(INSTALLDIR)" 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) gamepack-manager + DOWNLOAD_GAMEPACKS="$(DOWNLOAD_GAMEPACKS)" DOWNLOADDIR="$(DOWNLOADDIR)" INSTALLDIR="$(INSTALLDIR)/gamepacks" GIT="$(GIT)" SVN="$(SVN)" WGET="$(WGET)" RM_R="$(RM_R)" MV="$(MV)" UNZIPPER="$(UNZIPPER)" ECHO="$(ECHO)" CP="$(CP)" CP_R="$(CP_R)" ./gamepack-manager $(ECHO) $(RADIANT_MAJOR_VERSION) > $(INSTALLDIR)/RADIANT_MAJOR $(ECHO) $(RADIANT_MINOR_VERSION) > $(INSTALLDIR)/RADIANT_MINOR $(ECHO) $(RADIANT_PATCH_VERSION) > $(INSTALLDIR)/RADIANT_PATCH diff --combined libs/string/string.h index 5d63925d,e780303b..e41779cd --- a/libs/string/string.h +++ b/libs/string/string.h @@@ -150,6 -150,11 +150,11 @@@ inline bool string_equal_suffix( const return string_equal_n( s , suffix, string_length( suffix ) ); } + inline bool string_equal_suffix_nocase( const char* string, const char* suffix){ + const char *s = string + string_length( string ) - string_length( suffix ); + return string_equal_nocase_n( s , suffix, string_length( suffix ) ); + } + /// \brief Copies \p other into \p string and returns \p string. /// Assumes that the space allocated for \p string is at least string_length(other) + 1. /// O(n) @@@ -259,52 -264,50 +264,52 @@@ inline char* string_to_uppercase( char /// \brief A re-entrant string tokeniser similar to strchr. class StringTokeniser { -bool istoken( char c ) const { - if ( strchr( m_delimiters, c ) != 0 ) { - return false; - } - return true; -} -const char* advance(){ - const char* token = m_pos; - bool intoken = true; - while ( !string_empty( m_pos ) ) - { - if ( !istoken( *m_pos ) ) { - *m_pos = '\0'; - intoken = false; +private: + bool istoken( char c ) const { + if ( strchr( m_delimiters, c ) != 0 ) { + return false; } - else if ( !intoken ) { - return token; + return true; + } + const char* advance(){ + const char* token = m_pos; + bool intoken = true; + while ( !string_empty( m_pos ) ) + { + if ( !istoken( *m_pos ) ) { + *m_pos = '\0'; + intoken = false; + } + else if ( !intoken ) { + return token; + } + ++m_pos; } - ++m_pos; + return token; } - return token; -} -std::size_t m_length; -char* m_string; -char* m_pos; -const char* m_delimiters; + std::size_t m_length; + char* m_string; + char* m_pos; + const char* m_delimiters; + public: -StringTokeniser( const char* string, const char* delimiters = " \n\r\t\v" ) : - m_length( string_length( string ) ), - m_string( string_copy( string_new( m_length ), string ) ), - m_pos( m_string ), - m_delimiters( delimiters ){ - while ( !string_empty( m_pos ) && !istoken( *m_pos ) ) - { - ++m_pos; + StringTokeniser( const char* string, const char* delimiters = " \n\r\t\v" ) : + m_length( string_length( string ) ), + m_string( string_copy( string_new( m_length ), string ) ), + m_pos( m_string ), + m_delimiters( delimiters ){ + while ( !string_empty( m_pos ) && !istoken( *m_pos ) ) + { + ++m_pos; + } + } + ~StringTokeniser(){ + string_release( m_string, m_length ); + } + /// \brief Returns the next token or "" if there are no more tokens available. + const char* getToken(){ + return advance(); } -} -~StringTokeniser(){ - string_release( m_string, m_length ); -} -/// \brief Returns the next token or "" if there are no more tokens available. -const char* getToken(){ - return advance(); -} }; /// \brief A non-mutable c-style string. @@@ -318,41 -321,40 +323,41 @@@ template @@@ -400,45 -402,44 +405,45 @@@ inline void swap( String& self template class CopiedBuffer : private Allocator { -char* m_string; + char* m_string; -char* copy_range( StringRange range ){ - return string_clone_range( range, static_cast( *this ) ); -} -char* copy( const char* other ){ - return string_clone( other, static_cast( *this ) ); -} -void destroy( char* string ){ - string_release( string, string_length( string ), static_cast( *this ) ); -} + char* copy_range( StringRange range ){ + return string_clone_range( range, static_cast( *this ) ); + } + char* copy( const char* other ){ + return string_clone( other, static_cast( *this ) ); + } + void destroy( char* string ){ + string_release( string, string_length( string ), static_cast( *this ) ); + } protected: -~CopiedBuffer(){ - destroy( m_string ); -} + ~CopiedBuffer(){ + destroy( m_string ); + } + public: -CopiedBuffer() - : m_string( copy( "" ) ){ -} -explicit CopiedBuffer( const Allocator& allocator ) - : Allocator( allocator ), m_string( copy( "" ) ){ -} -CopiedBuffer( const CopiedBuffer& other ) - : Allocator( other ), m_string( copy( other.m_string ) ){ -} -CopiedBuffer( const char* string, const Allocator& allocator = Allocator() ) - : Allocator( allocator ), m_string( copy( string ) ){ -} -CopiedBuffer( StringRange range, const Allocator& allocator = Allocator() ) - : Allocator( allocator ), m_string( copy_range( range ) ){ -} -const char* c_str() const { - return m_string; -} -void swap( CopiedBuffer& other ){ - string_swap( m_string, other.m_string ); -} + CopiedBuffer() + : m_string( copy( "" ) ){ + } + explicit CopiedBuffer( const Allocator& allocator ) + : Allocator( allocator ), m_string( copy( "" ) ){ + } + CopiedBuffer( const CopiedBuffer& other ) + : Allocator( other ), m_string( copy( other.m_string ) ){ + } + CopiedBuffer( const char* string, const Allocator& allocator = Allocator() ) + : Allocator( allocator ), m_string( copy( string ) ){ + } + CopiedBuffer( StringRange range, const Allocator& allocator = Allocator() ) + : Allocator( allocator ), m_string( copy_range( range ) ){ + } + const char* c_str() const { + return m_string; + } + void swap( CopiedBuffer& other ){ + string_swap( m_string, other.m_string ); + } }; /// \brief A non-mutable string which uses copy-by-value for assignment. @@@ -449,67 -450,65 +454,67 @@@ typedef String< CopiedBuffer< DefaultAl template class SmartBuffer : private Allocator { -char* m_buffer; - -char* copy_range( StringRange range ){ - char* buffer = Allocator::allocate( sizeof( std::size_t ) + ( range.last - range.first ) + 1 ); - strncpy( buffer + sizeof( std::size_t ), range.first, range.last - range.first ); - buffer[sizeof( std::size_t ) + ( range.last - range.first )] = '\0'; - *reinterpret_cast( buffer ) = 0; - return buffer; -} -char* copy( const char* string ){ - char* buffer = Allocator::allocate( sizeof( std::size_t ) + string_length( string ) + 1 ); - strcpy( buffer + sizeof( std::size_t ), string ); - *reinterpret_cast( buffer ) = 0; - return buffer; -} -void destroy( char* buffer ){ - Allocator::deallocate( buffer, sizeof( std::size_t ) + string_length( c_str() ) + 1 ); -} +private: + char* m_buffer; + + char* copy_range( StringRange range ){ + char* buffer = Allocator::allocate( sizeof( std::size_t ) + ( range.last - range.first ) + 1 ); + strncpy( buffer + sizeof( std::size_t ), range.first, range.last - range.first ); + buffer[sizeof( std::size_t ) + ( range.last - range.first )] = '\0'; + *reinterpret_cast( buffer ) = 0; + return buffer; + } + char* copy( const char* string ){ + char* buffer = Allocator::allocate( sizeof( std::size_t ) + string_length( string ) + 1 ); + strcpy( buffer + sizeof( std::size_t ), string ); + *reinterpret_cast( buffer ) = 0; + return buffer; + } + void destroy( char* buffer ){ + Allocator::deallocate( buffer, sizeof( std::size_t ) + string_length( c_str() ) + 1 ); + } -void incref( char* buffer ){ - ++( *reinterpret_cast( buffer ) ); -} -void decref( char* buffer ){ - if ( --( *reinterpret_cast( buffer ) ) == 0 ) { - destroy( buffer ); + void incref( char* buffer ){ + ++( *reinterpret_cast( buffer ) ); + } + void decref( char* buffer ){ + if ( --( *reinterpret_cast( buffer ) ) == 0 ) { + destroy( buffer ); + } } -} protected: -~SmartBuffer(){ - decref( m_buffer ); -} + ~SmartBuffer(){ + decref( m_buffer ); + } + public: -SmartBuffer() - : m_buffer( copy( "" ) ){ - incref( m_buffer ); -} -explicit SmartBuffer( const Allocator& allocator ) - : Allocator( allocator ), m_buffer( copy( "" ) ){ - incref( m_buffer ); -} -SmartBuffer( const SmartBuffer& other ) - : Allocator( other ), m_buffer( other.m_buffer ){ - incref( m_buffer ); -} -SmartBuffer( const char* string, const Allocator& allocator = Allocator() ) - : Allocator( allocator ), m_buffer( copy( string ) ){ - incref( m_buffer ); -} -SmartBuffer( StringRange range, const Allocator& allocator = Allocator() ) - : Allocator( allocator ), m_buffer( copy_range( range ) ){ - incref( m_buffer ); -} -const char* c_str() const { - return m_buffer + sizeof( std::size_t ); -} -void swap( SmartBuffer& other ){ - string_swap( m_buffer, other.m_buffer ); -} + SmartBuffer() + : m_buffer( copy( "" ) ){ + incref( m_buffer ); + } + explicit SmartBuffer( const Allocator& allocator ) + : Allocator( allocator ), m_buffer( copy( "" ) ){ + incref( m_buffer ); + } + SmartBuffer( const SmartBuffer& other ) + : Allocator( other ), m_buffer( other.m_buffer ){ + incref( m_buffer ); + } + SmartBuffer( const char* string, const Allocator& allocator = Allocator() ) + : Allocator( allocator ), m_buffer( copy( string ) ){ + incref( m_buffer ); + } + SmartBuffer( StringRange range, const Allocator& allocator = Allocator() ) + : Allocator( allocator ), m_buffer( copy_range( range ) ){ + incref( m_buffer ); + } + const char* c_str() const { + return m_buffer + sizeof( std::size_t ); + } + void swap( SmartBuffer& other ){ + string_swap( m_buffer, other.m_buffer ); + } }; /// \brief A non-mutable string which uses copy-by-reference for assignment of SmartString. @@@ -518,9 -517,9 +523,9 @@@ typedef String< SmartBuffer< DefaultAll class StringEqualNoCase { public: -bool operator()( const CopiedString& key, const CopiedString& other ) const { - return string_equal_nocase( key.c_str(), other.c_str() ); -} + bool operator()( const CopiedString& key, const CopiedString& other ) const { + return string_equal_nocase( key.c_str(), other.c_str() ); + } }; struct StringLessNoCase diff --combined radiant/build.cpp index 179ae632,3a524a76..23436751 --- a/radiant/build.cpp +++ b/radiant/build.cpp @@@ -41,12 -41,12 +41,12 @@@ void build_set_variable( const char* na g_build_variables[name] = value; } -const char* build_get_variable( const char* name ){ - Variables::iterator i = g_build_variables.find( name ); +const char* build_get_variable( const std::string& name ){ + Variables::iterator i = g_build_variables.find( name.c_str() ); if ( i != g_build_variables.end() ) { return ( *i ).second.c_str(); } - globalErrorStream() << "undefined build variable: " << makeQuoted( name ) << "\n"; + globalErrorStream() << "undefined build variable: " << makeQuoted( name.c_str() ) << "\n"; return ""; } @@@ -57,80 -57,55 +57,80 @@@ class Evaluatabl { public: virtual ~Evaluatable() = default; -virtual void evaluate( StringBuffer& output ) = 0; +virtual std::string evaluate() = 0; virtual void exportXML( XMLImporter& importer ) = 0; }; class VariableString : public Evaluatable { -CopiedString m_string; +std::string m_string; public: VariableString() : m_string(){ } -VariableString( const char* string ) : m_string( string ){ +VariableString( std::string string ) : m_string( std::move(string) ){ } const char* c_str() const { return m_string.c_str(); } -void setString( const char* string ){ +void setString( const std::string& string ){ m_string = string; } -void evaluate( StringBuffer& output ){ - StringBuffer variable; +std::string evaluate(){ + // replace ".[ExecutableType]" with "[ExecutableExt]" + { + size_t pos; + const std::string pattern = ".[ExecutableType]"; + while ( ( pos = m_string.find(pattern) ) != std::string::npos ) { + m_string.replace(pos, pattern.length(), "[ExecutableExt]"); + } + } + + // add missing [ExtraQ3map2Args] if "[RadiantPath]q3map2[ExecutableExt]" + { + size_t pos; + const std::string pattern = "\"[RadiantPath]q3map2[ExecutableExt]\""; + const std::string extra = "[ExtraQ3map2Args]"; + if ( ( pos = m_string.find(pattern) ) != std::string::npos + && m_string.find(extra) == std::string::npos ) + { + m_string.insert(pos + pattern.size(), " "); + m_string.insert(pos + pattern.size() + 1, extra); + } + } + + std::string output; + std::string variable_name; bool in_variable = false; - for ( const char* i = m_string.c_str(); *i != '\0'; ++i ) + for ( const char c : m_string ) { if ( !in_variable ) { - switch ( *i ) + switch ( c ) { case '[': in_variable = true; break; default: - output.push_back( *i ); + output += c; break; } } else { - switch ( *i ) + switch ( c ) { case ']': in_variable = false; - output.push_string( build_get_variable( variable.c_str() ) ); - variable.clear(); + output += build_get_variable( variable_name ); + variable_name.clear(); break; default: - variable.push_back( *i ); + variable_name += c; break; } } } + + return output; } void exportXML( XMLImporter& importer ){ importer << c_str(); @@@ -148,12 -123,12 +148,12 @@@ Conditional( VariableString* test ) : m delete m_test; delete m_result; } -void evaluate( StringBuffer& output ){ - StringBuffer buffer; - m_test->evaluate( buffer ); - if ( !string_empty( buffer.c_str() ) ) { - m_result->evaluate( output ); +std::string evaluate(){ + std::string result = m_test->evaluate(); + if ( result.empty() ) { + return result; } + return m_result->evaluate(); } void exportXML( XMLImporter& importer ){ StaticElement conditionElement( "cond" ); @@@ -179,13 -154,11 +179,13 @@@ public void push_back( Evaluatable* evaluatable ){ m_evaluatables.push_back( evaluatable ); } -void evaluate( StringBuffer& output ){ +std::string evaluate(){ + std::string result; for ( Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i ) { - ( *i )->evaluate( output ); + result += ( *i )->evaluate(); } + return result; } void exportXML( XMLImporter& importer ){ for ( Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i ) @@@ -207,16 -180,16 +207,16 @@@ virtual void popElement( const char* na class VariableStringXMLConstructor : public XMLElementParser { -StringBuffer m_buffer; +std::string m_buffer; VariableString& m_variableString; public: VariableStringXMLConstructor( VariableString& variableString ) : m_variableString( variableString ){ } ~VariableStringXMLConstructor(){ - m_variableString.setString( m_buffer.c_str() ); + m_variableString.setString( std::move(m_buffer) ); } std::size_t write( const char* buffer, std::size_t length ){ - m_buffer.push_range( buffer, buffer + length ); + m_buffer.append( buffer, length ); return length; } XMLElementParser& pushElement( const XMLElement& element ){ @@@ -229,16 -202,16 +229,16 @@@ void popElement( const char* name ) class ConditionalXMLConstructor : public XMLElementParser { -StringBuffer m_buffer; +std::string m_buffer; Conditional& m_conditional; public: ConditionalXMLConstructor( Conditional& conditional ) : m_conditional( conditional ){ } ~ConditionalXMLConstructor(){ - m_conditional.m_result = new VariableString( m_buffer.c_str() ); + m_conditional.m_result = new VariableString( std::move( m_buffer ) ); } std::size_t write( const char* buffer, std::size_t length ){ - m_buffer.push_range( buffer, buffer + length ); + m_buffer.append( buffer, length ); return length; } XMLElementParser& pushElement( const XMLElement& element ){ @@@ -251,7 -224,7 +251,7 @@@ void popElement( const char* name ) class ToolXMLConstructor : public XMLElementParser { -StringBuffer m_buffer; +std::string m_buffer; Tool& m_tool; ConditionalXMLConstructor* m_conditional; public: @@@ -261,7 -234,7 +261,7 @@@ ToolXMLConstructor( Tool& tool ) : m_to flush(); } std::size_t write( const char* buffer, std::size_t length ){ - m_buffer.push_range( buffer, buffer + length ); + m_buffer.append( buffer, length ); return length; } XMLElementParser& pushElement( const XMLElement& element ){ @@@ -286,7 -259,7 +286,7 @@@ void popElement( const char* name ) void flush(){ if ( !m_buffer.empty() ) { - m_tool.push_back( new VariableString( m_buffer.c_str() ) ); + m_tool.push_back( new VariableString( std::move( m_buffer ) ) ); m_buffer.clear(); } } @@@ -501,7 -474,8 +501,7 @@@ void project_verify( Project& project, void build_run( const char* name, CommandListener& listener ){ for ( Tools::iterator i = g_build_tools.begin(); i != g_build_tools.end(); ++i ) { - StringBuffer output; - ( *i ).second.evaluate( output ); + std::string output = ( *i ).second.evaluate(); build_set_variable( ( *i ).first.c_str(), output.c_str() ); } @@@ -511,7 -485,8 +511,7 @@@ Build& build = ( *i ).second; for ( Build::iterator j = build.begin(); j != build.end(); ++j ) { - StringBuffer output; - ( *j ).evaluate( output ); + std::string output = ( *j ).evaluate(); listener.execute( output.c_str() ); } } @@@ -785,7 -760,7 +785,7 @@@ gboolean project_selection_changed( ui: return FALSE; } -gboolean commands_cell_edited(ui::CellRendererText cell, gchar* path_string, gchar* new_text, ui::ListStore store ){ +gboolean commands_cell_edited(ui::CellRendererText cell, const gchar* path_string, const gchar* new_text, ui::ListStore store ){ if ( g_current_build == 0 ) { return FALSE; } @@@ -851,12 -826,6 +851,12 @@@ gboolean commands_key_press( ui::TreeVi ui::Window BuildMenuDialog_construct( ModalDialog& modal, ProjectList& projectList ){ ui::Window window = MainFrame_getWindow().create_dialog_window("Build Menu", G_CALLBACK(dialog_delete_callback ), &modal, -1, 400 ); + // FIXME: GTK_WIN_POS_CENTER_ON_PARENT must be used instead but does not work + // for unknown reason. + // It's possible MaingFrame_getWindow() does not return the main window. + // It's known the preferences window has same issue when using MaingFrame_getWindow(). + gtk_window_set_position( window, GTK_WIN_POS_CENTER_ALWAYS ); + { auto table1 = create_dialog_table( 2, 2, 4, 4, 4 ); window.add(table1); @@@ -909,7 -878,7 +909,7 @@@ } } { - auto frame = create_dialog_frame( "Commandline" ); + auto frame = create_dialog_frame( "Command line" ); table1.attach(frame, {0, 1, 1, 2}); { auto scr = create_scrolled_window( ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4 ); @@@ -954,6 -923,7 +954,7 @@@ namespace { CopiedString g_buildMenu; + CopiedString g_lastExecutedBuild; } void LoadBuildMenu(); @@@ -994,6 -964,7 +995,7 @@@ BuildMenuItem( const char* name, ui::Me : m_name( name ), m_item( item ){ } void run(){ + g_lastExecutedBuild = m_name; RunBSP( m_name ); } typedef MemberCaller RunCaller; @@@ -1067,3 -1038,13 +1069,13 @@@ void BuildMenu_Construct() void BuildMenu_Destroy(){ SaveBuildMenu(); } + + + void Build_runRecentExecutedBuild(){ + if( g_lastExecutedBuild.empty() ){ + g_BuildMenuItems.begin()->run(); + } + else{ + RunBSP( g_lastExecutedBuild.c_str() ); + } + } diff --combined radiant/csg.cpp index 069c5c01,2b7d82be..be01396d --- a/radiant/csg.cpp +++ b/radiant/csg.cpp @@@ -34,7 -34,7 +34,7 @@@ void Face_makeBrush( Face& face, const Brush& brush, brush_vector_t& out, float offset ){ if ( face.contributes() ) { out.push_back( new Brush( brush ) ); - Face* newFace = out.back()->addFace( face ); + std::shared_ptr newFace = out.back()->addFace( face ); face.getPlane().offset( -offset ); face.planeChanged(); if ( newFace != 0 ) { @@@ -50,7 -50,7 +50,7 @@@ void Face_extrude( Face& face, const Br face.getPlane().offset( offset ); out.push_back( new Brush( brush ) ); face.getPlane().offset( -offset ); - Face* newFace = out.back()->addFace( face ); + std::shared_ptr newFace = out.back()->addFace( face ); if ( newFace != 0 ) { newFace->flipWinding(); newFace->planeChanged(); @@@ -143,7 -143,7 +143,7 @@@ void operator()( Face& face ) const if( caulk ){ Brush_forEachFace( *out.back(), CaulkFace( ExclusionAxis, mindot, maxdot ) ); } - Face* newFace = out.back()->addFace( face ); + std::shared_ptr newFace = out.back()->addFace( face ); if ( newFace != 0 ) { newFace->flipWinding(); } @@@ -156,7 -156,7 +156,7 @@@ out.push_back( new Brush( brush ) ); if( !RemoveInner && caulk ) face.SetShader( getCaulkShader() ); - Face* newFace = out.back()->addFace( face ); + std::shared_ptr newFace = out.back()->addFace( face ); face.getPlane().offset( -offset ); face.planeChanged(); if( caulk ) @@@ -174,7 -174,7 +174,7 @@@ out.push_back( new Brush( brush ) ); out.back()->clear(); - Face* newFace = out.back()->addFace( face ); + std::shared_ptr newFace = out.back()->addFace( face ); if ( newFace != 0 ) { newFace->getPlane().offset( offset ); newFace->planeChanged(); @@@ -202,7 -202,7 +202,7 @@@ out.push_back( new Brush( brush ) ); out.back()->clear(); - Face* newFace = out.back()->addFace( face ); + std::shared_ptr newFace = out.back()->addFace( face ); if ( newFace != 0 ) { newFace->planeChanged(); @@@ -344,10 -344,10 +344,10 @@@ bool pre( const scene::Path& path, scen { ( *i )->removeEmptyFaces(); if( ( *i )->hasContributingFaces() ){ - NodeSmartReference node( ( new BrushNode() )->node() ); - Node_getBrush( node )->copy( *( *i ) ); - delete ( *i ); - Node_getTraversable( path.parent() )->insert( node ); + NodeSmartReference node( ( new BrushNode() )->node() ); + Node_getBrush( node )->copy( *( *i ) ); + delete ( *i ); + Node_getTraversable( path.parent() )->insert( node ); //path.push( makeReference( node.get() ) ); //selectPath( path, true ); //Instance_getSelectable( *GlobalSceneGraph().find( path ) )->setSelected( true ); @@@ -485,6 -485,15 +485,6 @@@ inline Dereference makeDerefer return Dereference( functor ); } -typedef Face* FacePointer; -const FacePointer c_nullFacePointer = 0; - -template -Face* Brush_findIf( const Brush& brush, const Predicate& predicate ){ - Brush::const_iterator i = std::find_if( brush.begin(), brush.end(), makeDereference( predicate ) ); - return i == brush.end() ? c_nullFacePointer : *i; // uses c_nullFacePointer instead of 0 because otherwise gcc 4.1 attempts conversion to int -} - template class BindArguments1 { @@@ -534,6 -543,7 +534,6 @@@ typedef Function& b : other ) { - if ( ( *i )->contributes() ) { - brushsplit_t split = Brush_classifyPlane( back, ( *i )->plane3() ); + if ( b->contributes() ) { + brushsplit_t split = Brush_classifyPlane( back, b->plane3() ); if ( split.counts[ePlaneFront] != 0 && split.counts[ePlaneBack] != 0 ) { fragments.push_back( new Brush( back ) ); - Face* newFace = fragments.back()->addFace( *( *i ) ); - if ( newFace != 0 ) { + std::shared_ptr newFace = fragments.back()->addFace( *b ); + if ( newFace != nullptr ) { newFace->flipWinding(); } - back.addFace( *( *i ) ); + back.addFace( *b ); } else if ( split.counts[ePlaneBack] == 0 ) { - for ( brush_vector_t::iterator i = fragments.begin(); i != fragments.end(); ++i ) - { - delete( *i ); + for ( Brush *i : fragments ) { + delete( i ); } + fragments.clear(); return false; } } @@@ -643,18 -656,23 +643,19 @@@ void post( const scene::Path& path, sce else { ++m_before; - for ( brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i ) - { + for ( Brush *b : out ) { ++m_after; - ( *i )->removeEmptyFaces(); - if ( !( *i )->empty() ) { + b->removeEmptyFaces(); + if ( !b->empty() ) { NodeSmartReference node( ( new BrushNode() )->node() ); - Node_getBrush( node )->copy( *( *i ) ); - delete ( *i ); + Node_getBrush( node )->copy( *b ); Node_getTraversable( path.parent() )->insert( node ); } - else{ - delete ( *i ); - } + delete b; } + scene::Node& parent = path.parent(); Path_deleteTop( path ); - if( Node_getTraversable( path.parent() )->empty() ){ + if( Node_getTraversable( parent )->empty() ){ m_eraseParent = true; } } @@@ -677,7 -695,9 +678,7 @@@ void CSG_Subtract() if ( selected_brushes.empty() ) { globalOutputStream() << "CSG Subtract: No brushes selected.\n"; - } - else - { + } else { globalOutputStream() << "CSG Subtract: Subtracting " << Unsigned( selected_brushes.size() ) << " brushes.\n"; UndoableCommand undo( "brushSubtract" ); @@@ -712,20 -732,12 +713,20 @@@ bool pre( const scene::Path& path, scen } void post( const scene::Path& path, scene::Instance& instance ) const { - if ( path.top().get().visible() ) { + if ( !path.top().get().visible() ) { + return; + } + Brush* brush = Node_getBrush( path.top() ); - if ( brush != 0 - && Instance_getSelectable( instance )->isSelected() ) { + if ( brush == nullptr || !Instance_getSelectable( instance )->isSelected() ) { + return; + } + Plane3 plane( plane3_for_points( m_p0, m_p1, m_p2 ) ); - if ( plane3_valid( plane ) ) { + if ( !plane3_valid( plane ) ) { + return; + } + brushsplit_t split = Brush_classifyPlane( *brush, m_split == eFront ? plane3_flipped( plane ) : plane ); if ( split.counts[ePlaneBack] && split.counts[ePlaneFront] ) { // the plane intersects this brush @@@ -733,8 -745,7 +734,8 @@@ NodeSmartReference node( ( new BrushNode() )->node() ); Brush* fragment = Node_getBrush( node ); fragment->copy( *brush ); - Face* newFace = fragment->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); + std::shared_ptr newFace = + fragment->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); if ( newFace != 0 && m_split != eFront ) { newFace->flipWinding(); } @@@ -749,7 -760,7 +750,7 @@@ } } - Face* newFace = brush->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); + std::shared_ptr newFace = brush->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); if ( newFace != 0 && m_split == eFront ) { newFace->flipWinding(); } @@@ -761,6 -772,9 +762,6 @@@ if ( m_split != eFrontAndBack && split.counts[ePlaneBack] != 0 ) { // the brush is "behind" the plane Path_deleteTop( path ); - } - } - } } } }; diff --combined radiant/environment.cpp index bd07533a,a1a13b86..1e02a141 --- a/radiant/environment.cpp +++ b/radiant/environment.cpp @@@ -140,10 -140,8 +140,10 @@@ void gamedetect() if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz.exe", buf, p - buf ) ) #elif GDEF_OS_MACOS if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "Nexuiz.app/Contents/Info.plist", buf, p - buf ) ) -#else +#elif GDEF_OS_LINUX if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz-linux-glx.sh", buf, p - buf ) ) +#else + if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", NULL, buf, p - buf ) ) #endif { return; } @@@ -168,17 -166,8 +168,17 @@@ namespace { -CopiedString home_path; -CopiedString app_path; + // executable file path + CopiedString app_filepath; + // directory paths + CopiedString home_path; + CopiedString app_path; + CopiedString lib_path; + CopiedString data_path; +} + +const char* environment_get_app_filepath(){ + return app_filepath.c_str(); } const char* environment_get_home_path(){ @@@ -189,26 -178,30 +189,40 @@@ const char* environment_get_app_path() return app_path.c_str(); } +const char *environment_get_lib_path() +{ + return lib_path.c_str(); +} + +const char *environment_get_data_path() +{ + return data_path.c_str(); +} + bool portable_app_setup(){ StringOutputStream confdir( 256 ); confdir << app_path.c_str() << "settings/"; - if ( file_exists( confdir.c_str() ) ) { + if ( file_is_directory( confdir.c_str() ) ) { home_path = confdir.c_str(); return true; } return false; } + + const char* openCmdMap; + + void cmdMap(){ + openCmdMap = NULL; + for ( int i = 1; i < g_argc; ++i ) + { + //if ( !stricmp( g_argv[i] + strlen(g_argv[i]) - 4, ".map" ) ){ + if( string_equal_suffix_nocase( g_argv[i], ".map" ) ){ + openCmdMap = g_argv[i]; + } + } + } + #if GDEF_OS_POSIX #include @@@ -220,32 -213,28 +234,32 @@@ const char* LINK_NAME = #if GDEF_OS_LINUX "/proc/self/exe" -#else // FreeBSD and OSX +#else // FreeBSD and macOS "/proc/curproc/file" #endif ; -/// brief Returns the filename of the executable belonging to the current process, or 0 if not found. +/// brief Returns the filename of the executable belonging to the current process, or empty string if not found. char const* getexename( char *buf ){ /* Now read the symbolic link */ - int ret = readlink( LINK_NAME, buf, PATH_MAX ); + const int ret = readlink( LINK_NAME, buf, PATH_MAX ); if ( ret == -1 ) { globalOutputStream() << "getexename: falling back to argv[0]: " << makeQuoted( g_argv[0] ); - const char* path = realpath( g_argv[0], buf ); - if ( path == 0 ) { + if( realpath( g_argv[0], buf ) == 0 ) { /* In case of an error, leave the handling up to the caller */ - return ""; + *buf = '\0'; } } + else { + /* Ensure proper NUL termination */ + buf[ret] = 0; + } - /* Ensure proper NUL termination */ - buf[ret] = 0; + return buf; +} +char const* getexepath( char *buf ) { /* delete the program name */ *( strrchr( buf, '/' ) ) = '\0'; @@@ -273,102 -262,31 +287,91 @@@ void environment_init( int argc, char c { char real[PATH_MAX]; - app_path = getexename( real ); - ASSERT_MESSAGE( !string_empty( app_path.c_str() ), "failed to deduce app path" ); + app_filepath = getexename( real ); + ASSERT_MESSAGE( !string_empty( app_filepath.c_str() ), "failed to deduce app path" ); + + strncpy( real, app_filepath.c_str(), strlen( app_filepath.c_str() ) ); + app_path = getexepath( real ); + } + + { +#if defined(RADIANT_FHS_INSTALL) + StringOutputStream buffer; + #if defined(RADIANT_ADDONS_DIR) + buffer << RADIANT_ADDONS_DIR << "/"; + #else + buffer << app_path.c_str() << "../lib/"; + buffer << RADIANT_LIB_ARCH << "/"; + buffer << RADIANT_BASENAME << "/"; + #endif + lib_path = buffer.c_str(); +#else + lib_path = app_path.c_str(); +#endif + } + + { +#if defined(RADIANT_FHS_INSTALL) + StringOutputStream buffer; + #if defined(RADIANT_DATA_DIR) + buffer << RADIANT_DATA_DIR << "/"; + #else + buffer << app_path.c_str() << "../share/"; + buffer << RADIANT_BASENAME << "/"; + #endif + data_path = buffer.c_str(); +#else + data_path = app_path.c_str(); +#endif } if ( !portable_app_setup() ) { StringOutputStream home( 256 ); - home << DirectoryCleaned( g_get_user_config_dir() ) << "netradiant/"; +#if GDEF_OS_MACOS + /* This is used on macOS, this will produce + ~/Library/Application Support/NetRadiant folder. */ + home << DirectoryCleaned( g_get_home_dir() ); + Q_mkdir( home.c_str() ); + home << "Library/"; + Q_mkdir( home.c_str() ); + home << "Application Support/"; + Q_mkdir( home.c_str() ); + home << RADIANT_NAME << "/"; +#else // if GDEF_OS_XDG + /* This is used on both Linux and FreeBSD, + this will produce ~/.config/netradiant folder + when environment has default settings, the + XDG_CONFIG_HOME variable modifies it. */ + home << DirectoryCleaned( g_get_user_config_dir() ); + Q_mkdir( home.c_str() ); + home << RADIANT_BASENAME << "/"; +#endif // ! GDEF_OS_MACOS Q_mkdir( home.c_str() ); home_path = home.c_str(); } + gamedetect(); + cmdMap(); } #elif GDEF_OS_WINDOWS #include - char* openCmdMap; - - void cmdMap(){ - openCmdMap = NULL; - for ( int i = 1; i < g_argc; ++i ) - { - if ( !stricmp( g_argv[i] + strlen(g_argv[i]) - 4, ".map" ) ){ - openCmdMap = g_argv[i]; - } - } - } - void environment_init( int argc, char const* argv[] ){ args_init( argc, argv ); { // get path to the editor char filename[MAX_PATH + 1]; + StringOutputStream app_filepath_stream( 256 ); + StringOutputStream app_path_stream( 256 ); + GetModuleFileName( 0, filename, MAX_PATH ); + + app_filepath_stream << PathCleaned( filename ); + app_filepath = app_filepath_stream.c_str(); + char* last_separator = strrchr( filename, '\\' ); if ( last_separator != 0 ) { *( last_separator + 1 ) = '\0'; @@@ -377,23 -295,16 +380,23 @@@ { filename[0] = '\0'; } - StringOutputStream app( 256 ); - app << PathCleaned( filename ); - app_path = app.c_str(); + + app_path_stream << PathCleaned( filename ); + app_path = app_path_stream.c_str(); + + lib_path = app_path; + data_path = app_path; } if ( !portable_app_setup() ) { char *appdata = getenv( "APPDATA" ); + StringOutputStream home( 256 ); home << PathCleaned( appdata ); - home << "/NetRadiantSettings/"; + home << "/"; + home << RADIANT_NAME; + home << "/"; + Q_mkdir( home.c_str() ); home_path = home.c_str(); } diff --combined radiant/environment.h index 2e57fb12,566a307e..a7de6d4f --- a/radiant/environment.h +++ b/radiant/environment.h @@@ -23,20 -23,12 +23,17 @@@ #define INCLUDED_ENVIRONMENT_H void environment_init( int argc, char const* argv[] ); + +const char* environment_get_app_filepath(); + const char* environment_get_home_path(); const char* environment_get_app_path(); +const char *environment_get_lib_path(); +const char *environment_get_data_path(); extern int g_argc; extern char const** g_argv; - #if defined( WIN32 ) - extern char* openCmdMap; - #endif - + extern const char* openCmdMap; #endif diff --combined radiant/main.cpp index a2d288f1,6093f879..20bea80f --- a/radiant/main.cpp +++ b/radiant/main.cpp @@@ -64,6 -64,8 +64,6 @@@ #include "main.h" #include "globaldefs.h" -#include "version.h" - #include "debugging/debugging.h" #include "iundo.h" @@@ -302,12 -304,12 +302,12 @@@ bool handleMessage() ScopedLock lock( m_lock ); if (GDEF_DEBUG) { m_buffer << "Break into the debugger?\n"; - bool handled = ui::alert(ui::root, m_buffer.c_str(), "Radiant - Runtime Error", ui::alert_type::YESNO, ui::alert_icon::Error) == ui::alert_response::NO; + bool handled = ui::alert(ui::root, m_buffer.c_str(), RADIANT_NAME " - Runtime Error", ui::alert_type::YESNO, ui::alert_icon::Error) == ui::alert_response::NO; m_buffer.clear(); return handled; } else { m_buffer << "Please report this error to the developers\n"; - ui::alert(ui::root, m_buffer.c_str(), "Radiant - Runtime Error", ui::alert_type::OK, ui::alert_icon::Error); + ui::alert(ui::root, m_buffer.c_str(), RADIANT_NAME " - Runtime Error", ui::alert_type::OK, ui::alert_icon::Error); m_buffer.clear(); } } @@@ -327,10 -329,7 +327,10 @@@ void paths_init() Q_mkdir( g_strSettingsPath.c_str() ); + g_strAppFilePath = environment_get_app_filepath(); g_strAppPath = environment_get_app_path(); + g_strLibPath = environment_get_lib_path(); + g_strDataPath = environment_get_data_path(); // radiant is installed in the parent dir of "tools/" // NOTE: this is not very easy for debugging @@@ -338,12 -337,12 +338,12 @@@ // (for now I had to create symlinks) { StringOutputStream path( 256 ); - path << g_strAppPath.c_str() << "bitmaps/"; + path << g_strDataPath.c_str() << "bitmaps/"; BitmapsPath_set( path.c_str() ); } // we will set this right after the game selection is done - g_strGameToolsPath = g_strAppPath; + g_strGameToolsPath = g_strDataPath; } bool check_version_file( const char* filename, const char* version ){ @@@ -363,6 -362,39 +363,6 @@@ return false; } -bool check_version(){ - // a safe check to avoid people running broken installations - // (otherwise, they run it, crash it, and blame us for not forcing them hard enough to pay attention while installing) - // make something idiot proof and someone will make better idiots, this may be overkill - // let's leave it disabled in debug mode in any case - // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431 - if (GDEF_DEBUG) { - return true; - } - // locate and open RADIANT_MAJOR and RADIANT_MINOR - bool bVerIsGood = true; - { - StringOutputStream ver_file_name(256); - ver_file_name << AppPath_get() << "RADIANT_MAJOR"; - bVerIsGood = check_version_file(ver_file_name.c_str(), RADIANT_MAJOR_VERSION); - } - { - StringOutputStream ver_file_name(256); - ver_file_name << AppPath_get() << "RADIANT_MINOR"; - bVerIsGood = check_version_file(ver_file_name.c_str(), RADIANT_MINOR_VERSION); - } - - if (!bVerIsGood) { - StringOutputStream msg(256); - msg - << "This editor binary (" RADIANT_VERSION ") doesn't match what the latest setup has configured in this directory\n" - "Make sure you run the right/latest editor binary you installed\n" - << AppPath_get(); - ui::alert(ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Default); - } - return bVerIsGood; -} - void create_global_pid(){ /*! the global prefs loading / game selection dialog might fail for any reason we don't know about @@@ -383,31 -415,31 +383,31 @@@ if ( remove( g_pidFile.c_str() ) == -1 ) { StringOutputStream msg( 256 ); msg << "WARNING: Could not delete " << g_pidFile.c_str(); - ui::alert( ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error ); + ui::alert( ui::root, msg.c_str(), RADIANT_NAME, ui::alert_type::OK, ui::alert_icon::Error ); } // in debug, never prompt to clean registry, turn console logging auto after a failed start if (!GDEF_DEBUG) { StringOutputStream msg(256); - msg << "Radiant failed to start properly the last time it was run.\n" + msg << RADIANT_NAME " failed to start properly the last time it was run.\n" "The failure may be related to current global preferences.\n" "Do you want to reset global preferences to defaults?"; - if (ui::alert(ui::root, msg.c_str(), "Radiant - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) { + if (ui::alert(ui::root, msg.c_str(), RADIANT_NAME " - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) { g_GamesDialog.Reset(); } msg.clear(); msg << "Logging console output to " << SettingsPath_get() - << "radiant.log\nRefer to the log if Radiant fails to start again."; + << "radiant.log\nRefer to the log if " RADIANT_NAME " fails to start again."; - ui::alert(ui::root, msg.c_str(), "Radiant - Console Log", ui::alert_type::OK); + ui::alert(ui::root, msg.c_str(), RADIANT_NAME " - Console Log", ui::alert_type::OK); } // set without saving, the class is not in a coherent state yet // just do the value change and call to start logging, CGamesDialog will pickup when relevant g_GamesDialog.m_bForceLogConsole = true; - Sys_LogFile( true ); + Sys_EnableLogFile( true ); } // create a primary .pid for global init run @@@ -425,7 -457,7 +425,7 @@@ void remove_global_pid() if ( remove( g_pidFile.c_str() ) == -1 ) { StringOutputStream msg( 256 ); msg << "WARNING: Could not delete " << g_pidFile.c_str(); - ui::alert( ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error ); + ui::alert( ui::root, msg.c_str(), RADIANT_NAME, ui::alert_type::OK, ui::alert_icon::Error ); } } @@@ -443,30 -475,30 +443,30 @@@ void create_local_pid() if ( remove( g_pidGameFile.c_str() ) == -1 ) { StringOutputStream msg; msg << "WARNING: Could not delete " << g_pidGameFile.c_str(); - ui::alert( ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error ); + ui::alert( ui::root, msg.c_str(), RADIANT_NAME, ui::alert_type::OK, ui::alert_icon::Error ); } // in debug, never prompt to clean registry, turn console logging auto after a failed start if (!GDEF_DEBUG) { StringOutputStream msg; - msg << "Radiant failed to start properly the last time it was run.\n" + msg << RADIANT_NAME " failed to start properly the last time it was run.\n" "The failure may be caused by current preferences.\n" "Do you want to reset all preferences to defaults?"; - if (ui::alert(ui::root, msg.c_str(), "Radiant - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) { + if (ui::alert(ui::root, msg.c_str(), RADIANT_NAME " - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) { Preferences_Reset(); } msg.clear(); msg << "Logging console output to " << SettingsPath_get() - << "radiant.log\nRefer to the log if Radiant fails to start again."; + << "radiant.log\nRefer to the log if " RADIANT_NAME " fails to start again."; - ui::alert(ui::root, msg.c_str(), "Radiant - Console Log", ui::alert_type::OK); + ui::alert(ui::root, msg.c_str(), RADIANT_NAME " - Console Log", ui::alert_type::OK); } // force console logging on! (will go in prefs too) g_GamesDialog.m_bForceLogConsole = true; - Sys_LogFile( true ); + Sys_EnableLogFile( true ); } else { @@@ -527,23 -559,7 +527,23 @@@ void add_local_rc_files() #endif // GARUX_DISABLE_GTKTHEME } +/* HACK: If ui::main is not called yet, +gtk_main_quit will not quit, so tell main +to not call ui::main. This happens when a +map is loaded from command line and require +a restart because of wrong format. +Delete this when the code to not have to +restart to load another format is merged. */ +bool g_dontStart = false; + int main( int argc, char* argv[] ){ +#if GTK_TARGET == 3 + // HACK: force legacy GL backend as we don't support GL3 yet + setenv("GDK_GL", "LEGACY", 0); +#if GDEF_OS_LINUX || GDEF_OS_BSD + setenv("GDK_BACKEND", "x11", 0); +#endif +#endif // GTK_TARGET == 3 crt_init(); streams_init(); @@@ -573,13 -589,7 +573,13 @@@ #endif const char* mapname = NULL; + +#if GDEF_OS_WINDOWS + StringOutputStream mapname_buffer( 256 ); +#endif + char const *error = NULL; + if ( !ui::init( &argc, &argv, "", &error) ) { g_print( "%s\n", error ); return -1; @@@ -588,21 -598,16 +588,21 @@@ // 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]; + + if ( g_str_has_suffix( mapname, ".map" ) ) { + if ( !g_path_is_absolute( mapname ) ) { + mapname = g_build_filename( g_get_current_dir(), mapname, NULL ); } - else { - mapname = g_build_filename( g_get_current_dir(), argv[1], NULL ); - } + +#if GDEF_OS_WINDOWS + mapname_buffer << PathCleaned( mapname ); + mapname = mapname_buffer.c_str(); +#endif } else { - g_print( "bad file name, will not load: %s\n", argv[1] ); + g_print( "bad file name, will not load: %s\n", mapname ); + mapname = NULL; } } } @@@ -631,6 -636,10 +631,6 @@@ add_local_rc_files(); - if ( !check_version() ) { - return EXIT_FAILURE; - } - show_splash(); create_global_pid(); @@@ -651,7 -660,7 +651,7 @@@ // we may have the console turned on and want to keep it that way // so we use a latching system if ( g_GamesDialog.m_bForceLogConsole ) { - Sys_LogFile( true ); + Sys_EnableLogFile( true ); g_Console_enableLogging = true; g_GamesDialog.m_bForceLogConsole = false; } @@@ -666,13 -675,10 +666,10 @@@ hide_splash(); - #ifdef WIN32 if( openCmdMap && *openCmdMap ){ Map_LoadFile( openCmdMap ); } - else - #endif // WIN32 - if ( mapname != NULL ) { + else if ( mapname != NULL ) { Map_LoadFile( mapname ); } else if ( g_bLoadLastMap && !g_strLastMap.empty() ) { @@@ -690,17 -696,7 +687,17 @@@ remove_local_pid(); + /* HACK: If ui::main is not called yet, + gtk_main_quit will not quit, so tell main + to not call ui::main. This happens when a + map is loaded from command line and require + a restart because of wrong format. + Delete this when the code to not have to + restart to load another format is merged. */ + if ( !g_dontStart ) + { ui::main(); + } // avoid saving prefs when the app is minimized if ( g_pParentWnd->IsSleeping() ) { @@@ -721,7 -717,7 +718,7 @@@ Radiant_Shutdown(); // close the log file if any - Sys_LogFile( false ); + Sys_EnableLogFile( false ); return EXIT_SUCCESS; } diff --combined radiant/mainframe.cpp index 7c74d2b4,4bd30a95..dd18db71 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@@ -102,24 -102,12 +102,24 @@@ #include "texwindow.h" #include "filterbar.h" +#if GDEF_OS_WINDOWS +#include +#else +#include +#endif + +#ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET +/* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ +#define WORKAROUND_GOBJECT_SET_GLWIDGET(window, widget) g_object_set_data( G_OBJECT( window ), "glwidget", G_OBJECT( widget ) ) +#else +#define WORKAROUND_GOBJECT_SET_GLWIDGET(window, widget) +#endif + #define GARUX_DISABLE_GTKTHEME #ifndef GARUX_DISABLE_GTKTHEME #include "gtktheme.h" #endif - struct layout_globals_t { WindowPosition m_position; @@@ -134,11 -122,11 +134,11 @@@ layout_globals_t() : m_position( -1, -1, 640, 480 ), - nXYHeight( 300 ), - nXYWidth( 300 ), - nCamWidth( 200 ), - nCamHeight( 200 ), - nState( GDK_WINDOW_STATE_MAXIMIZED ){ + nXYHeight( 350 ), + nXYWidth( 600 ), + nCamWidth( 300 ), + nCamHeight( 210 ), + nState( 0 ){ } }; @@@ -173,8 -161,6 +173,8 @@@ void VFS_Refresh() RefreshReferences(); // also refresh texture browser TextureBrowser_RefreshShaders(); + // also show textures (all or common) + TextureBrowser_ShowStartupShaders( GlobalTextureBrowser() ); } void VFS_Restart(){ @@@ -233,7 -219,9 +233,7 @@@ void HomePaths_Realise() } path.clear(); path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/"; -#endif - -#if GDEF_OS_WINDOWS +#elif GDEF_OS_WINDOWS TCHAR mydocsdir[MAX_PATH + 1]; wchar_t *mydocsdirw; HMODULE shfolder = LoadLibrary( "shfolder.dll" ); @@@ -270,19 -258,13 +270,19 @@@ break; } } -#endif - -#if GDEF_OS_POSIX +#elif GDEF_OS_XDG + path.clear(); + path << DirectoryCleaned( g_get_user_data_dir() ) << ( prefix + 1 ) << "/"; + if ( file_exists( path.c_str() ) && file_is_directory( path.c_str() ) ) { + g_qeglobals.m_userEnginePath = path.c_str(); + break; + } + else { path.clear(); path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/"; g_qeglobals.m_userEnginePath = path.c_str(); break; + } #endif } @@@ -458,32 -440,14 +458,32 @@@ void setPakPath( int num, const char* p } -// App Path +// executable file path (full path) +CopiedString g_strAppFilePath; + +// directory paths +CopiedString g_strAppPath; +CopiedString g_strLibPath; +CopiedString g_strDataPath; -CopiedString g_strAppPath; ///< holds the full path of the executable +const char* AppFilePath_get(){ + return g_strAppFilePath.c_str(); +} const char* AppPath_get(){ return g_strAppPath.c_str(); } +const char *LibPath_get() +{ + return g_strLibPath.c_str(); +} + +const char *DataPath_get() +{ + return g_strDataPath.c_str(); +} + /// the path to the local rc-dir const char* LocalRcPath_get( void ){ static CopiedString rc_path; @@@ -582,28 -546,39 +582,28 @@@ struct PakPath4 bool g_disableEnginePath = false; bool g_disableHomePath = false; -void Paths_constructPreferences( PreferencesPage& page ){ +void Paths_constructBasicPreferences( PreferencesPage& page ) { page.appendPathEntry( "Engine Path", true, make_property(g_strEnginePath) ); +} - page.appendCheckBox( - "", "Do not use Engine Path", - g_disableEnginePath - ); +void Paths_constructPreferences( PreferencesPage& page ){ + Paths_constructBasicPreferences( page ); - page.appendCheckBox( - "", "Do not use Home Path", - g_disableHomePath - ); + page.appendSpacer( 4 ); + page.appendLabel( "", "Advanced options" ); + page.appendCheckBox( "", "Do not use Engine Path", g_disableEnginePath ); + page.appendCheckBox( "", "Do not use Home Path", g_disableHomePath ); - for ( int i = 0; i < g_pakPathCount; i++ ) { - std::string label = "Pak Path " + std::to_string(i); - switch (i) { - case 0: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; - case 1: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; - case 2: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; - case 3: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; - case 4: - page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); - break; -} - } + page.appendSpacer( 4 ); + page.appendLabel( "", "Only a very few games support Pak Paths," ); + page.appendLabel( "", "if you don't know what it is, leave this blank." ); + + const char *label = "Pak Path "; + page.appendPathEntry( label, true, make_property( g_strPakPath[0] ) ); + page.appendPathEntry( label, true, make_property( g_strPakPath[1] ) ); + page.appendPathEntry( label, true, make_property( g_strPakPath[2] ) ); + page.appendPathEntry( label, true, make_property( g_strPakPath[3] ) ); + page.appendPathEntry( label, true, make_property( g_strPakPath[4] ) ); } void Paths_constructPage( PreferenceGroup& group ){ @@@ -620,14 -595,14 +620,14 @@@ class PathsDialog : public Dialo { public: ui::Window BuildDialog(){ - auto frame = create_dialog_frame( "Path settings", ui::Shadow::ETCHED_IN ); + auto frame = create_dialog_frame( "Path Settings", ui::Shadow::ETCHED_IN ); auto vbox2 = create_dialog_vbox( 0, 4 ); frame.add(vbox2); { - PreferencesPage preferencesPage( *this, vbox2 ); - Paths_constructPreferences( preferencesPage ); + PreferencesPage page( *this, vbox2 ); + Paths_constructBasicPreferences( page ); } return ui::Window(create_simple_modal_dialog_window( "Engine Path Not Found", m_modal, frame )); @@@ -786,7 -761,7 +786,7 @@@ void Radiant_detachGameToolsPathObserve void Radiant_Initialise(){ GlobalModuleServer_Initialise(); - Radiant_loadModulesFromRoot( AppPath_get() ); + Radiant_loadModulesFromRoot( LibPath_get() ); Preferences_Load(); @@@ -815,7 -790,7 +815,7 @@@ void Radiant_Shutdown() } void Exit(){ - if ( ConfirmModified( "Exit Radiant" ) ) { + if ( ConfirmModified( "Exit " RADIANT_NAME ) ) { gtk_main_quit(); } } @@@ -976,53 -951,6 +976,53 @@@ void ColorScheme_Ydnar() XY_UpdateAllWindows(); } +/* color scheme to fit the GTK Adwaita Dark theme */ +void ColorScheme_AdwaitaDark() +{ + // SI_Colors0 + // GlobalTextureBrowser().color_textureback + TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f)); + + // SI_Colors4 + g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f); + // SI_Colors12 + g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f); + CamWnd_Update(*g_pParentWnd->GetCamWnd()); + + // SI_Colors1 + g_xywindow_globals.color_gridback = Vector3(0.25f, 0.25f, 0.25f); + // SI_Colors2 + g_xywindow_globals.color_gridminor = Vector3(0.21f, 0.23f, 0.23f); + // SI_Colors3 + g_xywindow_globals.color_gridmajor = Vector3(0.14f, 0.15f, 0.15f); + // SI_Colors14 + g_xywindow_globals.color_gridmajor_alt = Vector3(1.0f, 0.0f, 0.0f); + // SI_Colors6 + g_xywindow_globals.color_gridblock = Vector3(1.0f, 1.0f, 1.0f); + // SI_Colors7 + g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f); + // ?? + g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f); + // ?? + g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f); + // SI_Colors8 + g_xywindow_globals.color_brushes = Vector3(0.73f, 0.73f, 0.73f); + + // SI_AxisColors0 + g_xywindow_globals.AxisColorX = Vector3(1.0f, 0.0f, 0.0f); + // SI_AxisColors1 + g_xywindow_globals.AxisColorY = Vector3(0.0f, 1.0f, 0.0f); + // SI_AxisColors2 + g_xywindow_globals.AxisColorZ = Vector3(0.0f, 0.0f, 1.0f); + SetWorldspawnColour(g_xywindow_globals.color_brushes); + // ?? + g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f); + XY_UpdateAllWindows(); + + // SI_Colors5 + // g_entity_globals.color_entity = Vector3(0.0f, 0.0f, 0.0f); +} + typedef Callback GetColourCallback; typedef Callback SetColourCallback; @@@ -1140,7 -1068,6 +1140,7 @@@ ui::MenuItem create_colours_menu() create_menu_item_with_mnemonic( menu_3, "Q3Radiant Original", "ColorSchemeQER" ); create_menu_item_with_mnemonic( menu_3, "Black and Green", "ColorSchemeBlackAndGreen" ); create_menu_item_with_mnemonic( menu_3, "Maya/Max/Lightwave Emulation", "ColorSchemeYdnar" ); + create_menu_item_with_mnemonic(menu_3, "Adwaita Dark", "ColorSchemeAdwaitaDark"); #ifndef GARUX_DISABLE_GTKTHEME create_menu_item_with_mnemonic( menu_in_menu, "GTK Theme...", "gtkThemeDlg" ); @@@ -1839,11 -1766,9 +1839,11 @@@ void Selection_SnapToGrid() static gint qe_every_second( gpointer data ){ - GdkModifierType mask; + if (g_pParentWnd == nullptr) + return TRUE; - gdk_window_get_pointer( 0, 0, 0, &mask ); + GdkModifierType mask; + gdk_window_get_pointer( gtk_widget_get_window(g_pParentWnd->m_window), nullptr, nullptr, &mask ); if ( ( mask & ( GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK ) ) == 0 ) { QE_CheckAutoSave(); @@@ -1955,18 -1880,15 +1955,18 @@@ void ScreenUpdates_Disable( const char bool isActiveApp = MainFrame_isActiveApp(); g_wait = create_wait_dialog( title, message ); - gtk_grab_add( g_wait.m_window ); if ( isActiveApp ) { g_wait.m_window.show(); + gtk_grab_add( g_wait.m_window ); ScreenUpdates_process(); } } else if ( g_wait.m_window.visible() ) { g_wait.m_label.text(message); + if ( GTK_IS_WINDOW(g_wait.m_window) ) { + gtk_grab_add(g_wait.m_window); + } ScreenUpdates_process(); } g_wait_stack.push_back( message ); @@@ -2191,9 -2113,6 +2191,9 @@@ ui::MenuItem create_view_menu( MainFram create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane In", "CubicClipZoomIn" ); create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane Out", "CubicClipZoomOut" ); menu_separator( camera_menu ); + create_menu_item_with_mnemonic( camera_menu, "Decrease FOV", "FOVDec" ); + create_menu_item_with_mnemonic( camera_menu, "Increase FOV", "FOVInc" ); + menu_separator( camera_menu ); create_menu_item_with_mnemonic( camera_menu, "Next leak spot", "NextLeakSpot" ); create_menu_item_with_mnemonic( camera_menu, "Previous leak spot", "PrevLeakSpot" ); menu_separator( camera_menu ); @@@ -2347,6 -2266,7 +2347,7 @@@ ui::MenuItem create_bsp_menu() } create_menu_item_with_mnemonic( menu, "Customize...", "BuildMenuCustomize" ); + create_menu_item_with_mnemonic( menu, "Run recent build", "Build_runRecentExecutedBuild" ); menu_separator( menu ); @@@ -2388,6 -2308,7 +2389,7 @@@ ui::MenuItem create_misc_menu() // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394 // create_menu_item_with_mnemonic(menu, "_Print XY View", FreeCaller()); create_menu_item_with_mnemonic( menu, "_Background select", makeCallbackF(WXY_BackgroundSelect) ); + create_menu_item_with_mnemonic( menu, "Fullscreen", "Fullscreen" ); return misc_menu_item; } @@@ -2446,7 -2367,7 +2448,7 @@@ ui::MenuItem create_help_menu() create_menu_item_with_mnemonic( menu, "Bug report", makeCallbackF(OpenBugReportURL) ); create_menu_item_with_mnemonic( menu, "Shortcuts list", makeCallbackF(DoCommandListDlg) ); - create_menu_item_with_mnemonic( menu, "_About", makeCallbackF(DoAbout) ); + create_menu_item_with_mnemonic( menu, "_About...", makeCallbackF(DoAbout) ); return help_menu_item; } @@@ -2836,14 -2757,10 +2838,14 @@@ MainFrame::~MainFrame() for ( std::vector::iterator i = g_floating_windows.begin(); i != g_floating_windows.end(); ++i ) { +#ifndef WORKAROUND_MACOS_GTK2_DESTROY i->destroy(); +#endif } +#ifndef WORKAROUND_MACOS_GTK2_DESTROY m_window.destroy(); +#endif } void MainFrame::SetActiveXY( XYWnd* p ){ @@@ -3000,16 -2917,13 +3002,16 @@@ WindowPositionTracker g_posXZWnd WindowPositionTracker g_posYZWnd; static gint mainframe_delete( ui::Widget widget, GdkEvent *event, gpointer data ){ - if ( ConfirmModified( "Exit Radiant" ) ) { + if ( ConfirmModified( "Exit " RADIANT_NAME ) ) { gtk_main_quit(); } return TRUE; } +PanedState g_single_hpaned = { 0.75f, -1, }; +PanedState g_single_vpaned = { 0.75f, -1, }; + void MainFrame::Create(){ ui::Window window = ui::Window( ui::window_type::TOP ); @@@ -3099,26 -3013,15 +3101,16 @@@ #if GDEF_OS_WINDOWS if ( g_multimon_globals.m_bStartOnPrimMon ) { PositionWindowOnPrimaryScreen( g_layout_globals.m_position ); - window_set_position( window, g_layout_globals.m_position ); } - else #endif - if ( g_layout_globals.nState & GDK_WINDOW_STATE_MAXIMIZED ) { - gtk_window_maximize( window ); - WindowPosition default_position( -1, -1, 640, 480 ); - window_set_position( window, default_position ); - } - else - { - window_set_position( window, g_layout_globals.m_position ); + window_set_position( window, g_layout_globals.m_position ); - } m_window = window; window.show(); - if ( CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft ) { + if ( CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft ) + { { ui::Widget hsplit = ui::HPaned(ui::New); m_hSplit = hsplit; @@@ -3136,23 -3039,23 +3128,23 @@@ m_vSplit2 = vsplit2; if ( CurrentStyle() == eRegular ){ - gtk_paned_add1( GTK_PANED( hsplit ), vsplit ); - gtk_paned_add2( GTK_PANED( hsplit ), vsplit2 ); + gtk_paned_pack1( GTK_PANED( hsplit ), vsplit, TRUE, TRUE ); + gtk_paned_pack2( GTK_PANED( hsplit ), vsplit2, TRUE, TRUE ); } else{ - gtk_paned_add2( GTK_PANED( hsplit ), vsplit ); - gtk_paned_add1( GTK_PANED( hsplit ), vsplit2 ); + gtk_paned_pack2( GTK_PANED( hsplit ), vsplit, TRUE, TRUE ); + gtk_paned_pack1( GTK_PANED( hsplit ), vsplit2, TRUE, TRUE ); } // console ui::Widget console_window = Console_constructWindow( window ); - gtk_paned_pack2( GTK_PANED( vsplit ), console_window, FALSE, TRUE ); + gtk_paned_pack2( GTK_PANED( vsplit ), console_window, TRUE, TRUE ); // xy m_pXYWnd = new XYWnd(); m_pXYWnd->SetViewType( XY ); ui::Widget xy_window = ui::Widget(create_framed_widget( m_pXYWnd->GetWidget( ) )); - gtk_paned_add1( GTK_PANED( vsplit ), xy_window ); + gtk_paned_pack1( GTK_PANED( vsplit ), xy_window, TRUE, TRUE ); { // camera @@@ -3161,30 -3064,17 +3153,18 @@@ CamWnd_setParent( *m_pCamWnd, window ); auto camera_window = create_framed_widget( CamWnd_getWidget( *m_pCamWnd ) ); - gtk_paned_add1( GTK_PANED( vsplit2 ), camera_window ); + gtk_paned_pack1( GTK_PANED( vsplit2 ), GTK_WIDGET( camera_window ) , TRUE, TRUE); // textures auto texture_window = create_framed_widget( TextureBrowser_constructWindow( window ) ); - gtk_paned_add2( GTK_PANED( vsplit2 ), texture_window ); + gtk_paned_pack2( GTK_PANED( vsplit2 ), GTK_WIDGET( texture_window ), TRUE, TRUE ); } } } - - gtk_paned_set_position( GTK_PANED( m_vSplit ), g_layout_globals.nXYHeight ); - - if ( CurrentStyle() == eRegular ) { - gtk_paned_set_position( GTK_PANED( m_hSplit ), g_layout_globals.nXYWidth ); - } - else - { - gtk_paned_set_position( GTK_PANED( m_hSplit ), g_layout_globals.nCamWidth ); - } - - gtk_paned_set_position( GTK_PANED( m_vSplit2 ), g_layout_globals.nCamHeight ); } - else if ( CurrentStyle() == eFloating ) { + else if ( CurrentStyle() == eFloating ) + { { ui::Window window = ui::Window(create_persistent_floating_window( "Camera", m_window )); global_accel_connect_window( window ); @@@ -3200,8 -3090,11 +3180,8 @@@ window.add(frame); } CamWnd_setParent( *m_pCamWnd, window ); -#define GARUX_GTK_WORKAROUND -#ifndef GARUX_GTK_WORKAROUND - /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ - g_object_set_data( G_OBJECT( window ), "glwidget", CamWnd_getWidget( *m_pCamWnd ) ); -#endif + + WORKAROUND_GOBJECT_SET_GLWIDGET( window, CamWnd_getWidget( *m_pCamWnd ) ); g_floating_windows.push_back( window ); } @@@ -3221,8 -3114,10 +3201,8 @@@ window.add(frame); } XY_Top_Shown_Construct( window ); -#ifndef GARUX_GTK_WORKAROUND - /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ - g_object_set_data( G_OBJECT( window ), "glwidget", m_pXYWnd->GetWidget() ); -#endif + + WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pXYWnd->GetWidget() ); g_floating_windows.push_back( window ); } @@@ -3242,8 -3137,10 +3222,8 @@@ } XZ_Front_Shown_Construct( window ); -#ifndef GARUX_GTK_WORKAROUND - /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ - g_object_set_data( G_OBJECT( window ), "glwidget", m_pXZWnd->GetWidget() ); -#endif + + WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pXZWnd->GetWidget() ); g_floating_windows.push_back( window ); } @@@ -3263,8 -3160,10 +3243,8 @@@ } YZ_Side_Shown_Construct( window ); -#ifndef GARUX_GTK_WORKAROUND - /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ - g_object_set_data( G_OBJECT( window ), "glwidget", m_pYZWnd->GetWidget() ); -#endif + + WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pYZWnd->GetWidget() ); g_floating_windows.push_back( window ); } @@@ -3272,13 -3171,16 +3252,13 @@@ { auto frame = create_framed_widget( TextureBrowser_constructWindow( GroupDialog_getWindow() ) ); g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() ); -#ifndef GARUX_GTK_WORKAROUND - /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ - g_object_set_data( G_OBJECT( GroupDialog_getWindow() ), "glwidget", TextureBrowser_getGLWidget() ); -#endif + WORKAROUND_GOBJECT_SET_GLWIDGET( GroupDialog_getWindow(), TextureBrowser_getGLWidget() ); } GroupDialog_show(); } - else // 4 way + else if ( CurrentStyle() == eSplit ) { m_pCamWnd = NewCamWnd(); GlobalCamera_setCamWnd( *m_pCamWnd ); @@@ -3307,60 -3209,12 +3287,60 @@@ { auto frame = create_framed_widget( TextureBrowser_constructWindow( GroupDialog_getWindow() ) ); g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() ); -#ifndef GARUX_GTK_WORKAROUND - /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ - g_object_set_data( G_OBJECT( GroupDialog_getWindow() ), "glwidget", TextureBrowser_getGLWidget() ); -#endif + + WORKAROUND_GOBJECT_SET_GLWIDGET( window, TextureBrowser_getGLWidget() ); } } + else // single window + { + m_pCamWnd = NewCamWnd(); + GlobalCamera_setCamWnd( *m_pCamWnd ); + CamWnd_setParent( *m_pCamWnd, window ); + + ui::Widget camera = CamWnd_getWidget( *m_pCamWnd ); + + m_pYZWnd = new XYWnd(); + m_pYZWnd->SetViewType( YZ ); + + ui::Widget yz = m_pYZWnd->GetWidget(); + + m_pXYWnd = new XYWnd(); + m_pXYWnd->SetViewType( XY ); + + ui::Widget xy = m_pXYWnd->GetWidget(); + + m_pXZWnd = new XYWnd(); + m_pXZWnd->SetViewType( XZ ); + + ui::Widget xz = m_pXZWnd->GetWidget(); + + ui::Widget hsplit = ui::HPaned(ui::New); + vbox.pack_start( hsplit, TRUE, TRUE, 0 ); + hsplit.show(); + + ui::Widget split = create_split_views( camera, yz, xy, xz ); + + ui::Widget vsplit = ui::VPaned(ui::New); + vsplit.show(); + + // textures + ui::Widget texture_window = create_framed_widget( TextureBrowser_constructWindow( window ) ); + + // console + ui::Widget console_window = create_framed_widget( Console_constructWindow( window ) ); + + gtk_paned_add1( GTK_PANED( hsplit ), split ); + gtk_paned_add2( GTK_PANED( hsplit ), vsplit ); + + gtk_paned_add1( GTK_PANED( vsplit ), texture_window ); + gtk_paned_add2( GTK_PANED( vsplit ), console_window ); + + hsplit.connect( "size_allocate", G_CALLBACK( hpaned_allocate ), &g_single_hpaned ); + hsplit.connect( "notify::position", G_CALLBACK( paned_position ), &g_single_hpaned ); + + vsplit.connect( "size_allocate", G_CALLBACK( vpaned_allocate ), &g_single_vpaned ); + vsplit.connect( "notify::position", G_CALLBACK( paned_position ), &g_single_vpaned ); + } EntityList_constructWindow( window ); PreferencesDialog_constructWindow( window ); @@@ -3379,6 -3233,25 +3359,25 @@@ EverySecondTimer_enable(); + if ( g_layout_globals.nState & GDK_WINDOW_STATE_MAXIMIZED ) { + gtk_window_maximize( window ); + } + if ( g_layout_globals.nState & GDK_WINDOW_STATE_FULLSCREEN ) { + gtk_window_fullscreen( window ); + } + if ( !FloatingGroupDialog() ) { + gtk_paned_set_position( GTK_PANED( m_vSplit ), g_layout_globals.nXYHeight ); + + if ( CurrentStyle() == eRegular ) { + gtk_paned_set_position( GTK_PANED( m_hSplit ), g_layout_globals.nXYWidth ); + } + else + { + gtk_paned_set_position( GTK_PANED( m_hSplit ), g_layout_globals.nCamWidth ); + } + + gtk_paned_set_position( GTK_PANED( m_vSplit2 ), g_layout_globals.nCamHeight ); + } //GlobalShortcuts_reportUnregistered(); } @@@ -3397,7 -3270,9 +3396,9 @@@ void MainFrame::SaveWindowInfo() g_layout_globals.nCamHeight = gtk_paned_get_position( GTK_PANED( m_vSplit2 ) ); } + if( gdk_window_get_state( GTK_WIDGET( m_window )->window ) == 0 ){ - g_layout_globals.m_position = m_position_tracker.getPosition(); + g_layout_globals.m_position = m_position_tracker.getPosition(); + } g_layout_globals.nState = gdk_window_get_state( gtk_widget_get_window(m_window ) ); } @@@ -3448,7 -3323,7 +3449,7 @@@ void MainFrame::SetStatusText( CopiedSt } void Sys_Status( const char* status ){ - if ( g_pParentWnd != 0 ) { + if ( g_pParentWnd != nullptr ) { g_pParentWnd->SetStatusText( g_pParentWnd->m_command_status, status ); } } @@@ -3480,7 -3355,7 +3481,7 @@@ void MainFrame::SetGridStatus() } void GridStatus_onTextureLockEnabledChanged(){ - if ( g_pParentWnd != 0 ) { + if ( g_pParentWnd != nullptr ) { g_pParentWnd->SetGridStatus(); } } @@@ -3525,7 -3400,7 +3526,7 @@@ void GlobalGL_sharedContextDestroyed() void Layout_constructPreferences( PreferencesPage& page ){ { - const char* layouts[] = { "window1.png", "window2.png", "window3.png", "window4.png" }; + const char* layouts[] = { "window1.png", "window2.png", "window3.png", "window4.png", "window5.png" }; page.appendRadioIcons( "Window Layout", STRING_ARRAY_RANGE( layouts ), @@@ -3561,9 -3436,29 +3562,29 @@@ void Layout_registerPreferencesPage() PreferencesDialog_addInterfacePage( makeCallbackF(Layout_constructPage) ); } + void MainFrame_toggleFullscreen(){ + GtkWindow* wnd = MainFrame_getWindow(); + if( gdk_window_get_state( GTK_WIDGET( wnd )->window ) & GDK_WINDOW_STATE_FULLSCREEN ){ + //some portion of buttsex, because gtk_window_unfullscreen doesn't work correctly after calling some modal window + bool maximize = ( gdk_window_get_state( GTK_WIDGET( wnd )->window ) & GDK_WINDOW_STATE_MAXIMIZED ); + gtk_window_unfullscreen( wnd ); + if( maximize ){ + gtk_window_unmaximize( wnd ); + gtk_window_maximize( wnd ); + } + else{ + gtk_window_move( wnd, g_layout_globals.m_position.x, g_layout_globals.m_position.y ); + gtk_window_resize( wnd, g_layout_globals.m_position.w, g_layout_globals.m_position.h ); + } + } + else{ + gtk_window_fullscreen( wnd ); + } + } + - #include "preferencesystem.h" #include "stringio.h" +#include "transformpath/transformpath.h" void MainFrame_Construct(){ GlobalCommands_insert( "OpenManual", makeCallbackF(OpenHelpURL), Accelerator( GDK_KEY_F1 ) ); @@@ -3622,6 -3517,7 +3643,7 @@@ GlobalCommands_insert( "ArbitraryScale", makeCallbackF(DoScaleDlg) ); GlobalCommands_insert( "BuildMenuCustomize", makeCallbackF(DoBuildMenu) ); + GlobalCommands_insert( "Build_runRecentExecutedBuild", makeCallbackF(Build_runRecentExecutedBuild), Accelerator( GDK_F5 ) ); GlobalCommands_insert( "FindBrush", makeCallbackF(DoFind) ); @@@ -3644,7 -3540,6 +3666,7 @@@ GlobalCommands_insert( "ColorSchemeQER", makeCallbackF(ColorScheme_QER) ); GlobalCommands_insert( "ColorSchemeBlackAndGreen", makeCallbackF(ColorScheme_Black) ); GlobalCommands_insert( "ColorSchemeYdnar", makeCallbackF(ColorScheme_Ydnar) ); + GlobalCommands_insert("ColorSchemeAdwaitaDark", makeCallbackF(ColorScheme_AdwaitaDark)); GlobalCommands_insert( "ChooseTextureBackgroundColor", makeCallback( g_ColoursMenu.m_textureback ) ); GlobalCommands_insert( "ChooseGridBackgroundColor", makeCallback( g_ColoursMenu.m_xyback ) ); GlobalCommands_insert( "ChooseGridMajorColor", makeCallback( g_ColoursMenu.m_gridmajor ) ); @@@ -3660,6 -3555,8 +3682,8 @@@ GlobalCommands_insert( "ChooseClipperColor", makeCallback( g_ColoursMenu.m_clipper ) ); GlobalCommands_insert( "ChooseOrthoViewNameColor", makeCallback( g_ColoursMenu.m_viewname ) ); + GlobalCommands_insert( "Fullscreen", makeCallbackF( MainFrame_toggleFullscreen ), Accelerator( GDK_F11 ) ); + GlobalCommands_insert( "CSGSubtract", makeCallbackF(CSG_Subtract), Accelerator( 'U', (GdkModifierType)GDK_SHIFT_MASK ) ); GlobalCommands_insert( "CSGMerge", makeCallbackF(CSG_Merge), Accelerator( 'U', (GdkModifierType) GDK_CONTROL_MASK ) ); @@@ -3733,11 -3630,9 +3757,11 @@@ #error "unknown platform" #endif ; + StringOutputStream path( 256 ); path << DirectoryCleaned( g_pGameDescription->getRequiredKeyValue( ENGINEPATH_ATTRIBUTE ) ); - g_strEnginePath = path.c_str(); + + g_strEnginePath = transformPath( path.c_str() ).c_str(); GlobalPreferenceSystem().registerPreference( "EnginePath", make_property_string( g_strEnginePath ) ); } @@@ -3762,7 -3657,8 +3786,7 @@@ g_entityCount.setCountChangedCallback( makeCallbackF(QE_entityCountChanged) ); GlobalEntityCreator().setCounter( &g_entityCount ); - GLWidget_sharedContextCreated = GlobalGL_sharedContextCreated; - GLWidget_sharedContextDestroyed = GlobalGL_sharedContextDestroyed; + glwidget_set_shared_context_constructors( GlobalGL_sharedContextCreated, GlobalGL_sharedContextDestroyed); GlobalEntityClassManager().attach( g_WorldspawnColourEntityClassObserver ); } @@@ -3782,61 -3678,3 +3806,61 @@@ void GLWindow_Construct() void GLWindow_Destroy(){ } + +/* HACK: If ui::main is not called yet, +gtk_main_quit will not quit, so tell main +to not call ui::main. This happens when a +map is loaded from command line and require +a restart because of wrong format. +Delete this when the code to not have to +restart to load another format is merged. */ +extern bool g_dontStart; + +void Radiant_Restart(){ + // preferences are expected to be already saved in any way + // this is just to be sure and be future proof + Preferences_Save(); + + // this asks user for saving if map is modified + // user can chose to not save, it's ok + ConfirmModified( "Restart " RADIANT_NAME ); + + int status; + + char *argv[ 3 ]; + char exe_file[ 256 ]; + char map_file[ 256 ]; + bool with_map = false; + + strncpy( exe_file, g_strAppFilePath.c_str(), 256 ); + + if ( !Map_Unnamed( g_map ) ) { + strncpy( map_file, Map_Name( g_map ), 256 ); + with_map = true; + } + + argv[ 0 ] = exe_file; + argv[ 1 ] = with_map ? map_file : NULL; + argv[ 2 ] = NULL; + +#if GDEF_OS_WINDOWS + status = !_spawnvpe( P_NOWAIT, exe_file, argv, environ ); +#else + pid_t pid; + + status = posix_spawn( &pid, exe_file, NULL, NULL, argv, environ ); +#endif + + // quit if radiant successfully started + if ( status == 0 ) { + gtk_main_quit(); + /* HACK: If ui::main is not called yet, + gtk_main_quit will not quit, so tell main + to not call ui::main. This happens when a + map is loaded from command line and require + a restart because of wrong format. + Delete this when the code to not have to + restart to load another format is merged. */ + g_dontStart = true; + } +} diff --combined radiant/map.cpp index e1e6a727,5f22997c..91699dbc --- a/radiant/map.cpp +++ b/radiant/map.cpp @@@ -966,8 -966,6 +966,8 @@@ void Map_LoadFile( const char *filenam MRU_AddFile( filename ); g_strLastMapFolder = g_path_get_dirname( filename ); + bool switch_format = false; + { ScopeTimer timer( "map load" ); @@@ -994,7 -992,6 +994,7 @@@ if ( !format->wrongFormat ) { break; } + switch_format = !switch_format; } } @@@ -1015,8 -1012,6 +1015,8 @@@ Map_StartPosition(); g_currentMap = &g_map; + + Brush_switchFormat( switch_format ); } class Excluder @@@ -1583,55 -1578,54 +1583,55 @@@ tryDecompile const char *type = GlobalRadiant().getGameDescriptionKeyValue( "q3map2_type" ); int n = string_length( path_get_extension( filename ) ); if ( n && ( extension_equal( path_get_extension( filename ), "bsp" ) || extension_equal( path_get_extension( filename ), "map" ) ) ) { - StringBuffer output; - output.push_string( AppPath_get() ); - output.push_string( "q3map2." ); - output.push_string( RADIANT_EXECUTABLE ); - output.push_string( " -v -game " ); - output.push_string( ( type && *type ) ? type : "quake3" ); - output.push_string( " -fs_basepath \"" ); - output.push_string( EnginePath_get() ); - output.push_string( "\" -fs_homepath \"" ); - output.push_string( g_qeglobals.m_userEnginePath.c_str() ); - output.push_string( "\"" ); + std::string output; + output += AppPath_get(); + output += "q3map2"; + output += GDEF_OS_EXE_EXT; + + output += " -v -game "; + output += ( type && *type ) ? type : "quake3"; + output += " -fs_basepath \""; + output += EnginePath_get(); + output += "\" -fs_homepath \""; + output += g_qeglobals.m_userEnginePath.c_str(); + output += "\""; // extra pakpaths for ( int i = 0; i < g_pakPathCount; i++ ) { if ( g_strcmp0( g_strPakPath[i].c_str(), "") ) { - output.push_string( " -fs_pakpath \"" ); - output.push_string( g_strPakPath[i].c_str() ); - output.push_string( "\"" ); + output += " -fs_pakpath \""; + output += g_strPakPath[i].c_str(); + output += "\""; } } // extra switches if ( g_disableEnginePath ) { - output.push_string( " -fs_nobasepath " ); + output += " -fs_nobasepath "; } if ( g_disableHomePath ) { - output.push_string( " -fs_nohomepath " ); + output += " -fs_nohomepath "; } - output.push_string( " -fs_game " ); - output.push_string( gamename_get() ); - output.push_string( " -convert -format " ); - output.push_string( Brush::m_type == eBrushTypeQuake3BP ? "map_bp" : "map" ); + output += " -fs_game "; + output += gamename_get(); + output += " -convert -format "; + output += Brush::m_type == eBrushTypeQuake3BP ? "map_bp" : "map"; if ( extension_equal( path_get_extension( filename ), "map" ) ) { - output.push_string( " -readmap " ); + output += " -readmap "; } - output.push_string( " \"" ); - output.push_string( filename ); - output.push_string( "\"" ); + output += " \""; + output += filename; + output += "\""; // run Q_Exec( NULL, output.c_str(), NULL, false, true ); // rebuild filename as "filenamewithoutext_converted.map" - output.clear(); - output.push_range( filename, filename + string_length( filename ) - ( n + 1 ) ); - output.push_string( "_converted.map" ); + output = ""; + output.append( filename, string_length( filename ) - ( n + 1 ) ); + output += "_converted.map"; filename = output.c_str(); // open @@@ -1949,9 -1943,7 +1949,7 @@@ void SaveMap() } else if ( Map_Modified( g_map ) ) { Map_Save(); - #ifdef WIN32 MRU_AddFile( g_map.m_name.c_str() ); //add on saving, but not opening via cmd line: spoils the list - #endif } } diff --combined radiant/server.cpp index 879770c5,679e56bb..993472ae --- a/radiant/server.cpp +++ b/radiant/server.cpp @@@ -144,11 -144,9 +144,11 @@@ FunctionPointer findSymbol( const char #include +#if GDEF_OS_MACOS #ifndef RTLD_DEEPBIND #define RTLD_DEEPBIND 0 -#endif +#endif // RTLD_DEEPBIND +#endif // GDEF_OS_MACOS class DynamicLibrary { void *m_library; @@@ -156,7 -154,7 +156,7 @@@ public typedef int ( *FunctionPointer )(); DynamicLibrary( const char* filename ){ - m_library = dlopen( filename, RTLD_NOW ); + m_library = dlopen( filename, RTLD_NOW | (RTLD_DEEPBIND + 0) ); } ~DynamicLibrary(){ if ( !failed() ) { @@@ -178,9 -176,9 +178,9 @@@ FunctionPointer findSymbol( const char } }; -#else +#else // !GDEF_OS_POSIX #error "unsupported platform" -#endif +#endif // !GDEF_OS_POSIX class DynamicLibraryModule { diff --combined tools/quake3/q3map2/brush.c index db04b880,7769a0c5..d4808954 --- a/tools/quake3/q3map2/brush.c +++ b/tools/quake3/q3map2/brush.c @@@ -94,11 -94,13 +94,12 @@@ brush_t *AllocBrush( int numSides ) size_t c; /* allocate and clear */ - if ( numSides <= 0 ) { + /*if ( numSides <= 0 ) { Error( "AllocBrush called with numsides = %d", numSides ); } - c = (size_t)&( ( (brush_t*) 0 )->sides[ numSides ] ); + c = (size_t)&( ( (brush_t*) 0 )->sides[ numSides ] );*/ + c = sizeof(*bb) + (numSides > 6 ? sizeof(side_t)*(numSides - 6) : 0); - bb = safe_malloc( c ); - memset( bb, 0, c ); + bb = safe_malloc0( c ); if ( numthreads == 1 ) { numActiveBrushes++; } @@@ -828,7 -830,8 +829,7 @@@ void FilterStructuralBrushesIntoTree( e tree_t *AllocTree( void ){ tree_t *tree; - tree = safe_malloc( sizeof( *tree ) ); - memset( tree, 0, sizeof( *tree ) ); + tree = safe_malloc0( sizeof( *tree ) ); ClearBounds( tree->mins, tree->maxs ); return tree; @@@ -842,7 -845,8 +843,7 @@@ node_t *AllocNode( void ){ node_t *node; - node = safe_malloc( sizeof( *node ) ); - memset( node, 0, sizeof( *node ) ); + node = safe_malloc0( sizeof( *node ) ); return node; } diff --combined tools/quake3/q3map2/bspfile_abstract.c index 7286b039,a751f83a..f49d93ee --- a/tools/quake3/q3map2/bspfile_abstract.c +++ b/tools/quake3/q3map2/bspfile_abstract.c @@@ -94,7 -94,9 +94,7 @@@ void SetDrawVerts( int n ) numBSPDrawVerts = n; numBSPDrawVertsBuffer = numBSPDrawVerts; - bspDrawVerts = safe_malloc_info( sizeof( bspDrawVert_t ) * numBSPDrawVertsBuffer, "IncDrawVerts" ); - - memset( bspDrawVerts, 0, n * sizeof( bspDrawVert_t ) ); + bspDrawVerts = safe_malloc0_info( sizeof( bspDrawVert_t ) * numBSPDrawVertsBuffer, "IncDrawVerts" ); } int numBSPDrawSurfacesBuffer = 0; @@@ -105,7 -107,9 +105,7 @@@ void SetDrawSurfacesBuffer() numBSPDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS; - bspDrawSurfaces = safe_malloc_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" ); - - memset( bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof( bspDrawSurface_t ) ); + bspDrawSurfaces = safe_malloc0_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" ); } void SetDrawSurfaces( int n ){ @@@ -116,7 -120,9 +116,7 @@@ numBSPDrawSurfaces = n; numBSPDrawSurfacesBuffer = numBSPDrawSurfaces; - bspDrawSurfaces = safe_malloc_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" ); - - memset( bspDrawSurfaces, 0, n * sizeof( bspDrawSurface_t ) ); + bspDrawSurfaces = safe_malloc0_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" ); } void BSPFilesCleanup(){ @@@ -344,16 -350,14 +344,16 @@@ int CopyLump_Allocate( bspHeader_t *hea void AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length ){ bspLump_t *lump; - /* add lump to bsp file header */ lump = &header->lumps[ lumpNum ]; lump->offset = LittleLong( ftell( file ) ); lump->length = LittleLong( length ); /* write lump to file */ - SafeWrite( file, data, ( length + 3 ) & ~3 ); + SafeWrite( file, data, length ); + + /* write padding zeros */ + SafeWrite( file, (const byte[3]){ 0, 0, 0 }, ( ( length + 3 ) & ~3 ) - length ); } @@@ -531,7 -535,8 +531,7 @@@ epair_t *ParseEPair( void ) /* allocate and clear new epair */ - e = safe_malloc( sizeof( epair_t ) ); - memset( e, 0, sizeof( epair_t ) ); + e = safe_malloc0( sizeof( epair_t ) ); /* handle key */ if ( strlen( token ) >= ( MAX_KEY - 1 ) ) { @@@ -627,10 -632,9 +627,9 @@@ void InjectCommandLine( char **argv, in char *sentinel = newCommandLine + sizeof( newCommandLine ) - 1; int i; - if (nocmdline) - { - return; - } + if ( nocmdline ){ + return; + } previousCommandLine = ValueForKey( &entities[0], "_q3map2_cmdline" ); if ( previousCommandLine && *previousCommandLine ) { inpos = previousCommandLine; @@@ -646,9 -650,6 +645,9 @@@ for ( i = beginArgs; i < endArgs; ++i ) { + if ( argv[i] == NULL ) { + continue; + } if ( outpos != sentinel && i != beginArgs ) { *outpos++ = ' '; } diff --combined tools/quake3/q3map2/main.c index b0e6fa19,139a242a..3b87ee9f --- a/tools/quake3/q3map2/main.c +++ b/tools/quake3/q3map2/main.c @@@ -1007,8 -1007,14 +1007,14 @@@ skipEXfile Sys_Printf( "++%s\n", temp ); continue; } - Sys_Printf( " !FAIL! %s\n", pk3Shaders + i*65 ); - if ( i != pk3ShadersN - 1 ) packFAIL = qtrue; //levelshot typically + + if ( i == pk3ShadersN - 1 ){ //levelshot typically + Sys_Printf( " ~fail %s\n", pk3Shaders + i*65 ); + } + else{ + Sys_Printf( " !FAIL! %s\n", pk3Shaders + i*65 ); + packFAIL = qtrue; + } } } @@@ -1067,7 -1073,7 +1073,7 @@@ Sys_Printf( "++%s\n", temp ); } else{ - Sys_Printf( " !FAIL! %s\n", temp ); + Sys_Printf( " ~fail %s\n", temp ); } sprintf( temp, "scripts/%s.arena", nameOFmap ); @@@ -1075,7 -1081,7 +1081,7 @@@ Sys_Printf( "++%s\n", temp ); } else{ - Sys_Printf( " !FAIL! %s\n", temp ); + Sys_Printf( " ~fail %s\n", temp ); } sprintf( temp, "scripts/%s.defi", nameOFmap ); @@@ -1083,7 -1089,7 +1089,7 @@@ Sys_Printf( "++%s\n", temp ); } else{ - Sys_Printf( " !FAIL! %s\n", temp ); + Sys_Printf( " ~fail %s\n", temp ); } if ( !packFAIL ){ @@@ -2097,16 -2103,14 +2103,16 @@@ int main( int argc, char **argv ) /* -help */ if ( !strcmp( argv[ i ], "-h" ) || !strcmp( argv[ i ], "--help" ) || !strcmp( argv[ i ], "-help" ) ) { - HelpMain(argv[i+1]); + HelpMain( ( i + 1 < argc ) ? argv[ i + 1 ] : NULL ); return 0; } /* -connect */ if ( !strcmp( argv[ i ], "-connect" ) ) { - argv[ i ] = NULL; - i++; + if ( ++i >= argc || !argv[ i ] ) { + Error( "Out of arguments: No address specified after %s", argv[ i - 1 ] ); + } + argv[ i - 1 ] = NULL; Broadcast_Setup( argv[ i ] ); argv[ i ] = NULL; } @@@ -2133,10 -2137,8 +2139,10 @@@ /* patch subdivisions */ else if ( !strcmp( argv[ i ], "-subdivisions" ) ) { - argv[ i ] = NULL; - i++; + if ( ++i >= argc || !argv[ i ] ) { + Error( "Out of arguments: No value specified after %s", argv[ i - 1 ] ); + } + argv[ i - 1 ] = NULL; patchSubdivisions = atoi( argv[ i ] ); argv[ i ] = NULL; if ( patchSubdivisions <= 0 ) { @@@ -2146,10 -2148,8 +2152,10 @@@ /* threads */ else if ( !strcmp( argv[ i ], "-threads" ) ) { - argv[ i ] = NULL; - i++; + if ( ++i >= argc || !argv[ i ] ) { + Error( "Out of arguments: No value specified after %s", argv[ i - 1 ] ); + } + argv[ i - 1 ] = NULL; numthreads = atoi( argv[ i ] ); argv[ i ] = NULL; } @@@ -2186,7 -2186,7 +2192,7 @@@ Sys_Printf( "Q3Map - v1.0r (c) 1999 Id Software Inc.\n" ); Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" ); - Sys_Printf( "NetRadiant - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" ); + Sys_Printf( RADIANT_NAME " - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" ); Sys_Printf( "%s\n", Q3MAP_MOTD ); Sys_Printf( "%s\n", argv[0] ); @@@ -2284,9 -2284,6 +2290,9 @@@ /* ydnar: otherwise create a bsp */ else{ + /* used to write Smokin'Guns like tex file */ + compile_map = qtrue; + r = BSPMain( argc, argv ); } diff --combined tools/quake3/q3map2/q3map2.h index 1a7dd34e,f6296f1b..720dec29 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@@ -50,7 -50,11 +50,7 @@@ ------------------------------------------------------------------------------- */ /* platform-specific */ -#if GDEF_OS_LINUX || GDEF_OS_MACOS - #define Q_UNIX -#endif - -#ifdef Q_UNIX +#if GDEF_OS_POSIX #include #include #include @@@ -62,6 -66,8 +62,6 @@@ /* general */ -#include "version.h" /* ttimo: might want to guard that if built outside of the GtkRadiant tree */ - #include "cmdlib.h" #include "mathlib.h" #include "md5lib.h" @@@ -89,6 -95,14 +89,6 @@@ ------------------------------------------------------------------------------- */ -#define MAC_STATIC_HACK 0 -#if GDEF_OS_MACOS && MAC_STATIC_HACK - #define MAC_STATIC static -#else - #define MAC_STATIC -#endif - -#if 1 #if GDEF_OS_WINDOWS #define Q_stricmp stricmp #define Q_strncasecmp strnicmp @@@ -96,14 -110,6 +96,14 @@@ #define Q_stricmp strcasecmp #define Q_strncasecmp strncasecmp #endif + +// hack to declare and define in the same file +#ifdef MAIN_C + #define Q_EXTERN + #define Q_ASSIGN( a ) = a +#else + #define Q_EXTERN extern + #define Q_ASSIGN( a ) #endif /* macro version */ @@@ -126,10 -132,10 +126,10 @@@ /* general */ #define MAX_QPATH 64 -#define MAX_IMAGES 512 +#define MAX_IMAGES 2048 #define DEFAULT_IMAGE "*default" -#define MAX_MODELS 512 +#define MAX_MODELS 2048 #define DEF_BACKSPLASH_FRACTION 0.05f /* 5% backsplash by default */ #define DEF_BACKSPLASH_DISTANCE 23 @@@ -177,21 -183,6 +177,21 @@@ #define C_DETAIL 0x08000000 /* THIS MUST BE THE SAME AS IN RADIANT! */ +/* new tex surface flags, like Smokin'Guns */ +#define TEX_SURF_METAL 0x00001000 +#define TEX_SURF_WOOD 0x00080000 +#define TEX_SURF_CLOTH 0x00100000 +#define TEX_SURF_DIRT 0x00200000 +#define TEX_SURF_GLASS 0x00400000 +#define TEX_SURF_PLANT 0x00800000 +#define TEX_SURF_SAND 0x01000000 +#define TEX_SURF_SNOW 0x02000000 +#define TEX_SURF_STONE 0x04000000 +#define TEX_SURF_WATER 0x08000000 +#define TEX_SURF_GRASS 0x10000000 +#define TEX_SURF_BREAKABLE 0x20000000 + + /* shadow flags */ #define WORLDSPAWN_CAST_SHADOWS 1 #define WORLDSPAWN_RECV_SHADOWS 1 @@@ -213,7 -204,7 +213,7 @@@ #define HINT_PRIORITY 1000 /* ydnar: force hint splits first and antiportal/areaportal splits last */ #define ANTIPORTAL_PRIORITY -1000 #define AREAPORTAL_PRIORITY -1000 - #define DETAIL_PRIORITY -3000 + #define DETAIL_PRIORITY -3000 #define PSIDE_FRONT 1 #define PSIDE_BACK 2 @@@ -286,7 -277,7 +286,7 @@@ #define RAD_LUXEL_SIZE 3 #define SUPER_LUXEL_SIZE 4 #define SUPER_FLAG_SIZE 4 - #define FLAG_FORCE_SUBSAMPLING 1 + #define FLAG_FORCE_SUBSAMPLING 1 #define FLAG_ALREADY_SUBSAMPLED 2 #define SUPER_ORIGIN_SIZE 3 #define SUPER_NORMAL_SIZE 4 @@@ -560,13 -551,6 +560,13 @@@ typedef enu } miniMapMode_t; +typedef enum +{ + MINIMAP_SIDECAR_NONE, + MINIMAP_SIDECAR_UNVANQUISHED +} +miniMapSidecarFormat_t; + typedef struct game_s { char *arg; /* -game matches this */ @@@ -577,7 -561,6 +577,7 @@@ int maxLMSurfaceVerts; /* default maximum meta surface verts */ int maxSurfaceVerts; /* default maximum surface verts */ int maxSurfaceIndexes; /* default maximum surface indexes (tris * 3) */ + qboolean texFile; /* enable per shader prefix surface flags and .tex file */ qboolean emitFlares; /* when true, emit flare surfaces */ char *flareShader; /* default flare shader (MUST BE SET) */ qboolean wolfLight; /* when true, lights work like wolf q3map */ @@@ -603,7 -586,6 +603,7 @@@ qboolean miniMapKeepAspect; /* minimap keep aspect ratio by letterboxing */ miniMapMode_t miniMapMode; /* minimap mode */ char *miniMapNameFormat; /* minimap name format */ + miniMapSidecarFormat_t miniMapSidecarFormat; /* minimap sidecar format */ char *bspIdent; /* 4-letter bsp file prefix */ int bspVersion; /* bsp version to use */ qboolean lumpSwap; /* cod-style len/ofs order */ @@@ -848,7 -830,7 +848,7 @@@ typedef struct face_ struct face_s *next; int planenum; int priority; - //qboolean checked; + //qboolean checked; int compileFlags; winding_t *w; } @@@ -1024,7 -1006,7 +1024,7 @@@ typedef enu } surfaceType_t; -char *surfaceTypes[ NUM_SURFACE_TYPES ] +Q_EXTERN char *surfaceTypes[ NUM_SURFACE_TYPES ] #ifndef MAIN_C ; #else @@@ -1490,7 -1472,7 +1490,7 @@@ typedef struct rawLightmap_ float *bspLuxels[ MAX_LIGHTMAPS ]; float *radLuxels[ MAX_LIGHTMAPS ]; float *superLuxels[ MAX_LIGHTMAPS ]; - unsigned char *superFlags; + unsigned char *superFlags; float *superOrigins; float *superNormals; int *superClusters; @@@ -1838,7 -1820,6 +1838,7 @@@ void RadFreeLigh /* light_ydnar.c */ void ColorToBytes( const float *color, byte *colorBytes, float scale ); +void ColorToBytesNonZero( const float *color, byte *colorBytes, float scale ); void SmoothNormals( void ); void MapRawLightmap( int num ); @@@ -1879,7 -1860,7 +1879,7 @@@ int ImportLight void SetupSurfaceLightmaps( void ); void StitchSurfaceLightmaps( void ); -void StoreSurfaceLightmaps( qboolean fastAllocate ); +void StoreSurfaceLightmaps( qboolean fastAllocate, qboolean storeForReal ); /* exportents.c */ @@@ -1936,11 -1917,6 +1936,11 @@@ void PartialLoad void WriteBSPFile( const char *filename ); void PrintBSPFileSizes( void ); +void WriteTexFile( char *name ); +void LoadSurfaceFlags( char *filename ); +int GetSurfaceParm( const char *tex ); +void RestoreSurfaceFlags( char *filename ); + epair_t *ParseEPair( void ); void ParseEntities( void ); void UnparseEntities( void ); @@@ -1976,6 -1952,14 +1976,6 @@@ void WriteRBSPFi ------------------------------------------------------------------------------- */ -#ifdef MAIN_C - #define Q_EXTERN - #define Q_ASSIGN( a ) = a -#else - #define Q_EXTERN extern - #define Q_ASSIGN( a ) -#endif - /* game support */ Q_EXTERN game_t games[] #ifndef MAIN_C @@@ -1984,26 -1968,16 +1984,26 @@@ = { #include "game_quake3.h" + , + #include "game_nexuiz.h" /* must be after game_quake3.h as they share defines! */ + , + #include "game_oa.h" /* must be after game_quake3.h as they share defines! */ + , + #include "game_q3rally.h" /* must be after game_quake3.h as they share defines! */ , #include "game_quakelive.h" /* must be after game_quake3.h as they share defines! */ , - #include "game_nexuiz.h" /* must be after game_quake3.h as they share defines! */ + #include "game_reaction.h" /* must be after game_quake3.h */ , - #include "game_xonotic.h" /* must be after game_quake3.h as they share defines! */ + #include "game_smokinguns.h" /* must be after game_quake3.h */ , #include "game_tremulous.h" /*LinuxManMikeC: must be after game_quake3.h, depends on #define's set in it */ , #include "game_unvanquished.h" /* must be after game_tremulous.h as they share defines! */ + , + #include "game_wop.h" /* must be after game_quake3.h as they share defines! */ + , + #include "game_xonotic.h" /* must be after game_quake3.h as they share defines! */ , #include "game_tenebrae.h" , @@@ -2023,13 -1997,11 +2023,13 @@@ , #include "game_qfusion.h" /* qfusion game */ , - #include "game_reaction.h" /* must be after game_quake3.h */ + #include "game_warsow.h" /* must be after game_qfusion.h as they share defines! */ + , + #include "game_warfork.h" /* must be after game_qfusion.h as they share defines! */ , - #include "game_darkplaces.h" /* vortex: darkplaces q1 engine */ + #include "game_darkplaces.h" /* darkplaces q1 engine */ , - #include "game_dq.h" /* vortex: deluxe quake game ( darkplaces q1 engine) */ + #include "game_dq.h" /* deluxe quake game ( darkplaces q1 engine) */ , #include "game_prophecy.h" /* vortex: prophecy game ( darkplaces q1 engine) */ , @@@ -2060,11 -2032,11 +2060,10 @@@ Q_EXTERN qboolean warnImage Q_ASSIGN( q /* ydnar: sinusoid samples */ Q_EXTERN float jitters[ MAX_JITTERS ]; -/* can't code */ +/*can't code*/ Q_EXTERN qboolean doingBSP Q_ASSIGN( qfalse ); /* commandline arguments */ - Q_EXTERN qboolean nocmdline Q_ASSIGN( qfalse ); -Q_EXTERN qboolean verbose; Q_EXTERN qboolean verboseEntities Q_ASSIGN( qfalse ); Q_EXTERN qboolean force Q_ASSIGN( qfalse ); Q_EXTERN qboolean infoMode Q_ASSIGN( qfalse ); @@@ -2083,9 -2055,10 +2082,10 @@@ Q_EXTERN qboolean nofog Q_ASSIGN( qfals Q_EXTERN qboolean noHint Q_ASSIGN( qfalse ); /* ydnar */ Q_EXTERN qboolean renameModelShaders Q_ASSIGN( qfalse ); /* ydnar */ Q_EXTERN qboolean skyFixHack Q_ASSIGN( qfalse ); /* ydnar */ - Q_EXTERN qboolean bspAlternateSplitWeights Q_ASSIGN( qfalse ); /* 27 */ - Q_EXTERN qboolean deepBSP Q_ASSIGN( qfalse ); /* div0 */ + Q_EXTERN qboolean bspAlternateSplitWeights Q_ASSIGN( qfalse ); /* 27 */ + Q_EXTERN qboolean deepBSP Q_ASSIGN( qfalse ); /* div0 */ Q_EXTERN qboolean maxAreaFaceSurface Q_ASSIGN( qfalse ); /* divVerent */ + Q_EXTERN qboolean nocmdline Q_ASSIGN( qfalse ); Q_EXTERN int patchSubdivisions Q_ASSIGN( 8 ); /* ydnar: -patchmeta subdivisions */ @@@ -2581,7 -2554,7 +2581,7 @@@ Q_EXTERN int allocatedBSPBrushSides Q_A Q_EXTERN bspBrushSide_t* bspBrushSides Q_ASSIGN( NULL ); Q_EXTERN int numBSPLightBytes Q_ASSIGN( 0 ); - Q_EXTERN byte *bspLightBytes Q_ASSIGN( NULL ); + Q_EXTERN byte *bspLightBytes Q_ASSIGN( NULL ); //% Q_EXTERN int numBSPGridPoints Q_ASSIGN( 0 ); //% Q_EXTERN byte *bspGridPoints Q_ASSIGN( NULL ); @@@ -2593,11 -2566,11 +2593,11 @@@ Q_EXTERN int numBSPVisBytes Q_ASSIGN( Q_EXTERN byte bspVisBytes[ MAX_MAP_VISIBILITY ]; Q_EXTERN int numBSPDrawVerts Q_ASSIGN( 0 ); - Q_EXTERN bspDrawVert_t *bspDrawVerts Q_ASSIGN( NULL ); + Q_EXTERN bspDrawVert_t *bspDrawVerts Q_ASSIGN( NULL ); Q_EXTERN int numBSPDrawIndexes Q_ASSIGN( 0 ); Q_EXTERN int allocatedBSPDrawIndexes Q_ASSIGN( 0 ); - Q_EXTERN int *bspDrawIndexes Q_ASSIGN( NULL ); + Q_EXTERN int *bspDrawIndexes Q_ASSIGN( NULL ); Q_EXTERN int numBSPDrawSurfaces Q_ASSIGN( 0 ); Q_EXTERN bspDrawSurface_t *bspDrawSurfaces Q_ASSIGN( NULL ); @@@ -2608,46 -2581,28 +2608,46 @@@ Q_EXTERN bspFog_t bspFogs[ MAX_MAP_FOG Q_EXTERN int numBSPAds Q_ASSIGN( 0 ); Q_EXTERN bspAdvertisement_t bspAds[ MAX_MAP_ADVERTISEMENTS ]; -#define AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def ) \ +// Used for tex file support, Smokin'Guns globals +Q_EXTERN qboolean compile_map; + +#define _AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def, fillWithZeros ) \ do \ { \ + int prevAllocated = allocated; \ if ( reqitem >= allocated ) \ { \ if ( allocated == 0 ) { \ - allocated = def; } \ + allocated = def; \ + } \ while ( reqitem >= allocated && allocated ) \ + { \ allocated *= 2; \ + } \ if ( !allocated || allocated > 2147483647 / (int)sizeof( *ptr ) ) \ { \ - Error( #ptr " over 2 GB" ); \ + Error( # ptr " over 2 GB" ); \ } \ ptr = realloc( ptr, sizeof( *ptr ) * allocated ); \ if ( !ptr ) { \ - Error( # ptr " out of memory" ); } \ + Error( #ptr " out of memory" ); \ + } \ + if ( fillWithZeros ) \ + { \ + memset( ptr + ( sizeof( *ptr ) * prevAllocated ), 0 , sizeof( *ptr ) * ( allocated - prevAllocated ) ); \ + } \ } \ } \ while ( 0 ) +#define AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def ) _AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def, qfalse ) + +#define AUTOEXPAND_BY_REALLOC0( ptr, reqitem, allocated, def ) _AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def, qtrue ) + - #define AUTOEXPAND_BY_REALLOC_BSP( suffix, def ) AUTOEXPAND_BY_REALLOC( bsp##suffix, numBSP##suffix, allocatedBSP##suffix, def ) + #define AUTOEXPAND_BY_REALLOC_BSP( suffix, def ) AUTOEXPAND_BY_REALLOC( bsp ## suffix, numBSP ## suffix, allocatedBSP ## suffix, def ) +#define AUTOEXPAND_BY_REALLOC0_BSP( suffix, def ) AUTOEXPAND_BY_REALLOC0( bsp##suffix, numBSP##suffix, allocatedBSP##suffix, def ) + #define Image_LinearFloatFromsRGBFloat( c ) ( ( ( c ) <= 0.04045f ) ? ( c ) * ( 1.0f / 12.92f ) : (float)pow( ( ( c ) + 0.055f ) * ( 1.0f / 1.055f ), 2.4f ) ) #define Image_sRGBFloatFromLinearFloat( c ) ( ( ( c ) < 0.0031308f ) ? ( c ) * 12.92f : 1.055f * (float)pow( ( c ), 1.0f / 2.4f ) - 0.055f )