2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2023-10-07 12:04:27 +00:00
Copyright ( C ) 2015 - 2023 Robert Beckebans
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
# pragma hdrstop
2024-06-17 20:10:50 +00:00
# if !defined( DMAP )
# include "../renderer/Image.h"
# include "../renderer/DXT/DXTCodec.h"
# include "../renderer/Color/ColorSpace.h"
# include "../renderer/CmdlineProgressbar.h"
# endif
2012-11-26 18:58:24 +00:00
/*
GUIs and script remain separately parsed
Following a parse , all referenced media ( and other decls ) will have been touched .
sinTable and cosTable are required for the rotate material keyword to function
A new FindType on a purged decl will cause it to be reloaded , but a stale pointer to a purged
decl will look like a defaulted decl .
Moving a decl from one file to another will not be handled correctly by a reload , the material
will be defaulted .
NULL or empty decl names will always return NULL
Should probably make a default decl for this
Decls are initially created without a textSource
A parse without textSource set should always just call MakeDefault ( )
A parse that has an error should internally call MakeDefault ( )
A purge does nothing to a defaulted decl
Should we have a " purged " media state separate from the " defaulted " media state ?
reloading over a decl name that was defaulted
reloading over a decl name that was valid
missing reload over a previously explicit definition
*/
# define USE_COMPRESSED_DECLS
//#define GET_HUFFMAN_FREQUENCIES
2012-11-28 15:47:07 +00:00
class idDeclType
{
2012-11-26 18:58:24 +00:00
public :
idStr typeName ;
declType_t type ;
2012-11-28 15:47:07 +00:00
idDecl * ( * allocator ) ( ) ;
2012-11-26 18:58:24 +00:00
} ;
2012-11-28 15:47:07 +00:00
class idDeclFolder
{
2012-11-26 18:58:24 +00:00
public :
idStr folder ;
idStr extension ;
declType_t defaultType ;
} ;
class idDeclFile ;
2012-11-28 15:47:07 +00:00
class idDeclLocal : public idDeclBase
{
2012-11-26 18:58:24 +00:00
friend class idDeclFile ;
friend class idDeclManagerLocal ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
public :
2012-11-28 15:47:07 +00:00
idDeclLocal ( ) ;
2012-11-26 18:58:24 +00:00
virtual ~ idDeclLocal ( ) { } ;
2012-11-28 15:47:07 +00:00
virtual const char * GetName ( ) const ;
2012-11-26 18:58:24 +00:00
virtual declType_t GetType ( ) const ;
virtual declState_t GetState ( ) const ;
virtual bool IsImplicit ( ) const ;
virtual bool IsValid ( ) const ;
virtual void Invalidate ( ) ;
virtual void Reload ( ) ;
virtual void EnsureNotPurged ( ) ;
virtual int Index ( ) const ;
virtual int GetLineNum ( ) const ;
2012-11-28 15:47:07 +00:00
virtual const char * GetFileName ( ) const ;
2012-11-26 18:58:24 +00:00
virtual size_t Size ( ) const ;
2012-11-28 15:47:07 +00:00
virtual void GetText ( char * text ) const ;
2012-11-26 18:58:24 +00:00
virtual int GetTextLength ( ) const ;
2012-11-28 15:47:07 +00:00
virtual void SetText ( const char * text ) ;
2012-11-26 18:58:24 +00:00
virtual bool ReplaceSourceFileText ( ) ;
virtual bool SourceFileChanged ( ) const ;
virtual void MakeDefault ( ) ;
virtual bool EverReferenced ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
protected :
virtual bool SetDefaultText ( ) ;
2012-11-28 15:47:07 +00:00
virtual const char * DefaultDefinition ( ) const ;
virtual bool Parse ( const char * text , const int textLength , bool allowBinaryVersion ) ;
2012-11-26 18:58:24 +00:00
virtual void FreeData ( ) ;
virtual void List ( ) const ;
virtual void Print ( ) const ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
protected :
void AllocateSelf ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// Parses the decl definition.
// After calling parse, a decl will be guaranteed usable.
2012-11-26 18:58:24 +00:00
void ParseLocal ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// Does a MakeDefualt, but flags the decl so that it
// will Parse() the next time the decl is found.
2012-11-26 18:58:24 +00:00
void Purge ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
// Set textSource possible with compression.
void SetTextLocal ( const char * text , const int length ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
private :
2012-11-28 15:47:07 +00:00
idDecl * self ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idStr name ; // name of the decl
2012-11-28 15:47:07 +00:00
char * textSource ; // decl text definition
2012-11-26 18:58:24 +00:00
int textLength ; // length of textSource
int compressedLength ; // compressed length
2012-11-28 15:47:07 +00:00
idDeclFile * sourceFile ; // source file in which the decl was defined
2012-11-26 18:58:24 +00:00
int sourceTextOffset ; // offset in source file to decl text
int sourceTextLength ; // length of decl text in source file
int sourceLine ; // this is where the actual declaration token starts
int checksum ; // checksum of the decl text
declType_t type ; // decl type
declState_t declState ; // decl state
int index ; // index in the per-type list
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
bool parsedOutsideLevelLoad ; // these decls will never be purged
bool everReferenced ; // set to true if the decl was ever used
bool referencedThisLevel ; // set to true when the decl is used for the current level
bool redefinedInReload ; // used during file reloading to make sure a decl that has
2012-11-28 15:47:07 +00:00
// its source removed will be defaulted
idDeclLocal * nextInFile ; // next decl in the decl file
2012-11-26 18:58:24 +00:00
} ;
2012-11-28 15:47:07 +00:00
class idDeclFile
{
2012-11-26 18:58:24 +00:00
public :
2012-11-28 15:47:07 +00:00
idDeclFile ( ) ;
idDeclFile ( const char * fileName , declType_t defaultType ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
void Reload ( bool force ) ;
int LoadAndParse ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
public :
idStr fileName ;
declType_t defaultType ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
ID_TIME_T timestamp ;
int checksum ;
int fileSize ;
int numLines ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idDeclLocal * decls ;
2012-11-26 18:58:24 +00:00
} ;
2012-11-28 15:47:07 +00:00
class idDeclManagerLocal : public idDeclManager
{
2012-11-26 18:58:24 +00:00
friend class idDeclLocal ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
public :
virtual void Init ( ) ;
virtual void Init2 ( ) ;
2024-06-19 19:33:41 +00:00
virtual void InitTool ( ) ;
2012-11-26 18:58:24 +00:00
virtual void Shutdown ( ) ;
virtual void Reload ( bool force ) ;
virtual void BeginLevelLoad ( ) ;
virtual void EndLevelLoad ( ) ;
2012-11-28 15:47:07 +00:00
virtual void RegisterDeclType ( const char * typeName , declType_t type , idDecl * ( * allocator ) ( ) ) ;
virtual void RegisterDeclFolder ( const char * folder , const char * extension , declType_t defaultType ) ;
2012-11-26 18:58:24 +00:00
virtual int GetChecksum ( ) const ;
virtual int GetNumDeclTypes ( ) const ;
virtual int GetNumDecls ( declType_t type ) ;
2012-11-28 15:47:07 +00:00
virtual const char * GetDeclNameFromType ( declType_t type ) const ;
virtual declType_t GetDeclTypeFromName ( const char * typeName ) const ;
virtual const idDecl * FindType ( declType_t type , const char * name , bool makeDefault = true ) ;
virtual const idDecl * DeclByIndex ( declType_t type , int index , bool forceParse = true ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
virtual const idDecl * FindDeclWithoutParsing ( declType_t type , const char * name , bool makeDefault = true ) ;
2012-11-26 18:58:24 +00:00
virtual void ReloadFile ( const char * filename , bool force ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
virtual void ListType ( const idCmdArgs & args , declType_t type ) ;
virtual void PrintType ( const idCmdArgs & args , declType_t type ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
virtual idDecl * CreateNewDecl ( declType_t type , const char * name , const char * fileName ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//BSM Added for the material editors rename capabilities
virtual bool RenameDecl ( declType_t type , const char * oldName , const char * newName ) ;
2019-11-11 19:27:44 +00:00
2014-02-23 14:19:11 +00:00
virtual void MediaPrint ( VERIFY_FORMAT_STRING const char * fmt , . . . ) ID_INSTANCE_ATTRIBUTE_PRINTF ( 1 , 2 ) ;
2012-11-28 15:47:07 +00:00
virtual void WritePrecacheCommands ( idFile * f ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
virtual const idMaterial * FindMaterial ( const char * name , bool makeDefault = true ) ;
virtual const idMaterial * MaterialByIndex ( int index , bool forceParse = true ) ;
2024-06-17 20:10:50 +00:00
virtual const idDeclSkin * FindSkin ( const char * name , bool makeDefault = true ) ;
2012-11-28 15:47:07 +00:00
virtual const idDeclSkin * SkinByIndex ( int index , bool forceParse = true ) ;
2024-06-17 20:10:50 +00:00
2024-06-19 19:33:41 +00:00
# if !defined( DMAP )
2024-06-17 20:10:50 +00:00
virtual const idSoundShader * FindSound ( const char * name , bool makeDefault = true ) ;
2012-11-28 15:47:07 +00:00
virtual const idSoundShader * SoundByIndex ( int index , bool forceParse = true ) ;
2024-06-17 20:10:50 +00:00
# endif
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
virtual void Touch ( const idDecl * decl ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
public :
2012-11-28 15:47:07 +00:00
static void MakeNameCanonical ( const char * name , char * result , int maxLength ) ;
idDeclLocal * FindTypeWithoutParsing ( declType_t type , const char * name , bool makeDefault = true ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idDeclType * GetDeclType ( int type ) const
{
return declTypes [ type ] ;
}
const idDeclFile * GetImplicitDeclFile ( ) const
{
return & implicitDecls ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
void ConvertPDAsToStrings ( const idCmdArgs & args ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
private :
idSysMutex mutex ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idList < idDeclType * , TAG_IDLIB_LIST_DECL > declTypes ;
idList < idDeclFolder * , TAG_IDLIB_LIST_DECL > declFolders ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idList < idDeclFile * , TAG_IDLIB_LIST_DECL > loadedFiles ;
2012-11-26 18:58:24 +00:00
idHashIndex hashTables [ DECL_MAX_TYPES ] ;
2012-11-28 15:47:07 +00:00
idList < idDeclLocal * , TAG_IDLIB_LIST_DECL > linearLists [ DECL_MAX_TYPES ] ;
2012-11-26 18:58:24 +00:00
idDeclFile implicitDecls ; // this holds all the decls that were created because explicit
2012-11-28 15:47:07 +00:00
// text definitions were not found. Decls that became default
// because of a parse error are not in this list.
2012-11-26 18:58:24 +00:00
int checksum ; // checksum of all loaded decl text
int indent ; // for MediaPrint
bool insideLevelLoad ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
static idCVar decl_show ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
private :
2012-11-28 15:47:07 +00:00
static void ListDecls_f ( const idCmdArgs & args ) ;
static void ReloadDecls_f ( const idCmdArgs & args ) ;
static void TouchDecl_f ( const idCmdArgs & args ) ;
2016-03-05 20:19:14 +00:00
// RB begin
2023-10-07 12:04:27 +00:00
static void ExportEntityDefsToBlender_f ( const idCmdArgs & args ) ;
static void ExportMaterialsToBlender_f ( const idCmdArgs & args ) ;
static void ExportEntityDefsToTrenchBroom_f ( const idCmdArgs & args ) ;
2022-01-07 17:46:35 +00:00
static void ExportModelsToTrenchBroom_f ( const idCmdArgs & args ) ;
2022-01-20 21:25:06 +00:00
static void ExportImagesToTrenchBroom_f ( const idCmdArgs & args ) ;
2022-02-23 21:52:23 +00:00
static void MakeZooMapForModels_f ( const idCmdArgs & args ) ;
2016-03-05 20:19:14 +00:00
// RB end
2012-11-26 18:58:24 +00:00
} ;
2012-11-28 15:47:07 +00:00
idCVar idDeclManagerLocal : : decl_show ( " decl_show " , " 0 " , CVAR_SYSTEM , " set to 1 to print parses, 2 to also print references " , 0 , 2 , idCmdSystem : : ArgCompletion_Integer < 0 , 2 > ) ;
2012-11-26 18:58:24 +00:00
idDeclManagerLocal declManagerLocal ;
2012-11-28 15:47:07 +00:00
idDeclManager * declManager = & declManagerLocal ;
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
decl text huffman compression
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
const int MAX_HUFFMAN_SYMBOLS = 256 ;
2012-11-28 15:47:07 +00:00
typedef struct huffmanNode_s
{
2012-11-26 18:58:24 +00:00
int symbol ;
int frequency ;
2012-11-28 15:47:07 +00:00
struct huffmanNode_s * next ;
struct huffmanNode_s * children [ 2 ] ;
2012-11-26 18:58:24 +00:00
} huffmanNode_t ;
2012-11-28 15:47:07 +00:00
typedef struct huffmanCode_s
{
2012-12-11 22:04:53 +00:00
unsigned int bits [ 8 ] ; // DG: use int instead of long for 64bit compatibility
2012-11-26 18:58:24 +00:00
int numBits ;
} huffmanCode_t ;
// compression ratio = 64%
2012-11-28 15:47:07 +00:00
static int huffmanFrequencies [ ] =
{
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00078fb6 , 0x000352a7 , 0x00000002 , 0x00000001 , 0x0002795e , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00049600 , 0x000000dd , 0x00018732 , 0x0000005a , 0x00000007 , 0x00000092 , 0x0000000a , 0x00000919 ,
0x00002dcf , 0x00002dda , 0x00004dfc , 0x0000039a , 0x000058be , 0x00002d13 , 0x00014d8c , 0x00023c60 ,
0x0002ddb0 , 0x0000d1fc , 0x000078c4 , 0x00003ec7 , 0x00003113 , 0x00006b59 , 0x00002499 , 0x0000184a ,
0x0000250b , 0x00004e38 , 0x000001ca , 0x00000011 , 0x00000020 , 0x000023da , 0x00000012 , 0x00000091 ,
0x0000000b , 0x00000b14 , 0x0000035d , 0x0000137e , 0x000020c9 , 0x00000e11 , 0x000004b4 , 0x00000737 ,
0x000006b8 , 0x00001110 , 0x000006b3 , 0x000000fe , 0x00000f02 , 0x00000d73 , 0x000005f6 , 0x00000be4 ,
0x00000d86 , 0x0000014d , 0x00000d89 , 0x0000129b , 0x00000db3 , 0x0000015a , 0x00000167 , 0x00000375 ,
0x00000028 , 0x00000112 , 0x00000018 , 0x00000678 , 0x0000081a , 0x00000677 , 0x00000003 , 0x00018112 ,
0x00000001 , 0x000441ee , 0x000124b0 , 0x0001fa3f , 0x00026125 , 0x0005a411 , 0x0000e50f , 0x00011820 ,
0x00010f13 , 0x0002e723 , 0x00003518 , 0x00005738 , 0x0002cc26 , 0x0002a9b7 , 0x0002db81 , 0x0003b5fa ,
0x000185d2 , 0x00001299 , 0x00030773 , 0x0003920d , 0x000411cd , 0x00018751 , 0x00005fbd , 0x000099b0 ,
0x00009242 , 0x00007cf2 , 0x00002809 , 0x00005a1d , 0x00000001 , 0x00005a1d , 0x00000001 , 0x00000001 ,
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 , 0x00000001 ,
2012-11-26 18:58:24 +00:00
} ;
static huffmanCode_t huffmanCodes [ MAX_HUFFMAN_SYMBOLS ] ;
2012-11-28 15:47:07 +00:00
static huffmanNode_t * huffmanTree = NULL ;
2012-11-26 18:58:24 +00:00
static int totalUncompressedLength = 0 ;
static int totalCompressedLength = 0 ;
static int maxHuffmanBits = 0 ;
/*
= = = = = = = = = = = = = = = =
ClearHuffmanFrequencies
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void ClearHuffmanFrequencies ( )
{
2012-11-26 18:58:24 +00:00
int i ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_HUFFMAN_SYMBOLS ; i + + )
{
2012-11-26 18:58:24 +00:00
huffmanFrequencies [ i ] = 1 ;
}
}
/*
= = = = = = = = = = = = = = = =
InsertHuffmanNode
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
huffmanNode_t * InsertHuffmanNode ( huffmanNode_t * firstNode , huffmanNode_t * node )
{
huffmanNode_t * n , * lastNode ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
lastNode = NULL ;
2012-11-28 15:47:07 +00:00
for ( n = firstNode ; n ; n = n - > next )
{
if ( node - > frequency < = n - > frequency )
{
2012-11-26 18:58:24 +00:00
break ;
}
lastNode = n ;
}
2012-11-28 15:47:07 +00:00
if ( lastNode )
{
2012-11-26 18:58:24 +00:00
node - > next = lastNode - > next ;
lastNode - > next = node ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
node - > next = firstNode ;
firstNode = node ;
}
return firstNode ;
}
/*
= = = = = = = = = = = = = = = =
BuildHuffmanCode_r
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void BuildHuffmanCode_r ( huffmanNode_t * node , huffmanCode_t code , huffmanCode_t codes [ MAX_HUFFMAN_SYMBOLS ] )
{
if ( node - > symbol = = - 1 )
{
2012-11-26 18:58:24 +00:00
huffmanCode_t newCode = code ;
assert ( code . numBits < sizeof ( codes [ 0 ] . bits ) * 8 ) ;
newCode . numBits + + ;
2012-11-28 15:47:07 +00:00
if ( code . numBits > maxHuffmanBits )
{
2012-11-26 18:58:24 +00:00
maxHuffmanBits = newCode . numBits ;
}
BuildHuffmanCode_r ( node - > children [ 0 ] , newCode , codes ) ;
newCode . bits [ code . numBits > > 5 ] | = 1 < < ( code . numBits & 31 ) ;
BuildHuffmanCode_r ( node - > children [ 1 ] , newCode , codes ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
assert ( code . numBits < = sizeof ( codes [ 0 ] . bits ) * 8 ) ;
codes [ node - > symbol ] = code ;
}
}
/*
= = = = = = = = = = = = = = = =
FreeHuffmanTree_r
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void FreeHuffmanTree_r ( huffmanNode_t * node )
{
if ( node - > symbol = = - 1 )
{
2012-11-26 18:58:24 +00:00
FreeHuffmanTree_r ( node - > children [ 0 ] ) ;
FreeHuffmanTree_r ( node - > children [ 1 ] ) ;
}
delete node ;
}
/*
= = = = = = = = = = = = = = = =
HuffmanHeight_r
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int HuffmanHeight_r ( huffmanNode_t * node )
{
if ( node = = NULL )
{
2012-11-26 18:58:24 +00:00
return - 1 ;
}
int left = HuffmanHeight_r ( node - > children [ 0 ] ) ;
int right = HuffmanHeight_r ( node - > children [ 1 ] ) ;
2012-11-28 15:47:07 +00:00
if ( left > right )
{
2012-11-26 18:58:24 +00:00
return left + 1 ;
}
return right + 1 ;
}
/*
= = = = = = = = = = = = = = = =
SetupHuffman
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void SetupHuffman ( )
{
2012-11-26 18:58:24 +00:00
int i , height ;
2012-11-28 15:47:07 +00:00
huffmanNode_t * firstNode , * node ;
2012-11-26 18:58:24 +00:00
huffmanCode_t code ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
firstNode = NULL ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_HUFFMAN_SYMBOLS ; i + + )
{
node = new ( TAG_DECL ) huffmanNode_t ;
2012-11-26 18:58:24 +00:00
node - > symbol = i ;
node - > frequency = huffmanFrequencies [ i ] ;
node - > next = NULL ;
node - > children [ 0 ] = NULL ;
node - > children [ 1 ] = NULL ;
firstNode = InsertHuffmanNode ( firstNode , node ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
for ( i = 1 ; i < MAX_HUFFMAN_SYMBOLS ; i + + )
{
node = new ( TAG_DECL ) huffmanNode_t ;
2012-11-26 18:58:24 +00:00
node - > symbol = - 1 ;
node - > frequency = firstNode - > frequency + firstNode - > next - > frequency ;
node - > next = NULL ;
node - > children [ 0 ] = firstNode ;
node - > children [ 1 ] = firstNode - > next ;
firstNode = InsertHuffmanNode ( firstNode - > next - > next , node ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
maxHuffmanBits = 0 ;
memset ( & code , 0 , sizeof ( code ) ) ;
BuildHuffmanCode_r ( firstNode , code , huffmanCodes ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
huffmanTree = firstNode ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
height = HuffmanHeight_r ( firstNode ) ;
assert ( maxHuffmanBits = = height ) ;
}
/*
= = = = = = = = = = = = = = = =
ShutdownHuffman
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void ShutdownHuffman ( )
{
if ( huffmanTree )
{
2012-11-26 18:58:24 +00:00
FreeHuffmanTree_r ( huffmanTree ) ;
}
}
/*
= = = = = = = = = = = = = = = =
HuffmanCompressText
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int HuffmanCompressText ( const char * text , int textLength , byte * compressed , int maxCompressedSize )
{
2012-11-26 18:58:24 +00:00
int i , j ;
idBitMsg msg ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
totalUncompressedLength + = textLength ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
msg . InitWrite ( compressed , maxCompressedSize ) ;
msg . BeginWriting ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < textLength ; i + + )
{
const huffmanCode_t & code = huffmanCodes [ ( unsigned char ) text [ i ] ] ;
for ( j = 0 ; j < ( code . numBits > > 5 ) ; j + + )
{
2012-11-26 18:58:24 +00:00
msg . WriteBits ( code . bits [ j ] , 32 ) ;
}
2012-11-28 15:47:07 +00:00
if ( code . numBits & 31 )
{
2012-11-26 18:58:24 +00:00
msg . WriteBits ( code . bits [ j ] , code . numBits & 31 ) ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
totalCompressedLength + = msg . GetSize ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return msg . GetSize ( ) ;
}
/*
= = = = = = = = = = = = = = = =
HuffmanDecompressText
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int HuffmanDecompressText ( char * text , int textLength , const byte * compressed , int compressedSize )
{
2012-11-26 18:58:24 +00:00
int i , bit ;
idBitMsg msg ;
2012-11-28 15:47:07 +00:00
huffmanNode_t * node ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
msg . InitRead ( compressed , compressedSize ) ;
msg . SetSize ( compressedSize ) ;
msg . BeginReading ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < textLength ; i + + )
{
2012-11-26 18:58:24 +00:00
node = huffmanTree ;
2012-11-28 15:47:07 +00:00
do
{
2012-11-26 18:58:24 +00:00
bit = msg . ReadBits ( 1 ) ;
node = node - > children [ bit ] ;
2012-11-28 15:47:07 +00:00
}
while ( node - > symbol = = - 1 ) ;
2012-11-26 18:58:24 +00:00
text [ i ] = node - > symbol ;
}
text [ i ] = ' \0 ' ;
return msg . GetReadCount ( ) ;
}
/*
= = = = = = = = = = = = = = = =
ListHuffmanFrequencies_f
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void ListHuffmanFrequencies_f ( const idCmdArgs & args )
{
2012-11-26 18:58:24 +00:00
int i ;
float compression ;
compression = ! totalUncompressedLength ? 100 : 100 * totalCompressedLength / totalUncompressedLength ;
2012-11-28 15:47:07 +00:00
common - > Printf ( " // compression ratio = %d%% \n " , ( int ) compression ) ;
2012-11-26 18:58:24 +00:00
common - > Printf ( " static int huffmanFrequencies[] = { \n " ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < MAX_HUFFMAN_SYMBOLS ; i + = 8 )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " \t 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, \n " ,
2012-11-28 15:47:07 +00:00
huffmanFrequencies [ i + 0 ] , huffmanFrequencies [ i + 1 ] ,
huffmanFrequencies [ i + 2 ] , huffmanFrequencies [ i + 3 ] ,
huffmanFrequencies [ i + 4 ] , huffmanFrequencies [ i + 5 ] ,
huffmanFrequencies [ i + 6 ] , huffmanFrequencies [ i + 7 ] ) ;
2012-11-26 18:58:24 +00:00
}
common - > Printf ( " } \n " ) ;
}
2012-11-28 15:47:07 +00:00
void ConvertPDAsToStrings_f ( const idCmdArgs & args )
{
2012-11-26 18:58:24 +00:00
declManagerLocal . ConvertPDAsToStrings ( args ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idDeclFile
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = =
idDeclFile : : idDeclFile
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDeclFile : : idDeclFile ( const char * fileName , declType_t defaultType )
{
2012-11-26 18:58:24 +00:00
this - > fileName = fileName ;
this - > defaultType = defaultType ;
this - > timestamp = 0 ;
this - > checksum = 0 ;
this - > fileSize = 0 ;
this - > numLines = 0 ;
this - > decls = NULL ;
}
/*
= = = = = = = = = = = = = = = =
idDeclFile : : idDeclFile
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDeclFile : : idDeclFile ( )
{
2012-11-26 18:58:24 +00:00
this - > fileName = " <implicit file> " ;
this - > defaultType = DECL_MAX_TYPES ;
this - > timestamp = 0 ;
this - > checksum = 0 ;
this - > fileSize = 0 ;
this - > numLines = 0 ;
this - > decls = NULL ;
}
/*
= = = = = = = = = = = = = = = =
idDeclFile : : Reload
ForceReload will cause it to reload even if the timestamp hasn ' t changed
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclFile : : Reload ( bool force )
{
2012-11-26 18:58:24 +00:00
// check for an unchanged timestamp
2012-11-28 15:47:07 +00:00
if ( ! force & & timestamp ! = 0 )
{
2012-11-26 18:58:24 +00:00
ID_TIME_T testTimeStamp ;
fileSystem - > ReadFile ( fileName , NULL , & testTimeStamp ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( testTimeStamp = = timestamp )
{
2012-11-26 18:58:24 +00:00
return ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// parse the text
LoadAndParse ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idDeclFile : : LoadAndParse
This is used during both the initial load , and any reloads
= = = = = = = = = = = = = = = =
*/
int c_savedMemory = 0 ;
2012-11-28 15:47:07 +00:00
int idDeclFile : : LoadAndParse ( )
{
2012-11-26 18:58:24 +00:00
int i , numTypes ;
idLexer src ;
idToken token ;
int startMarker ;
2012-11-28 15:47:07 +00:00
char * buffer ;
2012-11-26 18:58:24 +00:00
int length , size ;
int sourceLine ;
idStr name ;
2012-11-28 15:47:07 +00:00
idDeclLocal * newDecl ;
2012-11-26 18:58:24 +00:00
bool reparse ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// load the text
common - > DPrintf ( " ...loading '%s' \n " , fileName . c_str ( ) ) ;
2012-11-28 15:47:07 +00:00
length = fileSystem - > ReadFile ( fileName , ( void * * ) & buffer , & timestamp ) ;
if ( length = = - 1 )
{
2012-11-26 18:58:24 +00:00
common - > FatalError ( " couldn't load %s " , fileName . c_str ( ) ) ;
return 0 ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! src . LoadMemory ( buffer , length , fileName ) )
{
2012-11-26 18:58:24 +00:00
common - > Error ( " Couldn't parse %s " , fileName . c_str ( ) ) ;
Mem_Free ( buffer ) ;
return 0 ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// mark all the defs that were from the last reload of this file
2012-11-28 15:47:07 +00:00
for ( idDeclLocal * decl = decls ; decl ; decl = decl - > nextInFile )
{
2012-11-26 18:58:24 +00:00
decl - > redefinedInReload = false ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
src . SetFlags ( DECL_LEXER_FLAGS ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
checksum = MD5_BlockChecksum ( buffer , length ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
fileSize = length ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// scan through, identifying each individual declaration
2012-11-28 15:47:07 +00:00
while ( 1 )
{
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
startMarker = src . GetFileOffset ( ) ;
sourceLine = src . GetLineNum ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// parse the decl type name
2012-11-28 15:47:07 +00:00
if ( ! src . ReadToken ( & token ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
declType_t identifiedType = DECL_MAX_TYPES ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// get the decl type from the type name
numTypes = declManagerLocal . GetNumDeclTypes ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numTypes ; i + + )
{
idDeclType * typeInfo = declManagerLocal . GetDeclType ( i ) ;
if ( typeInfo ! = NULL & & typeInfo - > typeName . Icmp ( token ) = = 0 )
{
identifiedType = ( declType_t ) typeInfo - > type ;
2012-11-26 18:58:24 +00:00
break ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( i > = numTypes )
{
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( token . Icmp ( " { " ) = = 0 )
{
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// if we ever see an open brace, we somehow missed the [type] <name> prefix
src . Warning ( " Missing decl name " ) ;
src . SkipBracedSection ( false ) ;
continue ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
}
else
{
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( defaultType = = DECL_MAX_TYPES )
{
2012-11-26 18:58:24 +00:00
src . Warning ( " No type " ) ;
continue ;
}
src . UnreadToken ( & token ) ;
// use the default type
identifiedType = defaultType ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// now parse the name
2012-11-28 15:47:07 +00:00
if ( ! src . ReadToken ( & token ) )
{
2012-11-26 18:58:24 +00:00
src . Warning ( " Type without definition at end of file " ) ;
break ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! token . Icmp ( " { " ) )
{
2012-11-26 18:58:24 +00:00
// if we ever see an open brace, we somehow missed the [type] <name> prefix
src . Warning ( " Missing decl name " ) ;
src . SkipBracedSection ( false ) ;
continue ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: export decls are only used by the model exporter, they are skipped here for now
2012-11-28 15:47:07 +00:00
if ( identifiedType = = DECL_MODELEXPORT )
{
2012-11-26 18:58:24 +00:00
src . SkipBracedSection ( ) ;
continue ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
name = token ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// make sure there's a '{'
2012-11-28 15:47:07 +00:00
if ( ! src . ReadToken ( & token ) )
{
2012-11-26 18:58:24 +00:00
src . Warning ( " Type without definition at end of file " ) ;
break ;
}
2012-11-28 15:47:07 +00:00
if ( token ! = " { " )
{
2012-11-26 18:58:24 +00:00
src . Warning ( " Expecting '{' but found '%s' " , token . c_str ( ) ) ;
continue ;
}
src . UnreadToken ( & token ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// now take everything until a matched closing brace
src . SkipBracedSection ( ) ;
size = src . GetFileOffset ( ) - startMarker ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// look it up, possibly getting a newly created default decl
reparse = false ;
newDecl = declManagerLocal . FindTypeWithoutParsing ( identifiedType , name , false ) ;
2012-11-28 15:47:07 +00:00
if ( newDecl )
{
2012-11-26 18:58:24 +00:00
// update the existing copy
2012-11-28 15:47:07 +00:00
if ( newDecl - > sourceFile ! = this | | newDecl - > redefinedInReload )
{
2012-11-26 18:58:24 +00:00
src . Warning ( " %s '%s' previously defined at %s:%i " , declManagerLocal . GetDeclNameFromType ( identifiedType ) ,
2012-11-28 15:47:07 +00:00
name . c_str ( ) , newDecl - > sourceFile - > fileName . c_str ( ) , newDecl - > sourceLine ) ;
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( newDecl - > declState ! = DS_UNPARSED )
{
2012-11-26 18:58:24 +00:00
reparse = true ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// allow it to be created as a default, then add it to the per-file list
newDecl = declManagerLocal . FindTypeWithoutParsing ( identifiedType , name , true ) ;
newDecl - > nextInFile = this - > decls ;
this - > decls = newDecl ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
newDecl - > redefinedInReload = true ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( newDecl - > textSource )
{
2012-11-26 18:58:24 +00:00
Mem_Free ( newDecl - > textSource ) ;
newDecl - > textSource = NULL ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
newDecl - > SetTextLocal ( buffer + startMarker , size ) ;
newDecl - > sourceFile = this ;
newDecl - > sourceTextOffset = startMarker ;
newDecl - > sourceTextLength = size ;
newDecl - > sourceLine = sourceLine ;
newDecl - > declState = DS_UNPARSED ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// if it is currently in use, reparse it immedaitely
2012-11-28 15:47:07 +00:00
if ( reparse )
{
2012-11-26 18:58:24 +00:00
newDecl - > ParseLocal ( ) ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
numLines = src . GetLineNum ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
Mem_Free ( buffer ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// any defs that weren't redefinedInReload should now be defaulted
2012-11-28 15:47:07 +00:00
for ( idDeclLocal * decl = decls ; decl ; decl = decl - > nextInFile )
{
if ( decl - > redefinedInReload = = false )
{
2012-11-26 18:58:24 +00:00
decl - > MakeDefault ( ) ;
decl - > sourceTextOffset = decl - > sourceFile - > fileSize ;
decl - > sourceTextLength = 0 ;
decl - > sourceLine = decl - > sourceFile - > numLines ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return checksum ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idDeclManagerLocal
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * listDeclStrings [ ] = { " current " , " all " , " ever " , NULL } ;
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : Init
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : Init ( )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " ----- Initializing Decls ----- \n " ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
checksum = 0 ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
# ifdef USE_COMPRESSED_DECLS
SetupHuffman ( ) ;
# endif
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
# ifdef GET_HUFFMAN_FREQUENCIES
ClearHuffmanFrequencies ( ) ;
# endif
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// decls used throughout the engine
RegisterDeclType ( " table " , DECL_TABLE , idDeclAllocator < idDeclTable > ) ;
RegisterDeclType ( " material " , DECL_MATERIAL , idDeclAllocator < idMaterial > ) ;
2024-06-19 19:33:41 +00:00
RegisterDeclType ( " skin " , DECL_SKIN , idDeclAllocator < idDeclSkin > ) ;
RegisterDeclType ( " entityDef " , DECL_ENTITYDEF , idDeclAllocator < idDeclEntityDef > ) ;
2024-06-17 20:10:50 +00:00
# if !defined( DMAP )
2012-11-26 18:58:24 +00:00
RegisterDeclType ( " sound " , DECL_SOUND , idDeclAllocator < idSoundShader > ) ;
RegisterDeclType ( " mapDef " , DECL_MAPDEF , idDeclAllocator < idDeclEntityDef > ) ;
RegisterDeclType ( " fx " , DECL_FX , idDeclAllocator < idDeclFX > ) ;
RegisterDeclType ( " particle " , DECL_PARTICLE , idDeclAllocator < idDeclParticle > ) ;
RegisterDeclType ( " articulatedFigure " , DECL_AF , idDeclAllocator < idDeclAF > ) ;
RegisterDeclType ( " pda " , DECL_PDA , idDeclAllocator < idDeclPDA > ) ;
RegisterDeclType ( " email " , DECL_EMAIL , idDeclAllocator < idDeclEmail > ) ;
RegisterDeclType ( " video " , DECL_VIDEO , idDeclAllocator < idDeclVideo > ) ;
RegisterDeclType ( " audio " , DECL_AUDIO , idDeclAllocator < idDeclAudio > ) ;
2024-06-17 20:10:50 +00:00
# endif
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
RegisterDeclFolder ( " materials " , " .mtr " , DECL_MATERIAL ) ;
2019-11-11 19:27:44 +00:00
2024-06-17 20:10:50 +00:00
# if !defined( DMAP )
2012-11-26 18:58:24 +00:00
// add console commands
cmdSystem - > AddCommand ( " listDecls " , ListDecls_f , CMD_FL_SYSTEM , " lists all decls " ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > AddCommand ( " reloadDecls " , ReloadDecls_f , CMD_FL_SYSTEM , " reloads decls " ) ;
cmdSystem - > AddCommand ( " touch " , TouchDecl_f , CMD_FL_SYSTEM , " touches a decl " ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > AddCommand ( " listTables " , idListDecls_f < DECL_TABLE > , CMD_FL_SYSTEM , " lists tables " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
cmdSystem - > AddCommand ( " listMaterials " , idListDecls_f < DECL_MATERIAL > , CMD_FL_SYSTEM , " lists materials " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
cmdSystem - > AddCommand ( " listSkins " , idListDecls_f < DECL_SKIN > , CMD_FL_SYSTEM , " lists skins " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
cmdSystem - > AddCommand ( " listSoundShaders " , idListDecls_f < DECL_SOUND > , CMD_FL_SYSTEM , " lists sound shaders " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > AddCommand ( " listEntityDefs " , idListDecls_f < DECL_ENTITYDEF > , CMD_FL_SYSTEM , " lists entity defs " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
cmdSystem - > AddCommand ( " listFX " , idListDecls_f < DECL_FX > , CMD_FL_SYSTEM , " lists FX systems " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
cmdSystem - > AddCommand ( " listParticles " , idListDecls_f < DECL_PARTICLE > , CMD_FL_SYSTEM , " lists particle systems " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
2012-11-28 15:47:07 +00:00
cmdSystem - > AddCommand ( " listAF " , idListDecls_f < DECL_AF > , CMD_FL_SYSTEM , " lists articulated figures " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > AddCommand ( " listPDAs " , idListDecls_f < DECL_PDA > , CMD_FL_SYSTEM , " lists PDAs " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
cmdSystem - > AddCommand ( " listEmails " , idListDecls_f < DECL_EMAIL > , CMD_FL_SYSTEM , " lists Emails " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
cmdSystem - > AddCommand ( " listVideos " , idListDecls_f < DECL_VIDEO > , CMD_FL_SYSTEM , " lists Videos " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
cmdSystem - > AddCommand ( " listAudios " , idListDecls_f < DECL_AUDIO > , CMD_FL_SYSTEM , " lists Audios " , idCmdSystem : : ArgCompletion_String < listDeclStrings > ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > AddCommand ( " printTable " , idPrintDecls_f < DECL_TABLE > , CMD_FL_SYSTEM , " prints a table " , idCmdSystem : : ArgCompletion_Decl < DECL_TABLE > ) ;
cmdSystem - > AddCommand ( " printMaterial " , idPrintDecls_f < DECL_MATERIAL > , CMD_FL_SYSTEM , " prints a material " , idCmdSystem : : ArgCompletion_Decl < DECL_MATERIAL > ) ;
cmdSystem - > AddCommand ( " printSkin " , idPrintDecls_f < DECL_SKIN > , CMD_FL_SYSTEM , " prints a skin " , idCmdSystem : : ArgCompletion_Decl < DECL_SKIN > ) ;
cmdSystem - > AddCommand ( " printSoundShader " , idPrintDecls_f < DECL_SOUND > , CMD_FL_SYSTEM , " prints a sound shader " , idCmdSystem : : ArgCompletion_Decl < DECL_SOUND > ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > AddCommand ( " printEntityDef " , idPrintDecls_f < DECL_ENTITYDEF > , CMD_FL_SYSTEM , " prints an entity def " , idCmdSystem : : ArgCompletion_Decl < DECL_ENTITYDEF > ) ;
cmdSystem - > AddCommand ( " printFX " , idPrintDecls_f < DECL_FX > , CMD_FL_SYSTEM , " prints an FX system " , idCmdSystem : : ArgCompletion_Decl < DECL_FX > ) ;
cmdSystem - > AddCommand ( " printParticle " , idPrintDecls_f < DECL_PARTICLE > , CMD_FL_SYSTEM , " prints a particle system " , idCmdSystem : : ArgCompletion_Decl < DECL_PARTICLE > ) ;
cmdSystem - > AddCommand ( " printAF " , idPrintDecls_f < DECL_AF > , CMD_FL_SYSTEM , " prints an articulated figure " , idCmdSystem : : ArgCompletion_Decl < DECL_AF > ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > AddCommand ( " printPDA " , idPrintDecls_f < DECL_PDA > , CMD_FL_SYSTEM , " prints an PDA " , idCmdSystem : : ArgCompletion_Decl < DECL_PDA > ) ;
cmdSystem - > AddCommand ( " printEmail " , idPrintDecls_f < DECL_EMAIL > , CMD_FL_SYSTEM , " prints an Email " , idCmdSystem : : ArgCompletion_Decl < DECL_EMAIL > ) ;
cmdSystem - > AddCommand ( " printVideo " , idPrintDecls_f < DECL_VIDEO > , CMD_FL_SYSTEM , " prints an Audio " , idCmdSystem : : ArgCompletion_Decl < DECL_VIDEO > ) ;
cmdSystem - > AddCommand ( " printAudio " , idPrintDecls_f < DECL_AUDIO > , CMD_FL_SYSTEM , " prints a Video " , idCmdSystem : : ArgCompletion_Decl < DECL_AUDIO > ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > AddCommand ( " listHuffmanFrequencies " , ListHuffmanFrequencies_f , CMD_FL_SYSTEM , " lists decl text character frequencies " ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
cmdSystem - > AddCommand ( " convertPDAsToStrings " , ConvertPDAsToStrings_f , CMD_FL_SYSTEM , " Converts *.pda files to text which can be plugged into *.lang files. " ) ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
// RB begin
2023-10-07 12:04:27 +00:00
cmdSystem - > AddCommand ( " exportEntitiesToBlender " , ExportEntityDefsToBlender_f , CMD_FL_SYSTEM , " exports all entity and model defs to _bl/entities.json " ) ;
cmdSystem - > AddCommand ( " exportMaterialsToBlender " , ExportMaterialsToBlender_f , CMD_FL_SYSTEM , " exports all materials to _bl/entities.json " ) ;
cmdSystem - > AddCommand ( " exportFGD " , ExportEntityDefsToTrenchBroom_f , CMD_FL_SYSTEM , " exports all entity and model defs to _tb/fgd/DOOM-3-*.fgd " ) ;
2022-01-07 17:46:35 +00:00
cmdSystem - > AddCommand ( " exportModelsToTrenchBroom " , ExportModelsToTrenchBroom_f , CMD_FL_SYSTEM , " exports all generated models like blwo, base .. to _tb/*.obj " ) ;
2022-01-20 21:25:06 +00:00
cmdSystem - > AddCommand ( " exportImagesToTrenchBroom " , ExportImagesToTrenchBroom_f , CMD_FL_SYSTEM , " exports all generated bimages to _tb/*.png " ) ;
2022-02-23 21:52:23 +00:00
cmdSystem - > AddCommand ( " makeZooMapForModels " , MakeZooMapForModels_f , CMD_FL_SYSTEM , " make a Source engine style zoo map with all generated models like .blwo, .base, .bmd5mesh et cetera " ) ;
2024-06-17 20:10:50 +00:00
# endif
2016-03-05 20:19:14 +00:00
// RB end
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " ------------------------------ \n " ) ;
}
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : Init2 ( )
{
2012-11-26 18:58:24 +00:00
RegisterDeclFolder ( " skins " , " .skin " , DECL_SKIN ) ;
RegisterDeclFolder ( " sound " , " .sndshd " , DECL_SOUND ) ;
}
2024-06-19 19:33:41 +00:00
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : InitTool
RB : only called by rbdmap
= = = = = = = = = = = = = = = = = = =
*/
# include "../d3xp/anim/Anim.h"
void idDeclManagerLocal : : InitTool ( )
{
common - > Printf ( " ----- Initializing Decls ----- \n " ) ;
checksum = 0 ;
# ifdef USE_COMPRESSED_DECLS
SetupHuffman ( ) ;
# endif
# ifdef GET_HUFFMAN_FREQUENCIES
ClearHuffmanFrequencies ( ) ;
# endif
// decls used throughout the engine
RegisterDeclType ( " table " , DECL_TABLE , idDeclAllocator < idDeclTable > ) ;
RegisterDeclType ( " material " , DECL_MATERIAL , idDeclAllocator < idMaterial > ) ;
RegisterDeclType ( " model " , DECL_MODELDEF , idDeclAllocator < idDeclModelDef > ) ;
RegisterDeclType ( " export " , DECL_MODELEXPORT , idDeclAllocator < idDecl > ) ;
RegisterDeclType ( " skin " , DECL_SKIN , idDeclAllocator < idDeclSkin > ) ;
RegisterDeclType ( " entityDef " , DECL_ENTITYDEF , idDeclAllocator < idDeclEntityDef > ) ;
RegisterDeclType ( " mapDef " , DECL_MAPDEF , idDeclAllocator < idDeclEntityDef > ) ;
RegisterDeclFolder ( " materials " , " .mtr " , DECL_MATERIAL ) ;
RegisterDeclFolder ( " skins " , " .skin " , DECL_SKIN ) ;
RegisterDeclFolder ( " def " , " .def " , DECL_ENTITYDEF ) ;
common - > Printf ( " ------------------------------ \n " ) ;
}
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : Shutdown
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : Shutdown ( )
{
2012-11-26 18:58:24 +00:00
int i , j ;
2012-11-28 15:47:07 +00:00
idDeclLocal * decl ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// free decls
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < DECL_MAX_TYPES ; i + + )
{
for ( j = 0 ; j < linearLists [ i ] . Num ( ) ; j + + )
{
2012-11-26 18:58:24 +00:00
decl = linearLists [ i ] [ j ] ;
2012-11-28 15:47:07 +00:00
if ( decl - > self ! = NULL )
{
2012-11-26 18:58:24 +00:00
decl - > self - > FreeData ( ) ;
delete decl - > self ;
}
2012-11-28 15:47:07 +00:00
if ( decl - > textSource )
{
2012-11-26 18:58:24 +00:00
Mem_Free ( decl - > textSource ) ;
decl - > textSource = NULL ;
}
delete decl ;
}
linearLists [ i ] . Clear ( ) ;
hashTables [ i ] . Free ( ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// free decl files
loadedFiles . DeleteContents ( true ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// free the decl types and folders
declTypes . DeleteContents ( true ) ;
declFolders . DeleteContents ( true ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
# ifdef USE_COMPRESSED_DECLS
ShutdownHuffman ( ) ;
# endif
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : Reload
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : Reload ( bool force )
{
for ( int i = 0 ; i < loadedFiles . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
loadedFiles [ i ] - > Reload ( force ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : BeginLevelLoad
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : BeginLevelLoad ( )
{
2012-11-26 18:58:24 +00:00
insideLevelLoad = true ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// clear all the referencedThisLevel flags and purge all the data
// so the next reference will cause a reparse
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < DECL_MAX_TYPES ; i + + )
{
2012-11-26 18:58:24 +00:00
int num = linearLists [ i ] . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < num ; j + + )
{
idDeclLocal * decl = linearLists [ i ] [ j ] ;
2012-11-26 18:58:24 +00:00
decl - > Purge ( ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : EndLevelLoad
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : EndLevelLoad ( )
{
2012-11-26 18:58:24 +00:00
insideLevelLoad = false ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// we don't need to do anything here, but the image manager, model manager,
// and sound sample manager will need to free media that was not referenced
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : RegisterDeclType
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : RegisterDeclType ( const char * typeName , declType_t type , idDecl * ( * allocator ) ( ) )
{
idDeclType * declType ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( type < declTypes . Num ( ) & & declTypes [ ( int ) type ] )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " idDeclManager::RegisterDeclType: type '%s' already exists " , typeName ) ;
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
declType = new ( TAG_DECL ) idDeclType ;
2012-11-26 18:58:24 +00:00
declType - > typeName = typeName ;
declType - > type = type ;
declType - > allocator = allocator ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ( int ) type + 1 > declTypes . Num ( ) )
{
declTypes . AssureSize ( ( int ) type + 1 , NULL ) ;
2012-11-26 18:58:24 +00:00
}
declTypes [ type ] = declType ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : RegisterDeclFolder
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : RegisterDeclFolder ( const char * folder , const char * extension , declType_t defaultType )
{
2012-11-26 18:58:24 +00:00
int i , j ;
idStr fileName ;
2012-11-28 15:47:07 +00:00
idDeclFolder * declFolder ;
idFileList * fileList ;
idDeclFile * df ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// check whether this folder / extension combination already exists
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < declFolders . Num ( ) ; i + + )
{
if ( declFolders [ i ] - > folder . Icmp ( folder ) = = 0 & & declFolders [ i ] - > extension . Icmp ( extension ) = = 0 )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( i < declFolders . Num ( ) )
{
2012-11-26 18:58:24 +00:00
declFolder = declFolders [ i ] ;
2012-11-28 15:47:07 +00:00
}
else
{
declFolder = new ( TAG_DECL ) idDeclFolder ;
2012-11-26 18:58:24 +00:00
declFolder - > folder = folder ;
declFolder - > extension = extension ;
declFolder - > defaultType = defaultType ;
declFolders . Append ( declFolder ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// scan for decl files
fileList = fileSystem - > ListFiles ( declFolder - > folder , declFolder - > extension , true ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// load and parse decl files
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < fileList - > GetNumFiles ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
fileName = declFolder - > folder + " / " + fileList - > GetFile ( i ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// check whether this file has already been loaded
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < loadedFiles . Num ( ) ; j + + )
{
if ( fileName . Icmp ( loadedFiles [ j ] - > fileName ) = = 0 )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( j < loadedFiles . Num ( ) )
{
2012-11-26 18:58:24 +00:00
df = loadedFiles [ j ] ;
2012-11-28 15:47:07 +00:00
}
else
{
df = new ( TAG_DECL ) idDeclFile ( fileName , defaultType ) ;
2012-11-26 18:58:24 +00:00
loadedFiles . Append ( df ) ;
}
df - > LoadAndParse ( ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
fileSystem - > FreeFileList ( fileList ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : GetChecksum
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idDeclManagerLocal : : GetChecksum ( ) const
{
2012-11-26 18:58:24 +00:00
int i , j , total , num ;
2012-11-28 15:47:07 +00:00
int * checksumData ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// get the total number of decls
total = 0 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < DECL_MAX_TYPES ; i + + )
{
2012-11-26 18:58:24 +00:00
total + = linearLists [ i ] . Num ( ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
checksumData = ( int * ) _alloca16 ( total * 2 * sizeof ( int ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
total = 0 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < DECL_MAX_TYPES ; i + + )
{
declType_t type = ( declType_t ) i ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: not particularly pretty but PDAs and associated decls are localized and should not be checksummed
2012-11-28 15:47:07 +00:00
if ( type = = DECL_PDA | | type = = DECL_VIDEO | | type = = DECL_AUDIO | | type = = DECL_EMAIL )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
num = linearLists [ i ] . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < num ; j + + )
{
idDeclLocal * decl = linearLists [ i ] [ j ] ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( decl - > sourceFile = = & implicitDecls )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
checksumData [ total * 2 + 0 ] = total ;
checksumData [ total * 2 + 1 ] = decl - > checksum ;
2012-11-26 18:58:24 +00:00
total + + ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
LittleRevBytes ( checksumData , sizeof ( int ) , total * 2 ) ;
2012-11-26 18:58:24 +00:00
return MD5_BlockChecksum ( checksumData , total * 2 * sizeof ( int ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : GetNumDeclTypes
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idDeclManagerLocal : : GetNumDeclTypes ( ) const
{
2012-11-26 18:58:24 +00:00
return declTypes . Num ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : GetDeclNameFromType
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idDeclManagerLocal : : GetDeclNameFromType ( declType_t type ) const
{
int typeIndex = ( int ) type ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( typeIndex < 0 | | typeIndex > = declTypes . Num ( ) | | declTypes [ typeIndex ] = = NULL )
{
2012-11-26 18:58:24 +00:00
common - > FatalError ( " idDeclManager::GetDeclNameFromType: bad type: %i " , typeIndex ) ;
}
return declTypes [ typeIndex ] - > typeName ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : GetDeclTypeFromName
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
declType_t idDeclManagerLocal : : GetDeclTypeFromName ( const char * typeName ) const
{
2012-11-26 18:58:24 +00:00
int i ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < declTypes . Num ( ) ; i + + )
{
if ( declTypes [ i ] & & declTypes [ i ] - > typeName . Icmp ( typeName ) = = 0 )
{
return ( declType_t ) declTypes [ i ] - > type ;
2012-11-26 18:58:24 +00:00
}
}
return DECL_MAX_TYPES ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclManagerLocal : : FindType
External users will always cause the decl to be parsed before returning
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDecl * idDeclManagerLocal : : FindType ( declType_t type , const char * name , bool makeDefault )
{
idDeclLocal * decl ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idScopedCriticalSection cs ( mutex ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! name | | ! name [ 0 ] )
{
2012-11-26 18:58:24 +00:00
name = " _emptyName " ;
//common->Warning( "idDeclManager::FindType: empty %s name", GetDeclType( (int)type )->typeName.c_str() );
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
decl = FindTypeWithoutParsing ( type , name , makeDefault ) ;
2012-11-28 15:47:07 +00:00
if ( ! decl )
{
2012-11-26 18:58:24 +00:00
return NULL ;
2012-11-28 15:47:07 +00:00
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
decl - > AllocateSelf ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// if it hasn't been parsed yet, parse it now
2012-11-28 15:47:07 +00:00
if ( decl - > declState = = DS_UNPARSED )
{
2020-11-26 19:40:03 +00:00
// GK: Let's hope I didn't break anything important with that
// RB answer: this should be no issue with Vulkan but could remain a problem with OpenGL
#if 0
2012-11-28 15:47:07 +00:00
if ( ! idLib : : IsMainThread ( ) )
{
2012-11-26 18:58:24 +00:00
// we can't load images from a background thread on OpenGL,
// the renderer on the main thread should parse it if needed
idLib : : Error ( " Attempted to load %s decl '%s' from game thread! " , GetDeclNameFromType ( type ) , name ) ;
}
2020-11-26 19:40:03 +00:00
# endif
2012-11-26 18:58:24 +00:00
decl - > ParseLocal ( ) ;
2023-12-14 19:32:16 +00:00
// SRS - set non-purgeable flag only after ParseLocal(), don't reset if declState is parsed or defaulted
decl - > parsedOutsideLevelLoad = ! insideLevelLoad ;
2012-11-26 18:58:24 +00:00
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// mark it as referenced
decl - > referencedThisLevel = true ;
decl - > everReferenced = true ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return decl - > self ;
}
/*
= = = = = = = = = = = = = = =
idDeclManagerLocal : : FindDeclWithoutParsing
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDecl * idDeclManagerLocal : : FindDeclWithoutParsing ( declType_t type , const char * name , bool makeDefault )
{
2012-11-26 18:58:24 +00:00
idDeclLocal * decl ;
2012-11-28 15:47:07 +00:00
decl = FindTypeWithoutParsing ( type , name , makeDefault ) ;
if ( decl )
{
2012-11-26 18:58:24 +00:00
return decl - > self ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = =
idDeclManagerLocal : : ReloadFile
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : ReloadFile ( const char * filename , bool force )
{
for ( int i = 0 ; i < loadedFiles . Num ( ) ; i + + )
{
if ( ! loadedFiles [ i ] - > fileName . Icmp ( filename ) )
{
2012-11-26 18:58:24 +00:00
checksum ^ = loadedFiles [ i ] - > checksum ;
loadedFiles [ i ] - > Reload ( force ) ;
checksum ^ = loadedFiles [ i ] - > checksum ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : GetNumDecls
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idDeclManagerLocal : : GetNumDecls ( declType_t type )
{
int typeIndex = ( int ) type ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( typeIndex < 0 | | typeIndex > = declTypes . Num ( ) | | declTypes [ typeIndex ] = = NULL )
{
2012-11-26 18:58:24 +00:00
common - > FatalError ( " idDeclManager::GetNumDecls: bad type: %i " , typeIndex ) ;
return 0 ;
}
return linearLists [ typeIndex ] . Num ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : DeclByIndex
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idDecl * idDeclManagerLocal : : DeclByIndex ( declType_t type , int index , bool forceParse )
{
int typeIndex = ( int ) type ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( typeIndex < 0 | | typeIndex > = declTypes . Num ( ) | | declTypes [ typeIndex ] = = NULL )
{
2012-11-26 18:58:24 +00:00
common - > FatalError ( " idDeclManager::DeclByIndex: bad type: %i " , typeIndex ) ;
return NULL ;
}
2012-11-28 15:47:07 +00:00
if ( index < 0 | | index > = linearLists [ typeIndex ] . Num ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Error ( " idDeclManager::DeclByIndex: out of range " ) ;
}
2012-11-28 15:47:07 +00:00
idDeclLocal * decl = linearLists [ typeIndex ] [ index ] ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
decl - > AllocateSelf ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( forceParse & & decl - > declState = = DS_UNPARSED )
{
2012-11-26 18:58:24 +00:00
decl - > ParseLocal ( ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return decl - > self ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : ListType
list *
Lists decls currently referenced
list * ever
Lists decls that have been referenced at least once since app launched
list * all
Lists every decl declared , even if it hasn ' t been referenced or parsed
FIXME : alphabetized , wildcards ?
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : ListType ( const idCmdArgs & args , declType_t type )
{
2012-11-26 18:58:24 +00:00
bool all , ever ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! idStr : : Icmp ( args . Argv ( 1 ) , " all " ) )
{
2012-11-26 18:58:24 +00:00
all = true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
all = false ;
}
2012-11-28 15:47:07 +00:00
if ( ! idStr : : Icmp ( args . Argv ( 1 ) , " ever " ) )
{
2012-11-26 18:58:24 +00:00
ever = true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
ever = false ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " -------------------- \n " ) ;
int printed = 0 ;
2012-11-28 15:47:07 +00:00
int count = linearLists [ ( int ) type ] . Num ( ) ;
for ( int i = 0 ; i < count ; i + + )
{
idDeclLocal * decl = linearLists [ ( int ) type ] [ i ] ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! all & & decl - > declState = = DS_UNPARSED )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! all & & ! ever & & ! decl - > referencedThisLevel )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2019-11-11 19:27:44 +00:00
2023-12-14 19:32:16 +00:00
if ( decl - > parsedOutsideLevelLoad )
{
common - > Printf ( " ! " ) ;
}
else if ( decl - > referencedThisLevel )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " * " ) ;
2012-11-28 15:47:07 +00:00
}
else if ( decl - > everReferenced )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " . " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " " ) ;
}
2012-11-28 15:47:07 +00:00
if ( decl - > declState = = DS_DEFAULTED )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " D " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " " ) ;
}
common - > Printf ( " %4i: " , decl - > index ) ;
printed + + ;
2012-11-28 15:47:07 +00:00
if ( decl - > declState = = DS_UNPARSED )
{
2012-11-26 18:58:24 +00:00
// doesn't have any type specific data yet
common - > Printf ( " %s \n " , decl - > GetName ( ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
decl - > self - > List ( ) ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " -------------------- \n " ) ;
common - > Printf ( " %i of %i %s \n " , printed , count , declTypes [ type ] - > typeName . c_str ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : PrintType
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : PrintType ( const idCmdArgs & args , declType_t type )
{
2012-11-26 18:58:24 +00:00
// individual decl types may use additional command parameters
2012-11-28 15:47:07 +00:00
if ( args . Argc ( ) < 2 )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " USAGE: Print<decl type> <decl name> [type specific parms] \n " ) ;
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// look it up, skipping the public path so it won't parse or reference
2012-11-28 15:47:07 +00:00
idDeclLocal * decl = FindTypeWithoutParsing ( type , args . Argv ( 1 ) , false ) ;
if ( ! decl )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " %s '%s' not found. \n " , declTypes [ type ] - > typeName . c_str ( ) , args . Argv ( 1 ) ) ;
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// print information common to all decls
common - > Printf ( " %s %s: \n " , declTypes [ type ] - > typeName . c_str ( ) , decl - > name . c_str ( ) ) ;
common - > Printf ( " source: %s:%i \n " , decl - > sourceFile - > fileName . c_str ( ) , decl - > sourceLine ) ;
common - > Printf ( " ---------- \n " ) ;
2012-11-28 15:47:07 +00:00
if ( decl - > textSource ! = NULL )
{
char * declText = ( char * ) _alloca ( decl - > textLength + 1 ) ;
2012-11-26 18:58:24 +00:00
decl - > GetText ( declText ) ;
common - > Printf ( " %s \n " , declText ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " NO SOURCE \n " ) ;
}
common - > Printf ( " ---------- \n " ) ;
2012-11-28 15:47:07 +00:00
switch ( decl - > declState )
{
2012-11-26 18:58:24 +00:00
case DS_UNPARSED :
common - > Printf ( " Unparsed. \n " ) ;
break ;
case DS_DEFAULTED :
common - > Printf ( " <DEFAULTED> \n " ) ;
break ;
case DS_PARSED :
common - > Printf ( " Parsed. \n " ) ;
break ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( decl - > referencedThisLevel )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " Currently referenced this level. \n " ) ;
2012-11-28 15:47:07 +00:00
}
else if ( decl - > everReferenced )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " Referenced in a previous level. \n " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " Never referenced. \n " ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// allow type-specific data to be printed
2012-11-28 15:47:07 +00:00
if ( decl - > self ! = NULL )
{
2012-11-26 18:58:24 +00:00
decl - > self - > Print ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : CreateNewDecl
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDecl * idDeclManagerLocal : : CreateNewDecl ( declType_t type , const char * name , const char * _fileName )
{
int typeIndex = ( int ) type ;
2012-11-26 18:58:24 +00:00
int i , hash ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( typeIndex < 0 | | typeIndex > = declTypes . Num ( ) | | declTypes [ typeIndex ] = = NULL | | typeIndex > = DECL_MAX_TYPES )
{
2012-11-26 18:58:24 +00:00
common - > FatalError ( " idDeclManager::CreateNewDecl: bad type: %i " , typeIndex ) ;
return NULL ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
char canonicalName [ MAX_STRING_CHARS ] ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
MakeNameCanonical ( name , canonicalName , sizeof ( canonicalName ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idStr fileName = _fileName ;
fileName . BackSlashesToSlashes ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// see if it already exists
hash = hashTables [ typeIndex ] . GenerateKey ( canonicalName , false ) ;
2012-11-28 15:47:07 +00:00
for ( i = hashTables [ typeIndex ] . First ( hash ) ; i > = 0 ; i = hashTables [ typeIndex ] . Next ( i ) )
{
if ( linearLists [ typeIndex ] [ i ] - > name . Icmp ( canonicalName ) = = 0 )
{
2012-11-26 18:58:24 +00:00
linearLists [ typeIndex ] [ i ] - > AllocateSelf ( ) ;
return linearLists [ typeIndex ] [ i ] - > self ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idDeclFile * sourceFile ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// find existing source file or create a new one
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < loadedFiles . Num ( ) ; i + + )
{
if ( loadedFiles [ i ] - > fileName . Icmp ( fileName ) = = 0 )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( i < loadedFiles . Num ( ) )
{
2012-11-26 18:58:24 +00:00
sourceFile = loadedFiles [ i ] ;
2012-11-28 15:47:07 +00:00
}
else
{
sourceFile = new ( TAG_DECL ) idDeclFile ( fileName , type ) ;
2012-11-26 18:58:24 +00:00
loadedFiles . Append ( sourceFile ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idDeclLocal * decl = new ( TAG_DECL ) idDeclLocal ;
2012-11-26 18:58:24 +00:00
decl - > name = canonicalName ;
decl - > type = type ;
decl - > declState = DS_UNPARSED ;
decl - > AllocateSelf ( ) ;
idStr header = declTypes [ typeIndex ] - > typeName ;
idStr defaultText = decl - > self - > DefaultDefinition ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int size = header . Length ( ) + 1 + idStr : : Length ( canonicalName ) + 1 + defaultText . Length ( ) ;
2012-11-28 15:47:07 +00:00
char * declText = ( char * ) _alloca ( size + 1 ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
memcpy ( declText , header , header . Length ( ) ) ;
declText [ header . Length ( ) ] = ' ' ;
memcpy ( declText + header . Length ( ) + 1 , canonicalName , idStr : : Length ( canonicalName ) ) ;
declText [ header . Length ( ) + 1 + idStr : : Length ( canonicalName ) ] = ' ' ;
memcpy ( declText + header . Length ( ) + 1 + idStr : : Length ( canonicalName ) + 1 , defaultText , defaultText . Length ( ) + 1 ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
decl - > SetTextLocal ( declText , size ) ;
decl - > sourceFile = sourceFile ;
decl - > sourceTextOffset = sourceFile - > fileSize ;
decl - > sourceTextLength = 0 ;
decl - > sourceLine = sourceFile - > numLines ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
decl - > ParseLocal ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// add this decl to the source file list
decl - > nextInFile = sourceFile - > decls ;
sourceFile - > decls = decl ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// add it to the hash table and linear list
decl - > index = linearLists [ typeIndex ] . Num ( ) ;
hashTables [ typeIndex ] . Add ( hash , linearLists [ typeIndex ] . Append ( decl ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return decl - > self ;
}
/*
= = = = = = = = = = = = = = =
idDeclManagerLocal : : RenameDecl
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDeclManagerLocal : : RenameDecl ( declType_t type , const char * oldName , const char * newName )
{
2012-11-26 18:58:24 +00:00
char canonicalOldName [ MAX_STRING_CHARS ] ;
2012-11-28 15:47:07 +00:00
MakeNameCanonical ( oldName , canonicalOldName , sizeof ( canonicalOldName ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
char canonicalNewName [ MAX_STRING_CHARS ] ;
MakeNameCanonical ( newName , canonicalNewName , sizeof ( canonicalNewName ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idDeclLocal * decl = NULL ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// make sure it already exists
2012-11-28 15:47:07 +00:00
int typeIndex = ( int ) type ;
2012-11-26 18:58:24 +00:00
int i , hash ;
hash = hashTables [ typeIndex ] . GenerateKey ( canonicalOldName , false ) ;
2012-11-28 15:47:07 +00:00
for ( i = hashTables [ typeIndex ] . First ( hash ) ; i > = 0 ; i = hashTables [ typeIndex ] . Next ( i ) )
{
if ( linearLists [ typeIndex ] [ i ] - > name . Icmp ( canonicalOldName ) = = 0 )
{
2012-11-26 18:58:24 +00:00
decl = linearLists [ typeIndex ] [ i ] ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! decl )
2019-11-11 19:27:44 +00:00
{
2012-11-26 18:58:24 +00:00
return false ;
2019-11-11 19:27:44 +00:00
}
2012-11-26 18:58:24 +00:00
//if ( !hashTables[(int)type].Get( canonicalOldName, &declPtr ) )
// return false;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//decl = *declPtr;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//Change the name
decl - > name = canonicalNewName ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// add it to the hash table
//hashTables[(int)decl->type].Set( decl->name, decl );
int newhash = hashTables [ typeIndex ] . GenerateKey ( canonicalNewName , false ) ;
hashTables [ typeIndex ] . Add ( newhash , decl - > index ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
//Remove the old hash item
2012-11-28 15:47:07 +00:00
hashTables [ typeIndex ] . Remove ( hash , decl - > index ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : MediaPrint
This is just used to nicely indent media caching prints
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : MediaPrint ( const char * fmt , . . . )
{
if ( ! decl_show . GetInteger ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < indent ; i + + )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " " ) ;
}
va_list argptr ;
char buffer [ 1024 ] ;
2012-11-28 15:47:07 +00:00
va_start ( argptr , fmt ) ;
idStr : : vsnPrintf ( buffer , sizeof ( buffer ) , fmt , argptr ) ;
va_end ( argptr ) ;
buffer [ sizeof ( buffer ) - 1 ] = ' \0 ' ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " %s " , buffer ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : WritePrecacheCommands
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : WritePrecacheCommands ( idFile * f )
{
for ( int i = 0 ; i < declTypes . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
int num ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( declTypes [ i ] = = NULL )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
num = linearLists [ i ] . Num ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < num ; j + + )
{
idDeclLocal * decl = linearLists [ i ] [ j ] ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! decl - > referencedThisLevel )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
char str [ 1024 ] ;
2023-06-20 16:24:24 +00:00
idStr : : snPrintf ( str , sizeof ( str ) , " touch %s %s \n " , declTypes [ i ] - > typeName . c_str ( ) , decl - > GetName ( ) ) ;
2012-11-26 18:58:24 +00:00
common - > Printf ( " %s " , str ) ;
f - > Printf ( " %s " , str ) ;
}
}
}
/********************************************************************/
2012-11-28 15:47:07 +00:00
const idMaterial * idDeclManagerLocal : : FindMaterial ( const char * name , bool makeDefault )
{
return static_cast < const idMaterial * > ( FindType ( DECL_MATERIAL , name , makeDefault ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
const idMaterial * idDeclManagerLocal : : MaterialByIndex ( int index , bool forceParse )
{
return static_cast < const idMaterial * > ( DeclByIndex ( DECL_MATERIAL , index , forceParse ) ) ;
2012-11-26 18:58:24 +00:00
}
/********************************************************************/
2012-11-28 15:47:07 +00:00
const idDeclSkin * idDeclManagerLocal : : FindSkin ( const char * name , bool makeDefault )
{
return static_cast < const idDeclSkin * > ( FindType ( DECL_SKIN , name , makeDefault ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
const idDeclSkin * idDeclManagerLocal : : SkinByIndex ( int index , bool forceParse )
{
return static_cast < const idDeclSkin * > ( DeclByIndex ( DECL_SKIN , index , forceParse ) ) ;
2012-11-26 18:58:24 +00:00
}
2024-06-19 19:33:41 +00:00
# if !defined( DMAP )
2012-11-26 18:58:24 +00:00
/********************************************************************/
2012-11-28 15:47:07 +00:00
const idSoundShader * idDeclManagerLocal : : FindSound ( const char * name , bool makeDefault )
{
return static_cast < const idSoundShader * > ( FindType ( DECL_SOUND , name , makeDefault ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
const idSoundShader * idDeclManagerLocal : : SoundByIndex ( int index , bool forceParse )
{
return static_cast < const idSoundShader * > ( DeclByIndex ( DECL_SOUND , index , forceParse ) ) ;
2012-11-26 18:58:24 +00:00
}
2024-06-17 20:10:50 +00:00
# endif
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : Touch
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : Touch ( const idDecl * decl )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( decl - > base - > GetState ( ) = = DS_UNPARSED )
{
2012-11-26 18:58:24 +00:00
// This should parse the decl as well.
FindType ( decl - > GetType ( ) , decl - > GetName ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : MakeNameCanonical
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : MakeNameCanonical ( const char * name , char * result , int maxLength )
{
2012-11-26 18:58:24 +00:00
int i , lastDot ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
lastDot = - 1 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < maxLength & & name [ i ] ! = ' \0 ' ; i + + )
{
2012-11-26 18:58:24 +00:00
int c = name [ i ] ;
2012-11-28 15:47:07 +00:00
if ( c = = ' \\ ' )
{
2012-11-26 18:58:24 +00:00
result [ i ] = ' / ' ;
2012-11-28 15:47:07 +00:00
}
else if ( c = = ' . ' )
{
2012-11-26 18:58:24 +00:00
lastDot = i ;
result [ i ] = c ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
result [ i ] = idStr : : ToLower ( c ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( lastDot ! = - 1 )
{
2012-11-26 18:58:24 +00:00
result [ lastDot ] = ' \0 ' ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
result [ i ] = ' \0 ' ;
}
}
/*
= = = = = = = = = = = = = = = =
idDeclManagerLocal : : ListDecls_f
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : ListDecls_f ( const idCmdArgs & args )
{
2012-11-26 18:58:24 +00:00
int i , j ;
int totalDecls = 0 ;
int totalText = 0 ;
int totalStructs = 0 ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < declManagerLocal . declTypes . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
int size , num ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( declManagerLocal . declTypes [ i ] = = NULL )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
num = declManagerLocal . linearLists [ i ] . Num ( ) ;
totalDecls + = num ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
size = 0 ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < num ; j + + )
{
2012-11-26 18:58:24 +00:00
size + = declManagerLocal . linearLists [ i ] [ j ] - > Size ( ) ;
2012-11-28 15:47:07 +00:00
if ( declManagerLocal . linearLists [ i ] [ j ] - > self ! = NULL )
{
2012-11-26 18:58:24 +00:00
size + = declManagerLocal . linearLists [ i ] [ j ] - > self - > Size ( ) ;
}
}
totalStructs + = size ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " %4ik %4i %s \n " , size > > 10 , num , declManagerLocal . declTypes [ i ] - > typeName . c_str ( ) ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < declManagerLocal . loadedFiles . Num ( ) ; i + + )
{
idDeclFile * df = declManagerLocal . loadedFiles [ i ] ;
2012-11-26 18:58:24 +00:00
totalText + = df - > fileSize ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " %i total decls is %i decl files \n " , totalDecls , declManagerLocal . loadedFiles . Num ( ) ) ;
common - > Printf ( " %iKB in text, %iKB in structures \n " , totalText > > 10 , totalStructs > > 10 ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : ReloadDecls_f
Reload will not find any new files created in the directories , it
will only reload existing files .
A reload will never cause anything to be purged .
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : ReloadDecls_f ( const idCmdArgs & args )
{
2012-11-26 18:58:24 +00:00
bool force ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! idStr : : Icmp ( args . Argv ( 1 ) , " all " ) )
{
2012-11-26 18:58:24 +00:00
force = true ;
common - > Printf ( " reloading all decl files: \n " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
force = false ;
common - > Printf ( " reloading changed decl files: \n " ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
declManagerLocal . Reload ( force ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : TouchDecl_f
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : TouchDecl_f ( const idCmdArgs & args )
{
2012-11-26 18:58:24 +00:00
int i ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( args . Argc ( ) ! = 3 )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " usage: touch <type> <name> \n " ) ;
common - > Printf ( " valid types: " ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < declManagerLocal . declTypes . Num ( ) ; i + + )
{
if ( declManagerLocal . declTypes [ i ] )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " %s " , declManagerLocal . declTypes [ i ] - > typeName . c_str ( ) ) ;
}
}
common - > Printf ( " \n " ) ;
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < declManagerLocal . declTypes . Num ( ) ; i + + )
{
if ( declManagerLocal . declTypes [ i ] & & declManagerLocal . declTypes [ i ] - > typeName . Icmp ( args . Argv ( 1 ) ) = = 0 )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( i > = declManagerLocal . declTypes . Num ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " unknown decl type '%s' \n " , args . Argv ( 1 ) ) ;
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
const idDecl * decl = declManagerLocal . FindType ( ( declType_t ) i , args . Argv ( 2 ) , false ) ;
if ( ! decl )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " %s '%s' not found \n " , declManagerLocal . declTypes [ i ] - > typeName . c_str ( ) , args . Argv ( 2 ) ) ;
}
}
2016-03-05 20:19:14 +00:00
// RB begin
2024-06-17 20:10:50 +00:00
# if !defined( DMAP )
2023-10-07 12:04:27 +00:00
void idDeclManagerLocal : : ExportEntityDefsToBlender_f ( const idCmdArgs & args )
2016-03-05 20:19:14 +00:00
{
2023-04-02 13:42:14 +00:00
idStr jsonStringsFileName = " _bl/entities.json " ;
2016-03-05 20:19:14 +00:00
idFileLocal file ( fileSystem - > OpenFileWrite ( jsonStringsFileName , " fs_basepath " ) ) ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
if ( file = = NULL )
{
idLib : : Printf ( " Failed to entity declarations data to JSON. \n " ) ;
}
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
int totalEntitiesCount = 0 ;
int totalModelsCount = 0 ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
// avoid media cache
2021-01-09 17:27:06 +00:00
com_editors | = EDITOR_EXPORTDEFS ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
file - > Printf ( " { \n \t \" entities \" : { " ) ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
int count = declManagerLocal . linearLists [ DECL_ENTITYDEF ] . Num ( ) ;
for ( int i = 0 ; i < count ; i + + )
{
const idDeclEntityDef * decl = static_cast < const idDeclEntityDef * > ( declManagerLocal . FindType ( DECL_ENTITYDEF , declManagerLocal . linearLists [ DECL_ENTITYDEF ] [ i ] - > GetName ( ) , false ) ) ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
totalEntitiesCount + + ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
file - > Printf ( " \n \t \t \" %s \" : { \n " , decl - > GetName ( ) ) ;
decl - > dict . WriteJSON ( file , " \t \t " ) ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
if ( i = = ( count - 1 ) )
{
file - > Printf ( " \t \t } \n " ) ;
}
else
{
file - > Printf ( " \t \t }, \n " ) ;
}
}
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
file - > Printf ( " \t } \n " ) ;
file - > Printf ( " } \n " ) ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
file - > Flush ( ) ;
2019-11-11 19:27:44 +00:00
2021-01-09 17:27:06 +00:00
com_editors & = ~ EDITOR_EXPORTDEFS ;
2019-11-11 19:27:44 +00:00
2016-03-05 20:19:14 +00:00
idLib : : Printf ( " \n Data written to %s \n " , jsonStringsFileName . c_str ( ) ) ;
idLib : : Printf ( " ---------------------------- \n " ) ;
idLib : : Printf ( " Wrote %d Entities. \n " , totalEntitiesCount ) ;
idLib : : Printf ( " Wrote %d Models. \n " , totalModelsCount ) ;
}
2021-01-09 17:27:06 +00:00
2023-10-07 12:04:27 +00:00
void idDeclManagerLocal : : ExportMaterialsToBlender_f ( const idCmdArgs & args )
{
idStr jsonStringsFileName = " _bl/materials.json " ;
idFileLocal file ( fileSystem - > OpenFileWrite ( jsonStringsFileName , " fs_basepath " ) ) ;
if ( file = = NULL )
{
idLib : : Printf ( " Failed to entity declarations data to JSON. \n " ) ;
}
int totalMaterialsCount = 0 ;
// avoid media cache
com_editors | = EDITOR_EXPORTDEFS ;
file - > Printf ( " { \n \t \" materials \" : { " ) ;
int count = declManagerLocal . linearLists [ DECL_MATERIAL ] . Num ( ) ;
CommandlineProgressBar progressBar ( count , renderSystem - > GetWidth ( ) , renderSystem - > GetHeight ( ) ) ;
progressBar . Start ( ) ;
for ( int i = 0 ; i < count ; i + + )
{
const idMaterial * material = static_cast < const idMaterial * > ( declManagerLocal . FindType ( DECL_MATERIAL , declManagerLocal . linearLists [ DECL_MATERIAL ] [ i ] - > GetName ( ) , false ) ) ;
2023-10-08 12:27:22 +00:00
#if 0
const char * matName = material - > GetName ( ) ;
if ( idStr : : FindText ( matName , " textures/base_floor/ghotile3 " , false ) ! = - 1 )
{
totalMaterialsCount + + ;
}
# endif
2023-10-07 12:04:27 +00:00
material - > ExportJSON ( file , i = = ( count - 1 ) ) ;
totalMaterialsCount + + ;
progressBar . Increment ( true ) ;
}
file - > Printf ( " \t } \n " ) ;
file - > Printf ( " } \n " ) ;
file - > Flush ( ) ;
com_editors & = ~ EDITOR_EXPORTDEFS ;
idLib : : Printf ( " \n Data written to %s \n " , jsonStringsFileName . c_str ( ) ) ;
idLib : : Printf ( " ---------------------------- \n " ) ;
idLib : : Printf ( " Wrote %d Materials. \n " , totalMaterialsCount ) ;
}
2021-01-09 17:27:06 +00:00
class idSort_CompareEntityDefEntity : public idSort_Quick < const idDeclEntityDef * , idSort_CompareEntityDefEntity >
{
public :
int Compare ( const idDeclEntityDef * const & a , const idDeclEntityDef * const & b ) const
{
return idStr : : Icmp ( a - > GetName ( ) , b - > GetName ( ) ) ;
}
} ;
enum EVAR_TYPES
{
EVAR_STRING ,
EVAR_INT ,
EVAR_FLOAT ,
EVAR_BOOL ,
EVAR_COLOR ,
EVAR_MATERIAL ,
EVAR_MODEL ,
EVAR_GUI ,
EVAR_SOUND
} ;
struct evarPrefix_t
{
int type ;
const char * prefix ;
} ;
2021-04-26 14:31:04 +00:00
static const evarPrefix_t EvarPrefixes [ ] =
2021-01-09 17:27:06 +00:00
{
{ EVAR_STRING , " editor_var " } ,
{ EVAR_INT , " editor_int " } ,
{ EVAR_FLOAT , " editor_float " } ,
{ EVAR_BOOL , " editor_bool " } ,
{ EVAR_COLOR , " editor_color " } ,
{ EVAR_MATERIAL , " editor_mat " } ,
{ EVAR_MODEL , " editor_model " } ,
{ EVAR_GUI , " editor_gui " } ,
{ EVAR_SOUND , " editor_snd " }
} ;
2021-04-26 14:31:04 +00:00
static const int NumEvarPrefixes = sizeof ( EvarPrefixes ) / sizeof ( evarPrefix_t ) ;
2021-01-09 17:27:06 +00:00
2021-04-26 14:31:04 +00:00
struct LocalEvar_t
2021-01-09 17:27:06 +00:00
{
int type ;
idStr fullname ;
idStr name ;
idStr desc ;
2021-04-26 14:31:04 +00:00
} ;
2021-01-09 17:27:06 +00:00
2021-01-13 14:46:40 +00:00
# include <d3xp/anim/Anim.h> // idDeclModelDef
2023-10-07 12:04:27 +00:00
void idDeclManagerLocal : : ExportEntityDefsToTrenchBroom_f ( const idCmdArgs & args )
2021-01-09 17:27:06 +00:00
{
extern idCVar postLoadExportModels ;
// avoid media cache
com_editors | = EDITOR_EXPORTDEFS ;
// reload entities and skip "inherit" parsing because EDITOR_EXPORTDEFS is set
declManagerLocal . Reload ( true ) ;
int count = declManagerLocal . linearLists [ DECL_ENTITYDEF ] . Num ( ) ;
static idList < const idDeclEntityDef * , TAG_IDLIB_LIST_DECL > defsSorted ; //( count );
defsSorted . AssureSize ( count ) ;
for ( int i = 0 ; i < count ; i + + )
{
const idDeclEntityDef * decl = static_cast < const idDeclEntityDef * > ( declManagerLocal . FindType ( DECL_ENTITYDEF , declManagerLocal . linearLists [ DECL_ENTITYDEF ] [ i ] - > GetName ( ) , false ) ) ;
defsSorted [ i ] = decl ;
}
defsSorted . SortWithTemplate ( idSort_CompareEntityDefEntity ( ) ) ;
2021-02-15 22:06:58 +00:00
bool exportModels = false ;
2021-04-17 19:06:19 +00:00
if ( ! idStr : : Icmp ( args . Argv ( 1 ) , " nomodels " ) )
2021-02-15 22:06:58 +00:00
{
2021-04-17 19:06:19 +00:00
exportModels = false ;
common - > Printf ( " exporting entity decls to FGDs without models: \n " ) ;
2021-02-15 22:06:58 +00:00
}
else
{
2021-04-17 19:06:19 +00:00
exportModels = true ;
common - > Printf ( " exporting entity decls to FGDs with models: \n " ) ;
2021-02-15 22:06:58 +00:00
}
if ( exportModels )
{
postLoadExportModels . SetBool ( true ) ;
}
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
idStrList filenames ;
filenames . AddUnique ( " all " ) ;
2023-02-24 14:36:29 +00:00
filenames . AddUnique ( " all-and-models " ) ;
2021-01-12 14:39:30 +00:00
filenames . AddUnique ( " slim " ) ;
2023-02-24 14:36:29 +00:00
filenames . AddUnique ( " slim-and-models " ) ;
2021-02-13 17:46:34 +00:00
filenames . AddUnique ( " multiplayer " ) ;
2021-01-12 14:39:30 +00:00
idStrList ignoreList ;
// maps
ignoreList . AddUnique ( " admin " ) ;
ignoreList . AddUnique ( " alphalabs1 " ) ;
ignoreList . AddUnique ( " alphalabs2 " ) ;
ignoreList . AddUnique ( " alphalabs3 " ) ;
ignoreList . AddUnique ( " caverns " ) ;
ignoreList . AddUnique ( " cin " ) ;
ignoreList . AddUnique ( " comm1 " ) ;
ignoreList . AddUnique ( " commoutside " ) ;
ignoreList . AddUnique ( " cpu1 " ) ;
ignoreList . AddUnique ( " cpuboss " ) ;
ignoreList . AddUnique ( " delta " ) ;
ignoreList . AddUnique ( " ending " ) ;
ignoreList . AddUnique ( " enpro " ) ;
ignoreList . AddUnique ( " erebus " ) ;
ignoreList . AddUnique ( " hell " ) ;
ignoreList . AddUnique ( " maledict " ) ;
ignoreList . AddUnique ( " marscity " ) ;
ignoreList . AddUnique ( " monorail " ) ;
ignoreList . AddUnique ( " phobos2 " ) ;
ignoreList . AddUnique ( " recycling " ) ;
ignoreList . AddUnique ( " ronn " ) ;
ignoreList . AddUnique ( " seeker " ) ;
ignoreList . AddUnique ( " site3 " ) ;
ignoreList . AddUnique ( " ss " ) ;
ignoreList . AddUnique ( " test " ) ;
ignoreList . AddUnique ( " underground " ) ;
2021-11-09 18:47:06 +00:00
ignoreList . AddUnique ( " lm_ " ) ;
2021-01-12 14:39:30 +00:00
// xbox
ignoreList . AddUnique ( " xbox " ) ;
ignoreList . AddUnique ( " xmarscity " ) ;
ignoreList . AddUnique ( " xsp " ) ;
// misc
ignoreList . AddUnique ( " blooper " ) ;
ignoreList . AddUnique ( " npc " ) ;
ignoreList . AddUnique ( " zombie " ) ;
2022-11-02 14:51:12 +00:00
ignoreList . AddUnique ( " space " ) ;
ignoreList . AddUnique ( " static " ) ;
2021-01-12 14:39:30 +00:00
2021-11-09 18:47:06 +00:00
idStrList solidClassNames ;
solidClassNames . AddUnique ( " worldspawn " ) ;
2023-10-25 23:52:03 +00:00
2021-11-09 18:47:06 +00:00
solidClassNames . AddUnique ( " func_aas_obstacle " ) ;
solidClassNames . AddUnique ( " func_aas_portal " ) ;
2023-10-25 23:52:03 +00:00
2021-11-09 18:47:06 +00:00
solidClassNames . AddUnique ( " func_clipmodel " ) ;
2023-10-25 23:52:03 +00:00
solidClassNames . AddUnique ( " func_damagable " ) ;
2021-11-09 18:47:06 +00:00
solidClassNames . AddUnique ( " func_forcefield " ) ;
solidClassNames . AddUnique ( " func_fracture " ) ;
solidClassNames . AddUnique ( " func_liquid " ) ;
solidClassNames . AddUnique ( " func_splinemover " ) ;
2023-10-25 23:52:03 +00:00
solidClassNames . AddUnique ( " func_pendulum " ) ;
solidClassNames . AddUnique ( " func_plat " ) ;
solidClassNames . AddUnique ( " moveable_base_brick " ) ;
solidClassNames . AddUnique ( " moveable_guardian_brick " ) ;
2021-11-09 18:47:06 +00:00
solidClassNames . AddUnique ( " trigger_ " ) ;
2023-10-25 23:52:03 +00:00
// mixed classes that need extra _model pendants
solidClassNames . AddUnique ( " func_door " ) ;
2023-10-27 19:12:09 +00:00
solidClassNames . AddUnique ( " func_bobbing " ) ;
2023-10-25 23:52:03 +00:00
solidClassNames . AddUnique ( " func_mover " ) ;
solidClassNames . AddUnique ( " func_rotating " ) ;
2023-10-27 19:12:09 +00:00
solidClassNames . AddUnique ( " func_elevator " ) ;
2023-10-25 23:52:03 +00:00
solidClassNames . AddUnique ( " func_static " ) ; // misc_model
2021-01-12 14:39:30 +00:00
for ( int f = 0 ; f < filenames . Num ( ) ; f + + )
{
int totalEntitiesCount = 0 ;
int totalModelsCount = 0 ;
idStr fgdFileName ;
2022-02-27 16:26:58 +00:00
fgdFileName . Format ( " _tb/fgd/DOOM-3-%s.fgd " , filenames [ f ] . c_str ( ) ) ;
2021-01-12 14:39:30 +00:00
idFileLocal file ( fileSystem - > OpenFileWrite ( fgdFileName , " fs_basepath " ) ) ;
if ( file = = NULL )
{
2021-02-10 10:44:45 +00:00
common - > Printf ( " Failed to entity declarations data to FGD. \n " ) ;
2021-01-12 14:39:30 +00:00
}
2021-01-13 14:46:40 +00:00
file - > Printf ( " // DOOM 3 BFG game definition file (.fgd) generated by %s \n \n " , ENGINE_VERSION ) ;
2021-01-12 14:39:30 +00:00
for ( int d = 0 ; d < count ; d + + )
{
const idDeclEntityDef * decl = defsSorted [ d ] ;
totalEntitiesCount + + ;
// only include entityDefs with "editor_" values in them
2021-02-15 22:06:58 +00:00
if ( /*f > 0 &&*/ ! decl - > dict . MatchPrefix ( " editor_ " ) )
2021-01-12 14:39:30 +00:00
{
bool parentHasEditorKeys = false ;
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
const idDeclEntityDef * decl2 = decl ;
while ( 1 )
{
const idKeyValue * kv ;
kv = decl2 - > dict . MatchPrefix ( " inherit " , NULL ) ;
if ( ! kv )
{
break ;
}
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
const idDeclEntityDef * super = static_cast < const idDeclEntityDef * > ( declManager - > FindType ( DECL_ENTITYDEF , kv - > GetValue ( ) , false ) ) ;
if ( ! super )
{
//src.Warning( "Unknown entityDef '%s' inherited by '%s'", kv->GetValue().c_str(), GetName() );
break ;
}
else
{
decl2 = super ;
}
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
if ( decl2 - > dict . MatchPrefix ( " editor_ " ) )
{
parentHasEditorKeys = true ;
break ;
}
}
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
if ( ! parentHasEditorKeys )
{
continue ;
}
2021-01-09 17:27:06 +00:00
}
2023-02-24 14:36:29 +00:00
if ( f > 1 )
2021-01-12 14:39:30 +00:00
{
// ignore entities that begin with those prefices
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
bool ignore = false ;
for ( int i = 0 ; i < ignoreList . Num ( ) ; i + + )
{
const char * ignoreStr = ignoreList [ i ] . c_str ( ) ;
if ( idStr : : Icmpn ( decl - > GetName ( ) , ignoreStr , ( int ) strlen ( ignoreStr ) ) = = 0 )
{
ignore = true ;
break ;
}
}
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
if ( ignore )
{
continue ;
}
}
2021-01-09 17:27:06 +00:00
2022-11-02 14:51:12 +00:00
// ignore autogenerated model definitions for slim FGD
bool genmodel = false ;
2022-11-02 10:44:38 +00:00
if ( idStr : : Icmpn ( decl - > GetName ( ) , " genmodel_ " , 9 ) = = 0 )
{
2022-11-02 14:51:12 +00:00
genmodel = true ;
2022-11-02 10:44:38 +00:00
}
2021-02-13 17:46:34 +00:00
// filter multiplayer entities
bool multiplayer = ( idStr : : FindText ( decl - > GetName ( ) , " _mp " , false ) ! = - 1 | |
2022-11-02 14:51:12 +00:00
idStr : : FindText ( decl - > GetName ( ) , " team_ctf " , false ) ! = - 1 | |
2021-02-13 17:46:34 +00:00
idStr : : FindText ( decl - > GetName ( ) , " _coop " , false ) ! = - 1 ) ;
2023-02-24 14:36:29 +00:00
if ( f = = 4 )
2021-02-13 17:46:34 +00:00
{
2022-11-02 14:51:12 +00:00
if ( ! multiplayer | | genmodel )
2021-02-13 17:46:34 +00:00
{
continue ;
}
}
else
{
if ( multiplayer )
{
continue ;
}
2022-11-02 14:51:12 +00:00
2023-02-24 14:36:29 +00:00
if ( ( f % 2 ) = = 0 & & genmodel )
2022-11-02 14:51:12 +00:00
{
continue ;
}
2021-02-13 17:46:34 +00:00
}
2021-01-09 17:27:06 +00:00
2021-11-09 18:47:06 +00:00
bool solidClass = false ;
for ( int i = 0 ; i < solidClassNames . Num ( ) ; i + + )
{
const char * solidStr = solidClassNames [ i ] . c_str ( ) ;
2022-01-29 17:10:54 +00:00
if ( idStr : : Icmpn ( decl - > GetName ( ) , solidStr , ( int ) strlen ( solidStr ) ) = = 0 & &
! ( idStr : : FindText ( decl - > GetName ( ) , " _model " , false ) ! = - 1 | | idStr : : FindText ( decl - > GetName ( ) , " _amodel " , false ) ! = - 1 ) )
2021-11-09 18:47:06 +00:00
{
solidClass = true ;
break ;
}
}
if ( idStr : : Icmp ( decl - > GetName ( ) , " trigger_relay " ) = = 0 )
{
solidClass = false ;
}
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
//
// build header
//
2021-11-09 18:47:06 +00:00
if ( solidClass )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
file - > Printf ( " @SolidClass " ) ;
}
//else if( baseclass )
//{
// file->Printf( "@BaseClass " );
//}
else
{
file - > Printf ( " @PointClass " ) ;
2021-01-09 17:27:06 +00:00
}
2021-11-09 18:47:06 +00:00
const idKeyValue * kv ;
kv = decl - > dict . MatchPrefix ( " inherit " , NULL ) ;
2021-01-12 14:39:30 +00:00
if ( kv )
{
file - > Printf ( " base(%s) " , kv - > GetValue ( ) . c_str ( ) ) ;
}
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
idStr text = " " ;
kv = decl - > dict . MatchPrefix ( " editor_usage " ) ;
while ( kv ! = NULL )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
text + = kv - > GetValue ( ) ;
if ( ! kv - > GetValue ( ) . Length ( ) | | ( text [ text . Length ( ) - 1 ] ! = ' \n ' ) )
{
text + = " \n " ;
}
kv = decl - > dict . MatchPrefix ( " editor_usage " , kv ) ;
2021-01-09 17:27:06 +00:00
}
2021-01-12 14:39:30 +00:00
if ( text . IsEmpty ( ) )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
text + = " No description " ;
2021-01-09 17:27:06 +00:00
}
2021-01-12 14:39:30 +00:00
idVec3 color ;
if ( decl - > dict . GetVector ( " editor_color " , " 0 0 1 " , color ) )
2021-01-09 17:27:06 +00:00
{
2021-02-10 10:44:45 +00:00
file - > Printf ( " color(%i %i %i) " , int ( color . x * 255 ) & 0xFF , int ( color . y * 255 ) & 0xFF , int ( color . z * 255 ) & 0xFF ) ;
2021-01-09 17:27:06 +00:00
}
2022-01-29 17:10:54 +00:00
#if 0
2021-01-13 14:46:40 +00:00
//if( idStr::Icmp( decl->GetName(), "monster_zombie_maint_bald" ) == 0 )
if ( idStr : : Icmp ( decl - > GetName ( ) , " monster_demon_imp " ) = = 0 )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
text + = " " ;
2021-01-09 17:27:06 +00:00
}
2021-01-12 14:39:30 +00:00
# endif
// write size of entity
idVec3 size ;
idBounds bounds ;
bool writeSize = false ;
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
if ( decl - > dict . GetVector ( " mins " , NULL , bounds [ 0 ] ) & & decl - > dict . GetVector ( " maxs " , NULL , bounds [ 1 ] ) )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
if ( bounds [ 0 ] [ 0 ] > bounds [ 1 ] [ 0 ] | | bounds [ 0 ] [ 1 ] > bounds [ 1 ] [ 1 ] | | bounds [ 0 ] [ 2 ] > bounds [ 1 ] [ 2 ] )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
//gameLocal.Error( "Invalid bounds '%s'-'%s' on entity '%s'", bounds[0].ToString(), bounds[1].ToString(), name.c_str() );
}
else
{
writeSize = true ;
2021-01-09 17:27:06 +00:00
}
}
2021-01-12 14:39:30 +00:00
else if ( decl - > dict . GetVector ( " size " , NULL , size ) )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
if ( ( size . x < 0.0f ) | | ( size . y < 0.0f ) | | ( size . z < 0.0f ) )
{
//gameLocal.Error( "Invalid size '%s' on entity '%s'", size.ToString(), name.c_str() );
}
else
{
bounds [ 0 ] . Set ( size . x * - 0.5f , size . y * - 0.5f , 0.0f ) ;
bounds [ 1 ] . Set ( size . x * 0.5f , size . y * 0.5f , size . z ) ;
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
writeSize = true ;
}
}
else
{
idStr str ;
decl - > dict . GetString ( " editor_mins " , " " , str ) ;
if ( str ! = " ? " )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
if ( decl - > dict . GetVector ( " editor_mins " , " 0 0 0 " , bounds [ 0 ] ) & & decl - > dict . GetVector ( " editor_maxs " , " 0 0 0 " , bounds [ 1 ] ) )
{
writeSize = true ;
}
2021-01-09 17:27:06 +00:00
}
}
2021-01-12 14:39:30 +00:00
if ( writeSize )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
file - > Printf ( " size(%i %i %i, %i %i %i) " ,
2021-02-10 10:44:45 +00:00
int ( bounds [ 0 ] . x ) , int ( bounds [ 0 ] . y ) , int ( bounds [ 0 ] . z ) ,
int ( bounds [ 1 ] . x ) , int ( bounds [ 1 ] . y ) , int ( bounds [ 1 ] . z ) ) ;
2021-01-09 17:27:06 +00:00
}
2021-01-12 14:39:30 +00:00
// collect editor specific spawn flags
2021-04-26 14:31:04 +00:00
idList < LocalEvar_t > evars ;
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
for ( int i = 0 ; i < NumEvarPrefixes ; i + + )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
kv = decl - > dict . MatchPrefix ( EvarPrefixes [ i ] . prefix ) ;
while ( kv )
2021-01-09 17:27:06 +00:00
{
2021-04-26 14:31:04 +00:00
LocalEvar_t ev ;
2021-01-12 14:39:30 +00:00
ev . fullname = kv - > GetKey ( ) ;
kv - > GetKey ( ) . Right ( kv - > GetKey ( ) . Length ( ) - strlen ( EvarPrefixes [ i ] . prefix ) , ev . name ) ;
ev . desc = kv - > GetValue ( ) ;
ev . type = EvarPrefixes [ i ] . type ;
evars . Append ( ev ) ;
kv = decl - > dict . MatchPrefix ( EvarPrefixes [ i ] . prefix , kv ) ;
2021-01-09 17:27:06 +00:00
}
}
2021-01-12 14:39:30 +00:00
idDict dictToWrite ;
2021-01-09 17:27:06 +00:00
2021-02-15 22:06:58 +00:00
if ( idStr : : Icmp ( decl - > GetName ( ) , " light " ) = = 0 )
{
// entityDef light
// add missing property to control the radius
2021-04-26 14:31:04 +00:00
LocalEvar_t ev ;
2021-02-15 22:06:58 +00:00
ev . fullname = " editor_int light " ;
ev . name = " light " ;
ev . desc = " light radius " ;
ev . type = EVAR_INT ;
evars . Append ( ev ) ;
dictToWrite . Set ( " light " , " 300 " ) ;
}
2021-02-16 17:36:24 +00:00
if ( idStr : : Icmp ( decl - > GetName ( ) , " light " ) = = 0 | |
2022-01-29 17:10:54 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " misc_model " ) = = 0 | |
2023-10-25 23:52:03 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_bobbing_model " ) = = 0 | |
2022-01-29 17:10:54 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_door_model " ) = = 0 | |
2023-10-25 23:52:03 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_mover_model " ) = = 0 | |
2022-01-29 17:10:54 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_mover_amodel " ) = = 0 | |
idStr : : Icmp ( decl - > GetName ( ) , " func_plat_model " ) = = 0 | |
idStr : : Icmp ( decl - > GetName ( ) , " func_rotating_model " ) = = 0 )
2021-02-16 17:36:24 +00:00
{
// entities with dynamic models
2021-04-26 14:31:04 +00:00
LocalEvar_t ev ;
2021-02-16 17:36:24 +00:00
ev . fullname = " editor_model model " ;
ev . name = " model " ;
ev . desc = " Model Selection (ex mapobjects/model.obj) " ;
ev . type = EVAR_MODEL ;
evars . Append ( ev ) ;
2022-02-27 12:56:14 +00:00
ev . fullname = " editor_model proxymodel " ;
ev . name = " proxymodel " ;
ev . desc = " A proxy model in OBJ file format automatically set by RBDoom so it can be displayed in TrenchBroom " ;
ev . type = EVAR_MODEL ;
evars . Append ( ev ) ;
2021-02-16 17:36:24 +00:00
}
2021-01-12 14:39:30 +00:00
for ( int i = 0 ; i < decl - > dict . GetNumKeyVals ( ) ; i + + )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
kv = decl - > dict . GetKeyVal ( i ) ;
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
if ( kv - > GetKey ( ) . IcmpPrefix ( " editor_ " ) = = 0 )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
continue ;
}
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
if ( kv - > GetKey ( ) . Icmp ( " classname " ) = = 0 )
{
continue ;
}
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
if ( kv - > GetKey ( ) . Icmp ( " inherit " ) = = 0 )
{
continue ;
}
// TODO FIXME cinematic md5camera animations
2021-02-15 18:28:39 +00:00
//if( kv->GetKey().IcmpPrefix( "anim" ) == 0 )
//{
// continue;
//}
2021-01-12 14:39:30 +00:00
// is it an editor var or a regular spawn argument?
2021-04-26 14:31:04 +00:00
LocalEvar_t * ev = nullptr ;
2021-01-12 14:39:30 +00:00
int vc = evars . Num ( ) ;
for ( int j = 0 ; j < vc ; j + + )
{
if ( evars [ j ] . fullname . Icmp ( kv - > GetKey ( ) ) = = 0 )
{
ev = & evars [ j ] ;
2021-01-09 17:27:06 +00:00
break ;
2021-01-12 14:39:30 +00:00
}
}
// don't print the descriptive editor var itself yet
if ( ! ev )
{
//file->Printf( "\t%s(string)\n", kv->GetKey().c_str() );
const idKeyValue * kv2 = dictToWrite . FindKey ( kv - > GetKey ( ) ) ;
if ( ! kv2 )
{
dictToWrite . Set ( kv - > GetKey ( ) , kv - > GetValue ( ) ) ;
}
}
}
2021-01-12 20:40:20 +00:00
// add editor_vars that aren't already covered by the default vars
2021-01-12 14:39:30 +00:00
for ( int i = 0 ; i < evars . Num ( ) ; i + + )
{
2021-04-26 14:31:04 +00:00
const LocalEvar_t * ev = & evars [ i ] ;
2021-01-09 17:27:06 +00:00
2021-01-12 14:39:30 +00:00
const idKeyValue * kv2 = dictToWrite . FindKey ( ev - > name ) ;
if ( ! kv2 )
{
dictToWrite . Set ( ev - > name , ev - > desc ) ;
}
}
2021-01-12 20:40:20 +00:00
// export models as OBJ
bool writeModel = false ;
idStrStatic < MAX_OSPATH > exportedModelFileName ;
2021-02-16 17:36:24 +00:00
if ( idStr : : Icmp ( decl - > GetName ( ) , " light " ) ! = 0 & &
2022-01-29 17:10:54 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " misc_model " ) ! = 0 & &
2023-10-25 23:52:03 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_bobbing_model " ) ! = 0 & &
2022-01-29 17:10:54 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_door_model " ) ! = 0 & &
2023-10-25 23:52:03 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_elevator_model " ) ! = 0 & &
idStr : : Icmp ( decl - > GetName ( ) , " func_mover_model " ) ! = 0 & &
2022-01-29 17:10:54 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_mover_amodel " ) ! = 0 & &
idStr : : Icmp ( decl - > GetName ( ) , " func_plat_model " ) ! = 0 & &
idStr : : Icmp ( decl - > GetName ( ) , " func_rotating_model " ) ! = 0 )
2021-01-12 20:40:20 +00:00
{
2021-01-13 14:46:40 +00:00
const idKeyValue * kv = dictToWrite . FindKey ( " model " ) ;
if ( kv )
{
if ( kv - > GetValue ( ) . Length ( ) )
2021-01-12 20:40:20 +00:00
{
2021-01-13 14:46:40 +00:00
declManager - > MediaPrint ( " Precaching model %s \n " , kv - > GetValue ( ) . c_str ( ) ) ;
// HACK
writeModel = true ;
// precache model/animations
const idDeclModelDef * modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , kv - > GetValue ( ) , false ) ) ;
2024-05-18 19:23:41 +00:00
if ( modelDef ! = NULL )
2021-01-13 14:46:40 +00:00
{
idRenderModel * renderModel = modelDef - > ModelHandle ( ) ;
if ( renderModel )
{
exportedModelFileName = " _tb/ " ;
exportedModelFileName . AppendPath ( renderModel - > Name ( ) ) ;
exportedModelFileName . SetFileExtension ( " .obj " ) ;
}
}
2024-05-18 19:23:41 +00:00
else
{
// there is no modelDef so use direct path
renderModelManager - > FindModel ( kv - > GetValue ( ) ) ;
exportedModelFileName = " _tb/ " ;
exportedModelFileName . AppendPath ( kv - > GetValue ( ) ) ;
exportedModelFileName . SetFileExtension ( " .obj " ) ;
}
2021-01-12 20:40:20 +00:00
}
}
}
2021-01-13 14:46:40 +00:00
if ( writeModel & & ! exportedModelFileName . IsEmpty ( ) )
2021-01-12 20:40:20 +00:00
{
file - > Printf ( " model({ \" path \" : \" %s \" }) " , exportedModelFileName . c_str ( ) ) ;
}
2022-01-29 17:10:54 +00:00
else if ( idStr : : Icmp ( decl - > GetName ( ) , " misc_model " ) = = 0 | |
2024-05-18 19:23:41 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_animate " ) = = 0 | |
2023-10-25 23:52:03 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_bobbing_model " ) = = 0 | |
2022-01-29 17:10:54 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_door_model " ) = = 0 | |
2023-10-25 23:52:03 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_elevator_model " ) = = 0 | |
idStr : : Icmp ( decl - > GetName ( ) , " func_mover_model " ) = = 0 | |
2022-01-29 17:10:54 +00:00
idStr : : Icmp ( decl - > GetName ( ) , " func_mover_amodel " ) = = 0 | |
idStr : : Icmp ( decl - > GetName ( ) , " func_plat_model " ) = = 0 | |
idStr : : Icmp ( decl - > GetName ( ) , " func_rotating_model " ) = = 0 )
2021-02-16 17:36:24 +00:00
{
2022-02-27 12:56:14 +00:00
// dynamic model that prefers a TB specific proxymodel
2022-11-02 10:44:38 +00:00
file - > Printf ( " model({{ \n \t proxymodel -> { \" path \" : proxymodel }, \n \t { \" path \" : model } \n }}) " ) ;
2021-02-16 17:36:24 +00:00
}
2021-10-08 18:51:08 +00:00
else if ( idStr : : Icmp ( decl - > GetName ( ) , " light " ) = = 0 )
{
// default light sprite for TB editor sprites branch
2023-10-25 23:52:03 +00:00
//file->Printf( "model({ \"path\": \"sprites/light-bulb.png\", \"scale\": 0.03125 }) " );
file - > Printf ( " model({{ \n \t proxymodel -> { \" path \" : proxymodel }, \n \t { \" path \" : \" sprites/light-bulb.png \" , \" scale \" : 0.03125 } \n }}) " ) ;
2021-10-08 18:51:08 +00:00
}
else if ( idStr : : Icmp ( decl - > GetName ( ) , " speaker " ) = = 0 )
{
2021-11-06 18:09:40 +00:00
file - > Printf ( " model({ \" path \" : \" sprites/speaker.png \" , \" scale \" : 0.03125 }) " ) ;
2021-10-08 18:51:08 +00:00
}
2021-11-09 18:47:06 +00:00
else if ( idStr : : Icmp ( decl - > GetName ( ) , " env_probe " ) = = 0 )
{
file - > Printf ( " model({ \" path \" : \" sprites/360-degree.png \" , \" scale \" : 0.03125 }) " ) ;
}
2021-10-08 20:46:30 +00:00
else if ( idStr : : Icmpn ( decl - > GetName ( ) , " ai_ " , 3 ) = = 0 )
2021-10-08 18:51:08 +00:00
{
2021-11-06 18:09:40 +00:00
file - > Printf ( " model({ \" path \" : \" sprites/ai.png \" , \" scale \" : 0.03125 }) " ) ;
2021-10-08 18:51:08 +00:00
}
2021-10-08 20:46:30 +00:00
else if ( idStr : : Icmpn ( decl - > GetName ( ) , " info_vacuum " , 11 ) = = 0 )
2021-10-08 18:51:08 +00:00
{
2021-11-06 18:09:40 +00:00
file - > Printf ( " model({ \" path \" : \" sprites/air-conditioning.png \" , \" scale \" : 0.03125 }) " ) ;
2021-10-08 18:51:08 +00:00
}
else if ( idStr : : Icmpn ( decl - > GetName ( ) , " info_location " , 13 ) = = 0 )
{
2021-11-06 18:09:40 +00:00
file - > Printf ( " model({ \" path \" : \" sprites/information.png \" , \" scale \" : 0.03125 }) " ) ;
}
else if ( idStr : : Icmpn ( decl - > GetName ( ) , " item_objective " , 14 ) = = 0 )
{
file - > Printf ( " model({ \" path \" : \" sprites/objective.png \" , \" scale \" : 0.03125 }) " ) ;
2021-10-08 18:51:08 +00:00
}
else if ( idStr : : Icmpn ( decl - > GetName ( ) , " path_ " , 5 ) = = 0 )
{
2021-11-06 18:09:40 +00:00
file - > Printf ( " model({ \" path \" : \" sprites/waypoint.png \" , \" scale \" : 0.03125 }) " ) ;
}
else if ( idStr : : Icmp ( decl - > GetName ( ) , " func_emitter " ) = = 0 )
{
file - > Printf ( " model({ \" path \" : \" sprites/bonfire.png \" , \" scale \" : 0.03125 }) " ) ;
2021-10-08 18:51:08 +00:00
}
2021-11-06 18:09:40 +00:00
else if ( idStr : : Icmp ( decl - > GetName ( ) , " func_fx " ) = = 0 )
2021-10-08 18:51:08 +00:00
{
2021-11-06 18:09:40 +00:00
file - > Printf ( " model({ \" path \" : \" sprites/fx.png \" , \" scale \" : 0.03125 }) " ) ;
2021-10-08 20:46:30 +00:00
}
else if ( idStr : : Icmp ( decl - > GetName ( ) , " target_null " ) = = 0 )
{
2021-11-06 18:09:40 +00:00
file - > Printf ( " model({ \" path \" : \" sprites/info_notnull.png \" , \" scale \" : 0.25 }) " ) ;
}
else if ( idStr : : Icmp ( decl - > GetName ( ) , " target_checkpoint " ) = = 0 )
{
file - > Printf ( " model({ \" path \" : \" sprites/security-gate.png \" , \" scale \" : 0.03125 }) " ) ;
2021-10-08 20:46:30 +00:00
}
else if ( idStr : : Icmpn ( decl - > GetName ( ) , " target_ " , 7 ) = = 0 )
{
2021-11-06 18:09:40 +00:00
file - > Printf ( " model({ \" path \" : \" sprites/gamepad.png \" , \" scale \" : 0.03125 }) " ) ;
2021-10-08 20:46:30 +00:00
}
else if ( idStr : : Icmp ( decl - > GetName ( ) , " trigger_relay " ) = = 0 )
{
2021-11-06 18:09:40 +00:00
file - > Printf ( " model({ \" path \" : \" sprites/joystick.png \" , \" scale \" : 0.03125 }) " ) ;
}
else
{
const idKeyValue * kv = dictToWrite . FindKey ( " spawnclass " ) ;
if ( kv & & kv - > GetValue ( ) . Length ( ) & & idStr : : Icmp ( kv - > GetValue ( ) , " idCameraAnim " ) = = 0 )
{
file - > Printf ( " model({ \" path \" : \" sprites/camera.png \" , \" scale \" : 0.03125 }) " ) ;
}
2021-10-08 18:51:08 +00:00
}
2021-01-12 20:40:20 +00:00
file - > Printf ( " = %s : \" %s \" \n " , decl - > GetName ( ) , text . c_str ( ) ) ;
file - > Printf ( " [ \n " ) ;
2021-01-12 14:39:30 +00:00
2022-01-08 17:33:55 +00:00
if ( idStr : : Icmp ( decl - > GetName ( ) , " light " ) = = 0 )
{
// RB: hardcode for now to have proper light styles combobox names
file - > Printf (
" \t style(Choices) : \" Appearance \" : 0 = \n "
" \t [ \n "
" \t \t 0 : \" Normal \" \n "
" \t \t 10: \" Fluorescent flicker \" \n "
" \t \t 2 : \" Slow, strong pulse \" \n "
" \t \t 11: \" Slow pulse, noblack \" \n "
" \t \t 5 : \" Gentle pulse \" \n "
" \t \t 1 : \" Flicker A \" \n "
" \t \t 6 : \" Flicker B \" \n "
" \t \t 3 : \" Candle A \" \n "
" \t \t 7 : \" Candle B \" \n "
" \t \t 8 : \" Candle C \" \n "
" \t \t 4 : \" Fast strobe \" \n "
" \t \t 9 : \" Slow strobe \" \n "
" \t ] \n " ) ;
}
2021-01-12 14:39:30 +00:00
for ( int i = 0 ; i < dictToWrite . GetNumKeyVals ( ) ; i + + )
{
kv = dictToWrite . GetKeyVal ( i ) ;
// is it an editor var or a regular spawn argument?
2021-04-26 14:31:04 +00:00
LocalEvar_t * ev = nullptr ;
2021-01-12 14:39:30 +00:00
int vc = evars . Num ( ) ;
for ( int j = 0 ; j < vc ; j + + )
{
if ( evars [ j ] . name . Icmp ( kv - > GetKey ( ) ) = = 0 )
{
ev = & evars [ j ] ;
2021-01-09 17:27:06 +00:00
break ;
2021-01-12 14:39:30 +00:00
}
2021-01-09 17:27:06 +00:00
}
2021-01-12 14:39:30 +00:00
idStr cleanKey = kv - > GetKey ( ) ;
2021-02-15 18:28:39 +00:00
cleanKey . ReplaceChar ( ' ' , ' . ' ) ;
if ( cleanKey . Icmp ( " color " ) = = 0 )
{
cleanKey = " _color " ;
}
2021-01-12 14:39:30 +00:00
// don't print the descriptive editor var itself yet
if ( ev )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
file - > Printf ( " \t %s " , cleanKey . c_str ( ) ) ;
switch ( ev - > type )
{
case EVAR_INT :
file - > Printf ( " (integer) " ) ;
break ;
case EVAR_FLOAT :
file - > Printf ( " (float) " ) ;
break ;
case EVAR_BOOL :
file - > Printf ( " (boolean) " ) ;
break ;
case EVAR_COLOR :
case EVAR_MATERIAL :
case EVAR_MODEL :
case EVAR_GUI :
case EVAR_SOUND :
case EVAR_STRING :
default :
file - > Printf ( " (string) " ) ;
break ;
}
if ( ! ev - > desc . IsEmpty ( ) & & ev - > desc . Icmp ( kv - > GetValue ( ) . c_str ( ) ) )
2021-01-09 17:27:06 +00:00
{
2021-01-12 14:39:30 +00:00
if ( ev - > type ! = EVAR_INT & & ev - > type ! = EVAR_FLOAT & & ev - > type ! = EVAR_BOOL )
{
file - > Printf ( " : \" %s \" : \" %s \" \n " , ev - > desc . c_str ( ) , kv - > GetValue ( ) . c_str ( ) ) ;
}
else
{
file - > Printf ( " : \" %s \" : %s \n " , ev - > desc . c_str ( ) , kv - > GetValue ( ) . c_str ( ) ) ;
}
2021-01-09 17:27:06 +00:00
}
else
{
2021-01-12 14:39:30 +00:00
file - > Printf ( " : \" %s \" \n " , ev - > desc . c_str ( ) ) ;
2021-01-09 17:27:06 +00:00
}
}
else
{
2021-01-12 14:39:30 +00:00
file - > Printf ( " \t %s(string) : \" \" : \" %s \" \n " , cleanKey . c_str ( ) , kv - > GetValue ( ) . c_str ( ) ) ;
2021-01-09 17:27:06 +00:00
}
}
2021-01-12 14:39:30 +00:00
file - > Printf ( " ] \n \n " ) ;
2021-01-12 20:40:20 +00:00
2021-01-09 17:27:06 +00:00
}
2021-01-12 14:39:30 +00:00
file - > Flush ( ) ;
2021-01-09 17:27:06 +00:00
2021-02-10 10:44:45 +00:00
common - > Printf ( " \n Data written to %s \n " , fgdFileName . c_str ( ) ) ;
common - > Printf ( " ---------------------------- \n " ) ;
common - > Printf ( " Wrote %d Entities. \n " , totalEntitiesCount ) ;
common - > Printf ( " Wrote %d Models. \n " , totalModelsCount ) ;
2021-01-09 17:27:06 +00:00
}
com_editors & = ~ EDITOR_EXPORTDEFS ;
2021-02-15 22:06:58 +00:00
if ( exportModels )
{
postLoadExportModels . SetBool ( false ) ;
}
2021-01-09 17:27:06 +00:00
2021-02-10 10:44:45 +00:00
//declManagerLocal.Reload( true );
2024-05-18 19:23:41 +00:00
common - > FatalError ( " Exporting successful, need to restart engine manually " ) ;
2021-01-09 17:27:06 +00:00
}
2022-01-07 17:46:35 +00:00
2022-01-20 21:25:06 +00:00
void idDeclManagerLocal : : ExportImagesToTrenchBroom_f ( const idCmdArgs & args )
{
int totalImagesCount = 0 ;
idFileList * files = fileSystem - > ListFilesTree ( " generated " , " .bimage " , true , true ) ;
2022-01-22 15:20:21 +00:00
CommandlineProgressBar progressBar ( files - > GetList ( ) . Num ( ) , renderSystem - > GetWidth ( ) , renderSystem - > GetHeight ( ) ) ;
progressBar . Start ( ) ;
2022-01-20 21:25:06 +00:00
int totalStart = Sys_Milliseconds ( ) ;
for ( int f = 0 ; f < files - > GetList ( ) . Num ( ) ; f + + )
{
idStr imageName = files - > GetList ( ) [ f ] ;
2022-01-22 15:20:21 +00:00
progressBar . Increment ( true ) ;
2022-01-20 21:25:06 +00:00
if ( idStr : : Icmpn ( imageName , " generated/images/env/maps/game/ " , 31 ) = = 0 )
{
// skip HDR cache data
continue ;
}
if ( idStr : : FindText ( imageName , " addnormals " , false ) ! = - 1 )
{
continue ;
}
if ( idStr : : FindText ( imageName , " heightmap " , false ) ! = - 1 )
{
continue ;
}
if ( idStr : : FindText ( imageName , " makealpha " , false ) ! = - 1 )
{
continue ;
}
if ( idStr : : FindText ( imageName , " makeintensity " , false ) ! = - 1 )
{
continue ;
}
#if 0
// only export decals for testing
if ( idStr : : Icmpn ( imageName , " generated/images/textures/decals/ " , 33 ) ! = 0 )
{
continue ;
}
if ( idStr : : FindText ( imageName , " a_pipecap2a_d " , false ) ! = - 1 )
{
totalImagesCount + + ;
}
# endif
idFileLocal bFile = fileSystem - > OpenFileRead ( imageName ) ;
if ( bFile = = NULL )
{
continue ;
}
idBinaryImage im ( imageName ) ;
ID_TIME_T binaryFileTime = im . LoadFromGeneratedFile ( bFile , FILE_NOT_FOUND_TIMESTAMP ) ;
if ( binaryFileTime ! = FILE_NOT_FOUND_TIMESTAMP )
{
const bimageFile_t & imgHeader = im . GetFileHeader ( ) ;
const bimageImage_t & img = im . GetImageHeader ( 0 ) ;
const byte * data = im . GetImageData ( 0 ) ;
if ( ( imgHeader . format = = FMT_DXT5 | | imgHeader . format = = FMT_DXT1 ) & & ( imgHeader . colorFormat ! = CFM_GREEN_ALPHA ) )
{
2022-01-22 15:20:21 +00:00
//idLib::Printf( "Exporting image '%s'\n", imageName.c_str() );
2022-01-20 21:25:06 +00:00
// RB: Images that are were DXT compressed and aren't multiples of 4 were padded out before compressing
// however the idBinaryImageData stores the original input width and height.
// We need multiples of 4 for the decompression routines
int dxtWidth = 0 ;
int dxtHeight = 0 ;
if ( imgHeader . format = = FMT_DXT5 | | imgHeader . format = = FMT_DXT1 )
{
if ( ( img . width & 3 ) | | ( img . height & 3 ) )
{
dxtWidth = ( img . width + 3 ) & ~ 3 ;
dxtHeight = ( img . height + 3 ) & ~ 3 ;
}
else
{
dxtWidth = img . width ;
dxtHeight = img . height ;
}
}
idTempArray < byte > rgba ( dxtWidth * dxtHeight * 4 ) ;
memset ( rgba . Ptr ( ) , 255 , rgba . Size ( ) ) ;
if ( imgHeader . format = = FMT_DXT1 )
{
idDxtDecoder dxt ;
dxt . DecompressImageDXT1 ( data , rgba . Ptr ( ) , dxtWidth , dxtHeight ) ;
2022-01-31 15:40:29 +00:00
for ( int i = 0 ; i < ( dxtWidth * dxtHeight ) ; i + + )
{
rgba [ i * 4 + 3 ] = 255 ;
}
2022-01-20 21:25:06 +00:00
}
else if ( imgHeader . format = = FMT_DXT5 )
{
idDxtDecoder dxt ;
if ( imgHeader . colorFormat = = CFM_NORMAL_DXT5 )
{
dxt . DecompressNormalMapDXT5 ( data , rgba . Ptr ( ) , dxtWidth , dxtHeight ) ;
2022-01-31 15:40:29 +00:00
for ( int i = 0 ; i < ( dxtWidth * dxtHeight ) ; i + + )
{
rgba [ i * 4 + 3 ] = 255 ;
}
2022-01-20 21:25:06 +00:00
}
else if ( imgHeader . colorFormat = = CFM_YCOCG_DXT5 )
{
dxt . DecompressYCoCgDXT5 ( data , rgba . Ptr ( ) , dxtWidth , dxtHeight ) ;
idColorSpace : : ConvertCoCg_YToRGB ( rgba . Ptr ( ) , rgba . Ptr ( ) , dxtWidth , dxtHeight ) ;
for ( int i = 0 ; i < ( dxtWidth * dxtHeight ) ; i + + )
{
rgba [ i * 4 + 3 ] = 255 ;
}
}
else
{
dxt . DecompressImageDXT5 ( data , rgba . Ptr ( ) , dxtWidth , dxtHeight ) ;
2022-01-31 15:40:29 +00:00
for ( int i = 0 ; i < ( dxtWidth * dxtHeight ) ; i + + )
{
rgba [ i * 4 + 3 ] = 255 ;
}
2022-01-20 21:25:06 +00:00
}
}
imageName . StripLeadingOnce ( " generated/images/ " ) ;
2022-01-20 21:28:18 +00:00
idStrStatic < MAX_OSPATH > exportName = " _tb/ " ;
2022-01-20 21:25:06 +00:00
exportName + = imageName ;
int idx = exportName . Find ( ' # ' ) ;
exportName . CapLength ( idx ) ;
exportName . SetFileExtension ( " .png " ) ;
if ( dxtWidth ! = img . width | | dxtHeight ! = img . height )
{
// scale DXT sized images back to the original size
byte * scaled = R_Dropsample ( rgba . Ptr ( ) , dxtWidth , dxtHeight , img . width , img . height ) ;
if ( img . width > 16 & & img . height > 16 )
{
2024-06-19 16:21:42 +00:00
R_WritePNG ( exportName , scaled , 4 , img . width , img . height , " fs_basepath " ) ;
2022-01-20 21:25:06 +00:00
}
else
{
exportName . SetFileExtension ( " .tga " ) ;
R_WriteTGA ( exportName , scaled , img . width , img . height , false , " fs_basepath " ) ;
}
Mem_Free ( scaled ) ;
}
else
{
if ( img . width > 16 & & img . height > 16 )
{
2024-06-19 16:21:42 +00:00
R_WritePNG ( exportName , rgba . Ptr ( ) , 4 , img . width , img . height , " fs_basepath " ) ;
2022-01-20 21:25:06 +00:00
}
else
{
exportName . SetFileExtension ( " .tga " ) ;
R_WriteTGA ( exportName , rgba . Ptr ( ) , img . width , img . height , false , " fs_basepath " ) ;
}
}
}
}
totalImagesCount + + ;
}
fileSystem - > FreeFileList ( files ) ;
int totalEnd = Sys_Milliseconds ( ) ;
common - > Printf ( " ---------------------------- \n " ) ;
common - > Printf ( " Exported and decompressed %d images in %5.1f minutes. \n " , totalImagesCount , ( totalEnd - totalStart ) / ( 1000.0f * 60 ) ) ;
}
2022-02-23 21:52:23 +00:00
2022-02-25 21:14:45 +00:00
void idDeclManagerLocal : : ExportModelsToTrenchBroom_f ( const idCmdArgs & args )
{
extern idCVar postLoadExportModels ;
postLoadExportModels . SetBool ( true ) ;
// avoid media cache
com_editors | = EDITOR_EXPORTDEFS ;
int totalModelsCount = 0 ;
int totalEntitiesCount = 0 ;
idFileList * files = fileSystem - > ListFilesTree ( " generated " , " .blwo|.base|.bmd5mesh " , true , true ) ;
2022-02-27 15:58:25 +00:00
// FGD header
2022-02-25 21:14:45 +00:00
idStr fgdFileName ;
2022-02-27 16:26:58 +00:00
fgdFileName . Format ( " _tb/fgd/DOOM-3-models.fgd " ) ;
2022-02-25 21:14:45 +00:00
idFileLocal fgdFile ( fileSystem - > OpenFileWrite ( fgdFileName , " fs_basepath " ) ) ;
if ( fgdFile = = NULL )
{
common - > Printf ( " Failed to write entity declarations data to FGD. \n " ) ;
}
fgdFile - > Printf ( " // DOOM 3 BFG models definition file (.fgd) generated by %s \n \n " , ENGINE_VERSION ) ;
fgdFile - > Printf ( " @SolidClass color(0 0 0) = worldspawn : \" Every map should have exactly one worldspawn. \" \n [ \n " ) ;
fgdFile - > Printf ( " \t spawnclass(string) : \" \" : \" idWorldspawn \" \n " ) ;
fgdFile - > Printf ( " ] \n \n " ) ;
fgdFile - > Printf ( " @SolidClass color(0 127 204) = func_static : \" A brush model that just sits there, doing nothing. Can be used for conditional walls and models. When triggered, toggles between visible and hidden (see hide). Entity is non-solid when hidden. \" \n [ \n " ) ;
//fgdFile->Printf( "name(string) : \"\" : \"\"\n" );
fgdFile - > Printf ( " \t spawnclass(string) : \" \" : \" idStaticEntity \" \n " ) ;
fgdFile - > Printf ( " \t solid(boolean) : \" whether the object should be solid or not. \" : 1 \n " ) ;
fgdFile - > Printf ( " \t noclipmodel(boolean) : \" 0 by default. Sets whether or not to generate a collision model for an ASE/LWO func_static at level load. (Set to 1 for stuff the player can't interact with. This will save memory.) \" : 0 \n " ) ;
fgdFile - > Printf ( " \t hide(boolean) : \" whether the object should be visible when spawned. you need to set a value for triggering on/off to work \" \n " ) ;
fgdFile - > Printf ( " \t gui_noninteractive(boolean) : \" any gui attached will not be interactive \" \n " ) ;
fgdFile - > Printf ( " \t inline(boolean) : \" If true, turn the model into map geometry at dmap time \" \n " ) ;
fgdFile - > Printf ( " \t angles(string) : \" \" : \" 0 0 0 \" \n " ) ;
fgdFile - > Printf ( " \t gui(string) : \" gui attached to this static, gui2 and gui3 also work \" \n " ) ;
fgdFile - > Printf ( " \t gui_demonic(string) : \" demonic gui attached to this statit, gui_demonic2 and gui_demonic3 also work \" \n ] \n \n " ) ;
2022-02-27 15:58:25 +00:00
fgdFile - > Printf ( " @PointClass base(func_static) color(0 127 204) model({ \" path \" : proxymodel }) = misc_model : \" Just a model \" \n [ \n " ) ;
2022-02-25 21:14:45 +00:00
//fgdFile->Printf( "name(string) : \"\" : \"\"\n" );
fgdFile - > Printf ( " \t angles(string) : \" \" : \" 0 0 0 \" \n " ) ;
fgdFile - > Printf ( " ] \n \n " ) ;
fgdFile - > Printf ( " @PointClass base(misc_model) = auto_generated_model : \" Entity definition for a specific model \" [] \n \n " ) ;
2022-02-27 15:58:25 +00:00
// DEF header
idStr defFileName ;
defFileName . Format ( " def/_tb_models.def " ) ;
idFileLocal defFile ( fileSystem - > OpenFileWrite ( defFileName , " fs_basepath " ) ) ;
if ( defFile = = NULL )
{
common - > Printf ( " Failed to write entity declarations data to DEF. \n " ) ;
}
defFile - > Printf ( " // DOOM 3 BFG models definition file (.def) generated by %s \n \n " , ENGINE_VERSION ) ;
2022-02-25 21:14:45 +00:00
for ( int f = 0 ; f < files - > GetList ( ) . Num ( ) ; f + + )
{
totalModelsCount + + ;
idStr modelName = files - > GetList ( ) [ f ] ;
modelName . StripLeadingOnce ( " generated/rendermodels/ " ) ;
idStr ext ;
modelName . ExtractFileExtension ( ext ) ;
bool dynamicModel = false ;
if ( ext . Icmp ( " blwo " ) = = 0 )
{
modelName . SetFileExtension ( " lwo " ) ;
}
if ( ext . Icmp ( " base " ) = = 0 )
{
modelName . SetFileExtension ( " ase " ) ;
}
if ( ext . Icmp ( " bdae " ) = = 0 )
{
modelName . SetFileExtension ( " dae " ) ;
}
if ( ext . Icmp ( " bmd5mesh " ) = = 0 )
{
modelName . SetFileExtension ( " md5mesh " ) ;
dynamicModel = true ;
}
// skip TB specific helper models
if ( idStr : : Icmpn ( modelName , " _tb " , 3 ) = = 0 )
{
continue ;
}
idLib : : Printf ( " Exporting model '%s' \n " , modelName . c_str ( ) ) ;
// make an OBJ version of the model for TrenchBroom
idRenderModel * renderModel = renderModelManager - > FindModel ( modelName ) ;
2023-10-25 23:52:03 +00:00
#if 0
2022-02-25 21:14:45 +00:00
if ( idStr : : Icmpn ( modelName , " models/mapobjects " , 17 ) ! = 0 )
{
continue ;
}
# endif
if ( idStr : : Icmpn ( modelName , " models/items " , 12 ) = = 0 )
{
continue ;
}
if ( idStr : : Icmpn ( modelName , " models/particles " , 16 ) = = 0 )
{
continue ;
}
if ( idStr : : Icmpn ( modelName , " models/weapons " , 14 ) = = 0 )
{
continue ;
}
idBounds bounds = renderModel - > Bounds ( ) ;
2022-02-27 15:58:25 +00:00
bounds [ 0 ] . Snap ( ) ;
bounds [ 1 ] . Snap ( ) ;
2022-02-25 21:14:45 +00:00
// put model as mapobject into the models FGD
if ( ! renderModel - > IsDefaultModel ( ) & & bounds . GetVolume ( ) > 0 & & bounds . GetRadius ( ) < 1400 )
{
idStrStatic < MAX_OSPATH > originalModelFileName ;
originalModelFileName = modelName ;
idStrStatic < MAX_OSPATH > exportedModelFileName ;
exportedModelFileName = " _tb/ " ;
exportedModelFileName . AppendPath ( modelName ) ;
exportedModelFileName . SetFileExtension ( " .obj " ) ;
idStrStatic < MAX_OSPATH > entityName ;
2022-02-27 15:58:25 +00:00
/*
2022-02-25 21:14:45 +00:00
if ( idStr : : Icmpn ( modelName , " models/mapobjects " , 17 ) = = 0 )
{
modelName . StripLeadingOnce ( " models/mapobjects " ) ;
entityName = " mob " ;
entityName . AppendPath ( modelName ) ;
}
else
2022-02-27 15:58:25 +00:00
*/
2022-02-25 21:14:45 +00:00
{
2022-02-27 15:58:25 +00:00
modelName . StripLeadingOnce ( " models " ) ;
2022-02-25 21:14:45 +00:00
2022-02-27 15:58:25 +00:00
entityName = " genmodel " ;
2022-02-25 21:14:45 +00:00
entityName . AppendPath ( modelName ) ;
}
entityName . BackSlashesToSlashes ( ) ;
entityName . ReplaceChar ( ' / ' , ' _ ' ) ;
entityName . ReplaceChar ( ' ( ' , ' _ ' ) ;
entityName . ReplaceChar ( ' ) ' , ' _ ' ) ;
entityName . StripFileExtension ( ) ;
fgdFile - > Printf ( " @PointClass " ) ;
2022-11-02 14:51:12 +00:00
#if 0
2022-02-25 21:14:45 +00:00
if ( bounds . GetVolume ( ) > 0 )
{
fgdFile - > Printf ( " size(%i %i %i, %i %i %i) " ,
int ( bounds [ 0 ] . x ) , int ( bounds [ 0 ] . y ) , int ( bounds [ 0 ] . z ) ,
int ( bounds [ 1 ] . x ) , int ( bounds [ 1 ] . y ) , int ( bounds [ 1 ] . z ) ) ;
}
2022-11-02 14:51:12 +00:00
//#else
//fgdFile->Printf( "size(-8 -8 0, 8 8 16) " );
2022-02-25 21:14:45 +00:00
# endif
fgdFile - > Printf ( " base(auto_generated_model) model({ \" path \" : \" %s \" }) = %s : \" Display entity \" \n [ \n " , exportedModelFileName . c_str ( ) , entityName . c_str ( ) ) ;
//fgdFile->Printf( "[\n\t angles(string) : \"\" : \"0 0 0\"\n]\n\n");
2022-02-27 12:56:14 +00:00
fgdFile - > Printf ( " \t proxymodel(string) : \" \" : \" %s \" \n " , exportedModelFileName . c_str ( ) ) ;
fgdFile - > Printf ( " \t model(string) : \" \" : \" %s \" \n " , originalModelFileName . c_str ( ) ) ;
2022-02-25 21:14:45 +00:00
fgdFile - > Printf ( " ] \n \n " , exportedModelFileName . c_str ( ) ) ;
2022-02-27 15:58:25 +00:00
// write .def file for Doom
//defFile->Printf( "base(auto_generated_model) model({ \"path\": \"%s\" }) = %s : \"Display entity\"\n[\n", exportedModelFileName.c_str(), entityName.c_str() );
defFile - > Printf ( " entityDef %s \n { \n " , entityName . c_str ( ) ) ;
defFile - > Printf ( " \t \" inherit \" \" misc_model \" \n " ) ;
defFile - > Printf ( " \t \" proxymodel \" \" %s \" \n " , exportedModelFileName . c_str ( ) ) ;
defFile - > Printf ( " \t \" model \" \" %s \" \n " , originalModelFileName . c_str ( ) ) ;
2022-11-02 14:51:12 +00:00
#if 0
if ( bounds . GetVolume ( ) > 0 )
{
defFile - > Printf ( " \t \" editor_mins \" \" %i %i %i \" \n " , int ( bounds [ 0 ] . x ) , int ( bounds [ 0 ] . y ) , int ( bounds [ 0 ] . z ) ) ;
defFile - > Printf ( " \t \" editor_maxs \" \" %i %i %i \" \n " , int ( bounds [ 1 ] . x ) , int ( bounds [ 1 ] . y ) , int ( bounds [ 1 ] . z ) ) ;
}
# endif
2022-02-27 15:58:25 +00:00
defFile - > Printf ( " } \n \n " , exportedModelFileName . c_str ( ) ) ;
2022-02-25 21:14:45 +00:00
totalEntitiesCount + + ;
}
}
fileSystem - > FreeFileList ( files ) ;
com_editors & = ~ EDITOR_EXPORTDEFS ;
postLoadExportModels . SetBool ( false ) ;
fgdFile - > Flush ( ) ;
common - > Printf ( " \n FGD written to %s \n " , fgdFileName . c_str ( ) ) ;
common - > Printf ( " ---------------------------- \n " ) ;
common - > Printf ( " Wrote %d Entities. \n " , totalEntitiesCount ) ;
common - > Printf ( " Wrote %d Models. \n " , totalModelsCount ) ;
common - > FatalError ( " Exporting successful, need to restart manually " ) ;
}
2022-02-26 14:29:39 +00:00
static idMapBrush * MakeUnitBrush ( const idVec3 & origin , const idVec3 & scale , bool border )
{
/*
TrenchBroom
// brush 0
{
( - 1 - 64 - 16 ) ( - 1 - 63 - 16 ) ( - 1 - 64 - 15 ) rock / lfwall15_lanrock1 [ 0 1 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
( - 64 - 1 - 16 ) ( - 64 - 1 - 15 ) ( - 63 - 1 - 16 ) rock / lfwall15_lanrock1 [ 1 0 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
( - 64 - 64 - 1 ) ( - 63 - 64 - 1 ) ( - 64 - 63 - 1 ) rock / lfwall15_lanrock1 [ 1 0 0 0 ] [ 0 - 1 0 0 ] 0 0.5 0.5
( 64 64 1 ) ( 64 65 1 ) ( 65 64 1 ) rock / lfwall15_lanrock1 [ 1 0 0 0 ] [ 0 - 1 0 0 ] 0 0.5 0.5
( 64 1 16 ) ( 65 1 16 ) ( 64 1 17 ) rock / lfwall15_lanrock1 [ 1 0 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
( 1 64 16 ) ( 1 64 17 ) ( 1 65 16 ) rock / lfwall15_lanrock1 [ 0 1 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
}
*/
const char * tbUnitBrush = R " (
( - 1 - 64 - 16 ) ( - 1 - 63 - 16 ) ( - 1 - 64 - 15 ) rock / lfwall15_lanrock1 [ 0 1 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
( - 64 - 1 - 16 ) ( - 64 - 1 - 15 ) ( - 63 - 1 - 16 ) rock / lfwall15_lanrock1 [ 1 0 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
( - 64 - 64 - 1 ) ( - 63 - 64 - 1 ) ( - 64 - 63 - 1 ) rock / lfwall15_lanrock1 [ 1 0 0 0 ] [ 0 - 1 0 0 ] 0 0.5 0.5
( 64 64 1 ) ( 64 65 1 ) ( 65 64 1 ) rock / lfwall15_lanrock1 [ 1 0 0 0 ] [ 0 - 1 0 0 ] 0 0.5 0.5
( 64 1 16 ) ( 65 1 16 ) ( 64 1 17 ) rock / lfwall15_lanrock1 [ 1 0 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
( 1 64 16 ) ( 1 64 17 ) ( 1 65 16 ) rock / lfwall15_lanrock1 [ 0 1 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
}
}
) " ;
idLexer src ( LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES ) ;
src . LoadMemory ( tbUnitBrush , strlen ( tbUnitBrush ) , " DoomEdit Brush " ) ;
idMapBrush * brush = idMapBrush : : ParseValve220 ( src , origin ) ;
idMat3 axis ;
axis . Identity ( ) ;
// unit brush is not really a unit brush but 2, 2, 2
axis [ 0 ] [ 0 ] = scale . x * 0.5f ;
axis [ 1 ] [ 1 ] = scale . y * 0.5f ;
axis [ 2 ] [ 2 ] = scale . z * 0.5f ;
2022-02-25 21:14:45 +00:00
2022-02-26 14:29:39 +00:00
idMat4 transform ( axis , origin ) ;
for ( int i = 0 ; i < brush - > GetNumSides ( ) ; i + + )
{
auto side = brush - > GetSide ( i ) ;
if ( border )
{
side - > SetMaterial ( " textures/decals/achtung " ) ;
}
side - > planepts [ 0 ] * = transform ;
side - > planepts [ 1 ] * = transform ;
side - > planepts [ 2 ] * = transform ;
}
return brush ;
}
2022-02-25 21:14:45 +00:00
2022-02-24 21:14:40 +00:00
static idMapBrush * MakeCharBrush ( const idVec3 & brushOrigin , const idVec3 & uvOrigin , int ch )
{
const char * tbLetterBrush = R " (
( 0 - 1 7 ) ( 0 0 7 ) ( 0 - 1 8 ) common / nodraw [ 0 1 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
( 0 - 1 7 ) ( 0 - 1 8 ) ( 1 - 1 7 ) decals / alphabet6 [ 1 0 0 64 ] [ 0 0 - 1 - 224 ] 0 0.25 0.25
( 0 - 1 0 ) ( 1 - 1 0 ) ( 0 0 0 ) common / nodraw [ 1 0 0 0 ] [ 0 - 1 0 0 ] 0 0.5 0.5
( 11 0 8 ) ( 11 1 8 ) ( 12 0 8 ) common / nodraw [ 1 0 0 0 ] [ 0 - 1 0 0 ] 0 0.5 0.5
( 11 0 8 ) ( 12 0 8 ) ( 11 0 9 ) common / nodraw [ 1 0 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
( 8 0 8 ) ( 8 0 9 ) ( 8 1 8 ) common / nodraw [ 0 1 0 0 ] [ 0 0 - 1 0 ] 0 0.5 0.5
}
}
) " ;
idLexer src ( LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES ) ;
src . LoadMemory ( tbLetterBrush , strlen ( tbLetterBrush ) , " DoomEdit Brush " ) ;
idMapBrush * brush = idMapBrush : : ParseValve220 ( src , brushOrigin ) ;
for ( int i = 0 ; i < brush - > GetNumSides ( ) ; i + + )
{
auto side = brush - > GetSide ( i ) ;
side - > planepts [ 0 ] + = brushOrigin ;
side - > planepts [ 1 ] + = brushOrigin ;
side - > planepts [ 2 ] + = brushOrigin ;
}
// letter coordinates in the texture
int row = 0 ;
int col = 0 ;
ch & = 255 ;
if ( ch > = ' A ' & & ch < = ' Z ' )
{
ch - = ' A ' ;
col = ch & 7 ;
row = ch / 8 ;
}
else if ( ch > = ' a ' & & ch < = ' z ' )
{
ch = ch - ' a ' + 3 ;
col = ch & 7 ;
row = ch & 7 ;
}
// base offset moves from world to local coords
// brush is 8x1x8 but due to scaling texcoords are shifted by 32
idVec2i baseOffset ;
baseOffset . x = - uvOrigin . x * 4 ;
baseOffset . y = - uvOrigin . z * 4 + 32 ;
auto side = brush - > GetSide ( 1 ) ;
side - > texValve [ 0 ] [ 3 ] = baseOffset . x + col * 32 ;
side - > texValve [ 1 ] [ 3 ] = baseOffset . y + row * 32 ;
return brush ;
}
2022-02-26 14:29:39 +00:00
idMapEntity * MakeNamePlateFuncStatic ( idMapFile * mapFile , float x , float y , float topHeight , const idStr & origTitle )
{
idMapEntity * mapEnt = new ( TAG_SYSTEM ) idMapEntity ( ) ;
mapFile - > AddEntity ( mapEnt ) ;
idStrStatic < MAX_OSPATH > entityName ;
entityName . Format ( " info_board_%d " , mapFile - > GetNumEntities ( ) ) ;
mapEnt - > epairs . Set ( " classname " , " func_static " ) ;
mapEnt - > epairs . Set ( " name " , entityName ) ;
mapEnt - > epairs . Set ( " model " , entityName ) ;
# if 1
// add folder name as brushes
idStr title = origTitle ;
title . ToUpper ( ) ;
int numSlashes = 0 ;
int wordLen = 0 ;
for ( int i = 0 ; i < title . Length ( ) ; i + + )
{
//float x = categoryPositions[ c ].x + category->modelGroupPositions[ g ].x;
//float y = -categoryPositions[ c ].y - category->modelGroupPositions[ g ].y;// - group->totalSize.y;
idVec3 brushOrigin ;
brushOrigin . x = x + wordLen * 8 ;
brushOrigin . y = y ;
brushOrigin . z = topHeight - numSlashes * 8 ;
idVec3 uvOrigin ;
uvOrigin . x = x + wordLen * 8 ;
uvOrigin . y = y ;
uvOrigin . z = topHeight + numSlashes * 8 ;
wordLen + + ;
if ( title [ i ] = = ' / ' )
{
numSlashes + + ;
wordLen = 0 ;
continue ;
}
idMapBrush * ch = MakeCharBrush ( brushOrigin , uvOrigin , title [ i ] ) ;
mapEnt - > AddPrimitive ( ch ) ;
}
# else
idVec3 origin ;
origin . x = outputPositions [ g ] . x + group - > totalSize . x * 0.5 ;
origin . y = outputPositions [ g ] . y ;
origin . z = 128 ;
mapEnt - > epairs . Set ( " classname " , " misc_model " ) ;
mapEnt - > epairs . Set ( " model " , " _tb/models/mapobjects/signs/ceilingsign/ceilingsign.obj " ) ;
mapEnt - > epairs . Set ( " gui " , " guis/signs/directional.gui " ) ;
mapEnt - > epairs . Set ( " gui_parm1 " , group - > folder ) ;
# endif
return mapEnt ;
}
2022-02-23 21:52:23 +00:00
struct EntityInfo_t
{
idBounds bounds ;
idMapEntity * entity ;
idVec2i packedPos ;
} ;
2022-02-26 14:29:39 +00:00
// leaf node that actually contains model files
2022-02-23 21:52:23 +00:00
struct ModelsGroup_t
{
2022-02-26 14:29:39 +00:00
idStrStatic < MAX_OSPATH > path ; // e.g. models/mapobjects/doors/jumbodoor/
idList < EntityInfo_t * , TAG_SYSTEM > entityList ; // model files in that folder
idVec2i totalSize ;
} ;
// higher level folder node
struct Category_t
{
Category_t ( const char * name )
{
tagNames . AddUnique ( name ) ;
totalSize . x = 0 ;
totalSize . y = 0 ;
}
// data
idStrList tagNames ; // e.g. hell, delta, cpu
idList < ModelsGroup_t * , TAG_SYSTEM > modelGroups ;
idList < idVec2i > modelGroupPositions ;
2022-02-23 21:52:23 +00:00
idVec2i totalSize ;
2022-02-26 14:29:39 +00:00
// tree
//idList<Category_t*, TAG_SYSTEM> subFolders;
2022-02-23 21:52:23 +00:00
} ;
void RectAllocator ( const idList < idVec2i > & inputSizes , idList < idVec2i > & outputPositions , idVec2i & totalSize , const int START_MAX = 16384 , const int imageMax = - 1 ) ;
float RectPackingFraction ( const idList < idVec2i > & inputSizes , const idVec2i totalSize ) ;
2022-02-26 17:48:15 +00:00
void RectAllocatorBinPack2D ( const idList < idVec2i > & inputSizes , const idStrList & inputNames , idList < idVec2i > & outputPositions , idVec2i & totalSize , const int START_MAX ) ;
2022-02-26 14:29:39 +00:00
2022-02-23 21:52:23 +00:00
// uses BFG Rectangle Atlas packer to pack models in 3D
void idDeclManagerLocal : : MakeZooMapForModels_f ( const idCmdArgs & args )
{
int totalModelsCount = 0 ;
int totalEntitiesCount = 0 ;
2025-01-23 22:08:57 +00:00
idFileList * files = fileSystem - > ListFilesTree ( " generated " , " .blwo|.base|.bglb|.bobj|.bmd5mesh " , true , true ) ;
2022-02-23 21:52:23 +00:00
idStr mapName ( " maps/zoomaps/zoo_models.map " ) ;
idMapFile mapFile ;
idMapEntity * worldspawn = new ( TAG_SYSTEM ) idMapEntity ( ) ;
mapFile . AddEntity ( worldspawn ) ;
worldspawn - > epairs . Set ( " classname " , " worldspawn " ) ;
2022-02-25 21:14:45 +00:00
idStrList ignoreList ;
// non modular models, should probably a .cfg or .ini defined by an artist
ignoreList . AddUnique ( " models/mapobjects/alphalabs3/vagary/vagary_webs " ) ;
ignoreList . AddUnique ( " models/mapobjects/caves/caves1_1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/caves/caves1_2a " ) ;
ignoreList . AddUnique ( " models/mapobjects/caves/caves1_6 " ) ;
ignoreList . AddUnique ( " models/mapobjects/caves/caves1_7 " ) ;
ignoreList . AddUnique ( " models/mapobjects/caves/caves2_ " ) ;
ignoreList . AddUnique ( " models/mapobjects/caves/cav_corns " ) ;
ignoreList . AddUnique ( " models/mapobjects/com/com_underground1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/cpu/cpu_hell2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/cpu/cpu_hell3 " ) ;
ignoreList . AddUnique ( " models/mapobjects/cpu/cpu_hell4 " ) ;
ignoreList . AddUnique ( " models/mapobjects/cpu/sab_lightning1 " ) ;
ignoreList . AddUnique ( " _clip " ) ;
ignoreList . AddUnique ( " models/mapobjects/delta3/hellgoo_door1/hellgoo_door1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/delta3/hellgoo_elev2/hellgoo_elev2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/deltax/hall_hellgrowth " ) ;
ignoreList . AddUnique ( " models/mapobjects/deltax/room1_hellgrowth " ) ;
ignoreList . AddUnique ( " models/mapobjects/erebus/berzerker_hellgoo_2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/erebus/erebus2_puzzle_cavea_lo " ) ;
ignoreList . AddUnique ( " models/mapobjects/erebus/erebus4_cave " ) ;
ignoreList . AddUnique ( " models/mapobjects/erebus/erebus_cave2_puzzle_cave2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/erebus/erebus_cave2_room1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/erebus/erebus_cave2_room2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/erebus/erebus_lounge_ceiling " ) ;
ignoreList . AddUnique ( " models/mapobjects/erebus/mp_hellshaft " ) ;
ignoreList . AddUnique ( " models/mapobjects/exis/exis_terrain " ) ;
ignoreList . AddUnique ( " models/mapobjects/exis/existel_railing " ) ;
ignoreList . AddUnique ( " models/mapobjects/hangar/hangar1tower " ) ;
ignoreList . AddUnique ( " models/mapobjects/hangar/pillar1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/delta5/doora/eyeskin_b " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/delta5/doorb/hornskin " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/doom3ex/phobos/d3ex_goo_1a " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/maggotroom/worm " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/site3/fleshtube1/fleshtube_01 " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/site3/landscapesradar/canyona " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/site3/birthhole " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/guardian_lightning2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/hellhalldown3 " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/mancroomfloor " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/vagarycave " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/vagarycavehall " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/d3xp_brokensteps " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/d3xp_brokenwall " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/d3xp_hallcorner " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/d3xp_rock " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/d3xp_staircave2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/d3xp_temple_rubble " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/hellhole_cave " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/hellhole_coffinbricks2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/hellhole_crushstairs " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/hellhole_firstroom " ) ;
ignoreList . AddUnique ( " models/mapobjects/hellhole/hellhole_secondroom " ) ;
ignoreList . AddUnique ( " models/mapobjects/mc_underground/outside/mc_ug_out3 " ) ;
ignoreList . AddUnique ( " models/mapobjects/phobos/berg_lightning_fx " ) ;
ignoreList . AddUnique ( " models/mapobjects/phobos/phobos1_brockerybeef " ) ;
ignoreList . AddUnique ( " models/mapobjects/phobos/phobos_cave " ) ;
ignoreList . AddUnique ( " models/mapobjects/recycle/skybridge/skybridge_clip " ) ;
ignoreList . AddUnique ( " models/mapobjects/recycle/mancubusroom " ) ;
ignoreList . AddUnique ( " models/mapobjects/recycle/rec1bigfloor " ) ;
ignoreList . AddUnique ( " models/mapobjects/recycle/rec1cave1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/recycle/rec1sfloor " ) ;
ignoreList . AddUnique ( " models/mapobjects/recycle/rec1sfloorgoop " ) ;
ignoreList . AddUnique ( " models/mapobjects/recycle/rec1tunnel1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/ruins/ruin_wire " ) ;
ignoreList . AddUnique ( " models/mapobjects/site/site3_exitpit " ) ;
ignoreList . AddUnique ( " models/mapobjects/site/site3_tunnel " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hell1ceiling1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hell1floor " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hell1hall1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hell1hall1ceiling " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hell1hall " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hell1lasthall " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hellcaves_1ahall " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hellcaves_ " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hellcaveshole1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hellhalldown2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/hornramp2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/map10_hell1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/map10_hell2 " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/map10_hell3 " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/pillar/pillar_hellrock_a " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/pillar/pillar_hellrock_b " ) ;
ignoreList . AddUnique ( " models/mapobjects/hell/pillar/pillar_hellrock_c " ) ;
ignoreList . AddUnique ( " models/mapobjects/ruins/pillarbroke " ) ;
ignoreList . AddUnique ( " models/mapobjects/delta3/teleporter_warpfx/betrugger_lightning " ) ;
ignoreList . AddUnique ( " models/mapobjects/steve_temp/map10_hell_smoke " ) ;
ignoreList . AddUnique ( " models/mapobjects/phobos/bridge/bridge_roof_1 " ) ;
2022-02-26 14:29:39 +00:00
ignoreList . AddUnique ( " models/mapobjects/phobos/bridge/bridge_wall_1 " ) ;
ignoreList . AddUnique ( " models/mapobjects/phobos/bridge/bridge_wall_2 " ) ;
// TODO generate these procedurally
idList < Category_t * > categories ;
categories . Append ( new Category_t ( " nocategory " ) ) ; // collect here that doesn't fit
categories . Append ( new Category_t ( " delta " ) ) ;
categories . Append ( new Category_t ( " erebus " ) ) ;
categories . Append ( new Category_t ( " phobos " ) ) ;
categories . Append ( new Category_t ( " cpu " ) ) ;
auto hellCat = new Category_t ( " hell " ) ;
hellCat - > tagNames . AddUnique ( " goo " ) ;
hellCat - > tagNames . AddUnique ( " steve_temp " ) ;
categories . Append ( hellCat ) ;
categories . Append ( new Category_t ( " caves " ) ) ;
categories . Append ( new Category_t ( " ruins " ) ) ;
2022-02-26 14:53:14 +00:00
categories . Append ( new Category_t ( " door " ) ) ;
categories . Append ( new Category_t ( " outside " ) ) ;
auto teleCat = new Category_t ( " teleporter " ) ;
teleCat - > tagNames . AddUnique ( " tele " ) ;
categories . Append ( teleCat ) ;
auto liftCat = new Category_t ( " elevator " ) ;
liftCat - > tagNames . AddUnique ( " lift " ) ;
categories . Append ( liftCat ) ;
2022-03-05 17:55:30 +00:00
categories . Append ( new Category_t ( " railing " ) ) ;
categories . Append ( new Category_t ( " pipe " ) ) ;
categories . Append ( new Category_t ( " ladder " ) ) ;
2022-02-26 14:29:39 +00:00
2022-02-25 21:14:45 +00:00
2022-02-26 14:29:39 +00:00
// collect all folders that actually contain models and sort them into categories
2022-02-23 21:52:23 +00:00
idHashTable < ModelsGroup_t * > entitiesPerFolder ;
for ( int f = 0 ; f < files - > GetList ( ) . Num ( ) /*&& totalEntitiesCount < 100*/ ; f + + )
{
totalModelsCount + + ;
idStr modelName = files - > GetList ( ) [ f ] ;
modelName . StripLeadingOnce ( " generated/rendermodels/ " ) ;
idStr ext ;
modelName . ExtractFileExtension ( ext ) ;
bool dynamicModel = false ;
if ( ext . Icmp ( " blwo " ) = = 0 )
{
modelName . SetFileExtension ( " lwo " ) ;
}
if ( ext . Icmp ( " base " ) = = 0 )
{
modelName . SetFileExtension ( " ase " ) ;
}
2025-01-23 22:08:57 +00:00
if ( ext . Icmp ( " bglb " ) = = 0 )
2022-02-23 21:52:23 +00:00
{
2025-01-23 22:08:57 +00:00
modelName . SetFileExtension ( " glb " ) ;
2022-02-23 21:52:23 +00:00
}
2022-03-05 17:55:30 +00:00
if ( ext . Icmp ( " bobj " ) = = 0 )
{
modelName . SetFileExtension ( " obj " ) ;
}
2022-02-23 21:52:23 +00:00
if ( ext . Icmp ( " bmd5mesh " ) = = 0 )
{
modelName . SetFileExtension ( " md5mesh " ) ;
dynamicModel = true ;
}
2022-02-25 21:14:45 +00:00
// skip TB specific helper models
if ( idStr : : Icmpn ( modelName , " _tb " , 3 ) = = 0 )
{
continue ;
}
2022-02-23 21:52:23 +00:00
idRenderModel * renderModel = renderModelManager - > FindModel ( modelName ) ;
2022-02-25 21:14:45 +00:00
// skip non modular models
bool ignore = false ;
for ( int i = 0 ; i < ignoreList . Num ( ) ; i + + )
{
const char * ignoreStr = ignoreList [ i ] . c_str ( ) ;
if ( modelName . Find ( ignoreStr ) ! = - 1 )
{
ignore = true ;
break ;
}
}
if ( ignore )
{
continue ;
}
2022-02-23 21:52:23 +00:00
# if 1
// discard everything that is not a mapobjects model
if ( idStr : : Icmpn ( modelName , " models/mapobjects " , 17 ) ! = 0 )
{
continue ;
}
# endif
2022-02-24 21:14:40 +00:00
/*
if ( idStr : : Icmpn ( modelName , " models/mapobjects/caves " , 23 ) = = 0 )
{
continue ;
}
*/
2022-02-23 21:52:23 +00:00
if ( idStr : : Icmpn ( modelName , " models/items " , 12 ) = = 0 )
{
continue ;
}
if ( idStr : : Icmpn ( modelName , " models/particles " , 16 ) = = 0 )
{
continue ;
}
if ( idStr : : Icmpn ( modelName , " models/weapons " , 14 ) = = 0 )
{
continue ;
}
idStr directory = modelName ;
directory . StripFilename ( ) ;
// find models group or create it
ModelsGroup_t * * groupptrptr = nullptr ;
ModelsGroup_t * group = nullptr ;
if ( ! entitiesPerFolder . Get ( directory , & groupptrptr ) )
{
group = new ( TAG_SYSTEM ) ModelsGroup_t ;
2022-02-26 14:29:39 +00:00
group - > path = directory ;
2022-02-23 21:52:23 +00:00
entitiesPerFolder . Set ( directory , group ) ;
}
else
{
group = * groupptrptr ;
}
idBounds bounds = renderModel - > Bounds ( ) ;
// put model as mapobject into the models FGD
if ( ! renderModel - > IsDefaultModel ( ) & & bounds . GetVolume ( ) > 0 & & bounds . GetRadius ( ) < 1400 )
{
idMapEntity * mapEnt = new ( TAG_SYSTEM ) idMapEntity ( ) ;
mapFile . AddEntity ( mapEnt ) ;
idStrStatic < MAX_OSPATH > entityName ;
entityName . Format ( " misc_model_%d " , mapFile . GetNumEntities ( ) ) ;
mapEnt - > epairs . Set ( " classname " , " misc_model " ) ;
mapEnt - > epairs . Set ( " name " , entityName ) ;
2025-01-23 22:08:57 +00:00
// .glb models are the fastest to load into TrenchBroom so skip proxymodel
if ( ext . Icmp ( " bglb " ) ! = 0 )
{
// build TB compatible model name
idStrStatic < MAX_OSPATH > exportedModelFileName ;
exportedModelFileName = " _tb/ " ;
exportedModelFileName . AppendPath ( modelName ) ;
exportedModelFileName . SetFileExtension ( " .obj " ) ;
mapEnt - > epairs . Set ( " proxymodel " , exportedModelFileName ) ;
}
2022-02-27 12:56:14 +00:00
mapEnt - > epairs . Set ( " model " , modelName ) ;
2022-02-23 21:52:23 +00:00
EntityInfo_t * entInfo = new ( TAG_SYSTEM ) EntityInfo_t ;
entInfo - > bounds = bounds ;
entInfo - > entity = mapEnt ;
group - > entityList . Append ( entInfo ) ;
totalEntitiesCount + + ;
}
}
fileSystem - > FreeFileList ( files ) ;
2022-02-26 17:48:15 +00:00
// BinPack2D is better, more efficient and can with all really big models but looks worse than the simple rectangle packer
const bool useBinpack2D = false ;
2022-02-23 21:52:23 +00:00
// pack models by 2D AABB inside of a folder
for ( int g = 0 ; g < entitiesPerFolder . Num ( ) ; g + + )
{
ModelsGroup_t * group = * entitiesPerFolder . GetIndex ( g ) ;
idList < idVec2i > inputSizes ;
2022-02-26 17:48:15 +00:00
idStrList inputNames ;
2022-02-23 21:52:23 +00:00
inputSizes . SetNum ( group - > entityList . Num ( ) ) ;
for ( int e = 0 ; e < group - > entityList . Num ( ) ; e + + )
{
EntityInfo_t * entInfo = group - > entityList [ e ] ;
idBounds & b = entInfo - > bounds ;
const int offset = 64 ;
idVec2i allocSize ( ( b [ 1 ] [ 0 ] - b [ 0 ] [ 0 ] ) + offset , ( b [ 1 ] [ 1 ] - b [ 0 ] [ 1 ] ) + offset ) ;
//idLib::Printf( "model size %ix%i in '%s'\n", allocSize.x, allocSize.y, group->folder.c_str() );
inputSizes [ e ] = allocSize ;
2022-02-27 12:56:14 +00:00
inputNames . Append ( entInfo - > entity - > epairs . GetString ( " model " ) ) ;
2022-02-23 21:52:23 +00:00
}
idList < idVec2i > outputPositions ;
idVec2i totalSize ;
2022-02-26 17:48:15 +00:00
if ( useBinpack2D )
{
RectAllocatorBinPack2D ( inputSizes , inputNames , outputPositions , totalSize , 1 < < 17 ) ;
}
else
{
RectAllocator ( inputSizes , outputPositions , totalSize , 1 < < 14 ) ;
}
2022-02-23 21:52:23 +00:00
group - > totalSize = totalSize ;
for ( int e = 0 ; e < group - > entityList . Num ( ) ; e + + )
{
EntityInfo_t * entInfo = group - > entityList [ e ] ;
entInfo - > packedPos = outputPositions [ e ] ;
}
}
2022-02-26 14:29:39 +00:00
// assign model folders to categories
2022-02-23 21:52:23 +00:00
for ( int g = 0 ; g < entitiesPerFolder . Num ( ) ; g + + )
{
ModelsGroup_t * group = * entitiesPerFolder . GetIndex ( g ) ;
2022-02-26 14:29:39 +00:00
bool inserted = false ;
for ( int i = 1 ; i < categories . Num ( ) ; i + + )
{
Category_t * category = categories [ i ] ;
2022-02-23 21:52:23 +00:00
2022-02-26 14:29:39 +00:00
for ( int j = 0 ; j < category - > tagNames . Num ( ) ; j + + )
{
2022-02-26 14:53:14 +00:00
if ( group - > path . Find ( category - > tagNames [ j ] , false ) ! = - 1 )
2022-02-26 14:29:39 +00:00
{
category - > modelGroups . Append ( group ) ;
inserted = true ;
break ;
}
}
}
2022-02-23 21:52:23 +00:00
2022-02-26 14:29:39 +00:00
if ( ! inserted )
{
categories [ 0 ] - > modelGroups . Append ( group ) ;
}
2022-02-23 21:52:23 +00:00
}
2022-02-26 14:29:39 +00:00
// pack folders in categories
for ( int i = 0 ; i < categories . Num ( ) ; i + + )
{
Category_t * category = categories [ i ] ;
idList < idVec2i > inputSizes ;
inputSizes . SetNum ( category - > modelGroups . Num ( ) ) ;
2022-02-26 17:48:15 +00:00
idStrList inputNames ;
2022-02-26 14:29:39 +00:00
for ( int g = 0 ; g < category - > modelGroups . Num ( ) ; g + + )
{
ModelsGroup_t * group = category - > modelGroups [ g ] ;
const int offset = 256 ;
idVec2i allocSize ( group - > totalSize . x + offset , group - > totalSize . y + offset ) ;
2022-02-26 17:48:15 +00:00
//idLib::Printf( "folder '%s' size %ix%i\n", group->path.c_str(), allocSize.x, allocSize.y );
2022-02-26 14:29:39 +00:00
inputSizes [ g ] = allocSize ;
2022-02-26 17:48:15 +00:00
inputNames . Append ( group - > path ) ;
2022-02-26 14:29:39 +00:00
}
idVec2i totalSize ;
2022-02-26 17:48:15 +00:00
if ( useBinpack2D )
{
RectAllocatorBinPack2D ( inputSizes , inputNames , category - > modelGroupPositions , totalSize , 1 < < 17 ) ;
}
else
{
RectAllocator ( inputSizes , category - > modelGroupPositions , totalSize , 1 < < 14 ) ;
}
2022-02-26 14:29:39 +00:00
category - > totalSize = totalSize ;
}
// pack categories
idList < idVec2i > inputSizes ;
inputSizes . SetNum ( categories . Num ( ) ) ;
2022-02-26 17:48:15 +00:00
idStrList inputNames ;
for ( int i = 0 ; i < categories . Num ( ) ; i + + )
{
inputNames . Append ( categories [ i ] - > tagNames [ 0 ] ) ;
}
2022-02-26 14:29:39 +00:00
idList < idVec2i > categoryPositions ;
2022-02-23 21:52:23 +00:00
idVec2i totalSize ;
2022-02-26 14:29:39 +00:00
for ( int i = 0 ; i < categories . Num ( ) ; i + + )
{
Category_t * category = categories [ i ] ;
const int offset = 256 ;
idVec2i allocSize ( category - > totalSize . x + offset , category - > totalSize . y + offset ) ;
idLib : : Printf ( " category '%s' size %ix%i \n " , category - > tagNames [ 0 ] . c_str ( ) , allocSize . x , allocSize . y ) ;
2022-02-23 21:52:23 +00:00
2022-02-26 14:29:39 +00:00
inputSizes [ i ] = allocSize ;
// smart allocator
2022-02-26 17:48:15 +00:00
if ( useBinpack2D )
{
RectAllocatorBinPack2D ( inputSizes , inputNames , categoryPositions , totalSize , 1 < < 17 ) ;
}
else
{
RectAllocator ( inputSizes , categoryPositions , totalSize , 1 < < 14 ) ;
}
2022-02-26 14:29:39 +00:00
}
2022-02-23 21:52:23 +00:00
// place entities inside packed folders
2022-02-26 14:29:39 +00:00
for ( int c = 0 ; c < categories . Num ( ) ; c + + )
2022-02-23 21:52:23 +00:00
{
2022-02-26 14:29:39 +00:00
Category_t * category = categories [ c ] ;
const int fontGridHeight = 128 ;
2022-02-23 21:52:23 +00:00
2022-02-26 14:29:39 +00:00
float catHeight = 0 ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
for ( int g = 0 ; g < category - > modelGroups . Num ( ) ; g + + )
2022-02-24 21:14:40 +00:00
{
2022-02-26 14:29:39 +00:00
ModelsGroup_t * group = category - > modelGroups [ g ] ;
// calculate top height of the entities in this group
// so we can place a name plate above the group
float topHeight = 0 ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
for ( int e = 0 ; e < group - > entityList . Num ( ) ; e + + )
2022-02-24 21:14:40 +00:00
{
2022-02-26 14:29:39 +00:00
EntityInfo_t * entInfo = group - > entityList [ e ] ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
if ( entInfo - > bounds [ 1 ] . z > topHeight )
{
topHeight = entInfo - > bounds [ 1 ] . z ;
}
}
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
topHeight + = 128 ;
topHeight = idMath : : Floor ( topHeight / fontGridHeight ) * fontGridHeight ;
2022-02-23 21:52:23 +00:00
2022-02-26 14:29:39 +00:00
if ( topHeight > catHeight )
2022-02-24 21:14:40 +00:00
{
2022-02-26 14:29:39 +00:00
catHeight = topHeight ;
}
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
float x = categoryPositions [ c ] . x + category - > modelGroupPositions [ g ] . x + group - > totalSize . x * 0.5f ;
float y = - categoryPositions [ c ] . y - category - > modelGroupPositions [ g ] . y - group - > totalSize . y ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
//idMapEntity* plateEnt =
MakeNamePlateFuncStatic ( & mapFile , x , y , topHeight , group - > path ) ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
// move entities along with the upper packed categories
for ( int e = 0 ; e < group - > entityList . Num ( ) ; e + + )
{
EntityInfo_t * entInfo = group - > entityList [ e ] ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
idVec3 origin ;
origin . x = categoryPositions [ c ] . x + category - > modelGroupPositions [ g ] . x + entInfo - > packedPos . x - entInfo - > bounds [ 0 ] [ 0 ] ;
origin . y = - categoryPositions [ c ] . y - category - > modelGroupPositions [ g ] . y - entInfo - > packedPos . y - entInfo - > bounds [ 1 ] [ 1 ] ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
// place entity above 0 if it goes below
origin . z = - entInfo - > bounds [ 0 ] . z + 1 ;
2022-02-25 21:14:45 +00:00
2022-02-26 14:29:39 +00:00
entInfo - > entity - > epairs . SetVector ( " origin " , origin ) ;
}
}
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
// put a name plate above the category with its main tag
float x = categoryPositions [ c ] . x + category - > totalSize . x * 0.5f ;
float y = - categoryPositions [ c ] . y - category - > totalSize . y * 0.5f ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
catHeight + = 128 ;
catHeight = idMath : : Floor ( catHeight / fontGridHeight ) * fontGridHeight ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
idMapEntity * plateEnt = MakeNamePlateFuncStatic ( & mapFile , x , y , catHeight , category - > tagNames [ 0 ] ) ;
#if 0
// place bottom place below
idVec3 origin ( x , y , - 32 ) ;
idVec3 scale ( category - > totalSize . x , category - > totalSize . y , 16 ) ;
idMapBrush * bottomPlate = MakeUnitBrush ( origin , scale ) ;
plateEnt - > AddPrimitive ( bottomPlate ) ;
2022-02-24 21:14:40 +00:00
# else
2022-02-26 14:29:39 +00:00
// place border brushes
// back
float xx = x ;
float yy = y + category - > totalSize . y * 0.5f ;
idVec3 origin ( xx , yy , - 40 ) ;
idVec3 scale ( category - > totalSize . x , 4 , 16 ) ;
idMapBrush * bottomPlate = MakeUnitBrush ( origin , scale , true ) ;
worldspawn - > AddPrimitive ( bottomPlate ) ;
// front
xx = x ;
yy = y - category - > totalSize . y * 0.5f ;
origin . Set ( xx , yy , - 40 ) ;
scale . Set ( category - > totalSize . x , 4 , 16 ) ;
bottomPlate = MakeUnitBrush ( origin , scale , true ) ;
worldspawn - > AddPrimitive ( bottomPlate ) ;
// left
xx = x - category - > totalSize . x * 0.5f ;
yy = y ;
origin . Set ( xx , yy , - 40 ) ;
scale . Set ( 4 , category - > totalSize . y , 16 ) ;
bottomPlate = MakeUnitBrush ( origin , scale , true ) ;
worldspawn - > AddPrimitive ( bottomPlate ) ;
// right
xx = x + category - > totalSize . x * 0.5f ;
yy = y ;
origin . Set ( xx , yy , - 40 ) ;
scale . Set ( 4 , category - > totalSize . y , 16 ) ;
bottomPlate = MakeUnitBrush ( origin , scale , true ) ;
worldspawn - > AddPrimitive ( bottomPlate ) ;
2022-02-24 21:14:40 +00:00
# endif
2022-02-23 21:52:23 +00:00
}
2025-01-23 22:08:57 +00:00
mapFile . ConvertToValve220Format ( false ) ;
2022-02-24 21:14:40 +00:00
2022-02-26 14:29:39 +00:00
worldspawn - > epairs . Set ( " _tb_textures " , " textures/common;textures/editor;textures/decals;textures/rock " ) ;
2022-02-27 16:26:58 +00:00
worldspawn - > epairs . Set ( " _tb_def " , " external:base/_tb/fgd/DOOM-3-models.fgd " ) ;
2022-02-24 21:14:40 +00:00
2025-01-23 22:08:57 +00:00
//"_tb_mod" "mod_unittests"
2022-02-23 21:52:23 +00:00
mapFile . Write ( mapName , " .map " ) ;
common - > Printf ( " \n Zoo map written to %s \n " , mapName . c_str ( ) ) ;
common - > Printf ( " ---------------------------- \n " ) ;
common - > Printf ( " Found %d Models. \n " , totalModelsCount ) ;
2022-02-26 14:29:39 +00:00
common - > Printf ( " Wrote %d Entities in %d Groups and %d Cateogories \n " , totalEntitiesCount , entitiesPerFolder . Num ( ) , categories . Num ( ) ) ;
2022-02-23 21:52:23 +00:00
}
2016-03-05 20:19:14 +00:00
// RB end
2024-06-17 20:10:50 +00:00
# endif // #if !defined( DMAP )
2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = =
idDeclManagerLocal : : FindTypeWithoutParsing
This finds or creats the decl , but does not cause a parse . This is only used internally .
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDeclLocal * idDeclManagerLocal : : FindTypeWithoutParsing ( declType_t type , const char * name , bool makeDefault )
{
int typeIndex = ( int ) type ;
2012-11-26 18:58:24 +00:00
int i , hash ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( typeIndex < 0 | | typeIndex > = declTypes . Num ( ) | | declTypes [ typeIndex ] = = NULL | | typeIndex > = DECL_MAX_TYPES )
{
2012-11-26 18:58:24 +00:00
common - > FatalError ( " idDeclManager::FindTypeWithoutParsing: bad type: %i " , typeIndex ) ;
return NULL ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
char canonicalName [ MAX_STRING_CHARS ] ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
MakeNameCanonical ( name , canonicalName , sizeof ( canonicalName ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// see if it already exists
hash = hashTables [ typeIndex ] . GenerateKey ( canonicalName , false ) ;
2012-11-28 15:47:07 +00:00
for ( i = hashTables [ typeIndex ] . First ( hash ) ; i > = 0 ; i = hashTables [ typeIndex ] . Next ( i ) )
{
if ( linearLists [ typeIndex ] [ i ] - > name . Icmp ( canonicalName ) = = 0 )
{
2012-11-26 18:58:24 +00:00
// only print these when decl_show is set to 2, because it can be a lot of clutter
2012-11-28 15:47:07 +00:00
if ( decl_show . GetInteger ( ) > 1 )
{
2012-11-26 18:58:24 +00:00
MediaPrint ( " referencing %s %s \n " , declTypes [ type ] - > typeName . c_str ( ) , name ) ;
}
return linearLists [ typeIndex ] [ i ] ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( ! makeDefault )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
idDeclLocal * decl = new ( TAG_DECL ) idDeclLocal ;
2012-11-26 18:58:24 +00:00
decl - > self = NULL ;
decl - > name = canonicalName ;
decl - > type = type ;
decl - > declState = DS_UNPARSED ;
decl - > textSource = NULL ;
decl - > textLength = 0 ;
decl - > sourceFile = & implicitDecls ;
decl - > referencedThisLevel = false ;
decl - > everReferenced = false ;
2023-12-14 19:32:16 +00:00
// SRS - initialize to false, otherwise all decls will be set to non-purgeable during Init()
decl - > parsedOutsideLevelLoad = false ; // !insideLevelLoad;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// add it to the linear list and hash table
decl - > index = linearLists [ typeIndex ] . Num ( ) ;
hashTables [ typeIndex ] . Add ( hash , linearLists [ typeIndex ] . Append ( decl ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return decl ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclManagerLocal : : ConvertPDAsToStrings
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclManagerLocal : : ConvertPDAsToStrings ( const idCmdArgs & args )
{
2012-11-26 18:58:24 +00:00
idStr pdaStringsFileName = " temppdas/pdas.lang " ;
idFileLocal file ( fileSystem - > OpenFileWrite ( pdaStringsFileName ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( file = = NULL )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " Failed to Convert PDA data to Strings. \n " ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int totalEmailCount = 0 ;
int totalAudioCount = 0 ;
int totalVideoCount = 0 ;
idStr headEnd = " \t \" #str_%s_ " ;
idStr tailEnd = " \" \t \" %s \" \n " ;
idStr temp ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int count = linearLists [ DECL_PDA ] . Num ( ) ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < count ; i + + )
{
const idDeclPDA * decl = static_cast < const idDeclPDA * > ( FindType ( DECL_PDA , linearLists [ DECL_PDA ] [ i ] - > GetName ( ) , false ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idStr pdaBaseStrId = va ( headEnd . c_str ( ) , decl - > GetName ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
temp = va ( " \n \n //////// %s PDA //////////// \n " , decl - > GetName ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idStr pdaBase = pdaBaseStrId + " pda_%s " + tailEnd ;
// Pda Name
temp = va ( pdaBase . c_str ( ) , " name " , decl - > GetPdaName ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Full Name
temp = va ( pdaBase . c_str ( ) , " fullname " , decl - > GetFullName ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// ID
temp = va ( pdaBase . c_str ( ) , " id " , decl - > GetID ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Post
temp = va ( pdaBase . c_str ( ) , " post " , decl - > GetPost ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Title
temp = va ( pdaBase . c_str ( ) , " title " , decl - > GetTitle ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Security
temp = va ( pdaBase . c_str ( ) , " security " , decl - > GetSecurity ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int emailCount = decl - > GetNumEmails ( ) ;
2012-11-28 15:47:07 +00:00
for ( int emailIter = 0 ; emailIter < emailCount ; emailIter + + )
{
const idDeclEmail * email = decl - > GetEmailByIndex ( emailIter ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idStr emailBaseStrId = va ( headEnd . c_str ( ) , email - > GetName ( ) ) ;
idStr emailBase = emailBaseStrId + " email_%s " + tailEnd ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
file - > Write ( " \t //Email \n " , 9 ) ;
// Date
temp = va ( emailBase , " date " , email - > GetDate ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// To
temp = va ( emailBase , " to " , email - > GetTo ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// From
temp = va ( emailBase , " from " , email - > GetFrom ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Subject
temp = va ( emailBase , " subject " , email - > GetSubject ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Body
idStr body = email - > GetBody ( ) ;
body . Replace ( " \n " , " \\ n " ) ;
temp = va ( emailBase , " text " , body . c_str ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
totalEmailCount + + ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int audioCount = decl - > GetNumAudios ( ) ;
2012-11-28 15:47:07 +00:00
for ( int audioIter = 0 ; audioIter < audioCount ; audioIter + + )
{
const idDeclAudio * audio = decl - > GetAudioByIndex ( audioIter ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idStr audioBaseStrId = va ( headEnd . c_str ( ) , audio - > GetName ( ) ) ;
idStr audioBase = audioBaseStrId + " audio_%s " + tailEnd ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
file - > Write ( " \t //Audio \n " , 9 ) ;
// Name
temp = va ( audioBase , " name " , audio - > GetAudioName ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Info
idStr info = audio - > GetInfo ( ) ;
info . Replace ( " \n " , " \\ n " ) ;
temp = va ( audioBase , " info " , info . c_str ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
totalAudioCount + + ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int infoEmailCount = linearLists [ DECL_EMAIL ] . Num ( ) ;
2012-11-28 15:47:07 +00:00
if ( infoEmailCount > 0 )
{
2012-11-26 18:58:24 +00:00
temp = " \n \n //////// PDA Info Emails //////////// \n " ;
file - > Write ( temp , temp . Length ( ) ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < infoEmailCount ; i + + )
{
const idDeclEmail * email = static_cast < const idDeclEmail * > ( FindType ( DECL_EMAIL , linearLists [ DECL_EMAIL ] [ i ] - > GetName ( ) , false ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idStr filename = email - > base - > GetFileName ( ) ;
2012-11-28 15:47:07 +00:00
if ( filename . Icmp ( " newpdas/info_emails.pda " ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idStr emailBaseStrId = va ( " \t \" #str_%s_ " , email - > GetName ( ) ) ;
idStr emailBase = emailBaseStrId + " email_%s " + tailEnd ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
file - > Write ( " \t //Email \n " , 9 ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// Date
temp = va ( emailBase , " date " , email - > GetDate ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// To
temp = va ( emailBase , " to " , email - > GetTo ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// From
temp = va ( emailBase , " from " , email - > GetFrom ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Subject
temp = va ( emailBase , " subject " , email - > GetSubject ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Body
idStr body = email - > GetBody ( ) ;
body . Replace ( " \n " , " \\ n " ) ;
temp = va ( emailBase , " text " , body . c_str ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
totalEmailCount + + ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
int videoCount = linearLists [ DECL_VIDEO ] . Num ( ) ;
2012-11-28 15:47:07 +00:00
if ( videoCount > 0 )
{
2012-11-26 18:58:24 +00:00
temp = " \n \n //////// PDA Videos //////////// \n " ;
file - > Write ( temp , temp . Length ( ) ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < videoCount ; i + + )
{
const idDeclVideo * video = static_cast < const idDeclVideo * > ( FindType ( DECL_VIDEO , linearLists [ DECL_VIDEO ] [ i ] - > GetName ( ) , false ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idStr videoBaseStrId = va ( " \t \" #str_%s_ " , video - > GetName ( ) ) ;
idStr videoBase = videoBaseStrId + " video_%s " + tailEnd ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
file - > Write ( " \t //Video \n " , 9 ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// Name
temp = va ( videoBase , " name " , video - > GetVideoName ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
// Info
idStr info = video - > GetInfo ( ) ;
info . Replace ( " \n " , " \\ n " ) ;
temp = va ( videoBase , " info " , info . c_str ( ) ) ;
file - > Write ( temp , temp . Length ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
totalVideoCount + + ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
file - > Flush ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " \n Data written to %s \n " , pdaStringsFileName . c_str ( ) ) ;
idLib : : Printf ( " ---------------------------- \n " ) ;
idLib : : Printf ( " Wrote %d PDAs. \n " , count ) ;
idLib : : Printf ( " Wrote %d Emails. \n " , totalEmailCount ) ;
idLib : : Printf ( " Wrote %d Audio Records. \n " , totalAudioCount ) ;
idLib : : Printf ( " Wrote %d Video Records. \n " , totalVideoCount ) ;
idLib : : Printf ( " Please copy the results into the appropriate .lang file. \n " ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idDeclLocal
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : idDeclLocal
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idDeclLocal : : idDeclLocal ( )
{
2012-11-26 18:58:24 +00:00
name = " unnamed " ;
textSource = NULL ;
textLength = 0 ;
compressedLength = 0 ;
sourceFile = NULL ;
sourceTextOffset = 0 ;
sourceTextLength = 0 ;
sourceLine = 0 ;
checksum = 0 ;
type = DECL_ENTITYDEF ;
index = 0 ;
declState = DS_UNPARSED ;
parsedOutsideLevelLoad = false ;
referencedThisLevel = false ;
everReferenced = false ;
redefinedInReload = false ;
nextInFile = NULL ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : GetName
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idDeclLocal : : GetName ( ) const
{
2012-11-26 18:58:24 +00:00
return name . c_str ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : GetType
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
declType_t idDeclLocal : : GetType ( ) const
{
2012-11-26 18:58:24 +00:00
return type ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : GetState
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
declState_t idDeclLocal : : GetState ( ) const
{
2012-11-26 18:58:24 +00:00
return declState ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : IsImplicit
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDeclLocal : : IsImplicit ( ) const
{
2012-11-26 18:58:24 +00:00
return ( sourceFile = = declManagerLocal . GetImplicitDeclFile ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : IsValid
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDeclLocal : : IsValid ( ) const
{
2012-11-26 18:58:24 +00:00
return ( declState ! = DS_UNPARSED ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : Invalidate
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : Invalidate ( )
{
2012-11-26 18:58:24 +00:00
declState = DS_UNPARSED ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : EnsureNotPurged
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : EnsureNotPurged ( )
{
if ( declState = = DS_UNPARSED )
{
2012-11-26 18:58:24 +00:00
ParseLocal ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : Index
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idDeclLocal : : Index ( ) const
{
2012-11-26 18:58:24 +00:00
return index ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : GetLineNum
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idDeclLocal : : GetLineNum ( ) const
{
2012-11-26 18:58:24 +00:00
return sourceLine ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : GetFileName
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idDeclLocal : : GetFileName ( ) const
{
2012-11-26 18:58:24 +00:00
return ( sourceFile ) ? sourceFile - > fileName . c_str ( ) : " *invalid* " ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : Size
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
size_t idDeclLocal : : Size ( ) const
{
2012-11-26 18:58:24 +00:00
return sizeof ( idDecl ) + name . Allocated ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : GetText
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : GetText ( char * text ) const
{
2012-11-26 18:58:24 +00:00
# ifdef USE_COMPRESSED_DECLS
2012-11-28 15:47:07 +00:00
HuffmanDecompressText ( text , textLength , ( byte * ) textSource , compressedLength ) ;
2012-11-26 18:58:24 +00:00
# else
2012-11-28 15:47:07 +00:00
memcpy ( text , textSource , textLength + 1 ) ;
2012-11-26 18:58:24 +00:00
# endif
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : GetTextLength
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idDeclLocal : : GetTextLength ( ) const
{
2012-11-26 18:58:24 +00:00
return textLength ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : SetText
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : SetText ( const char * text )
{
2012-11-26 18:58:24 +00:00
SetTextLocal ( text , idStr : : Length ( text ) ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : SetTextLocal
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : SetTextLocal ( const char * text , const int length )
{
2012-11-26 18:58:24 +00:00
Mem_Free ( textSource ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
checksum = MD5_BlockChecksum ( text , length ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
# ifdef GET_HUFFMAN_FREQUENCIES
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < length ; i + + )
{
huffmanFrequencies [ ( ( const unsigned char * ) text ) [ i ] ] + + ;
2012-11-26 18:58:24 +00:00
}
# endif
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
# ifdef USE_COMPRESSED_DECLS
int maxBytesPerCode = ( maxHuffmanBits + 7 ) > > 3 ;
2012-11-28 15:47:07 +00:00
byte * compressed = ( byte * ) _alloca ( length * maxBytesPerCode ) ;
2012-11-26 18:58:24 +00:00
compressedLength = HuffmanCompressText ( text , length , compressed , length * maxBytesPerCode ) ;
2012-11-28 15:47:07 +00:00
textSource = ( char * ) Mem_Alloc ( compressedLength , TAG_DECLTEXT ) ;
2012-11-26 18:58:24 +00:00
memcpy ( textSource , compressed , compressedLength ) ;
# else
compressedLength = length ;
2012-11-28 15:47:07 +00:00
textSource = ( char * ) Mem_Alloc ( length + 1 , TAG_DECLTEXT ) ;
2012-11-26 18:58:24 +00:00
memcpy ( textSource , text , length ) ;
textSource [ length ] = ' \0 ' ;
# endif
textLength = length ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : ReplaceSourceFileText
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDeclLocal : : ReplaceSourceFileText ( )
{
2012-11-26 18:58:24 +00:00
int oldFileLength , newFileLength ;
2012-11-28 15:47:07 +00:00
idFile * file ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
common - > Printf ( " Writing \' %s \' to \' %s \' ... \n " , GetName ( ) , GetFileName ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( sourceFile = = & declManagerLocal . implicitDecls )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " Can't save implicit declaration %s. " , GetName ( ) ) ;
return false ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// get length and allocate buffer to hold the file
oldFileLength = sourceFile - > fileSize ;
newFileLength = oldFileLength - sourceTextLength + textLength ;
idTempArray < char > buffer ( Max ( newFileLength , oldFileLength ) ) ;
memset ( buffer . Ptr ( ) , 0 , buffer . Size ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// read original file
2012-11-28 15:47:07 +00:00
if ( sourceFile - > fileSize )
{
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
file = fileSystem - > OpenFileRead ( GetFileName ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( ! file )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " Couldn't open %s for reading. " , GetFileName ( ) ) ;
return false ;
}
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( file - > Length ( ) ! = sourceFile - > fileSize | | file - > Timestamp ( ) ! = sourceFile - > timestamp )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " The file %s has been modified outside of the engine. " , GetFileName ( ) ) ;
return false ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
file - > Read ( buffer . Ptr ( ) , oldFileLength ) ;
fileSystem - > CloseFile ( file ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( MD5_BlockChecksum ( buffer . Ptr ( ) , oldFileLength ) ! = ( unsigned int ) sourceFile - > checksum )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " The file %s has been modified outside of the engine. " , GetFileName ( ) ) ;
return false ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// insert new text
2012-11-28 15:47:07 +00:00
char * declText = ( char * ) _alloca ( textLength + 1 ) ;
2012-11-26 18:58:24 +00:00
GetText ( declText ) ;
memmove ( buffer . Ptr ( ) + sourceTextOffset + textLength , buffer . Ptr ( ) + sourceTextOffset + sourceTextLength , oldFileLength - sourceTextOffset - sourceTextLength ) ;
memcpy ( buffer . Ptr ( ) + sourceTextOffset , declText , textLength ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// write out new file
file = fileSystem - > OpenFileWrite ( GetFileName ( ) , " fs_basepath " ) ;
2012-11-28 15:47:07 +00:00
if ( ! file )
{
2012-11-26 18:58:24 +00:00
common - > Warning ( " Couldn't open %s for writing. " , GetFileName ( ) ) ;
return false ;
}
file - > Write ( buffer . Ptr ( ) , newFileLength ) ;
fileSystem - > CloseFile ( file ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// set new file size, checksum and timestamp
sourceFile - > fileSize = newFileLength ;
sourceFile - > checksum = MD5_BlockChecksum ( buffer . Ptr ( ) , newFileLength ) ;
fileSystem - > ReadFile ( GetFileName ( ) , NULL , & sourceFile - > timestamp ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// move all decls in the same file
2012-11-28 15:47:07 +00:00
for ( idDeclLocal * decl = sourceFile - > decls ; decl ; decl = decl - > nextInFile )
{
if ( decl - > sourceTextOffset > sourceTextOffset )
{
2012-11-26 18:58:24 +00:00
decl - > sourceTextOffset + = textLength - sourceTextLength ;
}
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// set new size of text in source file
sourceTextLength = textLength ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : SourceFileChanged
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDeclLocal : : SourceFileChanged ( ) const
{
2012-11-26 18:58:24 +00:00
int newLength ;
ID_TIME_T newTimestamp ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( sourceFile - > fileSize < = 0 )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
newLength = fileSystem - > ReadFile ( GetFileName ( ) , NULL , & newTimestamp ) ;
2019-11-11 19:27:44 +00:00
2012-11-28 15:47:07 +00:00
if ( newLength ! = sourceFile - > fileSize | | newTimestamp ! = sourceFile - > timestamp )
{
2012-11-26 18:58:24 +00:00
return true ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : MakeDefault
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : MakeDefault ( )
{
2012-11-26 18:58:24 +00:00
static int recursionLevel ;
2012-11-28 15:47:07 +00:00
const char * defaultText ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
declManagerLocal . MediaPrint ( " DEFAULTED \n " ) ;
declState = DS_DEFAULTED ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
AllocateSelf ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
defaultText = self - > DefaultDefinition ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// a parse error inside a DefaultDefinition() string could
// cause an infinite loop, but normal default definitions could
// still reference other default definitions, so we can't
// just dump out on the first recursion
2012-11-28 15:47:07 +00:00
if ( + + recursionLevel > 100 )
{
2012-11-26 18:58:24 +00:00
common - > FatalError ( " idDecl::MakeDefault: bad DefaultDefinition(): %s " , defaultText ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// always free data before parsing
self - > FreeData ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// parse
self - > Parse ( defaultText , strlen ( defaultText ) , false ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// we could still eventually hit the recursion if we have enough Error() calls inside Parse...
- - recursionLevel ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : SetDefaultText
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDeclLocal : : SetDefaultText ( )
{
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : DefaultDefinition
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const char * idDeclLocal : : DefaultDefinition ( ) const
{
2012-11-26 18:58:24 +00:00
return " { } " ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : Parse
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDeclLocal : : Parse ( const char * text , const int textLength , bool allowBinaryVersion )
{
2012-11-26 18:58:24 +00:00
idLexer src ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
src . LoadMemory ( text , textLength , GetFileName ( ) , GetLineNum ( ) ) ;
src . SetFlags ( DECL_LEXER_FLAGS ) ;
src . SkipUntilString ( " { " ) ;
src . SkipBracedSection ( false ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : FreeData
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : FreeData ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : List
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : List ( ) const
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " %s \n " , GetName ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : Print
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : Print ( ) const
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : Reload
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : Reload ( )
{
2012-11-26 18:58:24 +00:00
this - > sourceFile - > Reload ( false ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : AllocateSelf
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : AllocateSelf ( )
{
if ( self = = NULL )
{
self = declManagerLocal . GetDeclType ( ( int ) type ) - > allocator ( ) ;
2012-11-26 18:58:24 +00:00
self - > base = this ;
}
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : ParseLocal
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : ParseLocal ( )
{
2012-11-26 18:58:24 +00:00
bool generatedDefaultText = false ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
AllocateSelf ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// always free data before parsing
self - > FreeData ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
declManagerLocal . MediaPrint ( " parsing %s %s \n " , declManagerLocal . declTypes [ type ] - > typeName . c_str ( ) , name . c_str ( ) ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// if no text source try to generate default text
2012-11-28 15:47:07 +00:00
if ( textSource = = NULL )
{
2012-11-26 18:58:24 +00:00
generatedDefaultText = self - > SetDefaultText ( ) ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// indent for DEFAULTED or media file references
declManagerLocal . indent + + ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// no text immediately causes a MakeDefault()
2012-11-28 15:47:07 +00:00
if ( textSource = = NULL )
{
2012-11-26 18:58:24 +00:00
MakeDefault ( ) ;
declManagerLocal . indent - - ;
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
declState = DS_PARSED ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// parse
2012-11-28 15:47:07 +00:00
char * declText = ( char * ) _alloca ( ( GetTextLength ( ) + 1 ) * sizeof ( char ) ) ;
2012-11-26 18:58:24 +00:00
GetText ( declText ) ;
self - > Parse ( declText , GetTextLength ( ) , true ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// free generated text
2012-11-28 15:47:07 +00:00
if ( generatedDefaultText )
{
2012-11-26 18:58:24 +00:00
Mem_Free ( textSource ) ;
textSource = NULL ;
textLength = 0 ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
declManagerLocal . indent - - ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : Purge
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idDeclLocal : : Purge ( )
{
2012-11-26 18:58:24 +00:00
// never purge things that were referenced outside level load,
// like the console and menu graphics
2012-11-28 15:47:07 +00:00
if ( parsedOutsideLevelLoad )
{
2012-11-26 18:58:24 +00:00
return ;
}
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
referencedThisLevel = false ;
MakeDefault ( ) ;
2019-11-11 19:27:44 +00:00
2012-11-26 18:58:24 +00:00
// the next Find() for this will re-parse the real data
declState = DS_UNPARSED ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclLocal : : EverReferenced
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idDeclLocal : : EverReferenced ( ) const
{
2012-11-26 18:58:24 +00:00
return everReferenced ;
2012-12-11 22:04:53 +00:00
}