* "BrushAlwaysCaulk" option is saveable for brush types other than q3

* brush format is preference for [maptypes, brushtypes]: [mapq1, quake], [mapq2, quake2], [mapq3, quake3]:
		preferences->Brush->Brush type: Axial projection, Brush primitives, Valve 220
	* autodetect brush type on map opening
	* brush face surfaceflags are optional on loading for flexibility
	* 'Snap planes to integer grid' option is always off by default
This commit is contained in:
Garux 2017-09-16 16:37:39 +03:00
parent 4e4b8e1407
commit 0b3f42ffbc
12 changed files with 309 additions and 131 deletions

View File

@ -27,6 +27,20 @@
#include "generic/vector.h" #include "generic/vector.h"
#include "itexdef.h" #include "itexdef.h"
enum EBrushType
{
eBrushTypeUNKNOWN = 0,
eBrushTypeQuake,
eBrushTypeQuake2,
eBrushTypeQuake3,
eBrushTypeQuake3BP,
eBrushTypeQuake3Valve220,
eBrushTypeDoom3,
eBrushTypeQuake4,
eBrushTypeValve220,
};
namespace scene namespace scene
{ {
class Node; class Node;
@ -103,7 +117,7 @@ public:
INTEGER_CONSTANT( Version, 1 ); INTEGER_CONSTANT( Version, 1 );
STRING_CONSTANT( Name, "brush" ); STRING_CONSTANT( Name, "brush" );
virtual scene::Node& createBrush() = 0; virtual scene::Node& createBrush() = 0;
virtual bool useAlternativeTextureProjection() const = 0; virtual EBrushType getCurrentFormat() const = 0;
virtual void Brush_forEachFace( scene::Node& brush, const BrushFaceDataCallback& callback ) = 0; virtual void Brush_forEachFace( scene::Node& brush, const BrushFaceDataCallback& callback ) = 0;
virtual bool Brush_addFace( scene::Node& brush, const _QERFaceData& faceData ) = 0; virtual bool Brush_addFace( scene::Node& brush, const _QERFaceData& faceData ) = 0;
}; };

View File

@ -46,6 +46,7 @@ virtual void exportTokens( TokenWriter& writer ) const = 0;
}; };
#include "iscenegraph.h" #include "iscenegraph.h"
#include "ibrush.h"
class EntityCreator; class EntityCreator;
@ -61,7 +62,7 @@ class MapFormat
public: public:
INTEGER_CONSTANT( Version, 2 ); INTEGER_CONSTANT( Version, 2 );
STRING_CONSTANT( Name, "map" ); STRING_CONSTANT( Name, "map" );
mutable bool wrongFormat; mutable EBrushType m_detectedFormat;
/// \brief Read a map graph into \p root from \p outputStream, using \p entityTable to create entities. /// \brief Read a map graph into \p root from \p outputStream, using \p entityTable to create entities.
virtual void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const = 0; virtual void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const = 0;

View File

@ -39,6 +39,7 @@ virtual const char* getToken() = 0;
virtual void ungetToken() = 0; virtual void ungetToken() = 0;
virtual std::size_t getLine() const = 0; virtual std::size_t getLine() const = 0;
virtual std::size_t getColumn() const = 0; virtual std::size_t getColumn() const = 0;
virtual bool bufferContains( const char* str ) = 0;
}; };
class TextInputStream; class TextInputStream;

View File

@ -41,7 +41,7 @@ typedef bool ( ScriptTokeniser::*Tokenise )( char c );
Tokenise m_stack[3]; Tokenise m_stack[3];
Tokenise* m_state; Tokenise* m_state;
SingleCharacterInputStream<TextInputStream> m_istream; SingleCharacterInputStreamDoubleBuffered<TextInputStream> m_istream;
std::size_t m_scriptline; std::size_t m_scriptline;
std::size_t m_scriptcolumn; std::size_t m_scriptcolumn;
@ -329,6 +329,9 @@ std::size_t getLine() const {
std::size_t getColumn() const { std::size_t getColumn() const {
return m_scriptcolumn; return m_scriptcolumn;
} }
bool bufferContains( const char* str ){
return m_istream.bufferContains( str );
}
}; };

View File

