Fixed x64 script/class connections and added material flags that are needed.

This commit is contained in:
Justin Marshall
2026-05-05 16:20:05 -07:00
parent 8d5f678b25
commit d06356e042
12 changed files with 2437 additions and 2202 deletions
+4 -4
View File
@@ -60,10 +60,10 @@ typedef enum {
} traceModel_t; } traceModel_t;
// these are bit cache limits // these are bit cache limits
#define MAX_TRACEMODEL_VERTS 32 #define MAX_TRACEMODEL_VERTS 64
#define MAX_TRACEMODEL_EDGES 32 #define MAX_TRACEMODEL_EDGES 64
#define MAX_TRACEMODEL_POLYS 16 #define MAX_TRACEMODEL_POLYS 32
#define MAX_TRACEMODEL_POLYEDGES 16 #define MAX_TRACEMODEL_POLYEDGES 32
typedef idVec3 traceModelVert_t; typedef idVec3 traceModelVert_t;
File diff suppressed because it is too large Load Diff
+57 -75
View File
@@ -12,7 +12,6 @@ instancing of objects.
#include "../Game_local.h" #include "../Game_local.h"
/*********************************************************************** /***********************************************************************
idTypeInfo idTypeInfo
@@ -882,7 +881,7 @@ idClass::ProcessEventArgs
bool idClass::ProcessEventArgs( const idEventDef *ev, int numargs, ... ) { bool idClass::ProcessEventArgs( const idEventDef *ev, int numargs, ... ) {
idTypeInfo *c; idTypeInfo *c;
int num; int num;
int data[ D_EVENT_MAXARGS ]; intptr_t data[ D_EVENT_MAXARGS ];
va_list args; va_list args;
assert( ev ); assert( ev );
@@ -990,106 +989,89 @@ bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg ar
idClass::ProcessEventArgPtr idClass::ProcessEventArgPtr
================ ================
*/ */
bool idClass::ProcessEventArgPtr( const idEventDef *ev, int *data ) { bool idClass::ProcessEventArgPtr( const idEventDef *ev, intptr_t*data ) {
idTypeInfo *c; idTypeInfo* c;
int num; int num;
eventCallback_t callback; eventCallback_t callback;
assert(ev);
assert( ev ); assert(idEvent::initialized);
assert( idEvent::initialized ); if (g_debugTriggers.GetBool() && (ev == &EV_Activate) && IsType(idEntity::Type)) {
const idEntity* ent = *reinterpret_cast<idEntity**>(data);
if ( g_debugTriggers.GetBool() && ( ev == &EV_Activate ) && IsType( idEntity::Type ) ) { gameLocal.Printf("%d: '%s' activated by '%s'\n", gameLocal.framenum, static_cast<idEntity*>(this)->GetName(), ent ? ent->GetName() : "NULL");
const idEntity *ent = *reinterpret_cast<idEntity **>( data );
gameLocal.Printf( "%d: '%s' activated by '%s'\n", gameLocal.framenum, static_cast<idEntity *>( this )->GetName(), ent ? ent->GetName() : "NULL" );
} }
c = GetType(); c = GetType();
num = ev->GetEventNum(); num = ev->GetEventNum();
if ( !c->eventMap[ num ] ) { if (!c->eventMap[num]) {
// we don't respond to this event, so ignore it // we don't respond to this event, so ignore it
return false; return false;
} }
callback = c->eventMap[num];
callback = c->eventMap[ num ]; // RB: I tried first to get CPU_EASYARGS switch running with x86_64
// but it caused many crashes with the Doom scripts.
#if !CPU_EASYARGS // The new Callbacks.cpp was generated with intptr_t and it works fine.
#if CPU_EASYARGS
/* /*
on ppc architecture, floats are passed in a seperate set of registers on ppc architecture, floats are passed in a separate set of registers
the function prototypes must have matching float declaration the function prototypes must have matching float declaration
http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/2rt_powerpc_abi/chapter_9_section_5.html
http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/2rt_powerpc_abi/chapter_9_section_5.html */
*/ switch (ev->GetFormatspecIndex())
{
switch( ev->GetFormatspecIndex() ) { case 1 << D_EVENT_MAXARGS:
case 1 << D_EVENT_MAXARGS : (this->*callback)();
( this->*callback )();
break; break;
// generated file - see CREATE_EVENT_CODE
// generated file - see CREATE_EVENT_CODE
#include "Callbacks.cpp" #include "Callbacks.cpp"
default: default:
gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() ); gameLocal.Warning("Invalid formatspec on event '%s'", ev->GetName());
break; break;
} }
#else #else
assert(D_EVENT_MAXARGS == 8);
assert( D_EVENT_MAXARGS == 8 ); // RB: 64 bit fixes, changed int to intptr_t
switch (ev->GetNumArgs())
switch( ev->GetNumArgs() ) { {
case 0 : case 0:
( this->*callback )(); (this->*callback)();
break; break;
case 1:
case 1 : typedef void (idClass::* eventCallback_1_t)(const intptr_t);
typedef void ( idClass::*eventCallback_1_t )( const int ); (this->*(eventCallback_1_t)callback)(data[0]);
( this->*( eventCallback_1_t )callback )( data[ 0 ] );
break; break;
case 2:
case 2 : typedef void (idClass::* eventCallback_2_t)(const intptr_t, const intptr_t);
typedef void ( idClass::*eventCallback_2_t )( const int, const int ); (this->*(eventCallback_2_t)callback)(data[0], data[1]);
( this->*( eventCallback_2_t )callback )( data[ 0 ], data[ 1 ] );
break; break;
case 3:
case 3 : typedef void (idClass::* eventCallback_3_t)(const intptr_t, const intptr_t, const intptr_t);
typedef void ( idClass::*eventCallback_3_t )( const int, const int, const int ); (this->*(eventCallback_3_t)callback)(data[0], data[1], data[2]);
( this->*( eventCallback_3_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ] );
break; break;
case 4:
case 4 : typedef void (idClass::* eventCallback_4_t)(const intptr_t, const intptr_t, const intptr_t, const intptr_t);
typedef void ( idClass::*eventCallback_4_t )( const int, const int, const int, const int ); (this->*(eventCallback_4_t)callback)(data[0], data[1], data[2], data[3]);
( this->*( eventCallback_4_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ] );
break; break;
case 5:
case 5 : typedef void (idClass::* eventCallback_5_t)(const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t);
typedef void ( idClass::*eventCallback_5_t )( const int, const int, const int, const int, const int ); (this->*(eventCallback_5_t)callback)(data[0], data[1], data[2], data[3], data[4]);
( this->*( eventCallback_5_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ] );
break; break;
case 6:
case 6 : typedef void (idClass::* eventCallback_6_t)(const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t);
typedef void ( idClass::*eventCallback_6_t )( const int, const int, const int, const int, const int, const int ); (this->*(eventCallback_6_t)callback)(data[0], data[1], data[2], data[3], data[4], data[5]);
( this->*( eventCallback_6_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
break; break;
case 7:
case 7 : typedef void (idClass::* eventCallback_7_t)(const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t);
typedef void ( idClass::*eventCallback_7_t )( const int, const int, const int, const int, const int, const int, const int ); (this->*(eventCallback_7_t)callback)(data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
( this->*( eventCallback_7_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ] );
break; break;
case 8:
case 8 : typedef void (idClass::* eventCallback_8_t)(const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t, const intptr_t);
typedef void ( idClass::*eventCallback_8_t )( const int, const int, const int, const int, const int, const int, const int, const int ); (this->*(eventCallback_8_t)callback)(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
( this->*( eventCallback_8_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ] );
break; break;
default: default:
gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() ); gameLocal.Warning("Invalid formatspec on event '%s'", ev->GetName());
break; break;
} }
// RB end
#endif #endif
return true; return true;
} }
+7 -7
View File
@@ -32,17 +32,17 @@ struct idEventFunc {
class idEventArg { class idEventArg {
public: public:
int type; int type;
int value; intptr_t value;
idEventArg() { type = D_EVENT_INTEGER; value = 0; }; idEventArg() { type = D_EVENT_INTEGER; value = 0; };
idEventArg( int data ) { type = D_EVENT_INTEGER; value = data; }; idEventArg( int data ) { type = D_EVENT_INTEGER; value = data; };
idEventArg( float data ) { type = D_EVENT_FLOAT; value = *reinterpret_cast<int *>( &data ); }; idEventArg( float data ) { type = D_EVENT_FLOAT; value = *reinterpret_cast<int *>( &data ); };
//HUMANHEAD: aob - added const to idVec3 //HUMANHEAD: aob - added const to idVec3
idEventArg( const idVec3 &data ) { type = D_EVENT_VECTOR; value = reinterpret_cast<int>( &data ); }; idEventArg( const idVec3 &data ) { type = D_EVENT_VECTOR; value = reinterpret_cast<intptr_t>( &data ); };
idEventArg( const idStr &data ) { type = D_EVENT_STRING; value = reinterpret_cast<int>( data.c_str() ); }; idEventArg( const idStr &data ) { type = D_EVENT_STRING; value = reinterpret_cast<intptr_t>( data.c_str() ); };
idEventArg( const char *data ) { type = D_EVENT_STRING; value = reinterpret_cast<int>( data ); }; idEventArg( const char *data ) { type = D_EVENT_STRING; value = reinterpret_cast<intptr_t>( data ); };
idEventArg( const class idEntity *data ) { type = D_EVENT_ENTITY; value = reinterpret_cast<int>( data ); }; idEventArg( const class idEntity *data ) { type = D_EVENT_ENTITY; value = reinterpret_cast<intptr_t>( data ); };
idEventArg( const struct trace_s *data ) { type = D_EVENT_TRACE; value = reinterpret_cast<int>( data ); }; idEventArg( const struct trace_s *data ) { type = D_EVENT_TRACE; value = reinterpret_cast<intptr_t>( data ); };
}; };
class idAllocError : public idException { class idAllocError : public idException {
@@ -206,7 +206,7 @@ public:
bool ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ); bool ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 );
bool ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ); bool ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 );
bool ProcessEventArgPtr( const idEventDef *ev, int *data ); bool ProcessEventArgPtr( const idEventDef *ev, intptr_t*data );
void CancelEvents( const idEventDef *ev ); void CancelEvents( const idEventDef *ev );
virtual // HUMANHEAD nla virtual // HUMANHEAD nla
void Event_Remove( void ); void Event_Remove( void );
+186 -119
View File
@@ -70,33 +70,43 @@ idEventDef::idEventDef( const char *command, const char *formatspec, char return
for( i = 0; i < numargs; i++ ) { for( i = 0; i < numargs; i++ ) {
argOffset[ i ] = argsize; argOffset[ i ] = argsize;
switch( formatspec[ i ] ) { switch( formatspec[ i ] ) {
case D_EVENT_FLOAT : case D_EVENT_FLOAT:
bits |= 1 << i; bits |= 1 << i;
argsize += sizeof( float ); // RB: 64 bit fix, changed sizeof( float ) to sizeof( intptr_t )
argsize += sizeof(intptr_t);
// RB end
break; break;
case D_EVENT_INTEGER : case D_EVENT_INTEGER:
argsize += sizeof( int ); // RB: 64 bit fix, changed sizeof( int ) to sizeof( intptr_t )
argsize += sizeof(intptr_t);
// RB end
break; break;
case D_EVENT_VECTOR : case D_EVENT_VECTOR:
argsize += sizeof( idVec3 ); // RB: 64 bit fix, changed sizeof( idVec3 ) to E_EVENT_SIZEOF_VEC
argsize += E_EVENT_SIZEOF_VEC;
// RB end
break; break;
case D_EVENT_STRING : case D_EVENT_STRING:
argsize += MAX_STRING_LEN; argsize += MAX_STRING_LEN;
break; break;
case D_EVENT_ENTITY : case D_EVENT_ENTITY:
argsize += sizeof( idEntityPtr<idEntity> ); // RB: 64 bit fix, sizeof( idEntityPtr<idEntity> ) to sizeof( intptr_t )
argsize += sizeof(intptr_t);
// RB end
break; break;
case D_EVENT_ENTITY_NULL : case D_EVENT_ENTITY_NULL:
argsize += sizeof( idEntityPtr<idEntity> ); // RB: 64 bit fix, sizeof( idEntityPtr<idEntity> ) to sizeof( intptr_t )
argsize += sizeof(intptr_t);
// RB end
break; break;
case D_EVENT_TRACE : case D_EVENT_TRACE:
argsize += sizeof( trace_t ) + MAX_STRING_LEN + sizeof( bool ); argsize += sizeof(trace_t) + MAX_STRING_LEN + sizeof(bool);
break; break;
default : default :
@@ -326,7 +336,7 @@ idEvent *idEvent::Alloc( const idEventDef *evdef, int numargs, va_list args ) {
idEvent::CopyArgs idEvent::CopyArgs
================ ================
*/ */
void idEvent::CopyArgs( const idEventDef *evdef, int numargs, va_list args, int data[ D_EVENT_MAXARGS ] ) { void idEvent::CopyArgs( const idEventDef *evdef, int numargs, va_list args, intptr_t data[ D_EVENT_MAXARGS ] ) {
int i; int i;
const char *format; const char *format;
idEventArg *arg; idEventArg *arg;
@@ -455,7 +465,7 @@ idEvent::ServiceEvents
void idEvent::ServiceEvents( void ) { void idEvent::ServiceEvents( void ) {
idEvent *event; idEvent *event;
int num; int num;
int args[ D_EVENT_MAXARGS ]; intptr_t args[ D_EVENT_MAXARGS ];
int offset; int offset;
int i; int i;
int numargs; int numargs;
@@ -628,68 +638,91 @@ int idEvent::NumQueuedEvents( const idClass *obj, const idEventDef *evdef ) {
idEvent::Save idEvent::Save
================ ================
*/ */
void idEvent::Save( idSaveGame *savefile ) { void idEvent::Save(idSaveGame* savefile) {
char *str; char* str;
int i, size; int i, size;
idEvent *event; idEvent* event;
byte *dataPtr; byte* dataPtr;
bool validTrace; bool validTrace;
const char *format; const char* format;
// RB: for missing D_EVENT_STRING
idStr s;
// RB end
savefile->WriteInt( EventQueue.Num() ); savefile->WriteInt(EventQueue.Num());
event = EventQueue.Next(); event = EventQueue.Next();
while( event != NULL ) { while (event != NULL)
savefile->WriteInt( event->time ); {
savefile->WriteString( event->eventdef->GetName() ); savefile->WriteInt(event->time);
savefile->WriteString( event->typeinfo->classname ); savefile->WriteString(event->eventdef->GetName());
savefile->WriteObject( event->object ); savefile->WriteString(event->typeinfo->classname);
savefile->WriteInt( event->eventdef->GetArgSize() ); savefile->WriteObject(event->object);
savefile->WriteInt(event->eventdef->GetArgSize());
format = event->eventdef->GetArgFormat(); format = event->eventdef->GetArgFormat();
for ( i = 0, size = 0; i < event->eventdef->GetNumArgs(); ++i) { for (i = 0, size = 0; i < event->eventdef->GetNumArgs(); ++i)
dataPtr = &event->data[ event->eventdef->GetArgOffset( i ) ]; {
switch( format[ i ] ) { dataPtr = &event->data[event->eventdef->GetArgOffset(i)];
case D_EVENT_FLOAT : switch (format[i])
savefile->WriteFloat( *reinterpret_cast<float *>( dataPtr ) ); {
size += sizeof( float ); case D_EVENT_FLOAT:
savefile->WriteFloat(*reinterpret_cast<float*>(dataPtr));
// RB: 64 bit fix, changed sizeof( float ) to sizeof( intptr_t )
size += sizeof(intptr_t);
// RB end
break; break;
case D_EVENT_INTEGER : case D_EVENT_INTEGER:
case D_EVENT_ENTITY : // RB: 64 bit fix, changed sizeof( int ) to sizeof( intptr_t )
case D_EVENT_ENTITY_NULL : savefile->WriteInt(*reinterpret_cast<int*>(dataPtr));
savefile->WriteInt( *reinterpret_cast<int *>( dataPtr ) ); size += sizeof(intptr_t);
size += sizeof( int );
break; break;
case D_EVENT_VECTOR : // RB end
savefile->WriteVec3( *reinterpret_cast<idVec3 *>( dataPtr ) ); case D_EVENT_ENTITY:
size += sizeof( idVec3 ); case D_EVENT_ENTITY_NULL:
// RB: 64 bit fix, changed alignment to sizeof( intptr_t )
reinterpret_cast<idEntityPtr<idEntity>*>(dataPtr)->Save(savefile);
size += sizeof(intptr_t);
// RB end
break; break;
case D_EVENT_TRACE : case D_EVENT_VECTOR:
validTrace = *reinterpret_cast<bool *>( dataPtr ); savefile->WriteVec3(*reinterpret_cast<idVec3*>(dataPtr));
savefile->WriteBool( validTrace ); // RB: 64 bit fix, changed sizeof( int ) to E_EVENT_SIZEOF_VEC
size += sizeof( bool ); size += E_EVENT_SIZEOF_VEC;
if ( validTrace ) { // RB end
size += sizeof( trace_t );
const trace_t &t = *reinterpret_cast<trace_t *>( dataPtr + sizeof( bool ) );
SaveTrace( savefile, t );
if ( t.c.material ) {
size += MAX_STRING_LEN;
str = reinterpret_cast<char *>( dataPtr + sizeof( bool ) + sizeof( trace_t ) );
savefile->Write( str, MAX_STRING_LEN );
}
}
break; break;
// HUMANHEAD mdl: Added support for saving strings passed in events #if 1
// RB: added missing D_EVENT_STRING case
case D_EVENT_STRING: case D_EVENT_STRING:
str = reinterpret_cast<char *>( dataPtr ); s.Clear();
savefile->Write( str, MAX_STRING_LEN ); s.Append(reinterpret_cast<char*>(dataPtr));
savefile->WriteString(s);
//size += s.Length();
size += MAX_STRING_LEN; size += MAX_STRING_LEN;
break; break;
// HUMANHEAD END // RB end
#endif
case D_EVENT_TRACE:
validTrace = *reinterpret_cast<bool*>(dataPtr);
savefile->WriteBool(validTrace);
size += sizeof(bool);
if (validTrace)
{
size += sizeof(trace_t);
const trace_t& t = *reinterpret_cast<trace_t*>(dataPtr + sizeof(bool));
SaveTrace(savefile, t);
if (t.c.material)
{
size += MAX_STRING_LEN;
str = reinterpret_cast<char*>(dataPtr + sizeof(bool) + sizeof(trace_t));
savefile->Write(str, MAX_STRING_LEN);
}
}
break;
default: default:
break; break;
} }
} }
assert( size == event->eventdef->GetArgSize() ); assert(size == (int)event->eventdef->GetArgSize());
event = event->eventNode.Next(); event = event->eventNode.Next();
} }
} }
@@ -699,96 +732,130 @@ void idEvent::Save( idSaveGame *savefile ) {
idEvent::Restore idEvent::Restore
================ ================
*/ */
void idEvent::Restore( idRestoreGame *savefile ) { void idEvent::Restore(idRestoreGame* savefile) {
char *str; char* str;
int num, argsize, i, j, size; int num, argsize, i, j, size;
idStr name; idStr name;
byte *dataPtr; byte* dataPtr;
idEvent *event; idEvent* event;
const char *format; const char* format;
// RB: for missing D_EVENT_STRING
idStr s;
// RB end
savefile->ReadInt( num ); savefile->ReadInt(num);
for ( i = 0; i < num; i++ ) { for (i = 0; i < num; i++)
if ( FreeEvents.IsListEmpty() ) { {
gameLocal.Error( "idEvent::Restore : No more free events" ); if (FreeEvents.IsListEmpty())
{
gameLocal.Error("idEvent::Restore : No more free events");
} }
event = FreeEvents.Next(); event = FreeEvents.Next();
event->eventNode.Remove(); event->eventNode.Remove();
event->eventNode.AddToEnd( EventQueue ); event->eventNode.AddToEnd(EventQueue);
savefile->ReadInt( event->time ); savefile->ReadInt(event->time);
// read the event name // read the event name
savefile->ReadString( name ); savefile->ReadString(name);
event->eventdef = idEventDef::FindEvent( name ); event->eventdef = idEventDef::FindEvent(name);
if ( !event->eventdef ) { if (event->eventdef == NULL)
savefile->Error( "idEvent::Restore: unknown event '%s'", name.c_str() ); {
savefile->Error("idEvent::Restore: unknown event '%s'", name.c_str());
return;
} }
// read the classtype // read the classtype
savefile->ReadString( name ); savefile->ReadString(name);
event->typeinfo = idClass::GetClass( name ); event->typeinfo = idClass::GetClass(name);
if ( !event->typeinfo ) { if (event->typeinfo == NULL)
savefile->Error( "idEvent::Restore: unknown class '%s' on event '%s'", name.c_str(), event->eventdef->GetName() ); {
savefile->Error("idEvent::Restore: unknown class '%s' on event '%s'", name.c_str(), event->eventdef->GetName());
return;
} }
savefile->ReadObject( event->object ); savefile->ReadObject(event->object);
// read the args // read the args
savefile->ReadInt( argsize ); savefile->ReadInt(argsize);
if ( argsize != event->eventdef->GetArgSize() ) { if (argsize != (int)event->eventdef->GetArgSize())
savefile->Error( "idEvent::Restore: arg size (%d) doesn't match saved arg size(%d) on event '%s'", event->eventdef->GetArgSize(), argsize, event->eventdef->GetName() ); {
// RB: fixed wrong formatting
savefile->Error("idEvent::Restore: arg size (%zd) doesn't match saved arg size(%zd) on event '%s'", event->eventdef->GetArgSize(), argsize, event->eventdef->GetName());
// RB end
} }
if ( argsize ) { if (argsize)
event->data = eventDataAllocator.Alloc( argsize ); {
event->data = eventDataAllocator.Alloc(argsize);
format = event->eventdef->GetArgFormat(); format = event->eventdef->GetArgFormat();
assert( format ); assert(format);
for ( j = 0, size = 0; j < event->eventdef->GetNumArgs(); ++j) { for (j = 0, size = 0; j < event->eventdef->GetNumArgs(); ++j)
dataPtr = &event->data[ event->eventdef->GetArgOffset( j ) ]; {
switch( format[ j ] ) { dataPtr = &event->data[event->eventdef->GetArgOffset(j)];
case D_EVENT_FLOAT : switch (format[j])
savefile->ReadFloat( *reinterpret_cast<float *>( dataPtr ) ); {
size += sizeof( float ); case D_EVENT_FLOAT:
savefile->ReadFloat(*reinterpret_cast<float*>(dataPtr));
// RB: 64 bit fix, changed sizeof( float ) to sizeof( intptr_t )
size += sizeof(intptr_t);
// RB end
break; break;
case D_EVENT_INTEGER : case D_EVENT_INTEGER:
case D_EVENT_ENTITY : // RB: 64 bit fix
case D_EVENT_ENTITY_NULL : savefile->ReadInt(*reinterpret_cast<int*>(dataPtr));
savefile->ReadInt( *reinterpret_cast<int *>( dataPtr ) ); size += sizeof(intptr_t);
size += sizeof( int );
break; break;
case D_EVENT_VECTOR : // RB end
savefile->ReadVec3( *reinterpret_cast<idVec3 *>( dataPtr ) ); case D_EVENT_ENTITY:
size += sizeof( idVec3 ); case D_EVENT_ENTITY_NULL:
// RB: 64 bit fix, changed alignment to sizeof( intptr_t )
reinterpret_cast<idEntityPtr<idEntity>*>(dataPtr)->Restore(savefile);
size += sizeof(intptr_t);
// RB end
break; break;
case D_EVENT_TRACE : case D_EVENT_VECTOR:
savefile->ReadBool( *reinterpret_cast<bool *>( dataPtr ) ); savefile->ReadVec3(*reinterpret_cast<idVec3*>(dataPtr));
size += sizeof( bool ); // RB: 64 bit fix, changed sizeof( int ) to E_EVENT_SIZEOF_VEC
if ( *reinterpret_cast<bool *>( dataPtr ) ) { size += E_EVENT_SIZEOF_VEC;
size += sizeof( trace_t ); // RB end
trace_t &t = *reinterpret_cast<trace_t *>( dataPtr + sizeof( bool ) );
RestoreTrace( savefile, t) ;
if ( t.c.material ) {
size += MAX_STRING_LEN;
str = reinterpret_cast<char *>( dataPtr + sizeof( bool ) + sizeof( trace_t ) );
savefile->Read( str, MAX_STRING_LEN );
}
}
break; break;
// HUMANHEAD mdl: Added support for saving strings passed in events #if 1
// RB: added missing D_EVENT_STRING case
case D_EVENT_STRING: case D_EVENT_STRING:
str = reinterpret_cast<char *>( dataPtr ); savefile->ReadString(s);
savefile->Read( str, MAX_STRING_LEN ); //idStr::Copynz(reinterpret_cast<char *>( dataPtr ), s, s.Length() );
//size += s.Length();
idStr::Copynz(reinterpret_cast<char*>(dataPtr), s, MAX_STRING_LEN);
size += MAX_STRING_LEN; size += MAX_STRING_LEN;
break; break;
// HUMANHEAD END // RB end
#endif
case D_EVENT_TRACE:
savefile->ReadBool(*reinterpret_cast<bool*>(dataPtr));
size += sizeof(bool);
if (*reinterpret_cast<bool*>(dataPtr))
{
size += sizeof(trace_t);
trace_t& t = *reinterpret_cast<trace_t*>(dataPtr + sizeof(bool));
RestoreTrace(savefile, t);
if (t.c.material)
{
size += MAX_STRING_LEN;
str = reinterpret_cast<char*>(dataPtr + sizeof(bool) + sizeof(trace_t));
savefile->Read(str, MAX_STRING_LEN);
}
}
break;
default: default:
break; break;
} }
} }
assert( size == event->eventdef->GetArgSize() ); assert(size == (int)event->eventdef->GetArgSize());
} else { }
else
{
event->data = NULL; event->data = NULL;
} }
} }
+6 -3
View File
@@ -22,6 +22,9 @@ Event are used for scheduling tasks and for linking script commands.
#define MAX_EVENTS 4096 #define MAX_EVENTS 4096
// stack size of idVec3, aligned to native pointer size
#define E_EVENT_SIZEOF_VEC ((sizeof(idVec3) + (sizeof(intptr_t) - 1)) & ~(sizeof(intptr_t) - 1))
//HUMANHEAD: aob - needed for networking to send the least amount of bits //HUMANHEAD: aob - needed for networking to send the least amount of bits
extern const int MAX_EVENTS_NUM_BITS; extern const int MAX_EVENTS_NUM_BITS;
//HUMANHEAD END //HUMANHEAD END
@@ -50,7 +53,7 @@ public:
const char *GetName( void ) const; const char *GetName( void ) const;
const char *GetArgFormat( void ) const; const char *GetArgFormat( void ) const;
unsigned int GetFormatspecIndex( void ) const; unsigned int GetFormatspecIndex( void ) const;
char GetReturnType( void ) const; int GetReturnType( void ) const;
int GetEventNum( void ) const; int GetEventNum( void ) const;
int GetNumArgs( void ) const; int GetNumArgs( void ) const;
size_t GetArgSize( void ) const; size_t GetArgSize( void ) const;
@@ -87,7 +90,7 @@ public:
~idEvent(); ~idEvent();
static idEvent *Alloc( const idEventDef *evdef, int numargs, va_list args ); static idEvent *Alloc( const idEventDef *evdef, int numargs, va_list args );
static void CopyArgs( const idEventDef *evdef, int numargs, va_list args, int data[ D_EVENT_MAXARGS ] ); static void CopyArgs( const idEventDef *evdef, int numargs, va_list args, intptr_t data[ D_EVENT_MAXARGS ] );
void Free( void ); void Free( void );
void Schedule( idClass *object, const idTypeInfo *cls, int time ); void Schedule( idClass *object, const idTypeInfo *cls, int time );
@@ -152,7 +155,7 @@ ID_INLINE unsigned int idEventDef::GetFormatspecIndex( void ) const {
idEventDef::GetReturnType idEventDef::GetReturnType
================ ================
*/ */
ID_INLINE char idEventDef::GetReturnType( void ) const { ID_INLINE int idEventDef::GetReturnType( void ) const {
return returnType; return returnType;
} }
+26 -7
View File
@@ -672,7 +672,9 @@ void idInterpreter::CallEvent( const function_t *func, int argsize ) {
varEval_t var; varEval_t var;
int pos; int pos;
int start; int start;
int data[ D_EVENT_MAXARGS ]; // RB: 64 bit fixes, changed int to intptr_t
intptr_t data[D_EVENT_MAXARGS];
// RB end
const idEventDef *evdef; const idEventDef *evdef;
const char *format; const char *format;
@@ -686,6 +688,9 @@ void idInterpreter::CallEvent( const function_t *func, int argsize ) {
start = localstackUsed - argsize; start = localstackUsed - argsize;
var.intPtr = ( int * )&localstack[ start ]; var.intPtr = ( int * )&localstack[ start ];
eventEntity = GetEntity( *var.entityNumberPtr ); eventEntity = GetEntity( *var.entityNumberPtr );
static int testme;
testme = *var.entityNumberPtr;
if ( !eventEntity || !eventEntity->RespondsTo( *evdef ) ) { if ( !eventEntity || !eventEntity->RespondsTo( *evdef ) ) {
if ( eventEntity && developer.GetBool() ) { if ( eventEntity && developer.GetBool() ) {
@@ -703,10 +708,11 @@ void idInterpreter::CallEvent( const function_t *func, int argsize ) {
// always return a safe value when an object doesn't exist // always return a safe value when an object doesn't exist
switch( evdef->GetReturnType() ) { switch( evdef->GetReturnType() ) {
case D_EVENT_INTEGER : case D_EVENT_INTEGER:
gameLocal.program.ReturnInteger( 0 ); gameLocal.program.ReturnInteger(0);
break; break;
case D_EVENT_FLOAT : case D_EVENT_FLOAT :
gameLocal.program.ReturnFloat( 0 ); gameLocal.program.ReturnFloat( 0 );
break; break;
@@ -739,13 +745,18 @@ void idInterpreter::CallEvent( const function_t *func, int argsize ) {
for( j = 0, i = 0, pos = type_object.Size(); ( pos < argsize ) || ( format[ i ] != 0 ); i++ ) { for( j = 0, i = 0, pos = type_object.Size(); ( pos < argsize ) || ( format[ i ] != 0 ); i++ ) {
switch( format[ i ] ) { switch( format[ i ] ) {
case D_EVENT_INTEGER : case D_EVENT_INTEGER :
var.intPtr = ( int * )&localstack[ start + pos ]; var.intPtr = (int*)&localstack[start + pos];
data[ i ] = int( *var.floatPtr ); // RB: fixed data alignment
//data[ i ] = int( *var.floatPtr );
(*(int*)&data[i]) = int(*var.floatPtr);
// RB end
break; break;
case D_EVENT_FLOAT : case D_EVENT_FLOAT :
var.intPtr = ( int * )&localstack[ start + pos ]; var.intPtr = ( int * )&localstack[ start + pos ];
( *( float * )&data[ i ] ) = *var.floatPtr; ( *( float * )&data[ i ] ) = *var.floatPtr;
static float value;
value = (*(float*)&data[i]);
break; break;
case D_EVENT_VECTOR : case D_EVENT_VECTOR :
@@ -869,7 +880,9 @@ void idInterpreter::CallSysEvent( const function_t *func, int argsize ) {
varEval_t source; varEval_t source;
int pos; int pos;
int start; int start;
int data[ D_EVENT_MAXARGS ]; // RB: 64 bit fixes, changed int to intptr_t
intptr_t data[D_EVENT_MAXARGS];
// RB end
const idEventDef *evdef; const idEventDef *evdef;
const char *format; const char *format;
@@ -1988,10 +2001,15 @@ bool idInterpreter::Execute( void ) {
break; break;
case OP_PUSH_V: case OP_PUSH_V:
var_a = GetVariable( st->a ); var_a = GetVariable(st->a);
// RB: 64 bit fix, changed individual pushes with PushVector
/*
Push( *reinterpret_cast<int *>( &var_a.vectorPtr->x ) ); Push( *reinterpret_cast<int *>( &var_a.vectorPtr->x ) );
Push( *reinterpret_cast<int *>( &var_a.vectorPtr->y ) ); Push( *reinterpret_cast<int *>( &var_a.vectorPtr->y ) );
Push( *reinterpret_cast<int *>( &var_a.vectorPtr->z ) ); Push( *reinterpret_cast<int *>( &var_a.vectorPtr->z ) );
*/
PushVector(*var_a.vectorPtr);
// RB end
break; break;
case OP_PUSH_OBJ: case OP_PUSH_OBJ:
@@ -2014,3 +2032,4 @@ bool idInterpreter::Execute( void ) {
return threadDying; return threadDying;
} }
+16 -5
View File
@@ -5,7 +5,7 @@
#define __SCRIPT_INTERPRETER_H__ #define __SCRIPT_INTERPRETER_H__
#define MAX_STACK_DEPTH 64 #define MAX_STACK_DEPTH 64
#define LOCALSTACK_SIZE 6144 #define LOCALSTACK_SIZE (6144 * 2)
typedef struct prstack_s { typedef struct prstack_s {
int s; int s;
@@ -33,10 +33,11 @@ private:
idThread *thread; idThread *thread;
void PushVector(const idVec3& vector);
void PopParms( int numParms ); void PopParms( int numParms );
void PushString( const char *string ); void PushString( const char *string );
public://HUMANHEAD: aob - so we can pass parms in manually public://HUMANHEAD: aob - so we can pass parms in manually
void Push( int value ); void Push( intptr_t value );
private://HUMANHEAD: aob - undo the public declaration private://HUMANHEAD: aob - undo the public declaration
const char *FloatToString( float value ); const char *FloatToString( float value );
void AppendString( idVarDef *def, const char *from ); void AppendString( idVarDef *def, const char *from );
@@ -115,12 +116,12 @@ ID_INLINE void idInterpreter::PopParms( int numParms ) {
idInterpreter::Push idInterpreter::Push
==================== ====================
*/ */
ID_INLINE void idInterpreter::Push( int value ) { ID_INLINE void idInterpreter::Push(intptr_t value ) {
if ( localstackUsed + sizeof( int ) > LOCALSTACK_SIZE ) { if ( localstackUsed + sizeof( int ) > LOCALSTACK_SIZE ) {
Error( "Push: locals stack overflow\n" ); Error( "Push: locals stack overflow\n" );
} }
*( int * )&localstack[ localstackUsed ] = value; *(intptr_t*)&localstack[localstackUsed] = value;
localstackUsed += sizeof( int ); localstackUsed += sizeof(intptr_t);
} }
/* /*
@@ -248,4 +249,14 @@ ID_INLINE void idInterpreter::NextInstruction( int position ) {
instructionPointer = position - 1; instructionPointer = position - 1;
} }
ID_INLINE void idInterpreter::PushVector(const idVec3& vector)
{
if (localstackUsed + E_EVENT_SIZEOF_VEC > LOCALSTACK_SIZE)
{
Error("Push: locals stack overflow\n");
}
*(idVec3*)&localstack[localstackUsed] = vector;
localstackUsed += E_EVENT_SIZEOF_VEC;
}
#endif /* !__SCRIPT_INTERPRETER_H__ */ #endif /* !__SCRIPT_INTERPRETER_H__ */
+41 -42
View File
@@ -16,23 +16,23 @@ static int globalOutputRunningSize = 0;
// simple types. function types are dynamically allocated // simple types. function types are dynamically allocated
idTypeDef type_void( ev_void, &def_void, "void", 0, NULL ); idTypeDef type_void( ev_void, &def_void, "void", 0, NULL );
idTypeDef type_scriptevent( ev_scriptevent, &def_scriptevent, "scriptevent", sizeof( void * ), NULL ); idTypeDef type_scriptevent(ev_scriptevent, &def_scriptevent, "scriptevent", sizeof(intptr_t), NULL);
idTypeDef type_namespace( ev_namespace, &def_namespace, "namespace", sizeof( void * ), NULL ); idTypeDef type_namespace(ev_namespace, &def_namespace, "namespace", sizeof(intptr_t), NULL);
//HUMANHEAD: aob - changed types to inherited types //HUMANHEAD: aob - changed types to inherited types
idTypeDefString type_string( ev_string, &def_string, "string", MAX_STRING_LEN, NULL ); idTypeDefString type_string( ev_string, &def_string, "string", MAX_STRING_LEN, NULL );
idTypeDefFloat type_float( ev_float, &def_float, "float", sizeof( float ), NULL ); idTypeDefFloat type_float( ev_float, &def_float, "float", sizeof(intptr_t), NULL );
idTypeDefVector type_vector( ev_vector, &def_vector, "vector", sizeof( idVec3 ), NULL ); idTypeDefVector type_vector( ev_vector, &def_vector, "vector", E_EVENT_SIZEOF_VEC, NULL );
idTypeDefEntity type_entity( ev_entity, &def_entity, "entity", sizeof( int * ), NULL ); // stored as entity number pointer idTypeDefEntity type_entity( ev_entity, &def_entity, "entity", sizeof(intptr_t), NULL ); // stored as entity number pointer
//HUMANHEAD END //HUMANHEAD END
idTypeDef type_field( ev_field, &def_field, "field", sizeof( void * ), NULL ); idTypeDef type_field( ev_field, &def_field, "field", sizeof(intptr_t), NULL );
idTypeDef type_function( ev_function, &def_function, "function", sizeof( void * ), &type_void ); idTypeDef type_function( ev_function, &def_function, "function", sizeof(intptr_t), &type_void );
idTypeDef type_virtualfunction( ev_virtualfunction, &def_virtualfunction, "virtual function", sizeof( int ), NULL ); idTypeDef type_virtualfunction( ev_virtualfunction, &def_virtualfunction, "virtual function", sizeof(intptr_t), NULL );
idTypeDef type_pointer( ev_pointer, &def_pointer, "pointer", sizeof( void * ), NULL ); idTypeDef type_pointer( ev_pointer, &def_pointer, "pointer", sizeof(intptr_t), NULL );
idTypeDef type_object( ev_object, &def_object, "object", sizeof( int * ), NULL ); // stored as entity number pointer idTypeDef type_object( ev_object, &def_object, "object", sizeof(intptr_t), NULL ); // stored as entity number pointer
idTypeDef type_jumpoffset( ev_jumpoffset, &def_jumpoffset, "<jump>", sizeof( int ), NULL ); // only used for jump opcodes idTypeDef type_jumpoffset( ev_jumpoffset, &def_jumpoffset, "<jump>", sizeof(intptr_t), NULL ); // only used for jump opcodes
idTypeDef type_argsize( ev_argsize, &def_argsize, "<argsize>", sizeof( int ), NULL ); // only used for function call and thread opcodes idTypeDef type_argsize( ev_argsize, &def_argsize, "<argsize>", sizeof(intptr_t), NULL ); // only used for function call and thread opcodes
//HUMANHEAD: aob - changed types to inherited types //HUMANHEAD: aob - changed types to inherited types
idTypeDefBool type_boolean( ev_boolean, &def_boolean, "boolean", sizeof( int ), NULL ); idTypeDefBool type_boolean( ev_boolean, &def_boolean, "boolean", sizeof(intptr_t), NULL );
//HUMANHEAD END //HUMANHEAD END
idVarDef def_void( &type_void ); idVarDef def_void( &type_void );
@@ -1341,24 +1341,22 @@ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scop
def->initialized = idVarDef::stackVariable; def->initialized = idVarDef::stackVariable;
scope->value.functionPtr->locals += type->Size(); scope->value.functionPtr->locals += type->Size();
} else if ( scope->TypeDef()->Inherits( &type_object ) ) { } else if ( scope->TypeDef()->Inherits( &type_object ) ) {
idTypeDef newtype( ev_field, NULL, "float field", 0, &type_float ); idTypeDef newtype(ev_field, NULL, "float field", 0, &type_float);
idTypeDef *type = GetType( newtype, true ); // RB: changed local type to ftype
idTypeDef* ftype = GetType(newtype, true);
// set the value to the variable's position in the object // set the value to the variable's position in the object
def->value.ptrOffset = scope->TypeDef()->Size(); def->value.ptrOffset = scope->TypeDef()->Size();
// make automatic defs for the vectors elements // make automatic defs for the vectors elements
// origin can be accessed as origin_x, origin_y, and origin_z // origin can be accessed as origin_x, origin_y, and origin_z
sprintf( element, "%s_x", def->Name() ); sprintf(element, "%s_x", def->Name());
def_x = AllocDef( type, element, scope, constant ); def_x = AllocDef(ftype, element, scope, constant);
sprintf(element, "%s_y", def->Name());
sprintf( element, "%s_y", def->Name() ); def_y = AllocDef(ftype, element, scope, constant);
def_y = AllocDef( type, element, scope, constant ); def_y->value.ptrOffset = def_x->value.ptrOffset + sizeof(float);
def_y->value.ptrOffset = def_x->value.ptrOffset + type_float.Size(); sprintf(element, "%s_z", def->Name());
def_z = AllocDef(ftype, element, scope, constant);
sprintf( element, "%s_z", def->Name() ); def_z->value.ptrOffset = def_y->value.ptrOffset + sizeof(float);
def_z = AllocDef( type, element, scope, constant ); // RB end
def_z->value.ptrOffset = def_y->value.ptrOffset + type_float.Size();
} else { } else {
// make automatic defs for the vectors elements // make automatic defs for the vectors elements
// origin can be accessed as origin_x, origin_y, and origin_z // origin can be accessed as origin_x, origin_y, and origin_z
@@ -1718,29 +1716,29 @@ idProgram::DisassembleStatement
============== ==============
*/ */
void idProgram::DisassembleStatement( idFile *file, int instructionPointer ) const { void idProgram::DisassembleStatement( idFile *file, int instructionPointer ) const {
opcode_t *op; opcode_t* op;
const statement_t *statement; const statement_t* statement;
statement = &statements[ instructionPointer ]; statement = &statements[instructionPointer];
op = &idCompiler::opcodes[ statement->op ]; op = &idCompiler::opcodes[statement->op];
file->Printf( "%20s(%d):\t%6d: %15s\t", fileList[ statement->file ].c_str(), statement->linenumber, instructionPointer, op->opname ); file->Printf("%20s(%d):\t%6d: %15s\t", fileList[statement->file].c_str(), statement->linenumber, instructionPointer, op->opname);
if ( statement->a ) { if (statement->a) {
file->Printf( "\ta: " ); file->Printf("\ta: ");
statement->a->PrintInfo( file, instructionPointer ); statement->a->PrintInfo(file, instructionPointer);
} }
if ( statement->b ) { if (statement->b) {
file->Printf( "\tb: " ); file->Printf("\tb: ");
statement->b->PrintInfo( file, instructionPointer ); statement->b->PrintInfo(file, instructionPointer);
} }
if ( statement->c ) { if (statement->c) {
file->Printf( "\tc: " ); file->Printf("\tc: ");
statement->c->PrintInfo( file, instructionPointer ); statement->c->PrintInfo(file, instructionPointer);
} }
file->Printf( "\n" ); file->Printf("\n");
} }
/* /*
@@ -2257,6 +2255,7 @@ idProgram::ReturnEntity
*/ */
void idProgram::ReturnEntity( idEntity *ent ) { void idProgram::ReturnEntity( idEntity *ent ) {
if ( ent ) { if ( ent ) {
assert(ent->entityNumber + 1 <= MAX_GENTITIES);
*returnDef->value.entityNumberPtr = ent->entityNumber + 1; *returnDef->value.entityNumberPtr = ent->entityNumber + 1;
} else { } else {
*returnDef->value.entityNumberPtr = 0; *returnDef->value.entityNumberPtr = 0;
+1
View File
@@ -346,6 +346,7 @@ typedef union varEval_s {
int argSize; int argSize;
varEval_s *evalPtr; varEval_s *evalPtr;
int ptrOffset; int ptrOffset;
INT_PTR highPtr;
} varEval_t; } varEval_t;
class idVarDef { class idVarDef {
+226 -110
View File
@@ -122,6 +122,11 @@ void idMaterial::CommonInit() {
decalInfo.end[1] = 0; decalInfo.end[1] = 0;
decalInfo.end[2] = 0; decalInfo.end[2] = 0;
decalInfo.end[3] = 0; decalInfo.end[3] = 0;
#ifdef PREY
subviewClass = SC_MIRROR;
directPortalDistance = 0;
#endif
} }
/* /*
@@ -279,20 +284,20 @@ static infoParm_t infoParms[] = {
{"nosteps", 0, SURF_NOSTEPS, 0 }, // no footsteps {"nosteps", 0, SURF_NOSTEPS, 0 }, // no footsteps
// material types for particle, sound, footstep feedback // material types for particle, sound, footstep feedback
{"metal", 0, SURFTYPE_METAL, 0 }, // metal {"matter_metal", 0, SURFTYPE_METAL, 0 }, // metal
{"stone", 0, SURFTYPE_STONE, 0 }, // stone {"matter_stone", 0, SURFTYPE_STONE, 0 }, // stone
{"flesh", 0, SURFTYPE_FLESH, 0 }, // flesh {"matter_flesh", 0, SURFTYPE_FLESH, 0 }, // flesh
{"wood", 0, SURFTYPE_WOOD, 0 }, // wood {"matter_wood", 0, SURFTYPE_WOOD, 0 }, // wood
{"cardboard", 0, SURFTYPE_CARDBOARD, 0 }, // cardboard {"matter_cardboard", 0, SURFTYPE_CARDBOARD, 0 }, // cardboard
{"liquid", 0, SURFTYPE_LIQUID, 0 }, // liquid {"matter_liquid", 0, SURFTYPE_LIQUID, 0 }, // liquid
{"glass", 0, SURFTYPE_GLASS, 0 }, // glass {"matter_glass", 0, SURFTYPE_GLASS, 0 }, // glass
{"tile", 0, SURFTYPE_TILE, 0 }, // tile {"matter_tile", 0, SURFTYPE_TILE, 0 }, // tile
{"wallwalk", 0, SURFTYPE_WALLWALK, 0 }, // wallwalk surface {"wallwalk", 0, SURFTYPE_WALLWALK, 0 }, // wallwalk surface
{"altmetal", 0, SURFTYPE_ALTMETAL, 0 }, // alternate metal {"matter_altmetal", 0, SURFTYPE_ALTMETAL, 0 }, // alternate metal
{"forcefield", 0, SURFTYPE_FORCEFIELD, 0 }, // forcefield material {"forcefield", 0, SURFTYPE_FORCEFIELD, 0 }, // forcefield material
{"pipe", 0, SURFTYPE_PIPE, 0 }, // pipe {"matter_pipe", 0, SURFTYPE_PIPE, 0 }, // pipe
{"spirit", 0, SURFTYPE_SPIRIT, 0 }, // spirit material {"matter_spirit", 0, SURFTYPE_SPIRIT, 0 }, // spirit material
{"chaff", 0, SURFTYPE_CHAFF, 0 }, // chaff material {"matter_chaff", 0, SURFTYPE_CHAFF, 0 }, // chaff material
}; };
#else #else
static infoParm_t infoParms[] = { static infoParm_t infoParms[] = {
@@ -1847,11 +1852,11 @@ Parse it into the global material variable. Later functions will optimize it.
If there is any error during parsing, defaultShader will be set. If there is any error during parsing, defaultShader will be set.
================= =================
*/ */
void idMaterial::ParseMaterial( idLexer &src ) { void idMaterial::ParseMaterial(idLexer& src) {
idToken token; idToken token;
int s; int s;
char buffer[1024]; char buffer[1024];
const char *str; const char* str;
idLexer newSrc; idLexer newSrc;
int i; int i;
@@ -1859,7 +1864,7 @@ void idMaterial::ParseMaterial( idLexer &src ) {
numOps = 0; numOps = 0;
numRegisters = EXP_REG_NUM_PREDEFINED; // leave space for the parms to be copied in numRegisters = EXP_REG_NUM_PREDEFINED; // leave space for the parms to be copied in
for ( i = 0 ; i < numRegisters ; i++ ) { for (i = 0; i < numRegisters; i++) {
pd->registerIsTemporary[i] = true; // they aren't constants that can be folded pd->registerIsTemporary[i] = true; // they aren't constants that can be folded
} }
@@ -1867,41 +1872,41 @@ void idMaterial::ParseMaterial( idLexer &src ) {
textureRepeat_t trpDefault = TR_REPEAT; // allow a global setting for repeat textureRepeat_t trpDefault = TR_REPEAT; // allow a global setting for repeat
while ( 1 ) { while (1) {
if ( TestMaterialFlag( MF_DEFAULTED ) ) { // we have a parse error if (TestMaterialFlag(MF_DEFAULTED)) { // we have a parse error
return; return;
} }
if ( !src.ExpectAnyToken( &token ) ) { if (!src.ExpectAnyToken(&token)) {
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
return; return;
} }
// end of material definition // end of material definition
if ( token == "}" ) { if (token == "}") {
break; break;
} }
else if ( !token.Icmp( "qer_editorimage") ) { else if (!token.Icmp("qer_editorimage")) {
src.ReadTokenOnLine( &token ); src.ReadTokenOnLine(&token);
editorImageName = token.c_str(); editorImageName = token.c_str();
src.SkipRestOfLine(); src.SkipRestOfLine();
continue; continue;
} }
// description // description
else if ( !token.Icmp( "description") ) { else if (!token.Icmp("description")) {
src.ReadTokenOnLine( &token ); src.ReadTokenOnLine(&token);
desc = token.c_str(); desc = token.c_str();
continue; continue;
} }
// check for the surface / content bit flags // check for the surface / content bit flags
else if ( CheckSurfaceParm( &token ) ) { else if (CheckSurfaceParm(&token)) {
continue; continue;
} }
// polygonOffset // polygonOffset
else if ( !token.Icmp( "polygonOffset" ) ) { else if (!token.Icmp("polygonOffset")) {
SetMaterialFlag( MF_POLYGONOFFSET ); SetMaterialFlag(MF_POLYGONOFFSET);
if ( !src.ReadTokenOnLine( &token ) ) { if (!src.ReadTokenOnLine(&token)) {
polygonOffset = 1; polygonOffset = 1;
continue; continue;
} }
@@ -1910,223 +1915,333 @@ void idMaterial::ParseMaterial( idLexer &src ) {
continue; continue;
} }
// noshadow // noshadow
else if ( !token.Icmp( "noShadows" ) ) { else if (!token.Icmp("noShadows")) {
SetMaterialFlag( MF_NOSHADOWS ); SetMaterialFlag(MF_NOSHADOWS);
continue; continue;
} }
else if ( !token.Icmp( "suppressInSubview" ) ) { else if (!token.Icmp("suppressInSubview")) {
suppressInSubview = true; suppressInSubview = true;
continue; continue;
} }
else if ( !token.Icmp( "portalSky" ) ) { else if (!token.Icmp("portalSky")) {
portalSky = true; portalSky = true;
continue; continue;
} }
// noSelfShadow // noSelfShadow
else if ( !token.Icmp( "noSelfShadow" ) ) { else if (!token.Icmp("noSelfShadow")) {
SetMaterialFlag( MF_NOSELFSHADOW ); SetMaterialFlag(MF_NOSELFSHADOW);
continue; continue;
} }
// noPortalFog // noPortalFog
else if ( !token.Icmp( "noPortalFog" ) ) { else if (!token.Icmp("noPortalFog")) {
SetMaterialFlag( MF_NOPORTALFOG ); SetMaterialFlag(MF_NOPORTALFOG);
continue; continue;
} }
// forceShadows allows nodraw surfaces to cast shadows // forceShadows allows nodraw surfaces to cast shadows
else if ( !token.Icmp( "forceShadows" ) ) { else if (!token.Icmp("forceShadows")) {
SetMaterialFlag( MF_FORCESHADOWS ); SetMaterialFlag(MF_FORCESHADOWS);
continue; continue;
} }
#ifdef PREY
// HUMANHEAD PCF: explicitly skip collision clip for alpha-coverage surfaces.
else if (!token.Icmp("skipClip")) {
SetMaterialFlag(MF_SKIPCLIP);
continue;
}
// HUMANHEAD bjk: don't cull tris with the light bounds.
else if (!token.Icmp("lightWholeMesh")) {
SetMaterialFlag(MF_LIGHT_WHOLE_MESH);
continue;
}
#endif
// overlay / decal suppression // overlay / decal suppression
else if ( !token.Icmp( "noOverlays" ) ) { else if (!token.Icmp("noOverlays")) {
allowOverlays = false; allowOverlays = false;
continue; continue;
} }
// moster blood overlay forcing for alpha tested or translucent surfaces // moster blood overlay forcing for alpha tested or translucent surfaces
else if ( !token.Icmp( "forceOverlays" ) ) { else if (!token.Icmp("forceOverlays")) {
pd->forceOverlays = true; pd->forceOverlays = true;
continue; continue;
} }
// translucent // translucent
else if ( !token.Icmp( "translucent" ) ) { else if (!token.Icmp("translucent")) {
coverage = MC_TRANSLUCENT; coverage = MC_TRANSLUCENT;
continue; continue;
} }
// global zero clamp // global zero clamp
else if ( !token.Icmp( "zeroclamp" ) ) { else if (!token.Icmp("zeroclamp")) {
trpDefault = TR_CLAMP_TO_ZERO; trpDefault = TR_CLAMP_TO_ZERO;
continue; continue;
} }
// global clamp // global clamp
else if ( !token.Icmp( "clamp" ) ) { else if (!token.Icmp("clamp")) {
trpDefault = TR_CLAMP; trpDefault = TR_CLAMP;
continue; continue;
} }
// global clamp // global clamp
else if ( !token.Icmp( "alphazeroclamp" ) ) { else if (!token.Icmp("alphazeroclamp")) {
trpDefault = TR_CLAMP_TO_ZERO; trpDefault = TR_CLAMP_TO_ZERO;
continue; continue;
} }
// forceOpaque is used for skies-behind-windows // forceOpaque is used for skies-behind-windows
else if ( !token.Icmp( "forceOpaque" ) ) { else if (!token.Icmp("forceOpaque")) {
coverage = MC_OPAQUE; coverage = MC_OPAQUE;
continue; continue;
} }
// twoSided // twoSided
else if ( !token.Icmp( "twoSided" ) ) { else if (!token.Icmp("twoSided")) {
cullType = CT_TWO_SIDED; cullType = CT_TWO_SIDED;
// twoSided implies no-shadows, because the shadow // twoSided implies no-shadows, because the shadow
// volume would be coplanar with the surface, giving depth fighting // volume would be coplanar with the surface, giving depth fighting
// we could make this no-self-shadows, but it may be more important // we could make this no-self-shadows, but it may be more important
// to receive shadows from no-self-shadow monsters // to receive shadows from no-self-shadow monsters
SetMaterialFlag( MF_NOSHADOWS ); SetMaterialFlag(MF_NOSHADOWS);
} }
// backSided // backSided
else if ( !token.Icmp( "backSided" ) ) { else if (!token.Icmp("backSided")) {
cullType = CT_BACK_SIDED; cullType = CT_BACK_SIDED;
// the shadow code doesn't handle this, so just disable shadows. // the shadow code doesn't handle this, so just disable shadows.
// We could fix this in the future if there was a need. // We could fix this in the future if there was a need.
SetMaterialFlag( MF_NOSHADOWS ); SetMaterialFlag(MF_NOSHADOWS);
} }
// foglight // foglight
else if ( !token.Icmp( "fogLight" ) ) { else if (!token.Icmp("fogLight")) {
fogLight = true; fogLight = true;
continue; continue;
} }
// blendlight // blendlight
else if ( !token.Icmp( "blendLight" ) ) { else if (!token.Icmp("blendLight")) {
blendLight = true; blendLight = true;
continue; continue;
} }
// ambientLight // ambientLight
else if ( !token.Icmp( "ambientLight" ) ) { else if (!token.Icmp("ambientLight")) {
ambientLight = true; ambientLight = true;
continue; continue;
} }
// mirror // mirror
else if ( !token.Icmp( "mirror" ) ) { else if (!token.Icmp("mirror")) {
sort = SS_SUBVIEW; sort = SS_SUBVIEW;
coverage = MC_OPAQUE; coverage = MC_OPAQUE;
continue; continue;
} }
// noFog // noFog
else if ( !token.Icmp( "noFog" ) ) { else if (!token.Icmp("noFog")) {
noFog = true; noFog = true;
continue; continue;
} }
// unsmoothedTangents // unsmoothedTangents
else if ( !token.Icmp( "unsmoothedTangents" ) ) { else if (!token.Icmp("unsmoothedTangents")) {
unsmoothedTangents = true; unsmoothedTangents = true;
continue; continue;
} }
// lightFallofImage <imageprogram> // lightFallofImage <imageprogram>
// specifies the image to use for the third axis of projected // specifies the image to use for the third axis of projected
// light volumes // light volumes
else if ( !token.Icmp( "lightFalloffImage" ) ) { else if (!token.Icmp("lightFalloffImage")) {
str = R_ParsePastImageProgram( src ); str = R_ParsePastImageProgram(src);
idStr copy; idStr copy;
copy = str; // so other things don't step on it copy = str; // so other things don't step on it
lightFalloffImage = globalImages->ImageFromFile( copy, TF_DEFAULT, false, TR_CLAMP /* TR_CLAMP_TO_ZERO */, TD_DEFAULT ); lightFalloffImage = globalImages->ImageFromFile(copy, TF_DEFAULT, false, TR_CLAMP /* TR_CLAMP_TO_ZERO */, TD_DEFAULT);
continue; continue;
} }
// guisurf <guifile> | guisurf entity // guisurf <guifile> | guisurf entity
// an entity guisurf must have an idUserInterface // an entity guisurf must have an idUserInterface
// specified in the renderEntity // specified in the renderEntity
else if ( !token.Icmp( "guisurf" ) ) { else if (!token.Icmp("guisurf")) {
src.ReadTokenOnLine( &token ); src.ReadTokenOnLine(&token);
if ( !token.Icmp( "entity" ) ) { if (!token.Icmp("entity")) {
entityGui = 1; entityGui = 1;
} else if ( !token.Icmp( "entity2" ) ) { }
else if (!token.Icmp("entity2")) {
entityGui = 2; entityGui = 2;
} else if ( !token.Icmp( "entity3" ) ) { }
else if (!token.Icmp("entity3")) {
entityGui = 3; entityGui = 3;
} else { }
gui = uiManager->FindGui( token.c_str(), true ); else {
gui = uiManager->FindGui(token.c_str(), true);
} }
continue; continue;
} }
// sort // sort
else if ( !token.Icmp( "sort" ) ) { else if (!token.Icmp("sort")) {
ParseSort( src ); ParseSort(src);
continue; continue;
} }
// spectrum <integer> // spectrum <integer>
else if ( !token.Icmp( "spectrum" ) ) { else if (!token.Icmp("spectrum")) {
src.ReadTokenOnLine( &token ); src.ReadTokenOnLine(&token);
spectrum = atoi( token.c_str() ); spectrum = atoi(token.c_str());
continue; continue;
} }
// deform < sprite | tube | flare > // deform < sprite | tube | flare >
else if ( !token.Icmp( "deform" ) ) { else if (!token.Icmp("deform")) {
ParseDeform( src ); ParseDeform(src);
continue; continue;
} }
// decalInfo <staySeconds> <fadeSeconds> ( <start rgb> ) ( <end rgb> ) // decalInfo <staySeconds> <fadeSeconds> ( <start rgb> ) ( <end rgb> )
else if ( !token.Icmp( "decalInfo" ) ) { else if (!token.Icmp("decalInfo")) {
ParseDecalInfo( src ); ParseDecalInfo(src);
continue; continue;
} }
// renderbump <args...> // renderbump <args...>
else if ( !token.Icmp( "renderbump") ) { else if (!token.Icmp("renderbump")) {
src.ParseRestOfLine( renderBump ); src.ParseRestOfLine(renderBump);
continue; continue;
} }
#ifdef PREY
else if (!token.Icmp("glowmap")) {
src.ReadTokenOnLine(&token);
continue;
}
else if (!token.Icmp("highres")) {
continue;
}
#endif
// diffusemap for stage shortcut // diffusemap for stage shortcut
else if ( !token.Icmp( "diffusemap" ) ) { else if (!token.Icmp("diffusemap")) {
str = R_ParsePastImageProgram( src ); str = R_ParsePastImageProgram(src);
idStr::snPrintf( buffer, sizeof( buffer ), "blend diffusemap\nmap %s\n}\n", str ); idStr::snPrintf(buffer, sizeof(buffer), "blend diffusemap\nmap %s\n}\n", str);
newSrc.LoadMemory( buffer, strlen(buffer), "diffusemap" ); newSrc.LoadMemory(buffer, strlen(buffer), "diffusemap");
newSrc.SetFlags( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES ); newSrc.SetFlags(LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES);
ParseStage( newSrc, trpDefault ); ParseStage(newSrc, trpDefault);
newSrc.FreeSource(); newSrc.FreeSource();
continue; continue;
} }
// specularmap for stage shortcut // specularmap for stage shortcut
else if ( !token.Icmp( "specularmap" ) ) { else if (!token.Icmp("specularmap")) {
str = R_ParsePastImageProgram( src ); str = R_ParsePastImageProgram(src);
idStr::snPrintf( buffer, sizeof( buffer ), "blend specularmap\nmap %s\n}\n", str ); idStr::snPrintf(buffer, sizeof(buffer), "blend specularmap\nmap %s\n}\n", str);
newSrc.LoadMemory( buffer, strlen(buffer), "specularmap" ); newSrc.LoadMemory(buffer, strlen(buffer), "specularmap");
newSrc.SetFlags( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES ); newSrc.SetFlags(LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES);
ParseStage( newSrc, trpDefault ); ParseStage(newSrc, trpDefault);
newSrc.FreeSource(); newSrc.FreeSource();
continue; continue;
} }
// normalmap for stage shortcut // normalmap for stage shortcut
else if ( !token.Icmp( "bumpmap" ) ) { else if (!token.Icmp("bumpmap")) {
str = R_ParsePastImageProgram( src ); str = R_ParsePastImageProgram(src);
idStr::snPrintf( buffer, sizeof( buffer ), "blend bumpmap\nmap %s\n}\n", str ); idStr::snPrintf(buffer, sizeof(buffer), "blend bumpmap\nmap %s\n}\n", str);
newSrc.LoadMemory( buffer, strlen(buffer), "bumpmap" ); newSrc.LoadMemory(buffer, strlen(buffer), "bumpmap");
newSrc.SetFlags( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES ); newSrc.SetFlags(LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES);
ParseStage( newSrc, trpDefault ); ParseStage(newSrc, trpDefault);
newSrc.FreeSource(); newSrc.FreeSource();
continue; continue;
} }
// DECAL_MACRO for backwards compatibility with the preprocessor macros // DECAL_MACRO for backwards compatibility with the preprocessor macros
else if ( !token.Icmp( "DECAL_MACRO" ) ) { else if (!token.Icmp("DECAL_MACRO")) {
// polygonOffset // polygonOffset
SetMaterialFlag( MF_POLYGONOFFSET ); SetMaterialFlag(MF_POLYGONOFFSET);
polygonOffset = 1; polygonOffset = 1;
// discrete // discrete
surfaceFlags |= SURF_DISCRETE; surfaceFlags |= SURF_DISCRETE;
#ifdef PREY
surfaceFlags |= SURF_NOIMPACT;
#endif
contentFlags &= ~CONTENTS_SOLID; contentFlags &= ~CONTENTS_SOLID;
// sort decal // sort decal
sort = SS_DECAL; sort = SS_DECAL;
// noShadows // noShadows
SetMaterialFlag( MF_NOSHADOWS ); SetMaterialFlag(MF_NOSHADOWS);
#ifdef PREY
coverage = MC_TRANSLUCENT;
allowOverlays = false;
#endif
continue; continue;
} }
else if ( token == "{" ) { #ifdef PREY
// HUMANHEAD tmj: render this subview as a skybox portal.
else if (!token.Icmp("skyboxPortal")) {
sort = SS_SUBVIEW;
coverage = MC_OPAQUE;
subviewClass = SC_PORTAL_SKYBOX;
continue;
}
// HUMANHEAD CJR: render this subview as a direct portal, with distance-cull expression.
else if (!token.Icmp("directPortal")) {
sort = SS_SUBVIEW;
coverage = MC_OPAQUE;
subviewClass = SC_PORTAL;
directPortalDistance = ParseExpressionPriority(src, 4);
continue;
}
else if (!token.Icmp("DECAL_ALPHATEST_MACRO")) {
surfaceFlags |= SURF_NOIMPACT | SURF_DISCRETE;
contentFlags &= ~CONTENTS_SOLID;
sort = SS_DECAL;
SetMaterialFlag(MF_NOSHADOWS);
coverage = MC_TRANSLUCENT;
allowOverlays = false;
continue;
}
else if (!token.Icmp("SCORCH_MACRO") || !token.Icmp("OVERLAY_MACRO")) {
SetMaterialFlag(MF_POLYGONOFFSET);
polygonOffset = 1;
surfaceFlags |= SURF_NOIMPACT | SURF_DISCRETE;
contentFlags &= ~CONTENTS_SOLID;
sort = SS_DECAL;
SetMaterialFlag(MF_NOSHADOWS);
coverage = MC_TRANSLUCENT;
allowOverlays = false;
continue;
}
else if (!token.Icmp("GLASS_MACRO")) {
coverage = MC_TRANSLUCENT;
SetMaterialFlag(MF_NOSHADOWS);
pd->forceOverlays = true;
contentFlags &= ~CONTENTS_OPAQUE;
surfaceFlags = (surfaceFlags & ~SURF_TYPE_MASK) | SURFTYPE_GLASS;
sort = SS_MEDIUM;
continue;
}
else if (!token.Icmp("ALPHA_MACRO")) {
coverage = MC_TRANSLUCENT;
SetMaterialFlag(MF_NOSHADOWS);
surfaceFlags |= SURF_NOIMPACT;
cullType = CT_TWO_SIDED;
continue;
}
else if (!token.Icmp("EFFECT_MACRO")) {
coverage = MC_TRANSLUCENT;
SetMaterialFlag(MF_NOSHADOWS);
contentFlags &= ~CONTENTS_SOLID;
surfaceFlags |= SURF_NOIMPACT;
cullType = CT_TWO_SIDED;
continue;
}
else if (!token.Icmp("SPRITE_MACRO")) {
surfaceFlags |= SURF_DISCRETE;
contentFlags &= ~CONTENTS_SOLID;
SetMaterialFlag(MF_NOSHADOWS);
coverage = MC_TRANSLUCENT;
deform = DFRM_SPRITE;
cullType = CT_TWO_SIDED;
continue;
}
else if (!token.Icmp("SKYBOX_MACRO")) {
SetMaterialFlag(MF_NOSHADOWS | MF_NOSELFSHADOW);
allowOverlays = false;
coverage = MC_OPAQUE;
surfaceFlags |= SURF_NOIMPACT | SURF_NOFRAGMENT;
continue;
}
#endif
else if (token == "{") {
// create the new stage // create the new stage
ParseStage( src, trpDefault ); ParseStage(src, trpDefault);
continue; continue;
} }
else { else {
common->Warning( "unknown general material parameter '%s' in '%s'", token.c_str(), GetName() ); common->Warning("unknown general material parameter '%s' in '%s'", token.c_str(), GetName());
SetMaterialFlag( MF_DEFAULTED ); SetMaterialFlag(MF_DEFAULTED);
return; return;
} }
} }
@@ -2144,10 +2259,10 @@ void idMaterial::ParseMaterial( idLexer &src ) {
// we can't just call ReceivesLighting(), because the stages are still // we can't just call ReceivesLighting(), because the stages are still
// in temporary form // in temporary form
if ( cullType == CT_TWO_SIDED ) { if (cullType == CT_TWO_SIDED) {
for ( i = 0 ; i < numStages ; i++ ) { for (i = 0; i < numStages; i++) {
if ( pd->parseStages[i].lighting != SL_AMBIENT || pd->parseStages[i].texture.texgen != TG_EXPLICIT ) { if (pd->parseStages[i].lighting != SL_AMBIENT || pd->parseStages[i].texture.texgen != TG_EXPLICIT) {
if ( cullType == CT_TWO_SIDED ) { if (cullType == CT_TWO_SIDED) {
cullType = CT_FRONT_SIDED; cullType = CT_FRONT_SIDED;
shouldCreateBackSides = true; shouldCreateBackSides = true;
} }
@@ -2158,12 +2273,13 @@ void idMaterial::ParseMaterial( idLexer &src ) {
// currently a surface can only have one unique texgen for all the stages on old hardware // currently a surface can only have one unique texgen for all the stages on old hardware
texgen_t firstGen = TG_EXPLICIT; texgen_t firstGen = TG_EXPLICIT;
for ( i = 0; i < numStages; i++ ) { for (i = 0; i < numStages; i++) {
if ( pd->parseStages[i].texture.texgen != TG_EXPLICIT ) { if (pd->parseStages[i].texture.texgen != TG_EXPLICIT) {
if ( firstGen == TG_EXPLICIT ) { if (firstGen == TG_EXPLICIT) {
firstGen = pd->parseStages[i].texture.texgen; firstGen = pd->parseStages[i].texture.texgen;
} else if ( firstGen != pd->parseStages[i].texture.texgen ) { }
common->Warning( "material '%s' has multiple stages with a texgen", GetName() ); else if (firstGen != pd->parseStages[i].texture.texgen) {
common->Warning("material '%s' has multiple stages with a texgen", GetName());
break; break;
} }
} }
+147 -109
View File
@@ -42,6 +42,15 @@ class idCinematic;
class idUserInterface; class idUserInterface;
class idMegaTexture; class idMegaTexture;
#ifdef PREY
// HUMANHEAD tmj: type of subview that this surface represents
typedef enum {
SC_MIRROR,
SC_PORTAL,
SC_PORTAL_SKYBOX,
} subviewClass_t;
#endif
// moved from image.h for default parm // moved from image.h for default parm
typedef enum { typedef enum {
TF_LINEAR, TF_LINEAR,
@@ -133,6 +142,10 @@ typedef enum {
EXP_REG_GLOBAL6, EXP_REG_GLOBAL6,
EXP_REG_GLOBAL7, EXP_REG_GLOBAL7,
#ifdef PREY
EXP_REG_DISTANCE, // HUMANHEAD: CJR
#endif
EXP_REG_NUM_PREDEFINED EXP_REG_NUM_PREDEFINED
} expRegister_t; } expRegister_t;
@@ -157,8 +170,8 @@ typedef enum {
} texgen_t; } texgen_t;
typedef struct { typedef struct {
idCinematic * cinematic; idCinematic* cinematic;
idImage * image; idImage* image;
texgen_t texgen; texgen_t texgen;
bool hasMatrix; bool hasMatrix;
int matrix[2][3]; // we only allow a subset of the full projection matrix int matrix[2][3]; // we only allow a subset of the full projection matrix
@@ -195,9 +208,9 @@ typedef struct {
int fragmentProgram; int fragmentProgram;
int numFragmentProgramImages; int numFragmentProgramImages;
idImage * fragmentProgramImages[MAX_FRAGMENT_IMAGES]; idImage* fragmentProgramImages[MAX_FRAGMENT_IMAGES];
idMegaTexture *megaTexture; // handles all the binding and parameter setting idMegaTexture* megaTexture; // handles all the binding and parameter setting
} newShaderStage_t; } newShaderStage_t;
typedef struct { typedef struct {
@@ -213,7 +226,7 @@ typedef struct {
// if the surface is alpha tested // if the surface is alpha tested
float privatePolygonOffset; // a per-stage polygon offset float privatePolygonOffset; // a per-stage polygon offset
newShaderStage_t *newStage; // vertex / fragment program based stage newShaderStage_t* newStage; // vertex / fragment program based stage
} shaderStage_t; } shaderStage_t;
typedef enum { typedef enum {
@@ -266,6 +279,10 @@ typedef enum {
MF_NOSELFSHADOW = BIT(4), MF_NOSELFSHADOW = BIT(4),
MF_NOPORTALFOG = BIT(5), // this fog volume won't ever consider a portal fogged out MF_NOPORTALFOG = BIT(5), // this fog volume won't ever consider a portal fogged out
MF_EDITOR_VISIBLE = BIT(6), // in use (visible) per editor MF_EDITOR_VISIBLE = BIT(6), // in use (visible) per editor
#ifdef PREY
MF_USESDISTANCE = BIT(7), // HUMANHEAD pdm: distance optimization
MF_LIGHT_WHOLE_MESH = BIT(8), // HUMANHEAD bjk: don't cull tris with light bounds
#endif
MF_SKIPCLIP = BIT(9) MF_SKIPCLIP = BIT(9)
} materialFlags_t; } materialFlags_t;
@@ -314,7 +331,7 @@ typedef enum {
CONTENTS_NOCSG = BIT(21), // don't cut this brush with CSG operations in the editor CONTENTS_NOCSG = BIT(21), // don't cut this brush with CSG operations in the editor
#endif #endif
CONTENTS_REMOVE_UTIL = ~(CONTENTS_AREAPORTAL|CONTENTS_NOCSG) CONTENTS_REMOVE_UTIL = ~(CONTENTS_AREAPORTAL | CONTENTS_NOCSG)
} contentsFlags_t; } contentsFlags_t;
// surface types // surface types
@@ -367,7 +384,7 @@ typedef enum {
SURF_TYPE_BIT1 = BIT(1), // " SURF_TYPE_BIT1 = BIT(1), // "
SURF_TYPE_BIT2 = BIT(2), // " SURF_TYPE_BIT2 = BIT(2), // "
SURF_TYPE_BIT3 = BIT(3), // " SURF_TYPE_BIT3 = BIT(3), // "
SURF_TYPE_MASK = ( 1 << NUM_SURFACE_BITS ) - 1, SURF_TYPE_MASK = (1 << NUM_SURFACE_BITS) - 1,
SURF_NODAMAGE = BIT(4), // never give falling damage SURF_NODAMAGE = BIT(4), // never give falling damage
SURF_SLICK = BIT(5), // effects game physics SURF_SLICK = BIT(5), // effects game physics
@@ -388,106 +405,115 @@ public:
idMaterial(); idMaterial();
virtual ~idMaterial(); virtual ~idMaterial();
virtual size_t Size( void ) const; virtual size_t Size(void) const;
virtual bool SetDefaultText( void ); virtual bool SetDefaultText(void);
virtual const char *DefaultDefinition( void ) const; virtual const char* DefaultDefinition(void) const;
virtual bool Parse( const char *text, const int textLength ); virtual bool Parse(const char* text, const int textLength);
virtual void FreeData( void ); virtual void FreeData(void);
virtual void Print( void ) const; virtual void Print(void) const;
//BSM Nerve: Added for material editor //BSM Nerve: Added for material editor
bool Save( const char *fileName = NULL ); bool Save(const char* fileName = NULL);
// returns the internal image name for stage 0, which can be used // returns the internal image name for stage 0, which can be used
// for the renderer CaptureRenderToImage() call // for the renderer CaptureRenderToImage() call
// I'm not really sure why this needs to be virtual... // I'm not really sure why this needs to be virtual...
virtual const char *ImageName( void ) const; virtual const char* ImageName(void) const;
void ReloadImages( bool force ) const; void ReloadImages(bool force) const;
// returns number of stages this material contains // returns number of stages this material contains
const int GetNumStages( void ) const { return numStages; } const int GetNumStages(void) const { return numStages; }
// get a specific stage // get a specific stage
const shaderStage_t *GetStage( const int index ) const { assert(index >= 0 && index < numStages); return &stages[index]; } const shaderStage_t* GetStage(const int index) const { assert(index >= 0 && index < numStages); return &stages[index]; }
// get the first bump map stage, or NULL if not present. // get the first bump map stage, or NULL if not present.
// used for bumpy-specular // used for bumpy-specular
const shaderStage_t *GetBumpStage( void ) const; const shaderStage_t* GetBumpStage(void) const;
#ifdef PREY
// HUMANHEAD tmj: returns how the subview should be rendered (mirror/portal/skybox)
subviewClass_t GetSubviewClass(void) const { return subviewClass; }
#endif
// returns true if the material will draw anything at all. Triggers, portals, // returns true if the material will draw anything at all. Triggers, portals,
// etc, will not have anything to draw. A not drawn surface can still castShadow, // etc, will not have anything to draw. A not drawn surface can still castShadow,
// which can be used to make a simplified shadow hull for a complex object set // which can be used to make a simplified shadow hull for a complex object set
// as noShadow // as noShadow
bool IsDrawn( void ) const { return ( numStages > 0 || entityGui != 0 || gui != NULL ); } bool IsDrawn(void) const { return (numStages > 0 || entityGui != 0 || gui != NULL); }
// returns true if the material will draw any non light interaction stages // returns true if the material will draw any non light interaction stages
bool HasAmbient( void ) const { return ( numAmbientStages > 0 ); } bool HasAmbient(void) const { return (numAmbientStages > 0); }
// returns true if material has a gui // returns true if material has a gui
bool HasGui( void ) const { return ( entityGui != 0 || gui != NULL ); } bool HasGui(void) const { return (entityGui != 0 || gui != NULL); }
// returns true if the material will generate another view, either as // returns true if the material will generate another view, either as
// a mirror or dynamic rendered image // a mirror or dynamic rendered image
bool HasSubview( void ) const { return hasSubview; } bool HasSubview(void) const { return hasSubview; }
// returns true if the material will generate shadows, not making a // returns true if the material will generate shadows, not making a
// distinction between global and no-self shadows // distinction between global and no-self shadows
bool SurfaceCastsShadow( void ) const { return TestMaterialFlag( MF_FORCESHADOWS ) || !TestMaterialFlag( MF_NOSHADOWS ); } bool SurfaceCastsShadow(void) const { return TestMaterialFlag(MF_FORCESHADOWS) || !TestMaterialFlag(MF_NOSHADOWS); }
// returns true if the material will generate interactions with fog/blend lights // returns true if the material will generate interactions with fog/blend lights
// All non-translucent surfaces receive fog unless they are explicitly noFog // All non-translucent surfaces receive fog unless they are explicitly noFog
bool ReceivesFog( void ) const { return ( IsDrawn() && !noFog && coverage != MC_TRANSLUCENT ); } bool ReceivesFog(void) const { return (IsDrawn() && !noFog && coverage != MC_TRANSLUCENT); }
// jmarshall // jmarshall
idImage* GetDiffuseImage(void) const; idImage* GetDiffuseImage(void) const;
idImage* GetBumpImage(void) const; idImage* GetBumpImage(void) const;
bool IsSky(void) const; bool IsSky(void) const;
// jmarshall end // jmarshall end
// returns true if the material will generate interactions with normal lights // returns true if the material will generate interactions with normal lights
// Many special effect surfaces don't have any bump/diffuse/specular // Many special effect surfaces don't have any bump/diffuse/specular
// stages, and don't interact with lights at all // stages, and don't interact with lights at all
bool ReceivesLighting( void ) const { return numAmbientStages != numStages; } bool ReceivesLighting(void) const { return numAmbientStages != numStages; }
// returns true if the material should generate interactions on sides facing away // returns true if the material should generate interactions on sides facing away
// from light centers, as with noshadow and noselfshadow options // from light centers, as with noshadow and noselfshadow options
bool ReceivesLightingOnBackSides( void ) const { return ( materialFlags & (MF_NOSELFSHADOW|MF_NOSHADOWS) ) != 0; } bool ReceivesLightingOnBackSides(void) const { return (materialFlags & (MF_NOSELFSHADOW | MF_NOSHADOWS)) != 0; }
// Standard two-sided triangle rendering won't work with bump map lighting, because // Standard two-sided triangle rendering won't work with bump map lighting, because
// the normal and tangent vectors won't be correct for the back sides. When two // the normal and tangent vectors won't be correct for the back sides. When two
// sided lighting is desired. typically for alpha tested surfaces, this is // sided lighting is desired. typically for alpha tested surfaces, this is
// addressed by having CleanupModelSurfaces() create duplicates of all the triangles // addressed by having CleanupModelSurfaces() create duplicates of all the triangles
// with apropriate order reversal. // with apropriate order reversal.
bool ShouldCreateBackSides( void ) const { return shouldCreateBackSides; } bool ShouldCreateBackSides(void) const { return shouldCreateBackSides; }
// characters and models that are created by a complete renderbump can use a faster // characters and models that are created by a complete renderbump can use a faster
// method of tangent and normal vector generation than surfaces which have a flat // method of tangent and normal vector generation than surfaces which have a flat
// renderbump wrapped over them. // renderbump wrapped over them.
bool UseUnsmoothedTangents( void ) const { return unsmoothedTangents; } bool UseUnsmoothedTangents(void) const { return unsmoothedTangents; }
// by default, monsters can have blood overlays placed on them, but this can // by default, monsters can have blood overlays placed on them, but this can
// be overrided on a per-material basis with the "noOverlays" material command. // be overrided on a per-material basis with the "noOverlays" material command.
// This will always return false for translucent surfaces // This will always return false for translucent surfaces
bool AllowOverlays( void ) const { return allowOverlays; } bool AllowOverlays(void) const { return allowOverlays; }
// MC_OPAQUE, MC_PERFORATED, or MC_TRANSLUCENT, for interaction list linking and // MC_OPAQUE, MC_PERFORATED, or MC_TRANSLUCENT, for interaction list linking and
// dmap flood filling // dmap flood filling
// The depth buffer will not be filled for MC_TRANSLUCENT surfaces // The depth buffer will not be filled for MC_TRANSLUCENT surfaces
// FIXME: what do nodraw surfaces return? // FIXME: what do nodraw surfaces return?
materialCoverage_t Coverage( void ) const { return coverage; } materialCoverage_t Coverage(void) const { return coverage; }
// returns true if this material takes precedence over other in coplanar cases // returns true if this material takes precedence over other in coplanar cases
bool HasHigherDmapPriority( const idMaterial &other ) const { return ( IsDrawn() && !other.IsDrawn() ) || bool HasHigherDmapPriority(const idMaterial& other) const {
( Coverage() < other.Coverage() ); } return (IsDrawn() && !other.IsDrawn()) ||
(Coverage() < other.Coverage());
}
// returns a idUserInterface if it has a global gui, or NULL if no gui // returns a idUserInterface if it has a global gui, or NULL if no gui
idUserInterface * GlobalGui( void ) const { return gui; } idUserInterface* GlobalGui(void) const { return gui; }
// a discrete surface will never be merged with other surfaces by dmap, which is // a discrete surface will never be merged with other surfaces by dmap, which is
// necessary to prevent mutliple gui surfaces, mirrors, autosprites, and some other // necessary to prevent mutliple gui surfaces, mirrors, autosprites, and some other
// special effects from being combined into a single surface // special effects from being combined into a single surface
// guis, merging sprites or other effects, mirrors and remote views are always discrete // guis, merging sprites or other effects, mirrors and remote views are always discrete
bool IsDiscrete( void ) const { return ( entityGui || gui || deform != DFRM_NONE || sort == SS_SUBVIEW || bool IsDiscrete(void) const {
( surfaceFlags & SURF_DISCRETE ) != 0 ); } return (entityGui || gui || deform != DFRM_NONE || sort == SS_SUBVIEW ||
(surfaceFlags & SURF_DISCRETE) != 0);
}
// Normally, dmap chops each surface by every BSP boundary, then reoptimizes. // Normally, dmap chops each surface by every BSP boundary, then reoptimizes.
// For gigantic polygons like sky boxes, this can cause a huge number of planar // For gigantic polygons like sky boxes, this can cause a huge number of planar
@@ -497,7 +523,7 @@ public:
// of not automatically fixing up interpenetrations, so when this is used, you // of not automatically fixing up interpenetrations, so when this is used, you
// should manually make the edges of your sky box exactly meet, instead of poking // should manually make the edges of your sky box exactly meet, instead of poking
// into each other. // into each other.
bool NoFragment( void ) const { return ( surfaceFlags & SURF_NOFRAGMENT ) != 0; } bool NoFragment(void) const { return (surfaceFlags & SURF_NOFRAGMENT) != 0; }
//------------------------------------------------------------------ //------------------------------------------------------------------
// light shader specific functions, only called for light entities // light shader specific functions, only called for light entities
@@ -513,8 +539,10 @@ public:
// implicitly no-shadows lights (ambients, fogs, etc) will never cast shadows // implicitly no-shadows lights (ambients, fogs, etc) will never cast shadows
// but individual light entities can also override this value // but individual light entities can also override this value
bool LightCastsShadows() const { return TestMaterialFlag( MF_FORCESHADOWS ) || bool LightCastsShadows() const {
( !fogLight && !ambientLight && !blendLight && !TestMaterialFlag( MF_NOSHADOWS ) ); } return TestMaterialFlag(MF_FORCESHADOWS) ||
(!fogLight && !ambientLight && !blendLight && !TestMaterialFlag(MF_NOSHADOWS));
}
// fog lights, blend lights, ambient lights, etc will all have to have interaction // fog lights, blend lights, ambient lights, etc will all have to have interaction
// triangles generated for sides facing away from the light as well as those // triangles generated for sides facing away from the light as well as those
@@ -525,97 +553,97 @@ public:
bool LightEffectsBackSides() const { return fogLight || ambientLight || blendLight; } bool LightEffectsBackSides() const { return fogLight || ambientLight || blendLight; }
// NULL unless an image is explicitly specified in the shader with "lightFalloffShader <image>" // NULL unless an image is explicitly specified in the shader with "lightFalloffShader <image>"
idImage * LightFalloffImage() const { return lightFalloffImage; } idImage* LightFalloffImage() const { return lightFalloffImage; }
//------------------------------------------------------------------ //------------------------------------------------------------------
// returns the renderbump command line for this shader, or an empty string if not present // returns the renderbump command line for this shader, or an empty string if not present
const char * GetRenderBump() const { return renderBump; }; const char* GetRenderBump() const { return renderBump; };
// set specific material flag(s) // set specific material flag(s)
void SetMaterialFlag( const int flag ) const { materialFlags |= flag; } void SetMaterialFlag(const int flag) const { materialFlags |= flag; }
// clear specific material flag(s) // clear specific material flag(s)
void ClearMaterialFlag( const int flag ) const { materialFlags &= ~flag; } void ClearMaterialFlag(const int flag) const { materialFlags &= ~flag; }
// test for existance of specific material flag(s) // test for existance of specific material flag(s)
bool TestMaterialFlag( const int flag ) const { return ( materialFlags & flag ) != 0; } bool TestMaterialFlag(const int flag) const { return (materialFlags & flag) != 0; }
// get content flags // get content flags
const int GetContentFlags( void ) const { return contentFlags; } const int GetContentFlags(void) const { return contentFlags; }
// get surface flags // get surface flags
const int GetSurfaceFlags( void ) const { return surfaceFlags; } const int GetSurfaceFlags(void) const { return surfaceFlags; }
// gets name for surface type (stone, metal, flesh, etc.) // gets name for surface type (stone, metal, flesh, etc.)
const surfTypes_t GetSurfaceType( void ) const { return static_cast<surfTypes_t>( surfaceFlags & SURF_TYPE_MASK ); } const surfTypes_t GetSurfaceType(void) const { return static_cast<surfTypes_t>(surfaceFlags & SURF_TYPE_MASK); }
// get material description // get material description
const char * GetDescription( void ) const { return desc; } const char* GetDescription(void) const { return desc; }
// get sort order // get sort order
const float GetSort( void ) const { return sort; } const float GetSort(void) const { return sort; }
// this is only used by the gui system to force sorting order // this is only used by the gui system to force sorting order
// on images referenced from tga's instead of materials. // on images referenced from tga's instead of materials.
// this is done this way as there are 2000 tgas the guis use // this is done this way as there are 2000 tgas the guis use
void SetSort( float s ) const { sort = s; }; void SetSort(float s) const { sort = s; };
// DFRM_NONE, DFRM_SPRITE, etc // DFRM_NONE, DFRM_SPRITE, etc
deform_t Deform( void ) const { return deform; } deform_t Deform(void) const { return deform; }
// flare size, expansion size, etc // flare size, expansion size, etc
const int GetDeformRegister( int index ) const { return deformRegisters[index]; } const int GetDeformRegister(int index) const { return deformRegisters[index]; }
// particle system to emit from surface and table for turbulent // particle system to emit from surface and table for turbulent
const idDecl *GetDeformDecl( void ) const { return deformDecl; } const idDecl* GetDeformDecl(void) const { return deformDecl; }
// currently a surface can only have one unique texgen for all the stages // currently a surface can only have one unique texgen for all the stages
texgen_t Texgen() const; texgen_t Texgen() const;
// wobble sky parms // wobble sky parms
const int * GetTexGenRegisters( void ) const { return texGenRegisters; } const int* GetTexGenRegisters(void) const { return texGenRegisters; }
// get cull type // get cull type
const cullType_t GetCullType( void ) const { return cullType; } const cullType_t GetCullType(void) const { return cullType; }
float GetEditorAlpha( void ) const { return editorAlpha; } float GetEditorAlpha(void) const { return editorAlpha; }
int GetEntityGui( void ) const { return entityGui; } int GetEntityGui(void) const { return entityGui; }
decalInfo_t GetDecalInfo( void ) const { return decalInfo; } decalInfo_t GetDecalInfo(void) const { return decalInfo; }
// spectrums are used for "invisible writing" that can only be // spectrums are used for "invisible writing" that can only be
// illuminated by a light of matching spectrum // illuminated by a light of matching spectrum
int Spectrum( void ) const { return spectrum; } int Spectrum(void) const { return spectrum; }
float GetPolygonOffset( void ) const { return polygonOffset; } float GetPolygonOffset(void) const { return polygonOffset; }
float GetSurfaceArea( void ) const { return surfaceArea; } float GetSurfaceArea(void) const { return surfaceArea; }
void AddToSurfaceArea( float area ) { surfaceArea += area; } void AddToSurfaceArea(float area) { surfaceArea += area; }
//------------------------------------------------------------------ //------------------------------------------------------------------
// returns the length, in milliseconds, of the videoMap on this material, // returns the length, in milliseconds, of the videoMap on this material,
// or zero if it doesn't have one // or zero if it doesn't have one
int CinematicLength( void ) const; int CinematicLength(void) const;
void CloseCinematic( void ) const; void CloseCinematic(void) const;
void ResetCinematicTime( int time ) const; void ResetCinematicTime(int time) const;
void UpdateCinematic( int time ) const; void UpdateCinematic(int time) const;
//------------------------------------------------------------------ //------------------------------------------------------------------
// gets an image for the editor to use // gets an image for the editor to use
idImage * GetEditorImage( void ) const; idImage* GetEditorImage(void) const;
int GetImageWidth( void ) const; int GetImageWidth(void) const;
int GetImageHeight( void ) const; int GetImageHeight(void) const;
void SetGui( const char *_gui ) const; void SetGui(const char* _gui) const;
// just for resource tracking // just for resource tracking
void SetImageClassifications( int tag ) const; void SetImageClassifications(int tag) const;
//------------------------------------------------------------------ //------------------------------------------------------------------
@@ -623,61 +651,71 @@ public:
const int GetNumRegisters() const { return numRegisters; } const int GetNumRegisters() const { return numRegisters; }
// regs should point to a float array large enough to hold GetNumRegisters() floats // regs should point to a float array large enough to hold GetNumRegisters() floats
void EvaluateRegisters( float *regs, const float entityParms[MAX_ENTITY_SHADER_PARMS], void EvaluateRegisters(float* regs, const float entityParms[MAX_ENTITY_SHADER_PARMS],
const struct viewDef_s *view, idSoundEmitter *soundEmitter = NULL ) const; const struct viewDef_s* view, idSoundEmitter* soundEmitter = NULL) const;
// if a material only uses constants (no entityParm or globalparm references), this // if a material only uses constants (no entityParm or globalparm references), this
// will return a pointer to an internal table, and EvaluateRegisters will not need // will return a pointer to an internal table, and EvaluateRegisters will not need
// to be called. If NULL is returned, EvaluateRegisters must be used. // to be called. If NULL is returned, EvaluateRegisters must be used.
const float * ConstantRegisters() const; const float* ConstantRegisters() const;
bool SuppressInSubview() const { return suppressInSubview; }; bool SuppressInSubview() const { return suppressInSubview; };
bool IsPortalSky() const { return portalSky; }; bool IsPortalSky() const { return portalSky; };
void AddReference(); void AddReference();
#ifdef PREY
int GetDirectPortalDistance() const { return directPortalDistance; } // HUMANHEAD CJR
#endif
private: private:
// parse the entire material // parse the entire material
void CommonInit(); void CommonInit();
void ParseMaterial( idLexer &src ); void ParseMaterial(idLexer& src);
bool MatchToken( idLexer &src, const char *match ); bool MatchToken(idLexer& src, const char* match);
void ParseSort( idLexer &src ); void ParseSort(idLexer& src);
void ParseBlend( idLexer &src, shaderStage_t *stage ); void ParseBlend(idLexer& src, shaderStage_t* stage);
void ParseVertexParm( idLexer &src, newShaderStage_t *newStage ); void ParseVertexParm(idLexer& src, newShaderStage_t* newStage);
void ParseFragmentMap( idLexer &src, newShaderStage_t *newStage ); void ParseFragmentMap(idLexer& src, newShaderStage_t* newStage);
void ParseStage( idLexer &src, const textureRepeat_t trpDefault = TR_REPEAT ); void ParseStage(idLexer& src, const textureRepeat_t trpDefault = TR_REPEAT);
void ParseDeform( idLexer &src ); void ParseDeform(idLexer& src);
void ParseDecalInfo( idLexer &src ); void ParseDecalInfo(idLexer& src);
bool CheckSurfaceParm( idToken *token ); bool CheckSurfaceParm(idToken* token);
int GetExpressionConstant( float f ); int GetExpressionConstant(float f);
int GetExpressionTemporary( void ); int GetExpressionTemporary(void);
expOp_t * GetExpressionOp( void ); expOp_t* GetExpressionOp(void);
int EmitOp( int a, int b, expOpType_t opType ); int EmitOp(int a, int b, expOpType_t opType);
int ParseEmitOp( idLexer &src, int a, expOpType_t opType, int priority ); int ParseEmitOp(idLexer& src, int a, expOpType_t opType, int priority);
int ParseTerm( idLexer &src ); int ParseTerm(idLexer& src);
int ParseExpressionPriority( idLexer &src, int priority ); int ParseExpressionPriority(idLexer& src, int priority);
int ParseExpression( idLexer &src ); int ParseExpression(idLexer& src);
void ClearStage( shaderStage_t *ss ); void ClearStage(shaderStage_t* ss);
int NameToSrcBlendMode( const idStr &name ); int NameToSrcBlendMode(const idStr& name);
int NameToDstBlendMode( const idStr &name ); int NameToDstBlendMode(const idStr& name);
void MultiplyTextureMatrix( textureStage_t *ts, int registers[2][3] ); // FIXME: for some reason the const is bad for gcc and Mac void MultiplyTextureMatrix(textureStage_t* ts, int registers[2][3]); // FIXME: for some reason the const is bad for gcc and Mac
void SortInteractionStages(); void SortInteractionStages();
void AddImplicitStages( const textureRepeat_t trpDefault = TR_REPEAT ); void AddImplicitStages(const textureRepeat_t trpDefault = TR_REPEAT);
void CheckForConstantRegisters(); void CheckForConstantRegisters();
private: private:
#ifdef PREY
subviewClass_t subviewClass; // HUMANHEAD tmj: Type of subview this surface points to
#endif
idStr desc; // description idStr desc; // description
idStr renderBump; // renderbump command options, without the "renderbump" at the start idStr renderBump; // renderbump command options, without the "renderbump" at the start
idImage * lightFalloffImage; idImage* lightFalloffImage;
int entityGui; // draw a gui with the idUserInterface from the renderEntity_t int entityGui; // draw a gui with the idUserInterface from the renderEntity_t
// non zero will draw gui, gui2, or gui3 from renderEnitty_t // non zero will draw gui, gui2, or gui3 from renderEnitty_t
mutable idUserInterface *gui; // non-custom guis are shared by all users of a material mutable idUserInterface* gui; // non-custom guis are shared by all users of a material
bool noFog; // surface does not create fog interactions bool noFog; // surface does not create fog interactions
int spectrum; // for invisible writing, used for both lights and surfaces int spectrum; // for invisible writing, used for both lights and surfaces
#ifdef PREY
int directPortalDistance; // HUMANHEAD: Distance at which direct render portals are drawn
#endif
float polygonOffset; float polygonOffset;
int contentFlags; // content flags int contentFlags; // content flags
@@ -690,7 +728,7 @@ private:
mutable float sort; // lower numbered shaders draw before higher numbered mutable float sort; // lower numbered shaders draw before higher numbered
deform_t deform; deform_t deform;
int deformRegisters[4]; // numeric parameter for deforms int deformRegisters[4]; // numeric parameter for deforms
const idDecl *deformDecl; // for surface emitted particle deforms and tables const idDecl* deformDecl; // for surface emitted particle deforms and tables
int texGenRegisters[MAX_TEXGEN_REGISTERS]; // for wobbleSky int texGenRegisters[MAX_TEXGEN_REGISTERS]; // for wobbleSky
@@ -706,19 +744,19 @@ private:
bool allowOverlays; bool allowOverlays;
int numOps; int numOps;
expOp_t * ops; // evaluate to make expressionRegisters expOp_t* ops; // evaluate to make expressionRegisters
int numRegisters; // int numRegisters; //
float * expressionRegisters; float* expressionRegisters;
float * constantRegisters; // NULL if ops ever reference globalParms or entityParms float* constantRegisters; // NULL if ops ever reference globalParms or entityParms
int numStages; int numStages;
int numAmbientStages; int numAmbientStages;
shaderStage_t * stages; shaderStage_t* stages;
struct mtrParsingData_s *pd; // only used during parsing struct mtrParsingData_s* pd; // only used during parsing
float surfaceArea; // only for listSurfaceAreas float surfaceArea; // only for listSurfaceAreas
@@ -726,7 +764,7 @@ private:
// all the invisible and uncompressed images. // all the invisible and uncompressed images.
// If editorImage is NULL, it will atempt to load editorImageName, and set editorImage to that or defaultImage // If editorImage is NULL, it will atempt to load editorImageName, and set editorImage to that or defaultImage
idStr editorImageName; idStr editorImageName;
mutable idImage * editorImage; // image used for non-shaded preview mutable idImage* editorImage; // image used for non-shaded preview
float editorAlpha; float editorAlpha;
bool suppressInSubview; bool suppressInSubview;
@@ -734,6 +772,6 @@ private:
int refCount; int refCount;
}; };
typedef idList<const idMaterial *> idMatList; typedef idList<const idMaterial*> idMatList;
#endif /* !__MATERIAL_H__ */ #endif /* !__MATERIAL_H__ */