📄 entity.cpp
字号:
geVec3d_Subtract(&mOrigin, &wPoint, &wPoint);
return geVec3d_Length(&wPoint);
}
else
{
return 0;
}
}
// check whether or not this entity is within this
// bounding box
//==================================================================
// When we are done moving the entity we want to snap it to the
// grid etc.
//==================================================================
#define RoundDouble(x) (floor( (x) + 0.5 ))
static float SnapToGrid
(
float x,
double GridSize
)
{
return (float)(RoundDouble ((x/GridSize) ) * GridSize) ;
}
void CEntity::DoneMove(double GridSize, const EntityTable *pEntityDefs)
{
float x, y, z;
// Snap to the grid
x = SnapToGrid (mOrigin.X, GridSize);
y = SnapToGrid (mOrigin.Y, GridSize);
z = SnapToGrid (mOrigin.Z, GridSize);
SetOrigin (x, y, z, pEntityDefs);
}
// update our origin
void CEntity::UpdateOriginFirst(const EntityTable *pEntityDefs)
{
// find our origin
CString OriginStr;
// if we empty leave
if (!GetOriginString (OriginStr, pEntityDefs))
{
EntityStyle = ENTITY_S_BRUSH;
return;
}
else
{
EntityStyle = ENTITY_S_ORIGIN;
}
// get our x y z
int x, y, z;
sscanf(OriginStr, "%d %d %d", &x, &y, &z);
SetOrigin ((float)x, (float)y, (float)z, pEntityDefs);
}
#define CENTITYTYPE "CEntity"
#define CENTSTYLE "eStyle"
#define CENTORIGIN "eOrigin"
#define CENTRENDERORIGIN "eRenderOrigin"
#define CENTPAIRCOUNT "ePairCount"
#define CENTFLAGS "eFlags"
#define CENTGROUP "eGroup"
#define CENTKEY "K"
#define CENTVALUE "V"
#define CENDENTTYPE "End CEntity"
// -------------------------------------------------------------------------------
// saves the entity out to a specified file stream
geBoolean CEntity::SaveToFile( FILE *file )
{
ASSERT( file );
int Count; // number of keys
if (fprintf(file, "CEntity\neStyle %d\n", EntityStyle ) < 0) return GE_FALSE;
if (fprintf(file, "eOrigin %d %d %d 2\n",
Units_Round( mOrigin.X ), Units_Round( mOrigin.Y ), Units_Round( mOrigin.Z ) ) < 0) return GE_FALSE;
if (fprintf(file, "eFlags %d\n", mFlags) < 0) return GE_FALSE;
if (fprintf(file, "eGroup %d\n", mGroup) < 0) return GE_FALSE;
Count = GetNumKeyValuePairs ();
if (fprintf(file, "ePairCount %d\n", Count) < 0) return GE_FALSE;
for (int j = 0; j < Count; j++)
{
CString Key, Value;
if (GetKeyValuePair (j, Key, Value))
{
char QuotedValue[SCANNER_MAXDATA];
Util_QuoteString (Value, QuotedValue);
if (fprintf (file, "Key %s Value %s\n", (LPCSTR)Key, QuotedValue) < 0) return GE_FALSE;
}
}
return GE_TRUE;
}
static char *StripNewline
(
char *s
)
// terminates the string at the first cr or lf character
{
char *c;
ASSERT (s != NULL);
c = s;
while (*c != '\0')
{
switch (*c)
{
case '\r' :
case '\n' :
*c = '\0';
break;
default :
++c;
break;
}
}
return s;
}
// -----------------------------------------------------------------------------------
// reads the entity in from a specified file stream
geBoolean CEntity::ReadFromFile
(
Parse3dt *Parser,
int VersionMajor,
int VersionMinor,
const char **Expected,
const EntityTable *pEntityDefs
)
{
int Trash;
int Count;
assert (Parser != NULL);
if (!Parse3dt_ScanExpectingText (Parser, (*Expected = "CEntity"))) return GE_FALSE;
if (!Parse3dt_GetInt (Parser, (*Expected = "eStyle"), &Trash)) return GE_FALSE;
EntityStyle = (enum EntityStyles)Trash;
if (!Parse3dt_GetVec3d (Parser, (*Expected = "eOrigin"), &mOrigin)) return GE_FALSE;
if (!Parse3dt_GetInt (Parser, NULL, &Trash)) return GE_FALSE;
if ((VersionMajor == 1) && (VersionMinor < 21))
{
geVec3d TrashVec;
if (!Parse3dt_GetVec3d (Parser, (*Expected = "eRenderOrigin"), &TrashVec)) return GE_FALSE;
if (!Parse3dt_GetInt (Parser, NULL, &Trash)) return GE_FALSE;
}
// need to flip Z on file versions prior to 1.4
if ((VersionMajor==1) && (VersionMinor < 4))
{
mOrigin.Z =-mOrigin.Z;
}
if (!Parse3dt_GetInt (Parser, (*Expected = "eFlags"), &mFlags)) return GE_FALSE;
if (!Parse3dt_GetInt (Parser, (*Expected = "eGroup"), &mGroup)) return GE_FALSE;
if( (VersionMajor==1) && (VersionMinor <= 6 ) )
{
if( mGroup == -1 ) // "No group" was -1 and now is 0
mGroup = 0 ;
}
if (!Parse3dt_GetInt (Parser, (*Expected = "ePairCount"), &Count)) return GE_FALSE;
if ((VersionMajor == 1) && (VersionMinor < 14))
{
// old key/value stuff
FILE *file;
file = Scanner_GetFile (Parser->Scanner);
for( int j = 0; j < Count; j++)
{
char Key[255];
char Value[255];
fscanf( file, "K " );
fgets( Key, 255, file );
StripNewline (Key);
fscanf( file, "V " );
fgets( Value, 255, file );
StripNewline (Value);
this->SetKeyValue (Key, Value);
}
}
else
{
int j;
char Key[SCANNER_MAXDATA];
char Value[SCANNER_MAXDATA];
for (j = 0; j < Count; ++j)
{
if (!Parse3dt_GetIdentifier (Parser, (*Expected = "Key"), Key)) return GE_FALSE;
if (!Parse3dt_GetLiteral (Parser, (*Expected = "Value"), Value)) return GE_FALSE;
SetKeyValue (Key, Value);
}
}
/*
If the Z was flipped above (i.e. this is a version 1.3 file or earlier,
then the Z in the origin key string (if it exists) will not agree
with mOrigin.Z.
So here we make sure they agree. This has the effect of making the
origin key string superfluous on save/restore, but wtf.
*/
//versions < 1.10 need to convert to texels from centimeters
if ((VersionMajor==1) && (VersionMinor < 10))
{
geVec3d_Scale (&mOrigin, Units_CentimetersToEngine (1.0f), &mOrigin);
}
SetOrigin (mOrigin.X, mOrigin.Y, mOrigin.Z, pEntityDefs);
return GE_TRUE;
}
void CEntity::SetGroupId
(
int id
)
{
this->mGroup = id;
}
int CEntity::GetGroupId
(
void
) const
{
return this->mGroup;
}
void CEntity::SetVisible
(
BOOL flag
)
{
if (flag)
{
this->mFlags &= ~ENTITY_HIDDEN;
}
else
{
this->mFlags |= ENTITY_HIDDEN;
}
}
BOOL CEntity::IsVisible
(
void
) const
{
return !(this->mFlags & ENTITY_HIDDEN);
}
void CEntity::SetLock
(
BOOL flag
)
{
if (flag)
{
this->mFlags |= ENTITY_LOCKED;
}
else
{
this->mFlags &= ~ENTITY_LOCKED;
}
}
BOOL CEntity::IsLocked
(
void
) const
{
return (this->mFlags & ENTITY_LOCKED);
}
static CEntity const *EntityList_FindByName
(
CEntityArray *pEnts,
char const *pName
)
{
for (int i = 0; i < pEnts->GetSize (); ++i)
{
CEntity const *pEnt;
CString Name;
// pEnt = &((*mEntityArray)[CurrentEnt]);
pEnt = &((*pEnts)[i]);
pEnt->GetKeyValue ("%name%", Name);
if (stricmp (pName, Name) == 0)
{
return pEnt;
}
}
return NULL;
}
CEntity * EntityList_FindByClassName
(
CEntityArray * pEnts,
const char * pName
)
{
CEntity * pEnt;
for (int i = 0; i < pEnts->GetSize (); ++i)
{
pEnt = &((*pEnts)[i]);
if( pEnt->GetClassname().Compare( pName ) == 0 )
{
return pEnt;
}
}
return NULL;
}/* EntityList_FindByClassName */
BOOL CEntity::IsValidKey
(
CString const &Key,
ModelList const *pModels,
CEntityArray const *pEnts,
const EntityTable *pEntityDefs
) const
// returns TRUE if the key is one of the specials, or if it has type information
{
BOOL Success;
TopType EntityType;
CString EntityClassname = GetClassname ();
if ((Key == CLASSNAME) || (Key == "%name%"))
{
Success = TRUE;
}
else
{
Success = EntityTable_GetEntityPropertyType (pEntityDefs, EntityClassname, Key, &EntityType);
if (Success)
{
CString Value;
GetKeyValue (Key, Value);
switch (EntityType)
{
case T_STRUCT :
{
// look for an entity with this name...
CEntity const *Target;
// yeah, I know the cast is ugly.
// FindByName didn't like taking the address of something in a
// const array. I don't know what the deal is...
Target = EntityList_FindByName (const_cast<CEntityArray *>(pEnts), Value);
Success = (Target != NULL);
break;
}
case T_MODEL :
{
// look for model of this name in models list
Model *pModel;
pModel = ModelList_FindByName (pModels, Value);
Success = (pModel != NULL);
break;
}
default :
break;
}
}
}
return Success;
}
int CEntity::GetNumValidKeyValuePairs
(
ModelList const *pModels,
CEntityArray const *pEnts,
const EntityTable *pEntityDefs
) const
{
int j;
int NumKeys;
int NumValidKeys;
NumValidKeys = 0;
NumKeys = GetNumKeyValuePairs ();
for (j = 0; j < NumKeys; j++)
{
CString Key, Value;
if (GetKeyValuePair (j, Key, Value))
{
BOOL Success;
// only count those that have type information entries
Success = IsValidKey (Key, pModels, pEnts, pEntityDefs);
if (Success)
{
++NumValidKeys;
}
}
}
return NumValidKeys;
}
// writes the entity out to the map file
void CEntity::WriteToMap
(
FILE *exfile,
ModelList const *pModels,
CEntityArray const *pEnts,
const EntityTable *pEntityDefs
) const
{
int NumValidKeys;
int NumKeys;
#ifdef _DEBUG
int NumKeysWritten;
#endif
CString EntityClassname = GetClassname ();
TypeIO_WriteInt (exfile, 0); // numbrushes
TypeIO_WriteInt (exfile, 0); // no motion data today
// output entity key/value pairs
// We output only those keys that have type information entries.
NumValidKeys = GetNumValidKeyValuePairs (pModels, pEnts, pEntityDefs);
TypeIO_WriteInt (exfile, NumValidKeys); //number of keys
NumKeys = GetNumKeyValuePairs ();
#ifdef _DEBUG
NumKeysWritten = 0;
#endif
for(int j = 0; j < NumKeys; j++)
{
CString Key, Value;
if (GetKeyValuePair (j, Key, Value))
{
// only output those that have type information entries
BOOL Success;
Success = IsValidKey (Key, pModels, pEnts, pEntityDefs);
if (Success)
{
char ValueString [100]; // string to store value
TopType KeyType;
// get the type.
// Since classname and %name% don't have type info,
// we need to check success flag ...
Success = EntityTable_GetEntityPropertyType (pEntityDefs, GetClassname(), Key, &KeyType);
// Boolean keys are converted to integer
if (Success && (KeyType == T_BOOLEAN))
{
if (Value == "True")
{
strcpy (ValueString, "1");
}
else
{
strcpy (ValueString, "0");
}
}
else
{
strcpy (ValueString, Value);
}
// output name and value
TypeIO_WriteString (exfile, Key);
TypeIO_WriteString (exfile, ValueString);
#ifdef _DEBUG
++NumKeysWritten;
#endif
}
}
}
#ifdef _DEBUG
assert (NumKeysWritten == NumValidKeys);
#endif
}
int EntityList_Enum
(
CEntityArray& EntityArray,
void * lParam,
EntityList_CB CallBack
)
{
geBoolean bResult = GE_TRUE ; // TRUE means entire list was processed
int i ;
for( i=0; i< EntityArray.GetSize(); i++ )
{
if( (bResult = CallBack( EntityArray[i], lParam )) == GE_FALSE )
break ;
}
return bResult ;
}
const geBitmap *CEntity::GetBitmapPtr (const EntityTable *pEntityDefs) const
{
return EntityTable_GetBitmapPtr (pEntityDefs, GetClassname ());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -