2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/editor/editmode.c,v 1.73 2000/02/19 13:10:34 toml Exp $
60 // stuff for camera synch
66 // So that we can know whether we're switching into a cDarkPanel
67 // This wants to be handled *some* other way in the long run:
68 // #include <drkpanid.h>
72 #include <dbmem.h> // must be last header!
74 // convienience, since doug is lazy, and gedit.h uses vectors and stuff
75 // these are in gedit.h, but i dont want to need editbr and such in editmode
76 extern void gedit_enter(void), gedit_exit(void);
78 extern void UpdateMenuCheckmarks(void);
80 ////////////////////////////////////////
81 // LOOPMODE DESCRIPTOR
85 // Here is the list of the loop clients that this mode uses.
86 // Most clients are implemented in fooloop.c
89 static bool (*inpbnd_handler
)(uiEvent
*, Region
*, void *);
91 #define GAMESPEC_RESERVED_CLIENT 0
93 static tLoopClientID
* _Clients
[] =
95 &GUID_NULL
, // reserved for gamespec
108 // Here's the actual loopmode descriptor
109 // It gets added to the loop manager in loopapp.c
112 sLoopModeDesc EditLoopMode
=
114 { &LOOPID_EditMode
, "Edit mode"},
116 sizeof(_Clients
)/sizeof(_Clients
[0]),
119 ////////////////////////////////////////
120 // CONTEXT FOR LOOPMODE
123 // context for scrnman client
124 static sScrnMode scrnmode
=
126 kScrnModeDimsValid
|kScrnModeBitDepthValid
|kScrnModeFlagsValid
,
132 static ScrnManContext _scrndata
=
137 // context for ui client
138 static uiLoopContext _uidata
=
143 // context for resource sys client
144 static ResLoopContext _resdata
=
147 "editor.res", // a list of files to open
151 static sLoopModeInitParm _EditContext
[] =
153 { &LOOPID_ScrnMan
, (tLoopClientData
)&_scrndata
},
154 { &LOOPID_UI
, (tLoopClientData
)&_uidata
},
155 { &LOOPID_Res
, (tLoopClientData
)&_resdata
},
156 { &LOOPID_EditGeom
, (tLoopClientData
)1}, // listen to frame events.
158 { NULL
, } // terminator
161 ////////////////////////////////////////////////////////////
162 // GAME SPEC CLIENT INSTALLATION
164 void EditModeSetGameSpecClient(const GUID
* ID
)
166 _Clients
[GAMESPEC_RESERVED_CLIENT
] = ID
;
170 ////////////////////////////////////////
174 static sLoopInstantiator _instantiator
=
182 // This function fills out and returns the instantiator for this mode, based on
183 // an "edit mode descriptor structure." The point of this is to hide the list
184 // of loop clients behind the "edit mode" abstraction barrier. So a system
185 // that wants to change to edit mode doesn't need to know which loop client the
186 // mode uses to keep track of screen res, etc.
189 sLoopInstantiator
* DescribeEditMode(EditMinorMode minorMode
, EditModeDesc
* desc
)
191 if (minorMode
!= mmEditNoChange
)
193 _instantiator
.minorMode
= minorMode
;
198 ScrnModeCopy(&scrnmode
,desc
->scrnmode
,kScrnModeAllValid
);
201 return &_instantiator
;
208 /////////////////////////////////////////////////////////////
209 // EDITOR LOOP CLIENT
210 ////////////////////////////////////////////////////////////
212 // this is a generic loop client for all sorts of stuff that only happens in editor
213 // mode and doesn't quite merit its own loop client.
215 // This client has no context data. If it did, this type would not be void.
216 // Your client could have any type it wants.
217 typedef void Context
;
219 // The client stores all its state here, plus a pointer to its context.
220 // This client happens to have no state.
222 typedef struct _StateRecord
230 ////////////////////////////////////////
231 // Database message handler
234 static void synch_edit_camera(void)
236 // actually write the current camera pos back into the editor spotlight
239 Camera
* player_cam
= PlayerCamera();
240 if (vm_spotlight_loc(&plypos
,&plyang
))
241 CameraGetLocation(player_cam
, plypos
, plyang
);
244 static void db_message(DispatchData
* msg
)
246 msgDatabaseData data
;
247 data
.raw
= msg
->data
;
248 switch (DB_MSG(msg
->subtype
))
251 GFHSetCurrentBrush(NULL
);
253 case kDatabasePostLoad
:
254 if ((msg
->subtype
& (kObjPartConcrete
|kObjPartBriefcase
)) == kObjPartConcrete
)
255 if (!BackupLoading())
258 if (!(msg
->subtype
& kFiletypeAll
))
262 case kDatabaseDefault
:
272 ----------------------------------------
273 Processes keys sent from input binder
274 ----------------------------------------
276 static char *ProcessEditKey (char *cmd
, char *val
, BOOL already_down
)
278 return CommandExecute (cmd
);
279 }//end ProcessEditKey ()
282 ////////////////////////////////////////
284 // LOOP/DISPATCH callback
285 // Here's where we do the dirty work.
288 #pragma off(unreferenced)
289 static eLoopMessageResult LGAPI
_LoopFunc(void* data
, eLoopMessage msg
, tLoopMessageData hdata
)
292 Region
* root
= GetRootRegion();
293 // useful stuff for most clients
294 eLoopMessageResult result
= kLoopDispatchContinue
;
295 StateRecord
* state
= (StateRecord
*)data
;
298 // our specific stuff
299 struct tm time_of_day
;
301 static bool once
= FALSE
;
309 pal_update(); // set the palette
312 state
->first_frame
= TRUE
;
313 state
->in_mode
= TRUE
;
315 //input binding stuff
316 g_pInputBinder
->lpVtbl
->GetHandler (g_pInputBinder
, &inpbnd_handler
);
317 uiInstallRegionHandler (root
, UI_EVENT_KBD_COOKED
, inpbnd_handler
, NULL
, &cookie
);
318 g_pInputBinder
->lpVtbl
->SetMasterProcessCallback (g_pInputBinder
, ProcessEditKey
);
319 g_pInputBinder
->lpVtbl
->SetContext (g_pInputBinder
, HK_BRUSH_EDIT
, TRUE
);
320 HotkeyContext
= HK_BRUSH_EDIT
;
324 if (config_is_defined("editorcam_from_game"))
327 UpdateMenuCheckmarks();
328 state
->from_game
= IsEqualGUID(info
.mode
->from
.pID
,&LOOPID_GameMode
);
330 if (state
->from_game
)
332 ISimManager
* pSimMan
= AppGetObj(ISimManager
);
333 ISimManager_SuspendSim(pSimMan
);
334 SafeRelease(pSimMan
);
337 ParticleGroupEnterMode();
344 case kMsgSuspendMode
:
345 state
->in_mode
= FALSE
;
346 ParticleGroupExitMode();
353 // Determine if we're going into game mode...
354 if (IsEqualGUID(info
.mode
->to
.pID
,&LOOPID_GameMode
) ||
355 GameToolIsToGameModeGUID(info
.mode
->to
.pID
))
357 ISimManager
* pSimMan
= AppGetObj(ISimManager
);
358 sDispatchMsg msg
= { kSimInit
};
361 SaveBrushSelection();
363 ISimManager_StartSim(pSimMan
);
364 SafeRelease(pSimMan
);
371 InitDrawnRelations();
375 TermDrawnRelations();
382 case kMsgNormalFrame
:
384 memcpy(&time_of_day
, localtime(<ime
), sizeof(struct tm
));
385 StatusField(SF_TIME
,asctime(&time_of_day
));
387 GFHUpdate(GFH_FRAME
);
389 MotEditUpdate(info
.frame
->dTicks
);
391 if (state
->first_frame
)
394 process_config_scripts("edit_script");
396 process_config_scripts("edit_always_script");
398 if (state
->from_game
)
400 RestoreMissionBackup();
401 RemoveMissionBackup();
402 RestoreBrushSelection();
405 state
->first_frame
= FALSE
;
412 uieditStyleSetup(); // recompute the guiStyle
415 StatusDrawStringAll();
419 db_message(info
.dispatch
);
426 // Loop client factory function.
429 #pragma off(unreferenced)
430 static ILoopClient
* LGAPI
_CreateClient(sLoopClientDesc
* pDesc
, tLoopClientData data
)
433 // allocate space for our state, and fill out the fields
434 state
= Malloc(sizeof(StateRecord
));
435 memset(state
,0,sizeof(*state
));
436 state
->context
= (Context
*)data
;
438 return CreateSimpleLoopClient(_LoopFunc
,state
,&EditorLoopClientDesc
);
440 #pragma on(unreferenced)
443 // The loop client descriptor
446 sLoopClientDesc EditorLoopClientDesc
=
448 &LOOPID_Editor
, // client's guid
449 "Editor client", // string name
450 kPriorityNormal
, // priority
451 kMsgEnd
| kMsgsMode
| kMsgsFrame
| kMsgVisual
| kMsgDatabase
| kMsgsAppOuter
, // messages we want
459 { kConstrainAfter
, &LOOPID_ScrnMan
, kMsgsMode
},
460 { kConstrainAfter
, &LOOPID_UI
, kMsgsMode
},
461 { kConstrainAfter
, &LOOPID_Res
, kMsgsMode
},
462 { kConstrainAfter
, &LOOPID_EditGeom
, kMsgsMode
},
464 { kConstrainAfter
, &LOOPID_Player
, kMsgDatabase
},
465 { kConstrainBefore
, &LOOPID_ScrnMan
, kMsgVisual
},
467 // { kConstrainAfter, &LOOPID_People, kMsgsMode},
472 ////////////////////////////////////////////////////////////
473 // Command: edit_mode w,h
474 // Change to edit mode. w,h are screen dims
477 void enter_edit_mode(char* args
)
480 EditModeDesc
* desc
= &adesc
;
481 sScrnMode scrnmode
= { 0 };
484 desc
->scrnmode
= &scrnmode
;
486 sscanf(args
,"%d,%d",&w
,&h
);
487 if (w
!= 0 && h
!= 0)
489 scrnmode
.valid_fields
|= kScrnModeDimsValid
;
495 ILoop
* looper
= AppGetObj(ILoop
);
496 sLoopInstantiator
* loop
;
498 loop
= DescribeEditMode(mmEditNoChange
,desc
);
499 ILoop_ChangeMode(looper
,kLoopModeSwitch
,loop
);