6 //registercvar("menu_reloadlist","0");
9 // do one frame to make it possible to debug the parser
12 Menu_InitGarbageStats();
18 Parser_ParseMenu( MENU_MAINFILE, MENU_PLUGINDIR );
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 =
27 pStart = findstring( pStart, pFind1, pMatch );
28 if( pStart == null_entity )
30 if( pStart.pFind2 == pMatch2 )
37 void( entity pParent ) Menu_LinkChildren =
41 local entity lPrevious;
43 // build a list of all children
44 lChild = findchainstring( parent, pParent.name );
45 if( lChild == null_entity )
49 lPrevious = null_entity;
54 lChild.chain = lPrevious;
60 lOrder = 1; // we start with orderPos 1 (0 is auto-set)
61 lPrevious = null_entity;
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;
72 lOPrevious = findentity( null_entity, chain, lOverwrite );
73 lOPrevious.chain = lOverwrite.chain;
74 lOverwrite.chain = lChild;
77 lChild.orderPos = 0 - lOrder; //INFO: HACK: tell Spike
81 lPrevious._next = lChild;
83 pParent._child = lChild;
84 lChild._prev = lPrevious;
85 lChild._parent = pParent;
88 lChild = lChild.chain;
91 lPrevious._next = null_entity;
94 void() Menu_LinkWindows =
96 // first verify that MENU_NORMAL_NAME and MENU_INGAME_NAME exist
97 // if not add the default strings
100 dprint( "Loading defaults if necessary\n" );
102 lEntity = findstring( null_entity, name, MENU_NORMAL_NAME );
103 if( lEntity == null_entity )
104 loadfromdata( MENU_NORMAL_DEFAULT );
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" );
111 lEntity = findstring( null_entity, name, MENU_INGAME_NAME );
112 if( lEntity == null_entity )
113 loadfromdata( MENU_INGAME_DEFAULT );
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" );
120 dprint( "Verifying that every name is used only once\n" );
122 // verify that every name is only used *once*
123 lEntity = null_entity;
124 while( ( lEntity = nextent( lEntity ) ) != null_entity ) {
126 while( ( self = findstring( self, name, lEntity.name ) ) != null_entity )
127 if( self != null_entity )
128 objerror( "Name ", lEntity.name, " already used!\n" );
131 dprint( "Verification of: name, type and parent fields\n" );
134 // set the parent field with parent_name
135 // check the type field
137 while( ( self = nextent( self ) ) != null_entity ) {
138 if( self.name == "" ) {
139 objerror( "Name is missing!\n" );
143 if( self.type == "" ) {
144 objerror( "Type is missing!\n" );
148 if( !isfunction( strcat( self.type, "_Spawn" ) ) ) {
149 objerror( "Control ", self.type, " not found!\n" );
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 );
158 if( lEntity == null_entity ) {
159 objerror( "Item ", self.parent, " not found!\n" );
164 self._parent = null_entity;
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 );
173 dprint( "Calling the type functions\n" );
175 // call the type functions (former classname functions)
176 lEntity = null_entity;
177 while( ( lEntity = nextent( lEntity ) ) != null_entity ) {
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;
185 //print( "X ", lEntity.name, "\n" );
188 dprint( "Linking windows finished.\n" );
191 void( entity pItem ) Menu_LinkItem =
193 local entity lEntity;
194 local entity lOldSelf;
196 if( Menu_HasRunFlag( pItem, RUNFLAG_SPAWNED ) )
200 if( pItem.type == "" )
201 error( "LinkItem: Type is missing (", etos( pItem ), ")!\n" );
203 if( !isfunction( strcat( pItem.type, "_Spawn" ) ) )
204 error( "LinkItem: Control ", pItem.type, " not found (", etos( pItem ), ")!\n" );
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 ), ")!" );
212 if( pItem.parent != "" ) {
213 pItem._parent = findstring( null_entity, name, pItem.parent );
216 error( "LinkItem: Couldnt find parent '", pItem.parent, "' (", etos( pItem ), ")!" );
218 pItem._parent = null_entity;
221 Menu_LinkChildren( pItem );
224 for( lEntity = pItem._child ; lEntity ; lEntity = lEntity._next )
225 Menu_LinkItem( lEntity );
227 // call the spawn function
230 if( !Menu_HasFlag( self, FLAG_TEMPLATE ) ) {
231 callfunction( strcat( self.type, "_Spawn" ) );
232 self._runFlag = self._runFlag | RUNFLAG_SPAWNED;
239 Raise_Select( Menu_ActiveItem, false, false );
240 Menu_CollectGarbage( true );
241 Menu_ResetGarbageStats();
244 void() Menu_PerformReinit =
247 Menu_History_Clear();
249 // reset the key hook (if necessary at all)
250 Menu_KeyHook = Util_NullFunction;
252 // choose which menu to display
253 if( MENU_ALLOWINGAME && ( gamestatus & GAME_CONNECTED ) )
254 Menu_ActiveWindow = findstring( null_entity, name, MENU_INGAME_NAME );
256 Menu_ActiveWindow = findstring( null_entity, name, MENU_NORMAL_NAME );
258 // and reinit all menu items
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" );
267 Raise_Reinit( self ); // always call reinit
270 // run one runflag frame to (re)init the runflags
271 Menu_UpdateRunFlags();
273 Menu_Reselect( false );
276 void() Menu_Shutdown =
278 // call the terminate event for each object
280 while( ( self = nextent( self ) ) != null_entity )
281 Raise_Destroy( self );
284 entity( string pType, string pName, string pParent ) Menu_CreateItem =
289 error( "Bad pType '", pType, "'!" );
291 error( "Bad pName '", pName, "'!" );
294 parseentitydata( lItem, strcat( "{ type \"", pType, "\" name \"", strcat( pParent, "::", pName ), "\" parent \"", pParent, "\" }" ) );
298 entity( entity pTemplate, string pName, string pParent, bool pTree ) Menu_DeriveItem =
304 error( "Null pTemplate!" );
306 error( "Bad pName '", pName, "'!" );
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, "\" }" ) );
317 for( lChild = pTemplate._child ; lChild ; lChild = lChild._next ) {
319 lName = String_Zone( substring( lChild.name, strlen( lChild.parent ) + 2, 100000 ) );
320 Menu_DeriveItem( lChild, lName, lItem.name, true );
321 String_Free( lName );
327 void( entity pItem, string pData ) Menu_AddEntityData =
329 parseentitydata( pItem, pData );
332 void( entity pWindow ) Menu_LinkWindow =
334 Menu_LinkItem( pWindow );