]> icculus.org git repositories - divverent/nexuiz.git/blob - data/source/system/isframe.qc
restructure
[divverent/nexuiz.git] / data / source / system / isframe.qc
1 // DP/Nex Menu
2 // system/isframe.qc
3
4 void() Menu_Init =
5 {
6         //registercvar("menu_reloadlist","0");
7
8         Sys_Debug_Init();
9         // do one frame to make it possible to debug the parser
10         Sys_Debug_Frame();
11
12         Menu_InitGarbageStats();
13         Menu_Load();
14 };
15
16 void() Menu_Load =
17 {
18         Parser_ParseMenu( MENU_MAINFILE, MENU_PLUGINDIR );
19
20         Menu_LinkWindows();
21 };
22
23 // the good thing is, finddef doesnt fuck up any chain lists
24 entity(entity pStart, .string pFind1, string pMatch, .float pFind2, float pMatch2) finddef =
25 {
26         while( 1 ) {
27                 pStart = findstring( pStart, pFind1, pMatch );
28                 if( pStart == null_entity )
29                         break;
30                 if( pStart.pFind2 == pMatch2 )
31                         break;
32         }
33
34         return pStart;
35 };
36
37 void( entity pParent ) Menu_LinkChildren =
38 {
39         local entity lChild;
40         local float  lOrder;
41         local entity lPrevious;
42
43         // build a list of all children
44         lChild = findchainstring( parent, pParent.name );
45         if( lChild == null_entity )
46                 return;
47
48         // inverse the chain
49         lPrevious = null_entity;
50         while( lChild ) {
51                 local entity lNext;
52
53                 lNext = lChild.chain;
54                 lChild.chain = lPrevious;
55                 lPrevious = lChild;
56                 lChild = lNext;
57         }
58         lChild = lPrevious;
59
60         lOrder = 1; // we start with orderPos 1 (0 is auto-set)
61         lPrevious = null_entity;
62         while( lChild ) {
63                 local entity lOverwrite;
64                 // try to find an item that has the current orderPos set
65                 lOverwrite = finddef( null_entity, parent, pParent.name, orderPos, lOrder );
66                 if( lOverwrite == lChild )
67                         lChild.orderPos = lOrder;
68                 else if( lOverwrite ) {
69                         // insert lOverwrite in front of lChild
70                         local entity lOPrevious;
71
72                         lOPrevious = findentity( null_entity, chain, lOverwrite );
73                         lOPrevious.chain = lOverwrite.chain;
74                         lOverwrite.chain = lChild;
75                         lChild = lOverwrite;
76                 } else
77                         lChild.orderPos = 0 - lOrder; //INFO: HACK: tell Spike
78
79                 // link it
80                 if( lPrevious )
81                         lPrevious._next = lChild;
82                 else
83                         pParent._child = lChild;
84                 lChild._prev = lPrevious;
85                 lChild._parent = pParent;
86
87                 lPrevious = lChild;
88                 lChild = lChild.chain;
89                 lOrder++;
90         }
91         lPrevious._next = null_entity;
92 };
93
94 void() Menu_LinkWindows =
95 {
96         // first verify that MENU_NORMAL_NAME and MENU_INGAME_NAME exist
97         // if not add the default strings
98         local entity lEntity;
99
100         dprint( "Loading defaults if necessary\n" );
101
102         lEntity = findstring( null_entity, name, MENU_NORMAL_NAME );
103         if( lEntity == null_entity )
104                 loadfromdata( MENU_NORMAL_DEFAULT );
105
106         // verify again if MENU_NORMAL_NAME is there now
107         lEntity = findstring( null_entity, name, MENU_NORMAL_NAME );
108         if( lEntity == null_entity )
109                 error( "Bad MENU_NORMAL_DEFAULT!\n" );
110
111         lEntity = findstring( null_entity, name, MENU_INGAME_NAME );
112         if( lEntity == null_entity )
113                 loadfromdata( MENU_INGAME_DEFAULT );
114
115         // verify again if MENU_INGAME_NAME is there now
116         lEntity = findstring( null_entity, name, MENU_INGAME_NAME );
117         if( lEntity == null_entity )
118                 error( "Bad MENU_INGAME_DEFAULT!\n" );
119
120         dprint( "Verifying that every name is used only once\n" );
121
122         // verify that every name is only used *once*
123         lEntity = null_entity;
124         while( ( lEntity = nextent( lEntity ) ) != null_entity ) {
125                 self = lEntity;
126                 while( ( self = findstring( self, name, lEntity.name ) ) != null_entity )
127                         if( self != null_entity )
128                                 objerror( "Name ", lEntity.name, " already used!\n" );
129         }
130
131         dprint( "Verification of: name, type and parent fields\n" );
132
133         // now we have to :
134         // set the parent field with parent_name
135         // check the type field
136         self = null_entity;
137         while( ( self = nextent( self ) ) != null_entity ) {
138                 if( self.name == "" ) {
139                         objerror( "Name is missing!\n" );
140                         continue;
141                 }
142
143                 if( self.type == "" ) {
144                         objerror( "Type is missing!\n" );
145                         continue;
146                 }
147
148                 if( !isfunction( strcat( self.type, "_Spawn" ) ) ) {
149                         objerror( "Control ", self.type, " not found!\n" );
150                         continue;
151                 }
152
153                 // find parent
154                 // if parent_name is "" do nothing else check whether the parent exists
155                 if( self.parent != "" ) {
156                         lEntity = findstring( null_entity, name, self.parent );
157
158                         if( lEntity == null_entity ) {
159                                 objerror( "Item ", self.parent, " not found!\n" );
160                                 continue;
161                         }
162                 }
163                 else
164                         self._parent = null_entity;
165         }
166
167         dprint( "Building the child lists\n" );
168         // call LinkChildren for all entities
169         lEntity = null_entity;
170         while( ( lEntity = nextent( lEntity ) ) != null_entity )
171                 Menu_LinkChildren( lEntity );
172
173         dprint( "Calling the type functions\n" );
174
175         // call the type functions (former classname functions)
176         lEntity = null_entity;
177         while( ( lEntity = nextent( lEntity ) ) != null_entity ) {
178                 self = lEntity;
179                 //dprint("Calling ",self.type," (", etos(self),")\n");
180                 if( !Menu_HasFlag( self, FLAG_TEMPLATE ) && !Menu_HasRunFlag( self, RUNFLAG_SPAWNED ) ) {
181                         //print( lEntity.name, "\n" );
182                         callfunction( strcat( self.type, "_Spawn" ) );
183                         self._runFlag = self._runFlag | RUNFLAG_SPAWNED;
184                 } //else
185                         //print( "X ", lEntity.name, "\n" );
186         }
187
188         dprint( "Linking windows finished.\n" );
189 };
190
191 void( entity pItem ) Menu_LinkItem =
192 {
193         local entity lEntity;
194         local entity lOldSelf;
195
196         if( Menu_HasRunFlag( pItem, RUNFLAG_SPAWNED ) )
197                 return;
198
199         // verify the type
200         if( pItem.type == "" )
201                 error( "LinkItem: Type is missing (", etos( pItem ), ")!\n" );
202
203         if( !isfunction( strcat( pItem.type, "_Spawn" ) ) )
204                 error( "LinkItem: Control ", pItem.type, " not found (", etos( pItem ), ")!\n" );
205
206         // verify name and parent
207         lEntity = null_entity;
208         while( (lEntity = findstring( lEntity, name, pItem.name )) != null_entity )
209                 if( lEntity != pItem )
210                         error( "LinkItem: Name '", pItem.name, "' already in use (", etos( pItem ), ", ", etos( lEntity ), ")!" );
211
212         if( pItem.parent != "" ) {
213                 pItem._parent = findstring( null_entity, name, pItem.parent );
214
215                 if( !pItem._parent  )
216                         error( "LinkItem: Couldnt find parent '", pItem.parent, "' (", etos( pItem ), ")!" );
217         } else
218                 pItem._parent = null_entity;
219
220         // Add the children
221         Menu_LinkChildren( pItem );
222
223         // link children
224         for( lEntity = pItem._child ; lEntity ; lEntity = lEntity._next )
225                 Menu_LinkItem( lEntity );
226
227         // call the spawn function
228         lOldSelf = self;
229         self = pItem;
230         if( !Menu_HasFlag( self, FLAG_TEMPLATE ) ) {
231                 callfunction( strcat( self.type, "_Spawn" ) );
232                 self._runFlag = self._runFlag | RUNFLAG_SPAWNED;
233         }
234         self = lOldSelf;
235 };
236
237 void() Menu_Hide =
238 {
239         Raise_Select( Menu_ActiveItem, false, false );
240         Menu_CollectGarbage( true );
241         Menu_ResetGarbageStats();
242 };
243
244 void() Menu_PerformReinit =
245 {
246         // clear history
247         Menu_History_Clear();
248
249         // reset the key hook (if necessary at all)
250         Menu_KeyHook = Util_NullFunction;
251
252         // choose which menu to display
253         if( MENU_ALLOWINGAME && ( gamestatus & GAME_CONNECTED ) )
254                 Menu_ActiveWindow = findstring( null_entity, name, MENU_INGAME_NAME );
255         else
256                 Menu_ActiveWindow = findstring( null_entity, name, MENU_NORMAL_NAME );
257
258         // and reinit all menu items
259         self = null_entity;
260         while( (self = nextent( self ) ) != null_entity ) {
261                 if( self.parent == "" )
262                         self._parent = null_entity;
263                 //else actually this shouldnt happen
264                 else if( self._parent.name != self.parent )
265                         objerror( "Parent (should be ", self.parent, ") of menu item ", self.name, " changed to ", self._parent.name, " !\n" );
266
267                 Raise_Reinit( self ); // always call reinit
268         }
269
270         // run one runflag frame to (re)init the runflags
271         Menu_UpdateRunFlags();
272
273         Menu_Reselect( false );
274 };
275
276 void() Menu_Shutdown =
277 {
278         // call the terminate event for each object
279         self = null_entity;
280         while( ( self = nextent( self ) ) != null_entity )
281                 Raise_Destroy( self );
282 };
283
284 entity( string pType, string pName, string pParent ) Menu_CreateItem =
285 {
286         local entity lItem;
287
288         if( !pType )
289                 error( "Bad pType '", pType, "'!" );
290         if( !pName )
291                 error( "Bad pName '", pName, "'!" );
292
293         lItem = spawn();
294         parseentitydata( lItem, strcat( "{ type \"", pType, "\" name \"", strcat( pParent, "::", pName ), "\" parent \"", pParent, "\" }" ) );
295         return lItem;
296 };
297
298 entity( entity pTemplate, string pName, string pParent, bool pTree ) Menu_DeriveItem =
299 {
300         local entity lItem;
301         local entity lChild;
302
303         if( !pTemplate )
304                 error( "Null pTemplate!" );
305         if( !pName )
306                 error( "Bad pName '", pName, "'!" );
307
308         lItem = spawn();
309         copyentity( pTemplate, lItem );
310         if( lItem.flag & FLAG_TEMPLATE )
311                 lItem.flag = lItem.flag - FLAG_TEMPLATE;
312         if( lItem._runFlag & RUNFLAG_SPAWNED )
313                 lItem._runFlag = lItem._runFlag - RUNFLAG_SPAWNED;
314         parseentitydata( lItem, strcat( "{ name \"", strcat( pParent, "::", pName ), "\" parent \"", pParent, "\" }" ) );
315
316         if( pTree )
317                 for( lChild = pTemplate._child ; lChild ; lChild = lChild._next ) {
318                         local string lName;
319                         lName = String_Zone( substring( lChild.name, strlen( lChild.parent ) + 2, 100000 ) );
320                         Menu_DeriveItem( lChild, lName, lItem.name, true );
321                         String_Free( lName );
322                 }
323
324         return lItem;
325 };
326
327 void( entity pItem, string pData ) Menu_AddEntityData =
328 {
329         parseentitydata( pItem, pData );
330 };
331
332 void( entity pWindow ) Menu_LinkWindow =
333 {
334         Menu_LinkItem( pWindow );
335 };