@ -355,6 +355,47 @@ bool readChar( char& c ){
} }
}; };
/// doublefuffered to be able to read forward for map format (valve220) detection
template<typename TextInputStreamType, int SIZE = 1024>
class SingleCharacterInputStreamDoubleBuffered
{
TextInputStreamType& m_inputStream;
char m_bu[SIZE];
char* m_buffer;
char* m_cur;
char* m_end;
char m_bu2[SIZE];
char* m_buffer2;
char* m_end2;
bool fillBuffer(){
std::swap( m_buffer, m_buffer2 );
m_cur = m_buffer;
m_end = m_end2;
m_end2 = m_buffer2 + m_inputStream.read( m_buffer2, SIZE );
return m_cur != m_end;
}
public:
SingleCharacterInputStreamDoubleBuffered( TextInputStreamType& inputStream ) : m_inputStream( inputStream ), m_buffer( m_bu ), m_cur( m_buffer ), m_end( m_buffer ), m_buffer2( m_bu2 ){
m_end2 = m_buffer2 + m_inputStream.read( m_buffer2, SIZE );
}
bool readChar( char& c ){
if ( m_cur == m_end && !fillBuffer() ) {
return false;
}
c = *m_cur++;
return true;
}
bool bufferContains( const char* str ) const{
return ( std::search( m_cur, m_end, str, str + strlen( str ) ) != m_end ) ||
( std::search( m_buffer2, m_end2, str, str + strlen( str ) ) != m_end2 );
}
};
/// \brief A wrapper for a TextOutputStream, optimised for writing a single character at a time. /// \brief A wrapper for a TextOutputStream, optimised for writing a single character at a time.
class SingleCharacterOutputStream : public TextOutputStream class SingleCharacterOutputStream : public TextOutputStream
{ {

View File

@ -228,7 +228,6 @@ MapDependencies() :
class MapQ3API : public TypeSystemRef, public MapFormat, public PrimitiveParser class MapQ3API : public TypeSystemRef, public MapFormat, public PrimitiveParser
{ {
mutable bool detectedFormat;
public: public:
typedef MapFormat Type; typedef MapFormat Type;
STRING_CONSTANT( Name, "mapq3" ); STRING_CONSTANT( Name, "mapq3" );
@ -248,31 +247,38 @@ scene::Node& parsePrimitive( Tokeniser& tokeniser ) const {
if ( string_equal( primitive, "patchDef2" ) ) { if ( string_equal( primitive, "patchDef2" ) ) {
return GlobalPatchModule::getTable().createPatch(); return GlobalPatchModule::getTable().createPatch();
} }
if ( GlobalBrushModule::getTable().useAlternativeTextureProjection() ) { if( !m_detectedFormat ){
if ( string_equal( primitive, "brushDef" ) ) { if ( string_equal( primitive, "brushDef" ) ) {
detectedFormat = true; m_detectedFormat = eBrushTypeQuake3BP;
return GlobalBrushModule::getTable().createBrush(); globalErrorStream() << "m_detectedFormat = eBrushTypeQuake3BP\n";
} }
else if ( !detectedFormat && string_equal( primitive, "(" ) ) { else if ( string_equal( primitive, "(" ) && tokeniser.bufferContains( " [ " ) && tokeniser.bufferContains( " ] " ) ) {
detectedFormat = true; m_detectedFormat = eBrushTypeQuake3Valve220;
wrongFormat = true; globalErrorStream() << "m_detectedFormat = eBrushTypeQuake3Valve220\n";
Tokeniser_unexpectedError( tokeniser, primitive, "#quake3-switch-to-texdef" ); }
else if ( string_equal( primitive, "(" ) ) {
m_detectedFormat = eBrushTypeQuake3;
globalErrorStream() << "m_detectedFormat = eBrushTypeQuake3\n";
}
else{
globalErrorStream() << "Format is not detected\n";
}
if( m_detectedFormat != GlobalBrushModule::getTable().getCurrentFormat() ){
Tokeniser_unexpectedError( tokeniser, primitive, "#different-brush-format" );
return g_nullNode; return g_nullNode;
} }
} }
else
switch ( GlobalBrushModule::getTable().getCurrentFormat() )
{ {
if ( string_equal( primitive, "(" ) ) { case eBrushTypeQuake3:
detectedFormat = true; case eBrushTypeQuake3Valve220:
tokeniser.ungetToken(); // ( tokeniser.ungetToken(); // (
case eBrushTypeQuake3BP:
return GlobalBrushModule::getTable().createBrush(); return GlobalBrushModule::getTable().createBrush();
} default:
else if ( !detectedFormat && string_equal( primitive, "brushDef" ) ) { break;
detectedFormat = true;
wrongFormat = true;
Tokeniser_unexpectedError( tokeniser, primitive, "#quake3-switch-to-brush-primitives" );
return g_nullNode;
}
} }
} }
@ -281,8 +287,6 @@ scene::Node& parsePrimitive( Tokeniser& tokeniser ) const {
} }
void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const {
detectedFormat = false;
wrongFormat = false;
Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream );
Map_Read( root, tokeniser, entityTable, *this ); Map_Read( root, tokeniser, entityTable, *this );
tokeniser.release(); tokeniser.release();
@ -316,9 +320,38 @@ MapFormat* getTable(){
scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { scene::Node& parsePrimitive( Tokeniser& tokeniser ) const {
const char* primitive = tokeniser.getToken(); const char* primitive = tokeniser.getToken();
if ( primitive != 0 ) { if ( primitive != 0 ) {
if ( string_equal( primitive, "(" ) ) { if( !m_detectedFormat ){
if ( string_equal( primitive, "brushDef" ) ) {
m_detectedFormat = eBrushTypeQuake3BP;
globalErrorStream() << "m_detectedFormat = eBrushTypeQuake3BP\n";
}
else if ( string_equal( primitive, "(" ) && tokeniser.bufferContains( " [ " ) && tokeniser.bufferContains( " ] " ) ) {
m_detectedFormat = eBrushTypeValve220;
globalErrorStream() << "m_detectedFormat = eBrushTypeValve220\n";
}
else if ( string_equal( primitive, "(" ) ) {
m_detectedFormat = eBrushTypeQuake;
globalErrorStream() << "m_detectedFormat = eBrushTypeQuake\n";
}
else{
globalErrorStream() << "Format is not detected\n";
}
if( m_detectedFormat != GlobalBrushModule::getTable().getCurrentFormat() ){
Tokeniser_unexpectedError( tokeniser, primitive, "#different-brush-format" );
return g_nullNode;
}
}
switch ( GlobalBrushModule::getTable().getCurrentFormat() )
{
case eBrushTypeQuake:
case eBrushTypeValve220:
tokeniser.ungetToken(); // ( tokeniser.ungetToken(); // (
case eBrushTypeQuake3BP:
return GlobalBrushModule::getTable().createBrush(); return GlobalBrushModule::getTable().createBrush();
default:
break;
} }
} }
@ -401,9 +434,38 @@ MapFormat* getTable(){
scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { scene::Node& parsePrimitive( Tokeniser& tokeniser ) const {
const char* primitive = tokeniser.getToken(); const char* primitive = tokeniser.getToken();
if ( primitive != 0 ) { if ( primitive != 0 ) {
if ( string_equal( primitive, "(" ) ) { if( !m_detectedFormat ){
if ( string_equal( primitive, "brushDef" ) ) {
m_detectedFormat = eBrushTypeQuake3BP;
globalErrorStream() << "m_detectedFormat = eBrushTypeQuake3BP\n";
}
else if ( string_equal( primitive, "(" ) && tokeniser.bufferContains( " [ " ) && tokeniser.bufferContains( " ] " ) ) {
m_detectedFormat = eBrushTypeQuake3Valve220;
globalErrorStream() << "m_detectedFormat = eBrushTypeQuake3Valve220\n";
}
else if ( string_equal( primitive, "(" ) ) {
m_detectedFormat = eBrushTypeQuake2;
globalErrorStream() << "m_detectedFormat = eBrushTypeQuake2\n";
}
else{
globalErrorStream() << "Format is not detected\n";
}
if( m_detectedFormat != GlobalBrushModule::getTable().getCurrentFormat() ){
Tokeniser_unexpectedError( tokeniser, primitive, "#different-brush-format" );
return g_nullNode;
}
}
switch ( GlobalBrushModule::getTable().getCurrentFormat() )
{
case eBrushTypeQuake2:
case eBrushTypeQuake3Valve220:
tokeniser.ungetToken(); // ( tokeniser.ungetToken(); // (
case eBrushTypeQuake3BP:
return GlobalBrushModule::getTable().createBrush(); return GlobalBrushModule::getTable().createBrush();
default:
break;
} }
} }

View File

@ -68,17 +68,6 @@
const unsigned int BRUSH_DETAIL_FLAG = 27; const unsigned int BRUSH_DETAIL_FLAG = 27;
const unsigned int BRUSH_DETAIL_MASK = ( 1 << BRUSH_DETAIL_FLAG ); const unsigned int BRUSH_DETAIL_MASK = ( 1 << BRUSH_DETAIL_FLAG );
enum EBrushType
{
eBrushTypeQuake,
eBrushTypeQuake2,
eBrushTypeQuake3,
eBrushTypeQuake3BP,
eBrushTypeDoom3,
eBrushTypeQuake4,
eBrushTypeHalfLife,
};
#define BRUSH_CONNECTIVITY_DEBUG 0 #define BRUSH_CONNECTIVITY_DEBUG 0
#define BRUSH_DEGENERATE_DEBUG 0 #define BRUSH_DEGENERATE_DEBUG 0
@ -1934,15 +1923,11 @@ static void constructStatic( EBrushType type ){
g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_QUAKE; g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_QUAKE;
if ( m_type == eBrushTypeQuake3BP || m_type == eBrushTypeDoom3 || m_type == eBrushTypeQuake4 ) { if ( m_type == eBrushTypeQuake3BP || m_type == eBrushTypeDoom3 || m_type == eBrushTypeQuake4 ) {
g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_BRUSHPRIMITIVES; g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_BRUSHPRIMITIVES;
// g_brush_texturelock_enabled = true; // bad idea, this overrides user setting
} }
else if ( m_type == eBrushTypeHalfLife ) { else if ( m_type == eBrushTypeValve220 || m_type == eBrushTypeQuake3Valve220 ) {
g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_HALFLIFE; g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_HALFLIFE;
// g_brush_texturelock_enabled = true; // bad idea, this overrides user setting
} }
Face::m_quantise = ( m_type == eBrushTypeQuake ) ? quantiseInteger : quantiseFloating;
m_state_point = GlobalShaderCache().capture( "$POINT" ); m_state_point = GlobalShaderCache().capture( "$POINT" );
} }
static void destroyStatic(){ static void destroyStatic(){

View File

@ -128,9 +128,6 @@ enum TexdefTypeId
struct bp_globals_t struct bp_globals_t
{ {
// tells if we are internally using brush primitive (texture coordinates and map format)
// this is a shortcut for IntForKey( g_qeglobals.d_project_entity, "brush_primit" )
// NOTE: must keep the two ones in sync
TexdefTypeId m_texdefTypeId; TexdefTypeId m_texdefTypeId;
}; };

View File

@ -35,13 +35,36 @@
#include "preferences.h" #include "preferences.h"
LatchedBool g_useAlternativeTextureProjection( false, "Use alternative texture-projection (\"brush primitives\")" ); LatchedBool g_useAlternativeTextureProjection( false, "Use alternative texture-projection (\"brush primitives\")" );
bool g_showAlternativeTextureProjectionOption = false; bool g_multipleBrushTypes = false;
EBrushType g_brushTypes[3];
int g_brushType;
bool g_brush_always_caulk; bool g_brush_always_caulk;
bool getTextureLockEnabled(){ bool getTextureLockEnabled(){
return g_brush_texturelock_enabled; return g_brush_texturelock_enabled;
} }
const char* BrushType_getName( EBrushType type ){
switch ( type )
{
case eBrushTypeQuake:
case eBrushTypeQuake2:
case eBrushTypeQuake3:
return "Axial Projection";
case eBrushTypeQuake3BP:
return "Brush Primitives";
case eBrushTypeQuake3Valve220:
case eBrushTypeValve220:
return "Valve 220";
case eBrushTypeDoom3:
return "Doom3";
case eBrushTypeQuake4:
return "Quake4";
default:
return "unknown";
}
}
void Face_importSnapPlanes( bool value ){ void Face_importSnapPlanes( bool value ){
Face::m_quantise = value ? quantiseInteger : quantiseFloating; Face::m_quantise = value ? quantiseInteger : quantiseFloating;
} }
@ -62,11 +85,12 @@ void Brush_constructPreferences( PreferencesPage& page ){
"Default texture scale", "Default texture scale",
g_texdef_default_scale g_texdef_default_scale
); );
if ( g_showAlternativeTextureProjectionOption ) { if ( g_multipleBrushTypes ) {
page.appendCheckBox( const char* names[] = { BrushType_getName( g_brushTypes[0] ), BrushType_getName( g_brushTypes[1] ), BrushType_getName( g_brushTypes[2] ) };
"", "Use alternative texture-projection (\"brush primitives\")", page.appendCombo(
LatchedBoolImportCaller( g_useAlternativeTextureProjection ), "Brush Type",
BoolExportCaller( g_useAlternativeTextureProjection.m_latched ) g_brushType,
STRING_ARRAY_RANGE( names )
); );
} }
// d1223m // d1223m
@ -83,51 +107,38 @@ void Brush_registerPreferencesPage(){
PreferencesDialog_addSettingsPage( FreeCaller1<PreferenceGroup&, Brush_constructPage>() ); PreferencesDialog_addSettingsPage( FreeCaller1<PreferenceGroup&, Brush_constructPage>() );
} }
void Brush_unlatchPreferences(){ void Brush_toggleFormat( EBrushType type ){
Brush_toggleFormat( 0 ); if( g_multipleBrushTypes ){
}
void Brush_toggleFormat( int i ){
if ( g_showAlternativeTextureProjectionOption ) {
g_useAlternativeTextureProjection.m_value = g_useAlternativeTextureProjection.m_latched ^ i;
Brush::destroyStatic(); Brush::destroyStatic();
Brush::constructStatic( g_useAlternativeTextureProjection.m_value ? eBrushTypeQuake3BP : eBrushTypeQuake3 ); Brush::constructStatic( type );
} }
} }
int Brush_toggleFormatCount(){ void Brush_unlatchPreferences(){
if ( g_showAlternativeTextureProjectionOption ) { if( g_multipleBrushTypes )
return 2; Brush_toggleFormat( g_brushTypes[g_brushType] );
}
return 1;
} }
void Brush_Construct( EBrushType type ){ void Brush_Construct( EBrushType type ){
if ( type == eBrushTypeQuake3 ) { if ( g_multipleBrushTypes ) {
g_showAlternativeTextureProjectionOption = true; for ( int i = 0; i < 3; ++i ){
if( g_brushTypes[i] == type ){
const char *value = g_pGameDescription->getKeyValue( "brush_primit" ); g_brushType = i;
if ( !string_empty( value ) ) { break;
g_useAlternativeTextureProjection.m_latched = atoi( value ); }
} }
GlobalPreferenceSystem().registerPreference( GlobalPreferenceSystem().registerPreference(
"AlternativeTextureProjection", "BrushType",
BoolImportStringCaller( g_useAlternativeTextureProjection.m_latched ), IntImportStringCaller( g_brushType ),
BoolExportStringCaller( g_useAlternativeTextureProjection.m_latched ) IntExportStringCaller( g_brushType )
); );
g_useAlternativeTextureProjection.useLatched(); type = g_brushTypes[g_brushType];
if ( g_useAlternativeTextureProjection.m_value ) {
type = eBrushTypeQuake3BP;
} }
// d1223m // d1223m
GlobalPreferenceSystem().registerPreference( GlobalPreferenceSystem().registerPreference(
"BrushAlwaysCaulk", "BrushAlwaysCaulk",
BoolImportStringCaller( g_brush_always_caulk ), BoolImportStringCaller( g_brush_always_caulk ),
BoolExportStringCaller( g_brush_always_caulk ) ); BoolExportStringCaller( g_brush_always_caulk ) );
}
Brush_registerCommands(); Brush_registerCommands();
Brush_registerPreferencesPage(); Brush_registerPreferencesPage();
@ -137,6 +148,7 @@ void Brush_Construct( EBrushType type ){
BrushClipPlane::constructStatic(); BrushClipPlane::constructStatic();
BrushInstance::constructStatic(); BrushInstance::constructStatic();
Brush::constructStatic( type ); Brush::constructStatic( type );
Face::m_quantise = quantiseFloating;
Brush::m_maxWorldCoord = g_MaxWorldCoord; Brush::m_maxWorldCoord = g_MaxWorldCoord;
BrushInstance::m_counter = &g_brushCount; BrushInstance::m_counter = &g_brushCount;
@ -197,8 +209,8 @@ public:
scene::Node& createBrush(){ scene::Node& createBrush(){
return ( new BrushNode )->node(); return ( new BrushNode )->node();
} }
bool useAlternativeTextureProjection() const { EBrushType getCurrentFormat() const {
return g_useAlternativeTextureProjection.m_value; return Brush::m_type;
} }
void Brush_forEachFace( scene::Node& brush, const BrushFaceDataCallback& callback ){ void Brush_forEachFace( scene::Node& brush, const BrushFaceDataCallback& callback ){
::Brush_forEachFace( *Node_getBrush( brush ), FaceCallback( BrushFaceDataFromFaceCaller( callback ) ) ); ::Brush_forEachFace( *Node_getBrush( brush ), FaceCallback( BrushFaceDataFromFaceCaller( callback ) ) );
@ -288,7 +300,12 @@ typedef BrushCreator Type;
STRING_CONSTANT( Name, "quake3" ); STRING_CONSTANT( Name, "quake3" );
BrushQuake3API(){ BrushQuake3API(){
Brush_Construct( eBrushTypeQuake3 ); g_multipleBrushTypes = true;
g_brushTypes[0] = eBrushTypeQuake3;
g_brushTypes[1] = eBrushTypeQuake3BP;
g_brushTypes[2] = eBrushTypeQuake3Valve220;
Brush_Construct( eBrushTypeQuake3BP );
m_brushquake3 = &GetBrushCreator(); m_brushquake3 = &GetBrushCreator();
} }
@ -313,6 +330,11 @@ typedef BrushCreator Type;
STRING_CONSTANT( Name, "quake2" ); STRING_CONSTANT( Name, "quake2" );
BrushQuake2API(){ BrushQuake2API(){
g_multipleBrushTypes = true;
g_brushTypes[0] = eBrushTypeQuake2;
g_brushTypes[1] = eBrushTypeQuake3BP;
g_brushTypes[2] = eBrushTypeQuake3Valve220;
Brush_Construct( eBrushTypeQuake2 ); Brush_Construct( eBrushTypeQuake2 );
m_brushquake2 = &GetBrushCreator(); m_brushquake2 = &GetBrushCreator();
@ -338,6 +360,11 @@ typedef BrushCreator Type;
STRING_CONSTANT( Name, "quake" ); STRING_CONSTANT( Name, "quake" );
BrushQuake1API(){ BrushQuake1API(){
g_multipleBrushTypes = true;
g_brushTypes[0] = eBrushTypeQuake;
g_brushTypes[1] = eBrushTypeQuake3BP;
g_brushTypes[2] = eBrushTypeValve220;
Brush_Construct( eBrushTypeQuake ); Brush_Construct( eBrushTypeQuake );
m_brushquake1 = &GetBrushCreator(); m_brushquake1 = &GetBrushCreator();
@ -363,7 +390,7 @@ typedef BrushCreator Type;
STRING_CONSTANT( Name, "halflife" ); STRING_CONSTANT( Name, "halflife" );
BrushHalfLifeAPI(){ BrushHalfLifeAPI(){
Brush_Construct( eBrushTypeHalfLife ); Brush_Construct( eBrushTypeValve220 );
m_brushhalflife = &GetBrushCreator(); m_brushhalflife = &GetBrushCreator();
} }

View File

@ -22,9 +22,10 @@
#if !defined( INCLUDED_BRUSHMODULE_H ) #if !defined( INCLUDED_BRUSHMODULE_H )
#define INCLUDED_BRUSHMODULE_H #define INCLUDED_BRUSHMODULE_H
#include "ibrush.h"
void Brush_clipperColourChanged(); void Brush_clipperColourChanged();
void Brush_unlatchPreferences(); void Brush_unlatchPreferences();
int Brush_toggleFormatCount(); void Brush_toggleFormat( EBrushType type );
void Brush_toggleFormat( int i );
#endif #endif

View File

@ -67,7 +67,7 @@ inline bool FaceTexdef_BP_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser
return true; return true;
} }
inline bool FaceTexdef_HalfLife_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){ inline bool FaceTexdef_Valve220_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){
// parse texdef // parse texdef
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "[" ) ); RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "[" ) );
RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_s.x() ) ); RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_s.x() ) );
@ -221,7 +221,9 @@ bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///optional for more flexibility
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
}
m_face.getTexdef().m_scaleApplied = true; m_face.getTexdef().m_scaleApplied = true;
return true; return true;
} }
@ -237,7 +239,9 @@ bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///optional for more flexibility
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
}
m_face.getTexdef().m_projectionInitialised = true; m_face.getTexdef().m_projectionInitialised = true;
m_face.getTexdef().m_scaleApplied = true; m_face.getTexdef().m_scaleApplied = true;
@ -256,21 +260,45 @@ bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///try to load for more flexibility
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
}
m_face.getTexdef().m_scaleApplied = true; m_face.getTexdef().m_scaleApplied = true;
return true; return true;
} }
}; };
class HalfLifeFaceTokenImporter class Valve220FaceTokenImporter
{ {
Face& m_face; Face& m_face;
public: public:
HalfLifeFaceTokenImporter( Face& face ) : m_face( face ){ Valve220FaceTokenImporter( Face& face ) : m_face( face ){
} }
bool importTokens( Tokeniser& tokeniser ){ bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_HalfLife_importTokens( m_face.getTexdef(), tokeniser ) ); RETURN_FALSE_IF_FAIL( FaceTexdef_Valve220_importTokens( m_face.getTexdef(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///try to load for more flexibility
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
}
m_face.getTexdef().m_scaleApplied = true;
return true;
}
};
class Quake3Valve220FaceTokenImporter
{
Face& m_face;
public:
Quake3Valve220FaceTokenImporter( Face& face ) : m_face( face ){
}
bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_Valve220_importTokens( m_face.getTexdef(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///optional for more flexibility
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
}
m_face.getTexdef().m_scaleApplied = true; m_face.getTexdef().m_scaleApplied = true;
return true; return true;
} }
@ -471,11 +499,11 @@ void exportTokens( TokenWriter& writer ) const {
} }
}; };
class HalfLifeFaceTokenExporter class Valve220FaceTokenExporter
{ {
const Face& m_face; const Face& m_face;
public: public:
HalfLifeFaceTokenExporter( const Face& face ) : m_face( face ){ Valve220FaceTokenExporter( const Face& face ) : m_face( face ){
} }
void exportTokens( TokenWriter& writer ) const { void exportTokens( TokenWriter& writer ) const {
FacePlane_exportTokens( m_face.getPlane(), writer ); FacePlane_exportTokens( m_face.getPlane(), writer );
@ -485,6 +513,21 @@ void exportTokens( TokenWriter& writer ) const {
} }
}; };
class Quake3Valve220FaceTokenExporter
{
const Face& m_face;
public:
Quake3Valve220FaceTokenExporter( const Face& face ) : m_face( face ){
}
void exportTokens( TokenWriter& writer ) const {
FacePlane_exportTokens( m_face.getPlane(), writer );
FaceShader_exportTokens( m_face.getShader(), writer );
FaceTexdef_HalfLife_exportTokens( m_face.getTexdef(), writer );
FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
writer.nextLine();
}
};
class BrushTokenImporter : public MapImporter class BrushTokenImporter : public MapImporter
{ {
@ -554,9 +597,15 @@ bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
} }
break; break;
case eBrushTypeHalfLife: case eBrushTypeValve220:
{ {
HalfLifeFaceTokenImporter importer( face ); Valve220FaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
break;
case eBrushTypeQuake3Valve220:
{
Quake3Valve220FaceTokenImporter importer( face );
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) ); RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
} }
break; break;
@ -650,9 +699,15 @@ void exportTokens( TokenWriter& writer ) const {
exporter.exportTokens( writer ); exporter.exportTokens( writer );
} }
break; break;
case eBrushTypeHalfLife: case eBrushTypeValve220:
{ {
HalfLifeFaceTokenExporter exporter( face ); Valve220FaceTokenExporter exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake3Valve220:
{
Quake3Valve220FaceTokenExporter exporter( face );
exporter.exportTokens( writer ); exporter.exportTokens( writer );
} }
break; break;

View File

@ -1119,27 +1119,20 @@ void Map_LoadFile( const char *filename ){
if ( string_not_empty( moduleName ) ) { if ( string_not_empty( moduleName ) ) {
format = ReferenceAPI_getMapModules().findModule( moduleName ); format = ReferenceAPI_getMapModules().findModule( moduleName );
} }
if ( format ) {
for ( int i = 0; i < Brush_toggleFormatCount(); ++i ) format->m_detectedFormat = eBrushTypeUNKNOWN;
{
if ( i ) {
Map_Free();
} }
Brush_toggleFormat( i );
g_map.m_name = filename; g_map.m_name = filename;
Map_UpdateTitle( g_map ); Map_UpdateTitle( g_map );
g_map.m_resource = GlobalReferenceCache().capture( g_map.m_name.c_str() ); g_map.m_resource = GlobalReferenceCache().capture( g_map.m_name.c_str() );
if ( format ) {
format->wrongFormat = false;
}
g_map.m_resource->attach( g_map ); g_map.m_resource->attach( g_map );
if ( format ) { if ( format && format->m_detectedFormat && format->m_detectedFormat != GlobalBrushModule::getTable().getCurrentFormat() ) {
if ( !format->wrongFormat ) { Map_Free();
break; Brush_toggleFormat( format->m_detectedFormat );
g_map.m_resource = GlobalReferenceCache().capture( g_map.m_name.c_str() );
g_map.m_resource->attach( g_map );
} }
}
}
Node_getTraversable( GlobalSceneGraph().root() )->traverse( entity_updateworldspawn() ); Node_getTraversable( GlobalSceneGraph().root() )->traverse( entity_updateworldspawn() );
} }
@ -1675,22 +1668,20 @@ bool Map_ImportFile( const char* filename ){
if ( string_not_empty( moduleName ) ) { if ( string_not_empty( moduleName ) ) {
format = ReferenceAPI_getMapModules().findModule( moduleName ); format = ReferenceAPI_getMapModules().findModule( moduleName );
} }
if ( format ) { if ( format ) {
format->wrongFormat = false; format->m_detectedFormat = eBrushTypeUNKNOWN;
} }
Resource* resource = GlobalReferenceCache().capture( filename ); Resource* resource = GlobalReferenceCache().capture( filename );
resource->refresh(); // avoid loading old version if map has changed on disk since last import resource->refresh(); // avoid loading old version if map has changed on disk since last import
if ( !resource->load() ) { if ( !resource->load() ) {
GlobalReferenceCache().release( filename ); GlobalReferenceCache().release( filename );
goto tryDecompile; goto tryDecompile;
} }
if ( format ) { if ( format && /*format->m_detectedFormat &&*/ format->m_detectedFormat != GlobalBrushModule::getTable().getCurrentFormat() ) {
if ( format->wrongFormat ) {
GlobalReferenceCache().release( filename ); GlobalReferenceCache().release( filename );
goto tryDecompile; goto tryDecompile;
} }
}
NodeSmartReference clone( NewMapRoot( "" ) ); NodeSmartReference clone( NewMapRoot( "" ) );
Node_getTraversable( *resource->getNode() )->traverse( CloneAll( clone ) ); Node_getTraversable( *resource->getNode() )->traverse( CloneAll( clone ) );
Map_gatherNamespaced( clone ); Map_gatherNamespaced( clone );
@ -1744,7 +1735,7 @@ tryDecompile:
resource->refresh(); // avoid loading old version if map has changed on disk since last import resource->refresh(); // avoid loading old version if map has changed on disk since last import
if ( !resource->load() ) { if ( !resource->load() ) {
GlobalReferenceCache().release( filename ); GlobalReferenceCache().release( filename );
goto tryDecompile; return success;
} }
NodeSmartReference clone( NewMapRoot( "" ) ); NodeSmartReference clone( NewMapRoot( "" ) );
Node_getTraversable( *resource->getNode() )->traverse( CloneAll( clone ) ); Node_getTraversable( *resource->getNode() )->traverse( CloneAll( clone ) );