1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 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 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 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.
25 
26 ===========================================================================
27 */
28 
29 #ifndef __DECLMANAGER_H__
30 #define __DECLMANAGER_H__
31 
32 #include "idlib/Lexer.h"
33 
34 class idFile;
35 
36 /*
37 ===============================================================================
38 
39 	Declaration Manager
40 
41 	All "small text" data types, like materials, sound shaders, fx files,
42 	entity defs, etc. are managed uniformly, allowing reloading, purging,
43 	listing, printing, etc. All "large text" data types that never have more
44 	than one declaration in a given file, like maps, models, AAS files, etc.
45 	are not handled here.
46 
47 	A decl will never, ever go away once it is created. The manager is
48 	garranteed to always return the same decl pointer for a decl type/name
49 	combination. The index of a decl in the per type list also stays the
50 	same throughout the lifetime of the engine. Although the pointer to
51 	a decl always stays the same, one should never maintain pointers to
52 	data inside decls. The data stored in a decl is not garranteed to stay
53 	the same for more than one engine frame.
54 
55 	The decl indexes of explicitely defined decls are garrenteed to be
56 	consistent based on the parsed decl files. However, the indexes of
57 	implicit decls may be different based on the order in which levels
58 	are loaded.
59 
60 	The decl namespaces are separate for each type. Comments for decls go
61 	above the text definition to keep them associated with the proper decl.
62 
63 	During decl parsing, errors should never be issued, only warnings
64 	followed by a call to MakeDefault().
65 
66 ===============================================================================
67 */
68 
69 typedef enum {
70 	DECL_TABLE				= 0,
71 	DECL_MATERIAL,
72 	DECL_SKIN,
73 	DECL_SOUND,
74 	DECL_ENTITYDEF,
75 	DECL_MODELDEF,
76 	DECL_FX,
77 	DECL_PARTICLE,
78 	DECL_AF,
79 	DECL_PDA,
80 	DECL_VIDEO,
81 	DECL_AUDIO,
82 	DECL_EMAIL,
83 	DECL_MODELEXPORT,
84 	DECL_MAPDEF,
85 
86 	// new decl types can be added here
87 
88 	DECL_MAX_TYPES			= 32
89 } declType_t;
90 
91 typedef enum {
92 	DS_UNPARSED,
93 	DS_DEFAULTED,			// set if a parse failed due to an error, or the lack of any source
94 	DS_PARSED
95 } declState_t;
96 
97 const int DECL_LEXER_FLAGS	=	LEXFL_NOSTRINGCONCAT |				// multiple strings seperated by whitespaces are not concatenated
98 								LEXFL_NOSTRINGESCAPECHARS |			// no escape characters inside strings
99 								LEXFL_ALLOWPATHNAMES |				// allow path seperators in names
100 								LEXFL_ALLOWMULTICHARLITERALS |		// allow multi character literals
101 								LEXFL_ALLOWBACKSLASHSTRINGCONCAT |	// allow multiple strings seperated by '\' to be concatenated
102 								LEXFL_NOFATALERRORS;				// just set a flag instead of fatal erroring
103 
104 
105 class idDeclBase {
106 public:
~idDeclBase()107 	virtual					~idDeclBase() {};
108 	virtual const char *	GetName( void ) const = 0;
109 	virtual declType_t		GetType( void ) const = 0;
110 	virtual declState_t		GetState( void ) const = 0;
111 	virtual bool			IsImplicit( void ) const = 0;
112 	virtual bool			IsValid( void ) const = 0;
113 	virtual void			Invalidate( void ) = 0;
114 	virtual void			Reload( void ) = 0;
115 	virtual void			EnsureNotPurged( void ) = 0;
116 	virtual int				Index( void ) const = 0;
117 	virtual int				GetLineNum( void ) const = 0;
118 	virtual const char *	GetFileName( void ) const = 0;
119 	virtual void			GetText( char *text ) const = 0;
120 	virtual int				GetTextLength( void ) const = 0;
121 	virtual void			SetText( const char *text ) = 0;
122 	virtual bool			ReplaceSourceFileText( void ) = 0;
123 	virtual bool			SourceFileChanged( void ) const = 0;
124 	virtual void			MakeDefault( void ) = 0;
125 	virtual bool			EverReferenced( void ) const = 0;
126 	virtual bool			SetDefaultText( void ) = 0;
127 	virtual const char *	DefaultDefinition( void ) const = 0;
128 	virtual bool			Parse( const char *text, const int textLength ) = 0;
129 	virtual void			FreeData( void ) = 0;
130 	virtual size_t			Size( void ) const = 0;
131 	virtual void			List( void ) const = 0;
132 	virtual void			Print( void ) const = 0;
133 };
134 
135 
136 class idDecl {
137 public:
138 							// The constructor should initialize variables such that
139 							// an immediate call to FreeData() does no harm.
idDecl(void)140 							idDecl( void ) { base = NULL; }
~idDecl(void)141 	virtual					~idDecl( void ) {};
142 
143 							// Returns the name of the decl.
GetName(void)144 	const char *			GetName( void ) const { return base->GetName(); }
145 
146 							// Returns the decl type.
GetType(void)147 	declType_t				GetType( void ) const { return base->GetType(); }
148 
149 							// Returns the decl state which is usefull for finding out if a decl defaulted.
GetState(void)150 	declState_t				GetState( void ) const { return base->GetState(); }
151 
152 							// Returns true if the decl was defaulted or the text was created with a call to SetDefaultText.
IsImplicit(void)153 	bool					IsImplicit( void ) const { return base->IsImplicit(); }
154 
155 							// The only way non-manager code can have an invalid decl is if the *ByIndex()
156 							// call was used with forceParse = false to walk the lists to look at names
157 							// without touching the media.
IsValid(void)158 	bool					IsValid( void ) const { return base->IsValid(); }
159 
160 							// Sets state back to unparsed.
161 							// Used by decl editors to undo any changes to the decl.
Invalidate(void)162 	void					Invalidate( void ) { base->Invalidate(); }
163 
164 							// if a pointer might possible be stale from a previous level,
165 							// call this to have it re-parsed
EnsureNotPurged(void)166 	void					EnsureNotPurged( void ) { base->EnsureNotPurged(); }
167 
168 							// Returns the index in the per-type list.
Index(void)169 	int						Index( void ) const { return base->Index(); }
170 
171 							// Returns the line number the decl starts.
GetLineNum(void)172 	int						GetLineNum( void ) const { return base->GetLineNum(); }
173 
174 							// Returns the name of the file in which the decl is defined.
GetFileName(void)175 	const char *			GetFileName( void ) const { return base->GetFileName(); }
176 
177 							// Returns the decl text.
GetText(char * text)178 	void					GetText( char *text ) const { base->GetText( text ); }
179 
180 							// Returns the length of the decl text.
GetTextLength(void)181 	int						GetTextLength( void ) const { return base->GetTextLength(); }
182 
183 							// Sets new decl text.
SetText(const char * text)184 	void					SetText( const char *text ) { base->SetText( text ); }
185 
186 							// Saves out new text for the decl.
187 							// Used by decl editors to replace the decl text in the source file.
ReplaceSourceFileText(void)188 	bool					ReplaceSourceFileText( void ) { return base->ReplaceSourceFileText(); }
189 
190 							// Returns true if the source file changed since it was loaded and parsed.
SourceFileChanged(void)191 	bool					SourceFileChanged( void ) const { return base->SourceFileChanged(); }
192 
193 							// Frees data and makes the decl a default.
MakeDefault(void)194 	void					MakeDefault( void ) { base->MakeDefault(); }
195 
196 							// Returns true if the decl was ever referenced.
EverReferenced(void)197 	bool					EverReferenced( void ) const { return base->EverReferenced(); }
198 
199 public:
200 							// Sets textSource to a default text if necessary.
201 							// This may be overridden to provide a default definition based on the
202 							// decl name. For instance materials may default to an implicit definition
203 							// using a texture with the same name as the decl.
SetDefaultText(void)204 	virtual bool			SetDefaultText( void ) { return base->SetDefaultText(); }
205 
206 							// Each declaration type must have a default string that it is guaranteed
207 							// to parse acceptably. When a decl is not explicitly found, is purged, or
208 							// has an error while parsing, MakeDefault() will do a FreeData(), then a
209 							// Parse() with DefaultDefinition(). The defaultDefintion should start with
210 							// an open brace and end with a close brace.
DefaultDefinition(void)211 	virtual const char *	DefaultDefinition( void ) const { return base->DefaultDefinition(); }
212 
213 							// The manager will have already parsed past the type, name and opening brace.
214 							// All necessary media will be touched before return.
215 							// The manager will have called FreeData() before issuing a Parse().
216 							// The subclass can call MakeDefault() internally at any point if
217 							// there are parse errors.
Parse(const char * text,const int textLength)218 	virtual bool			Parse( const char *text, const int textLength ) { return base->Parse( text, textLength ); }
219 
220 							// Frees any pointers held by the subclass. This may be called before
221 							// any Parse(), so the constructor must have set sane values. The decl will be
222 							// invalid after issuing this call, but it will always be immediately followed
223 							// by a Parse()
FreeData(void)224 	virtual void			FreeData( void ) { base->FreeData(); }
225 
226 							// Returns the size of the decl in memory.
Size(void)227 	virtual size_t			Size( void ) const { return base->Size(); }
228 
229 							// If this isn't overridden, it will just print the decl name.
230 							// The manager will have printed 7 characters on the line already,
231 							// containing the reference state and index number.
List(void)232 	virtual void			List( void ) const { base->List(); }
233 
234 							// The print function will already have dumped the text source
235 							// and common data, subclasses can override this to dump more
236 							// explicit data.
Print(void)237 	virtual void			Print( void ) const { base->Print(); }
238 
239 public:
240 	idDeclBase *			base;
241 };
242 
243 
244 template< class type >
idDeclAllocator(void)245 ID_INLINE idDecl *idDeclAllocator( void ) {
246 	return new type;
247 }
248 
249 
250 class idMaterial;
251 class idDeclSkin;
252 class idSoundShader;
253 
254 class idDeclManager {
255 public:
~idDeclManager(void)256 	virtual					~idDeclManager( void ) {}
257 
258 	virtual void			Init( void ) = 0;
259 	virtual void			Shutdown( void ) = 0;
260 	virtual void			Reload( bool force ) = 0;
261 
262 	virtual void			BeginLevelLoad() = 0;
263 	virtual void			EndLevelLoad() = 0;
264 
265 							// Registers a new decl type.
266 	virtual void			RegisterDeclType( const char *typeName, declType_t type, idDecl *(*allocator)( void ) ) = 0;
267 
268 							// Registers a new folder with decl files.
269 	virtual void			RegisterDeclFolder( const char *folder, const char *extension, declType_t defaultType ) = 0;
270 
271 							// Returns a checksum for all loaded decl text.
272 	virtual int				GetChecksum( void ) const = 0;
273 
274 							// Returns the number of decl types.
275 	virtual int				GetNumDeclTypes( void ) const = 0;
276 
277 							// Returns the type name for a decl type.
278 	virtual const char *	GetDeclNameFromType( declType_t type ) const = 0;
279 
280 							// Returns the decl type for a type name.
281 	virtual declType_t		GetDeclTypeFromName( const char *typeName ) const = 0;
282 
283 							// If makeDefault is true, a default decl of appropriate type will be created
284 							// if an explicit one isn't found. If makeDefault is false, NULL will be returned
285 							// if the decl wasn't explcitly defined.
286 	virtual const idDecl *	FindType( declType_t type, const char *name, bool makeDefault = true ) = 0;
287 
288 	virtual const idDecl*	FindDeclWithoutParsing( declType_t type, const char *name, bool makeDefault = true ) = 0;
289 
290 	virtual void			ReloadFile( const char* filename, bool force ) = 0;
291 
292 							// Returns the number of decls of the given type.
293 	virtual int				GetNumDecls( declType_t type ) = 0;
294 
295 							// The complete lists of decls can be walked to populate editor browsers.
296 							// If forceParse is set false, you can get the decl to check name / filename / etc.
297 							// without causing it to parse the source and load media.
298 	virtual const idDecl *	DeclByIndex( declType_t type, int index, bool forceParse = true ) = 0;
299 
300 							// List and print decls.
301 	virtual void			ListType( const idCmdArgs &args, declType_t type ) = 0;
302 	virtual void			PrintType( const idCmdArgs &args, declType_t type ) = 0;
303 
304 							// Creates a new default decl of the given type with the given name in
305 							// the given file used by editors to create a new decls.
306 	virtual idDecl *		CreateNewDecl( declType_t type, const char *name, const char *fileName ) = 0;
307 
308 							// BSM - Added for the material editors rename capabilities
309 	virtual bool			RenameDecl( declType_t type, const char* oldName, const char* newName ) = 0;
310 
311 							// When media files are loaded, a reference line can be printed at a
312 							// proper indentation if decl_show is set
313 	virtual void			MediaPrint( const char *fmt, ... ) id_attribute((format(printf,2,3))) = 0;
314 
315 	virtual void			WritePrecacheCommands( idFile *f ) = 0;
316 
317 									// Convenience functions for specific types.
318 	virtual	const idMaterial *		FindMaterial( const char *name, bool makeDefault = true ) = 0;
319 	virtual const idDeclSkin *		FindSkin( const char *name, bool makeDefault = true ) = 0;
320 	virtual const idSoundShader *	FindSound( const char *name, bool makeDefault = true ) = 0;
321 
322 	virtual const idMaterial *		MaterialByIndex( int index, bool forceParse = true ) = 0;
323 	virtual const idDeclSkin *		SkinByIndex( int index, bool forceParse = true ) = 0;
324 	virtual const idSoundShader *	SoundByIndex( int index, bool forceParse = true ) = 0;
325 };
326 
327 extern idDeclManager *		declManager;
328 
329 
330 template< declType_t type >
idListDecls_f(const idCmdArgs & args)331 ID_INLINE void idListDecls_f( const idCmdArgs &args ) {
332 	declManager->ListType( args, type );
333 }
334 
335 template< declType_t type >
idPrintDecls_f(const idCmdArgs & args)336 ID_INLINE void idPrintDecls_f( const idCmdArgs &args ) {
337 	declManager->PrintType( args, type );
338 }
339 
340 #endif /* !__DECLMANAGER_H__ */
341