convert line ends
[canaan.git] / prj / cam / src / sim / doorprop.cpp
blob929500ffe29dd61a4e5324333dca7065193f8ef9
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 ///////////////////////////////////////////////////////////////////////////////
7 // $Header: r:/t2repos/thief2/src/sim/doorprop.cpp,v 1.23 2000/03/07 19:54:00 toml Exp $
8 //
9 //
11 #include <lg.h>
13 #include <objpos.h>
14 #include <matrix.h>
15 #include <osysbase.h>
17 #include <property.h>
18 #include <propbase.h>
19 #include <propert_.h>
20 #include <dataops_.h>
21 #include <propface.h>
22 #include <prophash.h>
23 #include <sdesbase.h>
24 #include <sdesc.h>
25 #include <simpwrap.h>
27 #include <physapi.h>
28 #include <phcore.h>
29 #include <phmods.h>
30 #include <phmod.h>
31 #include <doorprop.h>
32 #include <doorphys.h>
33 #include <phprop.h>
35 #include <objnotif.h>
37 // Must be last header
38 #include <dbmem.h>
40 ////////////////////////////////////////////////////////////////////////////////
42 IRotDoorProperty *g_pRotDoorProperty;
43 ITransDoorProperty *g_pTransDoorProperty;
45 ////////////////////////////////////////////////////////////////////////////////
47 sDoorProp *GetDoorProperty(int o_id)
49 sRotDoorProp *pRotDoorProp;
50 sTransDoorProp *pTransDoorProp;
52 if (g_pRotDoorProperty->Get(o_id, &pRotDoorProp))
53 return (sDoorProp *)pRotDoorProp;
55 if (g_pTransDoorProperty->Get(o_id, &pTransDoorProp))
56 return (sDoorProp *)pTransDoorProp;
58 return NULL;
61 ////////////////////////////////////////////////////////////////////////////////
63 // Constraints
64 static sPropertyConstraint door_constraints[] =
66 { kPropertyRequires, PHYS_TYPE_NAME },
67 { kPropertyNullConstraint }
70 ////////////////////////////////////////////////////////////////////////////////
72 // Rotating doors
75 // Description
76 static sPropertyDesc RotPropDesc =
78 PROP_ROTDOOR_NAME,
79 kPropertyNoInherit | kPropertyInstantiate,
80 door_constraints,
81 1, // version
82 0, // last ok version (0 means no other ok versions)
83 { "Door", "Rotating" },
84 kPropertyChangeLocally,
88 // Hey kids, lets get our own notify
90 typedef cGenericProperty<IRotDoorProperty,&IID_IRotDoorProperty, sRotDoorProp*> cRotDoorPropertyBase;
92 class cRotDoorProperty : public cRotDoorPropertyBase
94 cClassDataOps< sRotDoorProp> mOps;
96 public:
97 cRotDoorProperty(const sPropertyDesc* desc, IPropertyStore* store)
98 : cRotDoorPropertyBase(desc,store)
100 SetOps(&mOps);
103 cRotDoorProperty(const sPropertyDesc* desc, ePropertyImpl impl)
104 : cRotDoorPropertyBase(desc,NULL)
106 IPropertyStore* store = CreateGenericPropertyStore(impl);
107 SetStore(store);
108 SetOps(&mOps);
111 STDMETHOD_(void,Notify)(ePropertyNotifyMsg msg, PropNotifyData data)
113 switch(NOTIFY_MSG(msg))
115 case kObjNotifyPostLoad:
116 GenerateAllDoorRooms();
117 break;
119 cRotDoorPropertyBase::Notify(msg,data);
122 STANDARD_DESCRIBE_TYPE( sRotDoorProp);
125 ////////////////////////////////////////
127 static const char *pDoorStates[5] =
129 "Closed",
130 "Open",
131 "Closing",
132 "Opening",
133 "Halted",
136 static const char *pDoorAxes[3] =
138 "X-Axis",
139 "Y-Axis",
140 "Z-Axis",
143 static sFieldDesc RotDoorPropFields[] =
145 { "Closed Angle", kFieldTypeFloat, FieldLocation(sRotDoorProp, closed), kFieldFlagNone },
146 { "Open Angle", kFieldTypeFloat, FieldLocation(sRotDoorProp, open), kFieldFlagNone },
147 { "Base Speed", kFieldTypeFloat, FieldLocation(sRotDoorProp, base_speed), kFieldFlagNone },
148 { "Axis", kFieldTypeEnum, FieldLocation(sRotDoorProp, axis), kFieldFlagNone, 0, 3, 3, pDoorAxes },
149 { "Status", kFieldTypeEnum, FieldLocation(sRotDoorProp, status), kFieldFlagNone, 0, 5, 5, pDoorStates },
150 { "Hard Limits?", kFieldTypeBool, FieldLocation(sRotDoorProp, hard_limits), kFieldFlagNone },
151 { "Blocks Vision?", kFieldTypeBool, FieldLocation(sRotDoorProp, vision_blocking), kFieldFlagNone },
152 { "Blocks Sound %", kFieldTypeFloat, FieldLocation(sRotDoorProp, sound_blocking), kFieldFlagNone },
153 { "Push Mass", kFieldTypeFloat, FieldLocation(sRotDoorProp, push_mass), kFieldFlagNone },
154 { "Clockwise?", kFieldTypeBool, FieldLocation(sRotDoorProp, clockwise), kFieldFlagNone },
155 { "Room ID #1", kFieldTypeInt, FieldLocation(sRotDoorProp, room1), kFieldFlagNotEdit },
156 { "Room ID #2", kFieldTypeInt, FieldLocation(sRotDoorProp, room2), kFieldFlagNotEdit },
159 // build by hand
160 static sStructDesc RotDoorDesc = StructDescBuild(sRotDoorProp, kStructFlagNone, RotDoorPropFields);
162 ////////////////////////////////////////
164 void LGAPI RotDoorListener(sPropertyListenMsg *msg, PropListenerData data);
165 static void SetupRotDoorProperty(void);
167 ////////////////////////////////////////
169 class cRotDoorOps : public cClassDataOps<sRotDoorProp>
171 public:
172 STDMETHOD_(int,Version)();
173 STDMETHOD(Read)(sDatum* dat, IDataOpsFile* file, int version);
176 typedef cHashPropertyStore<cRotDoorOps> cRotDoorStore;
178 typedef cSpecificProperty<IRotDoorProperty, &IID_IRotDoorProperty, sRotDoorProp*, cRotDoorStore> cBaseRotDoorProp;
180 class cRotDoorProp : public cBaseRotDoorProp
182 public:
183 cRotDoorProp(const sPropertyDesc* desc) : cBaseRotDoorProp(desc) {};
185 STANDARD_DESCRIBE_TYPE(sRotDoorProp);
188 STDMETHODIMP_(int) cRotDoorOps::Version()
190 return 1001;
193 STDMETHODIMP cRotDoorOps::Read(sDatum* pdat, IDataOpsFile* file, int v)
195 if (!pdat->value)
196 *pdat = New();
198 sRotDoorProp *pRotDoorProp = (sRotDoorProp *)pdat->value;
200 file->Read(&pRotDoorProp->type, sizeof(int));
201 file->Read(&pRotDoorProp->closed, sizeof(mxs_real));
202 file->Read(&pRotDoorProp->open, sizeof(mxs_real));
203 file->Read(&pRotDoorProp->base_speed, sizeof(mxs_real));
204 file->Read(&pRotDoorProp->axis, sizeof(int));
205 file->Read(&pRotDoorProp->status, sizeof(int));
206 file->Read(&pRotDoorProp->hard_limits, sizeof(BOOL));
207 file->Read(&pRotDoorProp->sound_blocking, sizeof(mxs_real));
208 file->Read(&pRotDoorProp->vision_blocking, sizeof(BOOL));
209 if (v < 1000)
210 pRotDoorProp->push_mass = 25.0;
211 else
212 file->Read(&pRotDoorProp->push_mass, sizeof(mxs_real));
213 file->Read(&pRotDoorProp->base_closed_location, sizeof(mxs_vector));
214 file->Read(&pRotDoorProp->base_open_location, sizeof(mxs_vector));
215 file->Read(&pRotDoorProp->base_location, sizeof(mxs_vector));
216 file->Read(&pRotDoorProp->base_angle, sizeof(mxs_angvec));
217 file->Read(&pRotDoorProp->base, sizeof(mxs_real));
218 file->Read(&pRotDoorProp->room1, sizeof(int));
219 file->Read(&pRotDoorProp->room2, sizeof(int));
220 file->Read(&pRotDoorProp->clockwise, sizeof(BOOL));
221 if (v >= 1001)
223 file->Read(&pRotDoorProp->base_closed_facing, sizeof(mxs_angvec));
224 file->Read(&pRotDoorProp->base_open_facing, sizeof(mxs_angvec));
227 return S_OK;
230 ////////////////////////////////////////
232 IRotDoorProperty *RotDoorPropertyInit(void)
234 SetupRotDoorProperty();
236 g_pRotDoorProperty = new cRotDoorProp(&RotPropDesc);
238 // Install listener
239 g_pRotDoorProperty->Listen(kListenPropModify | kListenPropSet | kListenPropUnset | kListenPropLoad,
240 RotDoorListener, NULL);
242 return g_pRotDoorProperty;
245 ////////////////////////////////////////
247 void RotDoorPropertyTerm(void)
249 SafeRelease(g_pRotDoorProperty);
252 ////////////////////////////////////////
254 static void SetupRotDoorProperty(void)
256 StructDescRegister(&RotDoorDesc);
259 ////////////////////////////////////////
261 BOOL rot_door_lock = FALSE;
263 void LGAPI RotDoorListener(sPropertyListenMsg *msg, PropListenerData data)
265 sRotDoorProp *pDoorProp;
267 if (!msg->value.ptrval || rot_door_lock)
268 return;
270 pDoorProp = (sRotDoorProp *)msg->value.ptrval;
272 #if 0
273 if (OBJ_IS_CONCRETE(msg->obj) && !PhysObjHasPhysics(msg->obj) && !(msg->type & kListenPropUnset))
274 PhysRegisterOBBDefault(msg->obj);
275 #endif
277 // Load
278 if ((msg->type & kListenPropLoad) && (pDoorProp->status != kDoorClosed))
280 cPhysModel *pModel;
282 if ((pModel = g_PhysModels.Get(msg->obj)) != NULL)
284 pModel->ClearAngleLimits();
286 mxs_angvec cur_ang = ObjPosGet(msg->obj)->fac;
287 ObjRotate(msg->obj, &pDoorProp->base_angle);
289 pModel->AddAngleLimit(pDoorProp->axis, pDoorProp->open, RotDoorOpenCallback);
290 pModel->AddAngleLimit(pDoorProp->axis, 0, RotDoorCloseCallback);
292 ObjRotate(msg->obj, &cur_ang);
295 return;
299 // Creation
300 if (msg->type & kListenPropSet)
302 if (!(msg->type & kListenPropModify))
304 // default to the z-axis and 1.0 radians/sec
305 pDoorProp->axis = 2;
306 pDoorProp->base_speed = 1.0;
308 pDoorProp->type = ROTATING_DOOR;
310 pDoorProp->vision_blocking = TRUE;
311 pDoorProp->sound_blocking = 60.0;
313 pDoorProp->push_mass = 25.0;
315 pDoorProp->room1 = -1;
316 pDoorProp->room2 = -1;
319 if (OBJ_IS_CONCRETE(msg->obj))
321 UpdateDoorPhysics(msg->obj);
322 UpdateDoorBrush(msg->obj);
325 ROT_DOOR_LOCK;
326 g_pRotDoorProperty->Set(msg->obj, pDoorProp);
327 ROT_DOOR_UNLOCK;
329 return;
332 // Modification
333 if (msg->type & kListenPropModify)
335 // check for valid axis
336 if ((pDoorProp->axis < 0) || (pDoorProp->axis > 2))
337 pDoorProp->axis = 2;
339 // check for valid status
340 if ((pDoorProp->status < 0) || (pDoorProp->status > 3))
341 pDoorProp->status = 0;
343 // check for valid angle
344 if (pDoorProp->open < 0)
346 while (pDoorProp->open < 0)
347 pDoorProp->open += 360.0;
348 while (pDoorProp->open >= 360)
349 pDoorProp->open -= 360.0;
351 if (pDoorProp->closed < 0)
353 while (pDoorProp->closed < 0)
354 pDoorProp->closed += 360.0;
355 while (pDoorProp->closed >= 360)
356 pDoorProp->closed -= 360.0;
359 if (OBJ_IS_CONCRETE(msg->obj))
361 UpdateDoorPhysics(msg->obj);
362 GenerateBaseDoorLocations(msg->obj);
365 ROT_DOOR_LOCK;
366 g_pRotDoorProperty->Set(msg->obj, pDoorProp);
367 ROT_DOOR_UNLOCK;
369 return;
372 // Deletion
373 if (msg->type & kListenPropUnset)
375 return;
379 ////////////////////////////////////////////////////////////////////////////////
381 // Translating doors
384 // Description
385 static sPropertyDesc TransPropDesc =
387 PROP_TRANSDOOR_NAME,
388 kPropertyNoInherit | kPropertyInstantiate,
389 door_constraints,
390 1, // version
391 0, // last ok version (0 means no other ok versions)
392 { "Door", "Translating" },
393 kPropertyChangeLocally,
396 typedef cGenericProperty<ITransDoorProperty,&IID_ITransDoorProperty, sTransDoorProp*> cTransDoorPropertyBase;
398 class cTransDoorProperty : public cTransDoorPropertyBase
400 cClassDataOps< sTransDoorProp> mOps;
402 public:
403 cTransDoorProperty(const sPropertyDesc* desc, IPropertyStore* store)
404 : cTransDoorPropertyBase(desc,store)
406 SetOps(&mOps);
409 cTransDoorProperty(const sPropertyDesc* desc, ePropertyImpl impl)
410 : cTransDoorPropertyBase(desc,CreateGenericPropertyStore(impl))
412 SetOps(&mOps);
415 STANDARD_DESCRIBE_TYPE( sTransDoorProp);
418 ////////////////////////////////////////
420 static sFieldDesc TransDoorPropFields[] =
422 { "Closed Position", kFieldTypeFloat, FieldLocation(sTransDoorProp, closed), kFieldFlagNone },
423 { "Open Position", kFieldTypeFloat, FieldLocation(sTransDoorProp, open), kFieldFlagNone },
424 { "Base Speed", kFieldTypeFloat, FieldLocation(sTransDoorProp, base_speed), kFieldFlagNone },
425 { "Axis", kFieldTypeEnum, FieldLocation(sTransDoorProp, axis), kFieldFlagNone, 0, 3, 3, pDoorAxes },
426 { "Status", kFieldTypeEnum, FieldLocation(sTransDoorProp, status), kFieldFlagNone, 0, 5, 5, pDoorStates },
427 { "Hard Limits?", kFieldTypeBool, FieldLocation(sTransDoorProp, hard_limits), kFieldFlagNone },
428 { "Blocks Vision?", kFieldTypeBool, FieldLocation(sRotDoorProp, vision_blocking), kFieldFlagNone },
429 { "Blocks Sound %", kFieldTypeFloat, FieldLocation(sRotDoorProp, sound_blocking), kFieldFlagNone },
430 { "Push Mass", kFieldTypeFloat, FieldLocation(sRotDoorProp, push_mass), kFieldFlagNone },
431 { "Room ID #1", kFieldTypeInt, FieldLocation(sRotDoorProp, room1), kFieldFlagNotEdit },
432 { "Room ID #2", kFieldTypeInt, FieldLocation(sRotDoorProp, room2), kFieldFlagNotEdit },
435 // build by hand
436 static sStructDesc TransDoorDesc = StructDescBuild(sTransDoorProp, kStructFlagNone, TransDoorPropFields);
438 ////////////////////////////////////////
440 void LGAPI TransDoorListener(sPropertyListenMsg *msg, PropListenerData data);
441 static void SetupTransDoorProperty(void);
443 ////////////////////////////////////////
445 class cTransDoorOps : public cClassDataOps<sTransDoorProp>
447 public:
448 STDMETHOD_(int,Version)();
449 STDMETHOD(Read)(sDatum* dat, IDataOpsFile* file, int version);
452 typedef cHashPropertyStore<cTransDoorOps> cTransDoorStore;
454 typedef cSpecificProperty<ITransDoorProperty, &IID_ITransDoorProperty, sTransDoorProp*, cTransDoorStore> cBaseTransDoorProp;
456 class cTransDoorProp : public cBaseTransDoorProp
458 public:
459 cTransDoorProp(const sPropertyDesc* desc) : cBaseTransDoorProp(desc) {};
461 STANDARD_DESCRIBE_TYPE(sTransDoorProp);
464 STDMETHODIMP_(int) cTransDoorOps::Version()
466 return 1000;
469 STDMETHODIMP cTransDoorOps::Read(sDatum* pdat, IDataOpsFile* file, int v)
471 if (!pdat->value)
472 *pdat = New();
474 sTransDoorProp *pTransDoorProp = (sTransDoorProp *)pdat->value;
476 file->Read(&pTransDoorProp->type, sizeof(int));
477 file->Read(&pTransDoorProp->closed, sizeof(mxs_real));
478 file->Read(&pTransDoorProp->open, sizeof(mxs_real));
479 file->Read(&pTransDoorProp->base_speed, sizeof(mxs_real));
480 file->Read(&pTransDoorProp->axis, sizeof(int));
481 file->Read(&pTransDoorProp->status, sizeof(int));
482 file->Read(&pTransDoorProp->hard_limits, sizeof(BOOL));
483 file->Read(&pTransDoorProp->sound_blocking, sizeof(mxs_real));
484 file->Read(&pTransDoorProp->vision_blocking, sizeof(BOOL));
485 if (v < 1000)
486 pTransDoorProp->push_mass = 25.0;
487 else
488 file->Read(&pTransDoorProp->push_mass, sizeof(mxs_real));
489 file->Read(&pTransDoorProp->base_closed_location, sizeof(mxs_vector));
490 file->Read(&pTransDoorProp->base_open_location, sizeof(mxs_vector));
491 file->Read(&pTransDoorProp->base_location, sizeof(mxs_vector));
492 file->Read(&pTransDoorProp->base_angle, sizeof(mxs_angvec));
493 file->Read(&pTransDoorProp->base, sizeof(mxs_real));
494 file->Read(&pTransDoorProp->room1, sizeof(int));
495 file->Read(&pTransDoorProp->room2, sizeof(int));
497 return S_OK;
500 ////////////////////////////////////////
502 ITransDoorProperty *TransDoorPropertyInit(void)
504 SetupTransDoorProperty();
505 g_pTransDoorProperty = new cTransDoorProp(&TransPropDesc);
507 // Install listener
508 g_pTransDoorProperty->Listen(kListenPropModify | kListenPropSet | kListenPropUnset | kListenPropLoad,
509 TransDoorListener, NULL);
511 return g_pTransDoorProperty;
514 ////////////////////////////////////////
516 void TransDoorPropertyTerm(void)
518 SafeRelease(g_pTransDoorProperty);
521 ////////////////////////////////////////
523 static void SetupTransDoorProperty(void)
525 StructDescRegister(&TransDoorDesc);
528 ////////////////////////////////////////
530 static BOOL trans_door_lock = FALSE;
532 #define TRANS_DOOR_LOCK trans_door_lock = TRUE
533 #define TRANS_DOOR_UNLOCK trans_door_lock = FALSE
535 void LGAPI TransDoorListener(sPropertyListenMsg *msg, PropListenerData data)
537 sTransDoorProp *pDoorProp;
539 if (!msg->value.ptrval || trans_door_lock)
540 return;
542 pDoorProp = (sTransDoorProp *)msg->value.ptrval;
544 if (OBJ_IS_CONCRETE(msg->obj) && !PhysObjHasPhysics(msg->obj) && !(msg->type & kListenPropUnset))
545 PhysRegisterOBBDefault(msg->obj);
547 // Load
548 if ((msg->type & kListenPropLoad) && (pDoorProp->status != kDoorClosed))
550 cPhysModel *pModel;
552 if ((pModel = g_PhysModels.Get(msg->obj)) != NULL)
554 pModel->ClearTransLimits();
555 pModel->AddTransLimit(pDoorProp->base_open_location, TransDoorOpenCallback);
556 pModel->AddTransLimit(pDoorProp->base_closed_location, TransDoorClosedCallback);
559 return;
562 // Creation
563 if (msg->type & kListenPropSet)
565 if (!(msg->type & kListenPropModify))
567 // default to the x-axis and 1.0 ft/sec
568 pDoorProp->axis = 0;
569 pDoorProp->base_speed = 1.0;
571 pDoorProp->type = TRANSLATING_DOOR;
573 pDoorProp->vision_blocking = TRUE;
574 pDoorProp->sound_blocking = 60.0;
576 pDoorProp->push_mass = 25.0;
578 pDoorProp->room1 = -1;
579 pDoorProp->room2 = -1;
582 if (OBJ_IS_CONCRETE(msg->obj))
584 UpdateDoorPhysics(msg->obj);
585 UpdateDoorBrush(msg->obj);
588 TRANS_DOOR_LOCK;
589 g_pTransDoorProperty->Set(msg->obj, pDoorProp);
590 TRANS_DOOR_UNLOCK;
592 return;
595 // Modification
596 if (msg->type & kListenPropModify)
598 // check for valid axis
599 if ((pDoorProp->axis < 0) || (pDoorProp->axis > 2))
601 pDoorProp->axis = 2;
603 TRANS_DOOR_LOCK;
604 g_pTransDoorProperty->Set(msg->obj, pDoorProp);
605 TRANS_DOOR_UNLOCK;
608 // check for valid status
609 if ((pDoorProp->status < 0) || (pDoorProp->status > 3))
611 pDoorProp->status = 0;
613 TRANS_DOOR_LOCK;
614 g_pTransDoorProperty->Set(msg->obj, pDoorProp);
615 TRANS_DOOR_UNLOCK;
618 if (OBJ_IS_CONCRETE(msg->obj))
620 GenerateBaseDoorLocations(msg->obj);
621 UpdateDoorPhysics(msg->obj);
624 return;
627 // Deletion
628 if (msg->type & kListenPropUnset)
630 return;