* "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 "itexdef.h"
enum EBrushType
{
eBrushTypeUNKNOWN = 0,
eBrushTypeQuake,
eBrushTypeQuake2,
eBrushTypeQuake3,
eBrushTypeQuake3BP,
eBrushTypeQuake3Valve220,
eBrushTypeDoom3,
eBrushTypeQuake4,
eBrushTypeValve220,
};
namespace scene
{
class Node;
@ -103,7 +117,7 @@ public:
INTEGER_CONSTANT( Version, 1 );
STRING_CONSTANT( Name, "brush" );
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 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 "ibrush.h"
class EntityCreator;
@ -61,7 +62,7 @@ class MapFormat
public:
INTEGER_CONSTANT( Version, 2 );
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.
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 std::size_t getLine() const = 0;
virtual std::size_t getColumn() const = 0;
virtual bool bufferContains( const char* str ) = 0;
};
class TextInputStream;

View File

@ -41,7 +41,7 @@ typedef bool ( ScriptTokeniser::*Tokenise )( char c );
Tokenise m_stack[3];
Tokenise* m_state;
SingleCharacterInputStream<TextInputStream> m_istream;
SingleCharacterInputStreamDoubleBuffered<TextInputStream> m_istream;
std::size_t m_scriptline;
std::size_t m_scriptcolumn;
@ -329,6 +329,9 @@ std::size_t getLine() const {
std::size_t getColumn() const {
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.
class SingleCharacterOutputStream : public TextOutputStream
{

View File

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

View File

@ -68,17 +68,6 @@
const unsigned int BRUSH_DETAIL_FLAG = 27;
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_DEGENERATE_DEBUG 0
@ -1934,15 +1923,11 @@ static void constructStatic( EBrushType type ){
g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_QUAKE;
if ( m_type == eBrushTypeQuake3BP || m_type == eBrushTypeDoom3 || m_type == eBrushTypeQuake4 ) {
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_brush_texturelock_enabled = true; // bad idea, this overrides user setting
}
Face::m_quantise = ( m_type == eBrushTypeQuake ) ? quantiseInteger : quantiseFloating;
m_state_point = GlobalShaderCache().capture( "$POINT" );
}
static void destroyStatic(){

View File

@ -128,9 +128,6 @@ enum TexdefTypeId
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;
};

View File

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

View File

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

View File

@ -67,7 +67,7 @@ inline bool FaceTexdef_BP_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser
return true;
}
inline bool FaceTexdef_HalfLife_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){
inline bool FaceTexdef_Valve220_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){
// parse texdef
RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "[" ) );
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( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), 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;
return true;
}
@ -237,7 +239,9 @@ bool importTokens( Tokeniser& 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( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) { ///optional for more flexibility
RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
}
m_face.getTexdef().m_projectionInitialised = 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( FaceShader_importTokens( m_face.getShader(), 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;
return true;
}
};
class HalfLifeFaceTokenImporter
class Valve220FaceTokenImporter
{
Face& m_face;
public:
HalfLifeFaceTokenImporter( Face& face ) : m_face( face ){
Valve220FaceTokenImporter( 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_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;
return true;
}
@ -471,11 +499,11 @@ void exportTokens( TokenWriter& writer ) const {
}
};
class HalfLifeFaceTokenExporter
class Valve220FaceTokenExporter
{
const Face& m_face;
public:
HalfLifeFaceTokenExporter( const Face& face ) : m_face( face ){
Valve220FaceTokenExporter( const Face& face ) : m_face( face ){
}
void exportTokens( TokenWriter& writer ) const {
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
{
@ -554,9 +597,15 @@ bool importTokens( Tokeniser& tokeniser ){
RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
}
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 ) );
}
break;
@ -650,9 +699,15 @@ void exportTokens( TokenWriter& writer ) const {
exporter.exportTokens( writer );
}
break;
case eBrushTypeHalfLife:
case eBrushTypeValve220:
{
HalfLifeFaceTokenExporter exporter( face );
Valve220FaceTokenExporter exporter( face );
exporter.exportTokens( writer );
}
break;
case eBrushTypeQuake3Valve220:
{
Quake3Valve220FaceTokenExporter exporter( face );
exporter.exportTokens( writer );
}
break;

View File

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