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